phpunit-9.2.5.phar 3.0 MB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979498049814982498349844985498649874988498949904991499249934994499549964997499849995000500150025003500450055006500750085009501050115012501350145015501650175018501950205021502250235024502550265027502850295030503150325033503450355036503750385039504050415042504350445045504650475048504950505051505250535054505550565057505850595060506150625063506450655066506750685069507050715072507350745075507650775078507950805081508250835084508550865087508850895090509150925093509450955096509750985099510051015102510351045105510651075108510951105111511251135114511551165117511851195120512151225123512451255126512751285129513051315132513351345135513651375138513951405141514251435144514551465147514851495150515151525153515451555156515751585159516051615162516351645165516651675168516951705171517251735174517551765177517851795180518151825183518451855186518751885189519051915192519351945195519651975198519952005201520252035204520552065207520852095210521152125213521452155216521752185219522052215222522352245225522652275228522952305231523252335234523552365237523852395240524152425243524452455246524752485249525052515252525352545255525652575258525952605261526252635264526552665267526852695270527152725273527452755276527752785279528052815282528352845285528652875288528952905291529252935294529552965297529852995300530153025303530453055306530753085309531053115312531353145315531653175318531953205321532253235324532553265327532853295330533153325333533453355336533753385339534053415342534353445345534653475348534953505351535253535354535553565357535853595360536153625363536453655366536753685369537053715372537353745375537653775378537953805381538253835384538553865387538853895390539153925393539453955396539753985399540054015402540354045405540654075408540954105411541254135414541554165417541854195420542154225423542454255426542754285429543054315432543354345435543654375438543954405441544254435444544554465447544854495450545154525453545454555456545754585459546054615462546354645465546654675468546954705471547254735474547554765477547854795480548154825483548454855486548754885489549054915492549354945495549654975498549955005501550255035504550555065507550855095510551155125513551455155516551755185519552055215522552355245525552655275528552955305531553255335534553555365537553855395540554155425543554455455546554755485549555055515552555355545555555655575558555955605561556255635564556555665567556855695570557155725573557455755576557755785579558055815582558355845585558655875588558955905591559255935594559555965597559855995600560156025603560456055606560756085609561056115612561356145615561656175618561956205621562256235624562556265627562856295630563156325633563456355636563756385639564056415642564356445645564656475648564956505651565256535654565556565657565856595660566156625663566456655666566756685669567056715672567356745675567656775678567956805681568256835684568556865687568856895690569156925693569456955696569756985699570057015702570357045705570657075708570957105711571257135714571557165717571857195720572157225723572457255726572757285729573057315732573357345735573657375738573957405741574257435744574557465747574857495750575157525753575457555756575757585759576057615762576357645765576657675768576957705771577257735774577557765777577857795780578157825783578457855786578757885789579057915792579357945795579657975798579958005801580258035804580558065807580858095810581158125813581458155816581758185819582058215822582358245825582658275828582958305831583258335834583558365837583858395840584158425843584458455846584758485849585058515852585358545855585658575858585958605861586258635864586558665867586858695870587158725873587458755876587758785879588058815882588358845885588658875888588958905891589258935894589558965897589858995900590159025903590459055906590759085909591059115912591359145915591659175918591959205921592259235924592559265927592859295930593159325933593459355936593759385939594059415942594359445945594659475948594959505951595259535954595559565957595859595960596159625963596459655966596759685969597059715972597359745975597659775978597959805981598259835984598559865987598859895990599159925993599459955996599759985999600060016002600360046005600660076008600960106011601260136014601560166017601860196020602160226023602460256026602760286029603060316032603360346035603660376038603960406041604260436044604560466047604860496050605160526053605460556056605760586059606060616062606360646065606660676068606960706071607260736074607560766077607860796080608160826083608460856086608760886089609060916092609360946095609660976098609961006101610261036104610561066107610861096110611161126113611461156116611761186119612061216122612361246125612661276128612961306131613261336134613561366137613861396140614161426143614461456146614761486149615061516152615361546155615661576158615961606161616261636164616561666167616861696170617161726173617461756176617761786179618061816182618361846185618661876188618961906191619261936194619561966197619861996200620162026203620462056206620762086209621062116212621362146215621662176218621962206221622262236224622562266227622862296230623162326233623462356236623762386239624062416242624362446245624662476248624962506251625262536254625562566257625862596260626162626263626462656266626762686269627062716272627362746275627662776278627962806281628262836284628562866287628862896290629162926293629462956296629762986299630063016302630363046305630663076308630963106311631263136314631563166317631863196320632163226323632463256326632763286329633063316332633363346335633663376338633963406341634263436344634563466347634863496350635163526353635463556356635763586359636063616362636363646365636663676368636963706371637263736374637563766377637863796380638163826383638463856386638763886389639063916392639363946395639663976398639964006401640264036404640564066407640864096410641164126413641464156416641764186419642064216422642364246425642664276428642964306431643264336434643564366437643864396440644164426443644464456446644764486449645064516452645364546455645664576458645964606461646264636464646564666467646864696470647164726473647464756476647764786479648064816482648364846485648664876488648964906491649264936494649564966497649864996500650165026503650465056506650765086509651065116512651365146515651665176518651965206521652265236524652565266527652865296530653165326533653465356536653765386539654065416542654365446545654665476548654965506551655265536554655565566557655865596560656165626563656465656566656765686569657065716572657365746575657665776578657965806581658265836584658565866587658865896590659165926593659465956596659765986599660066016602660366046605660666076608660966106611661266136614661566166617661866196620662166226623662466256626662766286629663066316632663366346635663666376638663966406641664266436644664566466647664866496650665166526653665466556656665766586659666066616662666366646665666666676668666966706671667266736674667566766677667866796680668166826683668466856686668766886689669066916692669366946695669666976698669967006701670267036704670567066707670867096710671167126713671467156716671767186719672067216722672367246725672667276728672967306731673267336734673567366737673867396740674167426743674467456746674767486749675067516752675367546755675667576758675967606761676267636764676567666767676867696770677167726773677467756776677767786779678067816782678367846785678667876788678967906791679267936794679567966797679867996800680168026803680468056806680768086809681068116812681368146815681668176818681968206821682268236824682568266827682868296830683168326833683468356836683768386839684068416842684368446845684668476848684968506851685268536854685568566857685868596860686168626863686468656866686768686869687068716872687368746875687668776878687968806881688268836884688568866887688868896890689168926893689468956896689768986899690069016902690369046905690669076908690969106911691269136914691569166917691869196920692169226923692469256926692769286929693069316932693369346935693669376938693969406941694269436944694569466947694869496950695169526953695469556956695769586959696069616962696369646965696669676968696969706971697269736974697569766977697869796980698169826983698469856986698769886989699069916992699369946995699669976998699970007001700270037004700570067007700870097010701170127013701470157016701770187019702070217022702370247025702670277028702970307031703270337034703570367037703870397040704170427043704470457046704770487049705070517052705370547055705670577058705970607061706270637064706570667067706870697070707170727073707470757076707770787079708070817082708370847085708670877088708970907091709270937094709570967097709870997100710171027103710471057106710771087109711071117112711371147115711671177118711971207121712271237124712571267127712871297130713171327133713471357136713771387139714071417142714371447145714671477148714971507151715271537154715571567157715871597160716171627163716471657166716771687169717071717172717371747175717671777178717971807181718271837184718571867187718871897190719171927193719471957196719771987199720072017202720372047205720672077208720972107211721272137214721572167217721872197220722172227223722472257226722772287229723072317232723372347235723672377238723972407241724272437244724572467247724872497250725172527253725472557256725772587259726072617262726372647265726672677268726972707271727272737274727572767277727872797280728172827283728472857286728772887289729072917292729372947295729672977298729973007301730273037304730573067307730873097310731173127313731473157316731773187319732073217322732373247325732673277328732973307331733273337334733573367337733873397340734173427343734473457346734773487349735073517352735373547355735673577358735973607361736273637364736573667367736873697370737173727373737473757376737773787379738073817382738373847385738673877388738973907391739273937394739573967397739873997400740174027403740474057406740774087409741074117412741374147415741674177418741974207421742274237424742574267427742874297430743174327433743474357436743774387439744074417442744374447445744674477448744974507451745274537454745574567457745874597460746174627463746474657466746774687469747074717472747374747475747674777478747974807481748274837484748574867487748874897490749174927493749474957496749774987499750075017502750375047505750675077508750975107511751275137514751575167517751875197520752175227523752475257526752775287529753075317532753375347535753675377538753975407541754275437544754575467547754875497550755175527553755475557556755775587559756075617562756375647565756675677568756975707571757275737574757575767577757875797580758175827583758475857586758775887589759075917592759375947595759675977598759976007601760276037604760576067607760876097610761176127613761476157616761776187619762076217622762376247625762676277628762976307631763276337634763576367637763876397640764176427643764476457646764776487649765076517652765376547655765676577658765976607661766276637664766576667667766876697670767176727673767476757676767776787679768076817682768376847685768676877688768976907691769276937694769576967697769876997700770177027703770477057706770777087709771077117712771377147715771677177718771977207721772277237724772577267727772877297730773177327733773477357736773777387739774077417742774377447745774677477748774977507751775277537754775577567757775877597760776177627763776477657766776777687769777077717772777377747775777677777778777977807781778277837784778577867787778877897790779177927793779477957796779777987799780078017802780378047805780678077808780978107811781278137814781578167817781878197820782178227823782478257826782778287829783078317832783378347835783678377838783978407841784278437844784578467847784878497850785178527853785478557856785778587859786078617862786378647865786678677868786978707871787278737874787578767877787878797880788178827883788478857886788778887889789078917892789378947895789678977898789979007901790279037904790579067907790879097910791179127913791479157916791779187919792079217922792379247925792679277928792979307931793279337934793579367937793879397940794179427943794479457946794779487949795079517952795379547955795679577958795979607961796279637964796579667967796879697970797179727973797479757976797779787979798079817982798379847985798679877988798979907991799279937994799579967997799879998000800180028003800480058006800780088009801080118012801380148015801680178018801980208021802280238024802580268027802880298030803180328033803480358036803780388039804080418042804380448045804680478048804980508051805280538054805580568057805880598060806180628063806480658066806780688069807080718072807380748075807680778078807980808081808280838084808580868087808880898090809180928093809480958096809780988099810081018102810381048105810681078108810981108111811281138114811581168117811881198120812181228123812481258126812781288129813081318132813381348135813681378138813981408141814281438144814581468147814881498150815181528153815481558156815781588159816081618162816381648165816681678168816981708171817281738174817581768177817881798180818181828183818481858186818781888189819081918192819381948195819681978198819982008201820282038204820582068207820882098210821182128213821482158216821782188219822082218222822382248225822682278228822982308231823282338234823582368237823882398240824182428243824482458246824782488249825082518252825382548255825682578258825982608261826282638264826582668267826882698270827182728273827482758276827782788279828082818282828382848285828682878288828982908291829282938294829582968297829882998300830183028303830483058306830783088309831083118312831383148315831683178318831983208321832283238324832583268327832883298330833183328333833483358336833783388339834083418342834383448345834683478348834983508351835283538354835583568357835883598360836183628363836483658366836783688369837083718372837383748375837683778378837983808381838283838384838583868387838883898390839183928393839483958396839783988399840084018402840384048405840684078408840984108411841284138414841584168417841884198420842184228423842484258426842784288429843084318432843384348435843684378438843984408441844284438444844584468447844884498450845184528453845484558456845784588459846084618462846384648465846684678468846984708471847284738474847584768477847884798480848184828483848484858486848784888489849084918492849384948495849684978498849985008501850285038504850585068507850885098510851185128513851485158516851785188519852085218522852385248525852685278528852985308531853285338534853585368537853885398540854185428543854485458546854785488549855085518552855385548555855685578558855985608561856285638564856585668567856885698570857185728573857485758576857785788579858085818582858385848585858685878588858985908591859285938594859585968597859885998600860186028603860486058606860786088609861086118612861386148615861686178618861986208621862286238624862586268627862886298630863186328633863486358636863786388639864086418642864386448645864686478648864986508651865286538654865586568657865886598660866186628663866486658666866786688669867086718672867386748675867686778678867986808681868286838684868586868687868886898690869186928693869486958696869786988699870087018702870387048705870687078708870987108711871287138714871587168717871887198720872187228723872487258726872787288729873087318732873387348735873687378738873987408741874287438744874587468747874887498750875187528753875487558756875787588759876087618762876387648765876687678768876987708771877287738774877587768777877887798780878187828783878487858786878787888789879087918792879387948795879687978798879988008801880288038804880588068807880888098810881188128813881488158816881788188819882088218822882388248825882688278828882988308831883288338834883588368837883888398840884188428843884488458846884788488849885088518852885388548855885688578858885988608861886288638864886588668867886888698870887188728873887488758876887788788879888088818882888388848885888688878888888988908891889288938894889588968897889888998900890189028903890489058906890789088909891089118912891389148915891689178918891989208921892289238924892589268927892889298930893189328933893489358936893789388939894089418942894389448945894689478948894989508951895289538954895589568957895889598960896189628963896489658966896789688969897089718972897389748975897689778978897989808981898289838984898589868987898889898990899189928993899489958996899789988999900090019002900390049005900690079008900990109011901290139014901590169017901890199020902190229023902490259026902790289029903090319032903390349035903690379038903990409041904290439044904590469047904890499050905190529053905490559056905790589059906090619062906390649065906690679068906990709071907290739074907590769077907890799080908190829083908490859086908790889089909090919092909390949095909690979098909991009101910291039104910591069107910891099110911191129113911491159116911791189119912091219122912391249125912691279128912991309131913291339134913591369137913891399140914191429143914491459146914791489149915091519152915391549155915691579158915991609161916291639164916591669167916891699170917191729173917491759176917791789179918091819182918391849185918691879188918991909191919291939194919591969197919891999200920192029203920492059206920792089209921092119212921392149215921692179218921992209221922292239224922592269227922892299230923192329233923492359236923792389239924092419242924392449245924692479248924992509251925292539254925592569257925892599260926192629263926492659266926792689269927092719272927392749275927692779278927992809281928292839284928592869287928892899290929192929293929492959296929792989299930093019302930393049305930693079308930993109311931293139314931593169317931893199320932193229323932493259326932793289329933093319332933393349335933693379338933993409341934293439344934593469347934893499350935193529353935493559356935793589359936093619362936393649365936693679368936993709371937293739374937593769377937893799380938193829383938493859386938793889389939093919392939393949395939693979398939994009401940294039404940594069407940894099410941194129413941494159416941794189419942094219422942394249425942694279428942994309431943294339434943594369437943894399440944194429443944494459446944794489449945094519452945394549455945694579458945994609461946294639464946594669467946894699470947194729473947494759476947794789479948094819482948394849485948694879488948994909491949294939494949594969497949894999500950195029503950495059506950795089509951095119512951395149515951695179518951995209521952295239524952595269527952895299530953195329533953495359536953795389539954095419542954395449545954695479548954995509551955295539554955595569557955895599560956195629563956495659566956795689569957095719572957395749575957695779578957995809581958295839584958595869587958895899590959195929593959495959596959795989599960096019602960396049605960696079608960996109611961296139614961596169617961896199620962196229623962496259626962796289629963096319632963396349635963696379638963996409641964296439644964596469647964896499650965196529653965496559656965796589659966096619662966396649665966696679668966996709671967296739674967596769677967896799680968196829683968496859686968796889689969096919692969396949695969696979698969997009701970297039704970597069707970897099710971197129713971497159716971797189719972097219722972397249725972697279728972997309731973297339734973597369737973897399740974197429743974497459746974797489749975097519752975397549755975697579758975997609761976297639764976597669767976897699770977197729773977497759776977797789779978097819782978397849785978697879788978997909791979297939794979597969797979897999800980198029803980498059806980798089809981098119812981398149815981698179818981998209821982298239824982598269827982898299830983198329833983498359836983798389839984098419842984398449845984698479848984998509851985298539854985598569857985898599860986198629863986498659866986798689869987098719872987398749875987698779878987998809881988298839884988598869887988898899890989198929893989498959896989798989899990099019902990399049905990699079908990999109911991299139914991599169917991899199920992199229923992499259926992799289929993099319932993399349935993699379938993999409941994299439944994599469947994899499950995199529953995499559956995799589959996099619962996399649965996699679968996999709971997299739974997599769977997899799980998199829983998499859986998799889989999099919992999399949995999699979998999910000100011000210003100041000510006100071000810009100101001110012100131001410015100161001710018100191002010021100221002310024100251002610027100281002910030100311003210033100341003510036100371003810039100401004110042100431004410045100461004710048100491005010051100521005310054100551005610057100581005910060100611006210063100641006510066100671006810069100701007110072100731007410075100761007710078100791008010081100821008310084100851008610087100881008910090100911009210093100941009510096100971009810099101001010110102101031010410105101061010710108101091011010111101121011310114101151011610117101181011910120101211012210123101241012510126101271012810129101301013110132101331013410135101361013710138101391014010141101421014310144101451014610147101481014910150101511015210153101541015510156101571015810159101601016110162101631016410165101661016710168101691017010171101721017310174101751017610177101781017910180101811018210183101841018510186101871018810189101901019110192101931019410195101961019710198101991020010201102021020310204102051020610207102081020910210102111021210213102141021510216102171021810219102201022110222102231022410225102261022710228102291023010231102321023310234102351023610237102381023910240102411024210243102441024510246102471024810249102501025110252102531025410255102561025710258102591026010261102621026310264102651026610267102681026910270102711027210273102741027510276102771027810279102801028110282102831028410285102861028710288102891029010291102921029310294102951029610297102981029910300103011030210303103041030510306103071030810309103101031110312103131031410315103161031710318103191032010321103221032310324103251032610327103281032910330103311033210333103341033510336103371033810339103401034110342103431034410345103461034710348103491035010351103521035310354103551035610357103581035910360103611036210363103641036510366103671036810369103701037110372103731037410375103761037710378103791038010381103821038310384103851038610387103881038910390103911039210393103941039510396103971039810399104001040110402104031040410405104061040710408104091041010411104121041310414104151041610417104181041910420104211042210423104241042510426104271042810429104301043110432104331043410435104361043710438104391044010441104421044310444104451044610447104481044910450104511045210453104541045510456104571045810459104601046110462104631046410465104661046710468104691047010471104721047310474104751047610477104781047910480104811048210483104841048510486104871048810489104901049110492104931049410495104961049710498104991050010501105021050310504105051050610507105081050910510105111051210513105141051510516105171051810519105201052110522105231052410525105261052710528105291053010531105321053310534105351053610537105381053910540105411054210543105441054510546105471054810549105501055110552105531055410555105561055710558105591056010561105621056310564105651056610567105681056910570105711057210573105741057510576105771057810579105801058110582105831058410585105861058710588105891059010591105921059310594105951059610597105981059910600106011060210603106041060510606106071060810609106101061110612106131061410615106161061710618106191062010621106221062310624106251062610627106281062910630106311063210633106341063510636106371063810639106401064110642106431064410645106461064710648106491065010651106521065310654106551065610657106581065910660106611066210663106641066510666106671066810669106701067110672106731067410675106761067710678106791068010681106821068310684106851068610687106881068910690106911069210693106941069510696106971069810699107001070110702107031070410705107061070710708107091071010711107121071310714107151071610717107181071910720107211072210723107241072510726107271072810729107301073110732107331073410735107361073710738107391074010741107421074310744107451074610747107481074910750107511075210753107541075510756107571075810759107601076110762107631076410765107661076710768107691077010771107721077310774107751077610777107781077910780107811078210783107841078510786107871078810789107901079110792107931079410795107961079710798107991080010801108021080310804108051080610807108081080910810108111081210813108141081510816108171081810819108201082110822108231082410825108261082710828108291083010831108321083310834108351083610837108381083910840108411084210843108441084510846108471084810849108501085110852108531085410855108561085710858108591086010861108621086310864108651086610867108681086910870108711087210873108741087510876108771087810879108801088110882108831088410885108861088710888108891089010891108921089310894108951089610897108981089910900109011090210903109041090510906109071090810909109101091110912109131091410915109161091710918109191092010921109221092310924109251092610927109281092910930109311093210933109341093510936109371093810939109401094110942109431094410945109461094710948109491095010951109521095310954109551095610957109581095910960109611096210963109641096510966109671096810969109701097110972109731097410975109761097710978109791098010981109821098310984109851098610987109881098910990109911099210993109941099510996109971099810999110001100111002110031100411005110061100711008110091101011011110121101311014110151101611017110181101911020110211102211023110241102511026110271102811029110301103111032110331103411035110361103711038110391104011041110421104311044110451104611047110481104911050110511105211053110541105511056110571105811059110601106111062110631106411065110661106711068110691107011071110721107311074110751107611077110781107911080110811108211083110841108511086110871108811089110901109111092110931109411095110961109711098110991110011101111021110311104111051110611107111081110911110111111111211113111141111511116111171111811119111201112111122111231112411125111261112711128111291113011131111321113311134111351113611137111381113911140111411114211143111441114511146111471114811149111501115111152111531115411155111561115711158111591116011161111621116311164111651116611167111681116911170111711117211173111741117511176111771117811179111801118111182111831118411185111861118711188111891119011191111921119311194111951119611197111981119911200112011120211203112041120511206112071120811209112101121111212112131121411215112161121711218112191122011221112221122311224112251122611227112281122911230112311123211233112341123511236112371123811239112401124111242112431124411245112461124711248112491125011251112521125311254112551125611257112581125911260112611126211263112641126511266112671126811269112701127111272112731127411275112761127711278112791128011281112821128311284112851128611287112881128911290112911129211293112941129511296112971129811299113001130111302113031130411305113061130711308113091131011311113121131311314113151131611317113181131911320113211132211323113241132511326113271132811329113301133111332113331133411335113361133711338113391134011341113421134311344113451134611347113481134911350113511135211353113541135511356113571135811359113601136111362113631136411365113661136711368113691137011371113721137311374113751137611377113781137911380113811138211383113841138511386113871138811389113901139111392113931139411395113961139711398113991140011401114021140311404114051140611407114081140911410114111141211413114141141511416114171141811419114201142111422114231142411425114261142711428114291143011431114321143311434114351143611437114381143911440114411144211443114441144511446114471144811449114501145111452114531145411455114561145711458114591146011461114621146311464114651146611467114681146911470114711147211473114741147511476114771147811479114801148111482114831148411485114861148711488114891149011491114921149311494114951149611497114981149911500115011150211503115041150511506115071150811509115101151111512115131151411515115161151711518115191152011521115221152311524115251152611527115281152911530115311153211533115341153511536115371153811539115401154111542115431154411545115461154711548115491155011551115521155311554115551155611557115581155911560115611156211563115641156511566115671156811569115701157111572115731157411575115761157711578115791158011581115821158311584115851158611587115881158911590115911159211593115941159511596115971159811599116001160111602116031160411605116061160711608116091161011611116121161311614116151161611617116181161911620116211162211623116241162511626116271162811629116301163111632116331163411635116361163711638116391164011641116421164311644116451164611647116481164911650116511165211653116541165511656116571165811659116601166111662116631166411665116661166711668116691167011671116721167311674116751167611677116781167911680116811168211683116841168511686116871168811689116901169111692116931169411695116961169711698116991170011701117021170311704117051170611707117081170911710117111171211713117141171511716117171171811719117201172111722117231172411725117261172711728117291173011731117321173311734117351173611737117381173911740117411174211743117441174511746117471174811749117501175111752117531175411755117561175711758117591176011761117621176311764117651176611767117681176911770117711177211773117741177511776117771177811779117801178111782117831178411785117861178711788117891179011791117921179311794117951179611797117981179911800118011180211803118041180511806118071180811809118101181111812118131181411815118161181711818118191182011821118221182311824118251182611827118281182911830118311183211833118341183511836118371183811839118401184111842118431184411845118461184711848118491185011851118521185311854118551185611857118581185911860118611186211863118641186511866118671186811869118701187111872118731187411875118761187711878118791188011881118821188311884118851188611887118881188911890118911189211893118941189511896118971189811899119001190111902119031190411905119061190711908119091191011911119121191311914119151191611917119181191911920119211192211923119241192511926119271192811929119301193111932119331193411935119361193711938119391194011941119421194311944119451194611947119481194911950119511195211953119541195511956119571195811959119601196111962119631196411965119661196711968119691197011971119721197311974119751197611977119781197911980119811198211983119841198511986119871198811989119901199111992119931199411995119961199711998119991200012001120021200312004120051200612007120081200912010120111201212013120141201512016120171201812019120201202112022120231202412025120261202712028120291203012031120321203312034120351203612037120381203912040120411204212043120441204512046120471204812049120501205112052120531205412055120561205712058120591206012061120621206312064120651206612067120681206912070120711207212073120741207512076120771207812079120801208112082120831208412085120861208712088120891209012091120921209312094120951209612097120981209912100121011210212103121041210512106121071210812109121101211112112121131211412115121161211712118121191212012121121221212312124121251212612127121281212912130121311213212133121341213512136121371213812139121401214112142121431214412145121461214712148121491215012151121521215312154121551215612157121581215912160121611216212163121641216512166121671216812169121701217112172121731217412175121761217712178121791218012181121821218312184121851218612187121881218912190121911219212193121941219512196121971219812199122001220112202122031220412205122061220712208122091221012211122121221312214122151221612217122181221912220122211222212223122241222512226122271222812229122301223112232122331223412235122361223712238122391224012241122421224312244122451224612247122481224912250122511225212253122541225512256122571225812259122601226112262122631226412265122661226712268122691227012271122721227312274122751227612277122781227912280122811228212283122841228512286122871228812289122901229112292122931229412295122961229712298122991230012301123021230312304123051230612307123081230912310123111231212313123141231512316123171231812319123201232112322123231232412325123261232712328123291233012331123321233312334123351233612337123381233912340123411234212343123441234512346123471234812349123501235112352123531235412355123561235712358123591236012361123621236312364123651236612367123681236912370123711237212373123741237512376123771237812379123801238112382123831238412385123861238712388123891239012391123921239312394123951239612397123981239912400124011240212403124041240512406124071240812409124101241112412124131241412415124161241712418124191242012421124221242312424124251242612427124281242912430124311243212433124341243512436124371243812439124401244112442124431244412445124461244712448124491245012451124521245312454124551245612457124581245912460124611246212463124641246512466124671246812469124701247112472124731247412475124761247712478124791248012481124821248312484124851248612487124881248912490124911249212493124941249512496124971249812499125001250112502125031250412505125061250712508125091251012511125121251312514125151251612517125181251912520125211252212523125241252512526125271252812529125301253112532125331253412535125361253712538125391254012541125421254312544125451254612547125481254912550125511255212553125541255512556125571255812559125601256112562125631256412565125661256712568125691257012571125721257312574125751257612577125781257912580125811258212583125841258512586125871258812589125901259112592125931259412595125961259712598125991260012601126021260312604126051260612607126081260912610126111261212613126141261512616126171261812619126201262112622126231262412625126261262712628126291263012631126321263312634126351263612637126381263912640126411264212643126441264512646126471264812649126501265112652126531265412655126561265712658126591266012661126621266312664126651266612667126681266912670126711267212673126741267512676126771267812679126801268112682126831268412685126861268712688126891269012691126921269312694126951269612697126981269912700127011270212703127041270512706127071270812709127101271112712127131271412715127161271712718127191272012721127221272312724127251272612727127281272912730127311273212733127341273512736127371273812739127401274112742127431274412745127461274712748127491275012751127521275312754127551275612757127581275912760127611276212763127641276512766127671276812769127701277112772127731277412775127761277712778127791278012781127821278312784127851278612787127881278912790127911279212793127941279512796127971279812799128001280112802128031280412805128061280712808128091281012811128121281312814128151281612817128181281912820128211282212823128241282512826128271282812829128301283112832128331283412835128361283712838128391284012841128421284312844128451284612847128481284912850128511285212853128541285512856128571285812859128601286112862128631286412865128661286712868128691287012871128721287312874128751287612877128781287912880128811288212883128841288512886128871288812889128901289112892128931289412895128961289712898128991290012901129021290312904129051290612907129081290912910129111291212913129141291512916129171291812919129201292112922129231292412925129261292712928129291293012931129321293312934129351293612937129381293912940129411294212943129441294512946129471294812949129501295112952129531295412955129561295712958129591296012961129621296312964129651296612967129681296912970129711297212973129741297512976129771297812979129801298112982129831298412985129861298712988129891299012991129921299312994129951299612997129981299913000130011300213003130041300513006130071300813009130101301113012130131301413015130161301713018130191302013021130221302313024130251302613027130281302913030130311303213033130341303513036130371303813039130401304113042130431304413045130461304713048130491305013051130521305313054130551305613057130581305913060130611306213063130641306513066130671306813069130701307113072130731307413075130761307713078130791308013081130821308313084130851308613087130881308913090130911309213093130941309513096130971309813099131001310113102131031310413105131061310713108131091311013111131121311313114131151311613117131181311913120131211312213123131241312513126131271312813129131301313113132131331313413135131361313713138131391314013141131421314313144131451314613147131481314913150131511315213153131541315513156131571315813159131601316113162131631316413165131661316713168131691317013171131721317313174131751317613177131781317913180131811318213183131841318513186131871318813189131901319113192131931319413195131961319713198131991320013201132021320313204132051320613207132081320913210132111321213213132141321513216132171321813219132201322113222132231322413225132261322713228132291323013231132321323313234132351323613237132381323913240132411324213243132441324513246132471324813249132501325113252132531325413255132561325713258132591326013261132621326313264132651326613267132681326913270132711327213273132741327513276132771327813279132801328113282132831328413285132861328713288132891329013291132921329313294132951329613297132981329913300133011330213303133041330513306133071330813309133101331113312133131331413315133161331713318133191332013321133221332313324133251332613327133281332913330133311333213333133341333513336133371333813339133401334113342133431334413345133461334713348133491335013351133521335313354133551335613357133581335913360133611336213363133641336513366133671336813369133701337113372133731337413375133761337713378133791338013381133821338313384133851338613387133881338913390133911339213393133941339513396133971339813399134001340113402134031340413405134061340713408134091341013411134121341313414134151341613417134181341913420134211342213423134241342513426134271342813429134301343113432134331343413435134361343713438134391344013441134421344313444134451344613447134481344913450134511345213453134541345513456134571345813459134601346113462134631346413465134661346713468134691347013471134721347313474134751347613477134781347913480134811348213483134841348513486134871348813489134901349113492134931349413495134961349713498134991350013501135021350313504135051350613507135081350913510135111351213513135141351513516135171351813519135201352113522135231352413525135261352713528135291353013531135321353313534135351353613537135381353913540135411354213543135441354513546135471354813549135501355113552135531355413555135561355713558135591356013561135621356313564135651356613567135681356913570135711357213573135741357513576135771357813579135801358113582135831358413585135861358713588135891359013591135921359313594135951359613597135981359913600136011360213603136041360513606136071360813609136101361113612136131361413615136161361713618136191362013621136221362313624136251362613627136281362913630136311363213633136341363513636136371363813639136401364113642136431364413645136461364713648136491365013651136521365313654136551365613657136581365913660136611366213663136641366513666136671366813669136701367113672136731367413675136761367713678136791368013681136821368313684136851368613687136881368913690136911369213693136941369513696136971369813699137001370113702137031370413705137061370713708137091371013711137121371313714137151371613717137181371913720137211372213723137241372513726137271372813729137301373113732137331373413735137361373713738137391374013741137421374313744137451374613747137481374913750137511375213753137541375513756137571375813759137601376113762137631376413765137661376713768137691377013771137721377313774137751377613777137781377913780137811378213783137841378513786137871378813789137901379113792137931379413795137961379713798137991380013801138021380313804138051380613807138081380913810138111381213813138141381513816138171381813819138201382113822138231382413825138261382713828138291383013831138321383313834138351383613837138381383913840138411384213843138441384513846138471384813849138501385113852138531385413855138561385713858138591386013861138621386313864138651386613867138681386913870138711387213873138741387513876138771387813879138801388113882138831388413885138861388713888138891389013891138921389313894138951389613897138981389913900139011390213903139041390513906139071390813909139101391113912139131391413915139161391713918139191392013921139221392313924139251392613927139281392913930139311393213933139341393513936139371393813939139401394113942139431394413945139461394713948139491395013951139521395313954139551395613957139581395913960139611396213963139641396513966139671396813969139701397113972139731397413975139761397713978139791398013981139821398313984139851398613987139881398913990139911399213993139941399513996139971399813999140001400114002140031400414005140061400714008140091401014011140121401314014140151401614017140181401914020140211402214023140241402514026140271402814029140301403114032140331403414035140361403714038140391404014041140421404314044140451404614047140481404914050140511405214053140541405514056140571405814059140601406114062140631406414065140661406714068140691407014071140721407314074140751407614077140781407914080140811408214083140841408514086140871408814089140901409114092140931409414095140961409714098140991410014101141021410314104141051410614107141081410914110141111411214113141141411514116141171411814119141201412114122141231412414125141261412714128141291413014131141321413314134141351413614137141381413914140141411414214143141441414514146141471414814149141501415114152141531415414155141561415714158141591416014161141621416314164141651416614167141681416914170141711417214173141741417514176141771417814179141801418114182141831418414185141861418714188141891419014191141921419314194141951419614197141981419914200142011420214203142041420514206142071420814209142101421114212142131421414215142161421714218142191422014221142221422314224142251422614227142281422914230142311423214233142341423514236142371423814239142401424114242142431424414245142461424714248142491425014251142521425314254142551425614257142581425914260142611426214263142641426514266142671426814269142701427114272142731427414275142761427714278142791428014281142821428314284142851428614287142881428914290142911429214293142941429514296142971429814299143001430114302143031430414305143061430714308143091431014311143121431314314143151431614317143181431914320143211432214323143241432514326143271432814329143301433114332143331433414335143361433714338143391434014341143421434314344143451434614347143481434914350143511435214353143541435514356143571435814359143601436114362143631436414365143661436714368143691437014371143721437314374143751437614377143781437914380143811438214383143841438514386143871438814389143901439114392143931439414395143961439714398143991440014401144021440314404144051440614407144081440914410144111441214413144141441514416144171441814419144201442114422144231442414425144261442714428144291443014431144321443314434144351443614437144381443914440144411444214443144441444514446144471444814449144501445114452144531445414455144561445714458144591446014461144621446314464144651446614467144681446914470144711447214473144741447514476144771447814479144801448114482144831448414485144861448714488144891449014491144921449314494144951449614497144981449914500145011450214503145041450514506145071450814509145101451114512145131451414515145161451714518145191452014521145221452314524145251452614527145281452914530145311453214533145341453514536145371453814539145401454114542145431454414545145461454714548145491455014551145521455314554145551455614557145581455914560145611456214563145641456514566145671456814569145701457114572145731457414575145761457714578145791458014581145821458314584145851458614587145881458914590145911459214593145941459514596145971459814599146001460114602146031460414605146061460714608146091461014611146121461314614146151461614617146181461914620146211462214623146241462514626146271462814629146301463114632146331463414635146361463714638146391464014641146421464314644146451464614647146481464914650146511465214653146541465514656146571465814659146601466114662146631466414665146661466714668146691467014671146721467314674146751467614677146781467914680146811468214683146841468514686146871468814689146901469114692146931469414695146961469714698146991470014701147021470314704147051470614707147081470914710147111471214713147141471514716147171471814719147201472114722147231472414725147261472714728147291473014731147321473314734147351473614737147381473914740147411474214743147441474514746147471474814749147501475114752147531475414755147561475714758147591476014761147621476314764147651476614767147681476914770147711477214773147741477514776147771477814779147801478114782147831478414785147861478714788147891479014791147921479314794147951479614797147981479914800148011480214803148041480514806148071480814809148101481114812148131481414815148161481714818148191482014821148221482314824148251482614827148281482914830148311483214833148341483514836148371483814839148401484114842148431484414845148461484714848148491485014851148521485314854148551485614857148581485914860148611486214863148641486514866148671486814869148701487114872148731487414875148761487714878148791488014881148821488314884148851488614887148881488914890148911489214893148941489514896148971489814899149001490114902149031490414905149061490714908149091491014911149121491314914149151491614917149181491914920149211492214923149241492514926149271492814929149301493114932149331493414935149361493714938149391494014941149421494314944149451494614947149481494914950149511495214953149541495514956149571495814959149601496114962149631496414965149661496714968149691497014971149721497314974149751497614977149781497914980149811498214983149841498514986149871498814989149901499114992149931499414995149961499714998149991500015001150021500315004150051500615007150081500915010150111501215013150141501515016150171501815019150201502115022150231502415025150261502715028150291503015031150321503315034150351503615037150381503915040150411504215043150441504515046150471504815049150501505115052150531505415055150561505715058150591506015061150621506315064150651506615067150681506915070150711507215073150741507515076150771507815079150801508115082150831508415085150861508715088150891509015091150921509315094150951509615097150981509915100151011510215103151041510515106151071510815109151101511115112151131511415115151161511715118151191512015121151221512315124151251512615127151281512915130151311513215133151341513515136151371513815139151401514115142151431514415145151461514715148151491515015151151521515315154151551515615157151581515915160151611516215163151641516515166151671516815169151701517115172151731517415175151761517715178151791518015181151821518315184151851518615187151881518915190151911519215193151941519515196151971519815199152001520115202152031520415205152061520715208152091521015211152121521315214152151521615217152181521915220152211522215223152241522515226152271522815229152301523115232152331523415235152361523715238152391524015241152421524315244152451524615247152481524915250152511525215253152541525515256152571525815259152601526115262152631526415265152661526715268152691527015271152721527315274152751527615277152781527915280152811528215283152841528515286152871528815289152901529115292152931529415295152961529715298152991530015301153021530315304153051530615307153081530915310153111531215313153141531515316153171531815319153201532115322153231532415325153261532715328153291533015331153321533315334153351533615337153381533915340153411534215343153441534515346153471534815349153501535115352153531535415355153561535715358153591536015361153621536315364153651536615367153681536915370153711537215373153741537515376153771537815379153801538115382153831538415385153861538715388153891539015391153921539315394153951539615397153981539915400154011540215403154041540515406154071540815409154101541115412154131541415415154161541715418154191542015421154221542315424154251542615427154281542915430154311543215433154341543515436154371543815439154401544115442154431544415445154461544715448154491545015451154521545315454154551545615457154581545915460154611546215463154641546515466154671546815469154701547115472154731547415475154761547715478154791548015481154821548315484154851548615487154881548915490154911549215493154941549515496154971549815499155001550115502155031550415505155061550715508155091551015511155121551315514155151551615517155181551915520155211552215523155241552515526155271552815529155301553115532155331553415535155361553715538155391554015541155421554315544155451554615547155481554915550155511555215553155541555515556155571555815559155601556115562155631556415565155661556715568155691557015571155721557315574155751557615577155781557915580155811558215583155841558515586155871558815589155901559115592155931559415595155961559715598155991560015601156021560315604156051560615607156081560915610156111561215613156141561515616156171561815619156201562115622156231562415625156261562715628156291563015631156321563315634156351563615637156381563915640156411564215643156441564515646156471564815649156501565115652156531565415655156561565715658156591566015661156621566315664156651566615667156681566915670156711567215673156741567515676156771567815679156801568115682156831568415685156861568715688156891569015691156921569315694156951569615697156981569915700157011570215703157041570515706157071570815709157101571115712157131571415715157161571715718157191572015721157221572315724157251572615727157281572915730157311573215733157341573515736157371573815739157401574115742157431574415745157461574715748157491575015751157521575315754157551575615757157581575915760157611576215763157641576515766157671576815769157701577115772157731577415775157761577715778157791578015781157821578315784157851578615787157881578915790157911579215793157941579515796157971579815799158001580115802158031580415805158061580715808158091581015811158121581315814158151581615817158181581915820158211582215823158241582515826158271582815829158301583115832158331583415835158361583715838158391584015841158421584315844158451584615847158481584915850158511585215853158541585515856158571585815859158601586115862158631586415865158661586715868158691587015871158721587315874158751587615877158781587915880158811588215883158841588515886158871588815889158901589115892158931589415895158961589715898158991590015901159021590315904159051590615907159081590915910159111591215913159141591515916159171591815919159201592115922159231592415925159261592715928159291593015931159321593315934159351593615937159381593915940159411594215943159441594515946159471594815949159501595115952159531595415955159561595715958159591596015961159621596315964159651596615967159681596915970159711597215973159741597515976159771597815979159801598115982159831598415985159861598715988159891599015991159921599315994159951599615997159981599916000160011600216003160041600516006160071600816009160101601116012160131601416015160161601716018160191602016021160221602316024160251602616027160281602916030160311603216033160341603516036160371603816039160401604116042160431604416045160461604716048160491605016051160521605316054160551605616057160581605916060160611606216063160641606516066160671606816069160701607116072160731607416075160761607716078160791608016081160821608316084160851608616087160881608916090160911609216093160941609516096160971609816099161001610116102161031610416105161061610716108161091611016111161121611316114161151611616117161181611916120161211612216123161241612516126161271612816129161301613116132161331613416135161361613716138161391614016141161421614316144161451614616147161481614916150161511615216153161541615516156161571615816159161601616116162161631616416165161661616716168161691617016171161721617316174161751617616177161781617916180161811618216183161841618516186161871618816189161901619116192161931619416195161961619716198161991620016201162021620316204162051620616207162081620916210162111621216213162141621516216162171621816219162201622116222162231622416225162261622716228162291623016231162321623316234162351623616237162381623916240162411624216243162441624516246162471624816249162501625116252162531625416255162561625716258162591626016261162621626316264162651626616267162681626916270162711627216273162741627516276162771627816279162801628116282162831628416285162861628716288162891629016291162921629316294162951629616297162981629916300163011630216303163041630516306163071630816309163101631116312163131631416315163161631716318163191632016321163221632316324163251632616327163281632916330163311633216333163341633516336163371633816339163401634116342163431634416345163461634716348163491635016351163521635316354163551635616357163581635916360163611636216363163641636516366163671636816369163701637116372163731637416375163761637716378163791638016381163821638316384163851638616387163881638916390163911639216393163941639516396163971639816399164001640116402164031640416405164061640716408164091641016411164121641316414164151641616417164181641916420164211642216423164241642516426164271642816429164301643116432164331643416435164361643716438164391644016441164421644316444164451644616447164481644916450164511645216453164541645516456164571645816459164601646116462164631646416465164661646716468164691647016471164721647316474164751647616477164781647916480164811648216483164841648516486164871648816489164901649116492164931649416495164961649716498164991650016501165021650316504165051650616507165081650916510165111651216513165141651516516165171651816519165201652116522165231652416525165261652716528165291653016531165321653316534165351653616537165381653916540165411654216543165441654516546165471654816549165501655116552165531655416555165561655716558165591656016561165621656316564165651656616567165681656916570165711657216573165741657516576165771657816579165801658116582165831658416585165861658716588165891659016591165921659316594165951659616597165981659916600166011660216603166041660516606166071660816609166101661116612166131661416615166161661716618166191662016621166221662316624166251662616627166281662916630166311663216633166341663516636166371663816639166401664116642166431664416645166461664716648166491665016651166521665316654166551665616657166581665916660166611666216663166641666516666166671666816669166701667116672166731667416675166761667716678166791668016681166821668316684166851668616687166881668916690166911669216693166941669516696166971669816699167001670116702167031670416705167061670716708167091671016711167121671316714167151671616717167181671916720167211672216723167241672516726167271672816729167301673116732167331673416735167361673716738167391674016741167421674316744167451674616747167481674916750167511675216753167541675516756167571675816759167601676116762167631676416765167661676716768167691677016771167721677316774167751677616777167781677916780167811678216783167841678516786167871678816789167901679116792167931679416795167961679716798167991680016801168021680316804168051680616807168081680916810168111681216813168141681516816168171681816819168201682116822168231682416825168261682716828168291683016831168321683316834168351683616837168381683916840168411684216843168441684516846168471684816849168501685116852168531685416855168561685716858168591686016861168621686316864168651686616867168681686916870168711687216873168741687516876168771687816879168801688116882168831688416885168861688716888168891689016891168921689316894168951689616897168981689916900169011690216903169041690516906169071690816909169101691116912169131691416915169161691716918169191692016921169221692316924169251692616927169281692916930169311693216933169341693516936169371693816939169401694116942169431694416945169461694716948169491695016951169521695316954169551695616957169581695916960169611696216963169641696516966169671696816969169701697116972169731697416975169761697716978169791698016981169821698316984169851698616987169881698916990169911699216993169941699516996169971699816999170001700117002170031700417005170061700717008170091701017011170121701317014170151701617017170181701917020170211702217023170241702517026170271702817029170301703117032170331703417035170361703717038170391704017041170421704317044170451704617047170481704917050170511705217053170541705517056170571705817059170601706117062170631706417065170661706717068170691707017071170721707317074170751707617077170781707917080170811708217083170841708517086170871708817089170901709117092170931709417095170961709717098170991710017101171021710317104171051710617107171081710917110171111711217113171141711517116171171711817119171201712117122171231712417125171261712717128171291713017131171321713317134171351713617137171381713917140171411714217143171441714517146171471714817149171501715117152171531715417155171561715717158171591716017161171621716317164171651716617167171681716917170171711717217173171741717517176171771717817179171801718117182171831718417185171861718717188171891719017191171921719317194171951719617197171981719917200172011720217203172041720517206172071720817209172101721117212172131721417215172161721717218172191722017221172221722317224172251722617227172281722917230172311723217233172341723517236172371723817239172401724117242172431724417245172461724717248172491725017251172521725317254172551725617257172581725917260172611726217263172641726517266172671726817269172701727117272172731727417275172761727717278172791728017281172821728317284172851728617287172881728917290172911729217293172941729517296172971729817299173001730117302173031730417305173061730717308173091731017311173121731317314173151731617317173181731917320173211732217323173241732517326173271732817329173301733117332173331733417335173361733717338173391734017341173421734317344173451734617347173481734917350173511735217353173541735517356173571735817359173601736117362173631736417365173661736717368173691737017371173721737317374173751737617377173781737917380173811738217383173841738517386173871738817389173901739117392173931739417395173961739717398173991740017401174021740317404174051740617407174081740917410174111741217413174141741517416174171741817419174201742117422174231742417425174261742717428174291743017431174321743317434174351743617437174381743917440174411744217443174441744517446174471744817449174501745117452174531745417455174561745717458174591746017461174621746317464174651746617467174681746917470174711747217473174741747517476174771747817479174801748117482174831748417485174861748717488174891749017491174921749317494174951749617497174981749917500175011750217503175041750517506175071750817509175101751117512175131751417515175161751717518175191752017521175221752317524175251752617527175281752917530175311753217533175341753517536175371753817539175401754117542175431754417545175461754717548175491755017551175521755317554175551755617557175581755917560175611756217563175641756517566175671756817569175701757117572175731757417575175761757717578175791758017581175821758317584175851758617587175881758917590175911759217593175941759517596175971759817599176001760117602176031760417605176061760717608176091761017611176121761317614176151761617617176181761917620176211762217623176241762517626176271762817629176301763117632176331763417635176361763717638176391764017641176421764317644176451764617647176481764917650176511765217653176541765517656176571765817659176601766117662176631766417665176661766717668176691767017671176721767317674176751767617677176781767917680176811768217683176841768517686176871768817689176901769117692176931769417695176961769717698176991770017701177021770317704177051770617707177081770917710177111771217713177141771517716177171771817719177201772117722177231772417725177261772717728177291773017731177321773317734177351773617737177381773917740177411774217743177441774517746177471774817749177501775117752177531775417755177561775717758177591776017761177621776317764177651776617767177681776917770177711777217773177741777517776177771777817779177801778117782177831778417785177861778717788177891779017791177921779317794177951779617797177981779917800178011780217803178041780517806178071780817809178101781117812178131781417815178161781717818178191782017821178221782317824178251782617827178281782917830178311783217833178341783517836178371783817839178401784117842178431784417845178461784717848178491785017851178521785317854178551785617857178581785917860178611786217863178641786517866178671786817869178701787117872178731787417875178761787717878178791788017881178821788317884178851788617887178881788917890178911789217893178941789517896178971789817899179001790117902179031790417905179061790717908179091791017911179121791317914179151791617917179181791917920179211792217923179241792517926179271792817929179301793117932179331793417935179361793717938179391794017941179421794317944179451794617947179481794917950179511795217953179541795517956179571795817959179601796117962179631796417965179661796717968179691797017971179721797317974179751797617977179781797917980179811798217983179841798517986179871798817989179901799117992179931799417995179961799717998179991800018001180021800318004180051800618007180081800918010180111801218013180141801518016180171801818019180201802118022180231802418025180261802718028180291803018031180321803318034180351803618037180381803918040180411804218043180441804518046180471804818049180501805118052180531805418055180561805718058180591806018061180621806318064180651806618067180681806918070180711807218073180741807518076180771807818079180801808118082180831808418085180861808718088180891809018091180921809318094180951809618097180981809918100181011810218103181041810518106181071810818109181101811118112181131811418115181161811718118181191812018121181221812318124181251812618127181281812918130181311813218133181341813518136181371813818139181401814118142181431814418145181461814718148181491815018151181521815318154181551815618157181581815918160181611816218163181641816518166181671816818169181701817118172181731817418175181761817718178181791818018181181821818318184181851818618187181881818918190181911819218193181941819518196181971819818199182001820118202182031820418205182061820718208182091821018211182121821318214182151821618217182181821918220182211822218223182241822518226182271822818229182301823118232182331823418235182361823718238182391824018241182421824318244182451824618247182481824918250182511825218253182541825518256182571825818259182601826118262182631826418265182661826718268182691827018271182721827318274182751827618277182781827918280182811828218283182841828518286182871828818289182901829118292182931829418295182961829718298182991830018301183021830318304183051830618307183081830918310183111831218313183141831518316183171831818319183201832118322183231832418325183261832718328183291833018331183321833318334183351833618337183381833918340183411834218343183441834518346183471834818349183501835118352183531835418355183561835718358183591836018361183621836318364183651836618367183681836918370183711837218373183741837518376183771837818379183801838118382183831838418385183861838718388183891839018391183921839318394183951839618397183981839918400184011840218403184041840518406184071840818409184101841118412184131841418415184161841718418184191842018421184221842318424184251842618427184281842918430184311843218433184341843518436184371843818439184401844118442184431844418445184461844718448184491845018451184521845318454184551845618457184581845918460184611846218463184641846518466184671846818469184701847118472184731847418475184761847718478184791848018481184821848318484184851848618487184881848918490184911849218493184941849518496184971849818499185001850118502185031850418505185061850718508185091851018511185121851318514185151851618517185181851918520185211852218523185241852518526185271852818529185301853118532185331853418535185361853718538185391854018541185421854318544185451854618547185481854918550185511855218553185541855518556185571855818559185601856118562185631856418565185661856718568185691857018571185721857318574185751857618577185781857918580185811858218583185841858518586185871858818589185901859118592185931859418595185961859718598185991860018601186021860318604186051860618607186081860918610186111861218613186141861518616186171861818619186201862118622186231862418625186261862718628186291863018631186321863318634186351863618637186381863918640186411864218643186441864518646186471864818649186501865118652186531865418655186561865718658186591866018661186621866318664186651866618667186681866918670186711867218673186741867518676186771867818679186801868118682186831868418685186861868718688186891869018691186921869318694186951869618697186981869918700187011870218703187041870518706187071870818709187101871118712187131871418715187161871718718187191872018721187221872318724187251872618727187281872918730187311873218733187341873518736187371873818739187401874118742187431874418745187461874718748187491875018751187521875318754187551875618757187581875918760187611876218763187641876518766187671876818769187701877118772187731877418775187761877718778187791878018781187821878318784187851878618787187881878918790187911879218793187941879518796187971879818799188001880118802188031880418805188061880718808188091881018811188121881318814188151881618817188181881918820188211882218823188241882518826188271882818829188301883118832188331883418835188361883718838188391884018841188421884318844188451884618847188481884918850188511885218853188541885518856188571885818859188601886118862188631886418865188661886718868188691887018871188721887318874188751887618877188781887918880188811888218883188841888518886188871888818889188901889118892188931889418895188961889718898188991890018901189021890318904189051890618907189081890918910189111891218913189141891518916189171891818919189201892118922189231892418925189261892718928189291893018931189321893318934189351893618937189381893918940189411894218943189441894518946189471894818949189501895118952189531895418955189561895718958189591896018961189621896318964189651896618967189681896918970189711897218973189741897518976189771897818979189801898118982189831898418985189861898718988189891899018991189921899318994189951899618997189981899919000190011900219003190041900519006190071900819009190101901119012190131901419015190161901719018190191902019021190221902319024190251902619027190281902919030190311903219033190341903519036190371903819039190401904119042190431904419045190461904719048190491905019051190521905319054190551905619057190581905919060190611906219063190641906519066190671906819069190701907119072190731907419075190761907719078190791908019081190821908319084190851908619087190881908919090190911909219093190941909519096190971909819099191001910119102191031910419105191061910719108191091911019111191121911319114191151911619117191181911919120191211912219123191241912519126191271912819129191301913119132191331913419135191361913719138191391914019141191421914319144191451914619147191481914919150191511915219153191541915519156191571915819159191601916119162191631916419165191661916719168191691917019171191721917319174191751917619177191781917919180191811918219183191841918519186191871918819189191901919119192191931919419195191961919719198191991920019201192021920319204192051920619207192081920919210192111921219213192141921519216192171921819219192201922119222192231922419225192261922719228192291923019231192321923319234192351923619237192381923919240192411924219243192441924519246192471924819249192501925119252192531925419255192561925719258192591926019261192621926319264192651926619267192681926919270192711927219273192741927519276192771927819279192801928119282192831928419285192861928719288192891929019291192921929319294192951929619297192981929919300193011930219303193041930519306193071930819309193101931119312193131931419315193161931719318193191932019321193221932319324193251932619327193281932919330193311933219333193341933519336193371933819339193401934119342193431934419345193461934719348193491935019351193521935319354193551935619357193581935919360193611936219363193641936519366193671936819369193701937119372193731937419375193761937719378193791938019381193821938319384193851938619387193881938919390193911939219393193941939519396193971939819399194001940119402194031940419405194061940719408194091941019411194121941319414194151941619417194181941919420194211942219423194241942519426194271942819429194301943119432194331943419435194361943719438194391944019441194421944319444194451944619447194481944919450194511945219453194541945519456194571945819459194601946119462194631946419465194661946719468194691947019471194721947319474194751947619477194781947919480194811948219483194841948519486194871948819489194901949119492194931949419495194961949719498194991950019501195021950319504195051950619507195081950919510195111951219513195141951519516195171951819519195201952119522195231952419525195261952719528195291953019531195321953319534195351953619537195381953919540195411954219543195441954519546195471954819549195501955119552195531955419555195561955719558195591956019561195621956319564195651956619567195681956919570195711957219573195741957519576195771957819579195801958119582195831958419585195861958719588195891959019591195921959319594195951959619597195981959919600196011960219603196041960519606196071960819609196101961119612196131961419615196161961719618196191962019621196221962319624196251962619627196281962919630196311963219633196341963519636196371963819639196401964119642196431964419645196461964719648196491965019651196521965319654196551965619657196581965919660196611966219663196641966519666196671966819669196701967119672196731967419675196761967719678196791968019681196821968319684196851968619687196881968919690196911969219693196941969519696196971969819699197001970119702197031970419705197061970719708197091971019711197121971319714197151971619717197181971919720197211972219723197241972519726197271972819729197301973119732197331973419735197361973719738197391974019741197421974319744197451974619747197481974919750197511975219753197541975519756197571975819759197601976119762197631976419765197661976719768197691977019771197721977319774197751977619777197781977919780197811978219783197841978519786197871978819789197901979119792197931979419795197961979719798197991980019801198021980319804198051980619807198081980919810198111981219813198141981519816198171981819819198201982119822198231982419825198261982719828198291983019831198321983319834198351983619837198381983919840198411984219843198441984519846198471984819849198501985119852198531985419855198561985719858198591986019861198621986319864198651986619867198681986919870198711987219873198741987519876198771987819879198801988119882198831988419885198861988719888198891989019891198921989319894198951989619897198981989919900199011990219903199041990519906199071990819909199101991119912199131991419915199161991719918199191992019921199221992319924199251992619927199281992919930199311993219933199341993519936199371993819939199401994119942199431994419945199461994719948199491995019951199521995319954199551995619957199581995919960199611996219963199641996519966199671996819969199701997119972199731997419975199761997719978199791998019981199821998319984199851998619987199881998919990199911999219993199941999519996199971999819999200002000120002200032000420005200062000720008200092001020011200122001320014200152001620017200182001920020200212002220023200242002520026200272002820029200302003120032200332003420035200362003720038200392004020041200422004320044200452004620047200482004920050200512005220053200542005520056200572005820059200602006120062200632006420065200662006720068200692007020071200722007320074200752007620077200782007920080200812008220083200842008520086200872008820089200902009120092200932009420095200962009720098200992010020101201022010320104201052010620107201082010920110201112011220113201142011520116201172011820119201202012120122201232012420125201262012720128201292013020131201322013320134201352013620137201382013920140201412014220143201442014520146201472014820149201502015120152201532015420155201562015720158201592016020161201622016320164201652016620167201682016920170201712017220173201742017520176201772017820179201802018120182201832018420185201862018720188201892019020191201922019320194201952019620197201982019920200202012020220203202042020520206202072020820209202102021120212202132021420215202162021720218202192022020221202222022320224202252022620227202282022920230202312023220233202342023520236202372023820239202402024120242202432024420245202462024720248202492025020251202522025320254202552025620257202582025920260202612026220263202642026520266202672026820269202702027120272202732027420275202762027720278202792028020281202822028320284202852028620287202882028920290202912029220293202942029520296202972029820299203002030120302203032030420305203062030720308203092031020311203122031320314203152031620317203182031920320203212032220323203242032520326203272032820329203302033120332203332033420335203362033720338203392034020341203422034320344203452034620347203482034920350203512035220353203542035520356203572035820359203602036120362203632036420365203662036720368203692037020371203722037320374203752037620377203782037920380203812038220383203842038520386203872038820389203902039120392203932039420395203962039720398203992040020401204022040320404204052040620407204082040920410204112041220413204142041520416204172041820419204202042120422204232042420425204262042720428204292043020431204322043320434204352043620437204382043920440204412044220443204442044520446204472044820449204502045120452204532045420455204562045720458204592046020461204622046320464204652046620467204682046920470204712047220473204742047520476204772047820479204802048120482204832048420485204862048720488204892049020491204922049320494204952049620497204982049920500205012050220503205042050520506205072050820509205102051120512205132051420515205162051720518205192052020521205222052320524205252052620527205282052920530205312053220533205342053520536205372053820539205402054120542205432054420545205462054720548205492055020551205522055320554205552055620557205582055920560205612056220563205642056520566205672056820569205702057120572205732057420575205762057720578205792058020581205822058320584205852058620587205882058920590205912059220593205942059520596205972059820599206002060120602206032060420605206062060720608206092061020611206122061320614206152061620617206182061920620206212062220623206242062520626206272062820629206302063120632206332063420635206362063720638206392064020641206422064320644206452064620647206482064920650206512065220653206542065520656206572065820659206602066120662206632066420665206662066720668206692067020671206722067320674206752067620677206782067920680206812068220683206842068520686206872068820689206902069120692206932069420695206962069720698206992070020701207022070320704207052070620707207082070920710207112071220713207142071520716207172071820719207202072120722207232072420725207262072720728207292073020731207322073320734207352073620737207382073920740207412074220743207442074520746207472074820749207502075120752207532075420755207562075720758207592076020761207622076320764207652076620767207682076920770207712077220773207742077520776207772077820779207802078120782207832078420785207862078720788207892079020791207922079320794207952079620797207982079920800208012080220803208042080520806208072080820809208102081120812208132081420815208162081720818208192082020821208222082320824208252082620827208282082920830208312083220833208342083520836208372083820839208402084120842208432084420845208462084720848208492085020851208522085320854208552085620857208582085920860208612086220863208642086520866208672086820869208702087120872208732087420875208762087720878208792088020881208822088320884208852088620887208882088920890208912089220893208942089520896208972089820899209002090120902209032090420905209062090720908209092091020911209122091320914209152091620917209182091920920209212092220923209242092520926209272092820929209302093120932209332093420935209362093720938209392094020941209422094320944209452094620947209482094920950209512095220953209542095520956209572095820959209602096120962209632096420965209662096720968209692097020971209722097320974209752097620977209782097920980209812098220983209842098520986209872098820989209902099120992209932099420995209962099720998209992100021001210022100321004210052100621007210082100921010210112101221013210142101521016210172101821019210202102121022210232102421025210262102721028210292103021031210322103321034210352103621037210382103921040210412104221043210442104521046210472104821049210502105121052210532105421055210562105721058210592106021061210622106321064210652106621067210682106921070210712107221073210742107521076210772107821079210802108121082210832108421085210862108721088210892109021091210922109321094210952109621097210982109921100211012110221103211042110521106211072110821109211102111121112211132111421115211162111721118211192112021121211222112321124211252112621127211282112921130211312113221133211342113521136211372113821139211402114121142211432114421145211462114721148211492115021151211522115321154211552115621157211582115921160211612116221163211642116521166211672116821169211702117121172211732117421175211762117721178211792118021181211822118321184211852118621187211882118921190211912119221193211942119521196211972119821199212002120121202212032120421205212062120721208212092121021211212122121321214212152121621217212182121921220212212122221223212242122521226212272122821229212302123121232212332123421235212362123721238212392124021241212422124321244212452124621247212482124921250212512125221253212542125521256212572125821259212602126121262212632126421265212662126721268212692127021271212722127321274212752127621277212782127921280212812128221283212842128521286212872128821289212902129121292212932129421295212962129721298212992130021301213022130321304213052130621307213082130921310213112131221313213142131521316213172131821319213202132121322213232132421325213262132721328213292133021331213322133321334213352133621337213382133921340213412134221343213442134521346213472134821349213502135121352213532135421355213562135721358213592136021361213622136321364213652136621367213682136921370213712137221373213742137521376213772137821379213802138121382213832138421385213862138721388213892139021391213922139321394213952139621397213982139921400214012140221403214042140521406214072140821409214102141121412214132141421415214162141721418214192142021421214222142321424214252142621427214282142921430214312143221433214342143521436214372143821439214402144121442214432144421445214462144721448214492145021451214522145321454214552145621457214582145921460214612146221463214642146521466214672146821469214702147121472214732147421475214762147721478214792148021481214822148321484214852148621487214882148921490214912149221493214942149521496214972149821499215002150121502215032150421505215062150721508215092151021511215122151321514215152151621517215182151921520215212152221523215242152521526215272152821529215302153121532215332153421535215362153721538215392154021541215422154321544215452154621547215482154921550215512155221553215542155521556215572155821559215602156121562215632156421565215662156721568215692157021571215722157321574215752157621577215782157921580215812158221583215842158521586215872158821589215902159121592215932159421595215962159721598215992160021601216022160321604216052160621607216082160921610216112161221613216142161521616216172161821619216202162121622216232162421625216262162721628216292163021631216322163321634216352163621637216382163921640216412164221643216442164521646216472164821649216502165121652216532165421655216562165721658216592166021661216622166321664216652166621667216682166921670216712167221673216742167521676216772167821679216802168121682216832168421685216862168721688216892169021691216922169321694216952169621697216982169921700217012170221703217042170521706217072170821709217102171121712217132171421715217162171721718217192172021721217222172321724217252172621727217282172921730217312173221733217342173521736217372173821739217402174121742217432174421745217462174721748217492175021751217522175321754217552175621757217582175921760217612176221763217642176521766217672176821769217702177121772217732177421775217762177721778217792178021781217822178321784217852178621787217882178921790217912179221793217942179521796217972179821799218002180121802218032180421805218062180721808218092181021811218122181321814218152181621817218182181921820218212182221823218242182521826218272182821829218302183121832218332183421835218362183721838218392184021841218422184321844218452184621847218482184921850218512185221853218542185521856218572185821859218602186121862218632186421865218662186721868218692187021871218722187321874218752187621877218782187921880218812188221883218842188521886218872188821889218902189121892218932189421895218962189721898218992190021901219022190321904219052190621907219082190921910219112191221913219142191521916219172191821919219202192121922219232192421925219262192721928219292193021931219322193321934219352193621937219382193921940219412194221943219442194521946219472194821949219502195121952219532195421955219562195721958219592196021961219622196321964219652196621967219682196921970219712197221973219742197521976219772197821979219802198121982219832198421985219862198721988219892199021991219922199321994219952199621997219982199922000220012200222003220042200522006220072200822009220102201122012220132201422015220162201722018220192202022021220222202322024220252202622027220282202922030220312203222033220342203522036220372203822039220402204122042220432204422045220462204722048220492205022051220522205322054220552205622057220582205922060220612206222063220642206522066220672206822069220702207122072220732207422075220762207722078220792208022081220822208322084220852208622087220882208922090220912209222093220942209522096220972209822099221002210122102221032210422105221062210722108221092211022111221122211322114221152211622117221182211922120221212212222123221242212522126221272212822129221302213122132221332213422135221362213722138221392214022141221422214322144221452214622147221482214922150221512215222153221542215522156221572215822159221602216122162221632216422165221662216722168221692217022171221722217322174221752217622177221782217922180221812218222183221842218522186221872218822189221902219122192221932219422195221962219722198221992220022201222022220322204222052220622207222082220922210222112221222213222142221522216222172221822219222202222122222222232222422225222262222722228222292223022231222322223322234222352223622237222382223922240222412224222243222442224522246222472224822249222502225122252222532225422255222562225722258222592226022261222622226322264222652226622267222682226922270222712227222273222742227522276222772227822279222802228122282222832228422285222862228722288222892229022291222922229322294222952229622297222982229922300223012230222303223042230522306223072230822309223102231122312223132231422315223162231722318223192232022321223222232322324223252232622327223282232922330223312233222333223342233522336223372233822339223402234122342223432234422345223462234722348223492235022351223522235322354223552235622357223582235922360223612236222363223642236522366223672236822369223702237122372223732237422375223762237722378223792238022381223822238322384223852238622387223882238922390223912239222393223942239522396223972239822399224002240122402224032240422405224062240722408224092241022411224122241322414224152241622417224182241922420224212242222423224242242522426224272242822429224302243122432224332243422435224362243722438224392244022441224422244322444224452244622447224482244922450224512245222453224542245522456224572245822459224602246122462224632246422465224662246722468224692247022471224722247322474224752247622477224782247922480224812248222483224842248522486224872248822489224902249122492224932249422495224962249722498224992250022501225022250322504225052250622507225082250922510225112251222513225142251522516225172251822519225202252122522225232252422525225262252722528225292253022531225322253322534225352253622537225382253922540225412254222543225442254522546225472254822549225502255122552225532255422555225562255722558225592256022561225622256322564225652256622567225682256922570225712257222573225742257522576225772257822579225802258122582225832258422585225862258722588225892259022591225922259322594225952259622597225982259922600226012260222603226042260522606226072260822609226102261122612226132261422615226162261722618226192262022621226222262322624226252262622627226282262922630226312263222633226342263522636226372263822639226402264122642226432264422645226462264722648226492265022651226522265322654226552265622657226582265922660226612266222663226642266522666226672266822669226702267122672226732267422675226762267722678226792268022681226822268322684226852268622687226882268922690226912269222693226942269522696226972269822699227002270122702227032270422705227062270722708227092271022711227122271322714227152271622717227182271922720227212272222723227242272522726227272272822729227302273122732227332273422735227362273722738227392274022741227422274322744227452274622747227482274922750227512275222753227542275522756227572275822759227602276122762227632276422765227662276722768227692277022771227722277322774227752277622777227782277922780227812278222783227842278522786227872278822789227902279122792227932279422795227962279722798227992280022801228022280322804228052280622807228082280922810228112281222813228142281522816228172281822819228202282122822228232282422825228262282722828228292283022831228322283322834228352283622837228382283922840228412284222843228442284522846228472284822849228502285122852228532285422855228562285722858228592286022861228622286322864228652286622867228682286922870228712287222873228742287522876228772287822879228802288122882228832288422885228862288722888228892289022891228922289322894228952289622897228982289922900229012290222903229042290522906229072290822909229102291122912229132291422915229162291722918229192292022921229222292322924229252292622927229282292922930229312293222933229342293522936229372293822939229402294122942229432294422945229462294722948229492295022951229522295322954229552295622957229582295922960229612296222963229642296522966229672296822969229702297122972229732297422975229762297722978229792298022981229822298322984229852298622987229882298922990229912299222993229942299522996229972299822999230002300123002230032300423005230062300723008230092301023011230122301323014230152301623017230182301923020230212302223023230242302523026230272302823029230302303123032230332303423035230362303723038230392304023041230422304323044230452304623047230482304923050230512305223053230542305523056230572305823059230602306123062230632306423065230662306723068230692307023071230722307323074230752307623077230782307923080230812308223083230842308523086230872308823089230902309123092230932309423095230962309723098230992310023101231022310323104231052310623107231082310923110231112311223113231142311523116231172311823119231202312123122231232312423125231262312723128231292313023131231322313323134231352313623137231382313923140231412314223143231442314523146231472314823149231502315123152231532315423155231562315723158231592316023161231622316323164231652316623167231682316923170231712317223173231742317523176231772317823179231802318123182231832318423185231862318723188231892319023191231922319323194231952319623197231982319923200232012320223203232042320523206232072320823209232102321123212232132321423215232162321723218232192322023221232222322323224232252322623227232282322923230232312323223233232342323523236232372323823239232402324123242232432324423245232462324723248232492325023251232522325323254232552325623257232582325923260232612326223263232642326523266232672326823269232702327123272232732327423275232762327723278232792328023281232822328323284232852328623287232882328923290232912329223293232942329523296232972329823299233002330123302233032330423305233062330723308233092331023311233122331323314233152331623317233182331923320233212332223323233242332523326233272332823329233302333123332233332333423335233362333723338233392334023341233422334323344233452334623347233482334923350233512335223353233542335523356233572335823359233602336123362233632336423365233662336723368233692337023371233722337323374233752337623377233782337923380233812338223383233842338523386233872338823389233902339123392233932339423395233962339723398233992340023401234022340323404234052340623407234082340923410234112341223413234142341523416234172341823419234202342123422234232342423425234262342723428234292343023431234322343323434234352343623437234382343923440234412344223443234442344523446234472344823449234502345123452234532345423455234562345723458234592346023461234622346323464234652346623467234682346923470234712347223473234742347523476234772347823479234802348123482234832348423485234862348723488234892349023491234922349323494234952349623497234982349923500235012350223503235042350523506235072350823509235102351123512235132351423515235162351723518235192352023521235222352323524235252352623527235282352923530235312353223533235342353523536235372353823539235402354123542235432354423545235462354723548235492355023551235522355323554235552355623557235582355923560235612356223563235642356523566235672356823569235702357123572235732357423575235762357723578235792358023581235822358323584235852358623587235882358923590235912359223593235942359523596235972359823599236002360123602236032360423605236062360723608236092361023611236122361323614236152361623617236182361923620236212362223623236242362523626236272362823629236302363123632236332363423635236362363723638236392364023641236422364323644236452364623647236482364923650236512365223653236542365523656236572365823659236602366123662236632366423665236662366723668236692367023671236722367323674236752367623677236782367923680236812368223683236842368523686236872368823689236902369123692236932369423695236962369723698236992370023701237022370323704237052370623707237082370923710237112371223713237142371523716237172371823719237202372123722237232372423725237262372723728237292373023731237322373323734237352373623737237382373923740237412374223743237442374523746237472374823749237502375123752237532375423755237562375723758237592376023761237622376323764237652376623767237682376923770237712377223773237742377523776237772377823779237802378123782237832378423785237862378723788237892379023791237922379323794237952379623797237982379923800238012380223803238042380523806238072380823809238102381123812238132381423815238162381723818238192382023821238222382323824238252382623827238282382923830238312383223833238342383523836238372383823839238402384123842238432384423845238462384723848238492385023851238522385323854238552385623857238582385923860238612386223863238642386523866238672386823869238702387123872238732387423875238762387723878238792388023881238822388323884238852388623887238882388923890238912389223893238942389523896238972389823899239002390123902239032390423905239062390723908239092391023911239122391323914239152391623917239182391923920239212392223923239242392523926239272392823929239302393123932239332393423935239362393723938239392394023941239422394323944239452394623947239482394923950239512395223953239542395523956239572395823959239602396123962239632396423965239662396723968239692397023971239722397323974239752397623977239782397923980239812398223983239842398523986239872398823989239902399123992239932399423995239962399723998239992400024001240022400324004240052400624007240082400924010240112401224013240142401524016240172401824019240202402124022240232402424025240262402724028240292403024031240322403324034240352403624037240382403924040240412404224043240442404524046240472404824049240502405124052240532405424055240562405724058240592406024061240622406324064240652406624067240682406924070240712407224073240742407524076240772407824079240802408124082240832408424085240862408724088240892409024091240922409324094240952409624097240982409924100241012410224103241042410524106241072410824109241102411124112241132411424115241162411724118241192412024121241222412324124241252412624127241282412924130241312413224133241342413524136241372413824139241402414124142241432414424145241462414724148241492415024151241522415324154241552415624157241582415924160241612416224163241642416524166241672416824169241702417124172241732417424175241762417724178241792418024181241822418324184241852418624187241882418924190241912419224193241942419524196241972419824199242002420124202242032420424205242062420724208242092421024211242122421324214242152421624217242182421924220242212422224223242242422524226242272422824229242302423124232242332423424235242362423724238242392424024241242422424324244242452424624247242482424924250242512425224253242542425524256242572425824259242602426124262242632426424265242662426724268242692427024271242722427324274242752427624277242782427924280242812428224283242842428524286242872428824289242902429124292242932429424295242962429724298242992430024301243022430324304243052430624307243082430924310243112431224313243142431524316243172431824319243202432124322243232432424325243262432724328243292433024331243322433324334243352433624337243382433924340243412434224343243442434524346243472434824349243502435124352243532435424355243562435724358243592436024361243622436324364243652436624367243682436924370243712437224373243742437524376243772437824379243802438124382243832438424385243862438724388243892439024391243922439324394243952439624397243982439924400244012440224403244042440524406244072440824409244102441124412244132441424415244162441724418244192442024421244222442324424244252442624427244282442924430244312443224433244342443524436244372443824439244402444124442244432444424445244462444724448244492445024451244522445324454244552445624457244582445924460244612446224463244642446524466244672446824469244702447124472244732447424475244762447724478244792448024481244822448324484244852448624487244882448924490244912449224493244942449524496244972449824499245002450124502245032450424505245062450724508245092451024511245122451324514245152451624517245182451924520245212452224523245242452524526245272452824529245302453124532245332453424535245362453724538245392454024541245422454324544245452454624547245482454924550245512455224553245542455524556245572455824559245602456124562245632456424565245662456724568245692457024571245722457324574245752457624577245782457924580245812458224583245842458524586245872458824589245902459124592245932459424595245962459724598245992460024601246022460324604246052460624607246082460924610246112461224613246142461524616246172461824619246202462124622246232462424625246262462724628246292463024631246322463324634246352463624637246382463924640246412464224643246442464524646246472464824649246502465124652246532465424655246562465724658246592466024661246622466324664246652466624667246682466924670246712467224673246742467524676246772467824679246802468124682246832468424685246862468724688246892469024691246922469324694246952469624697246982469924700247012470224703247042470524706247072470824709247102471124712247132471424715247162471724718247192472024721247222472324724247252472624727247282472924730247312473224733247342473524736247372473824739247402474124742247432474424745247462474724748247492475024751247522475324754247552475624757247582475924760247612476224763247642476524766247672476824769247702477124772247732477424775247762477724778247792478024781247822478324784247852478624787247882478924790247912479224793247942479524796247972479824799248002480124802248032480424805248062480724808248092481024811248122481324814248152481624817248182481924820248212482224823248242482524826248272482824829248302483124832248332483424835248362483724838248392484024841248422484324844248452484624847248482484924850248512485224853248542485524856248572485824859248602486124862248632486424865248662486724868248692487024871248722487324874248752487624877248782487924880248812488224883248842488524886248872488824889248902489124892248932489424895248962489724898248992490024901249022490324904249052490624907249082490924910249112491224913249142491524916249172491824919249202492124922249232492424925249262492724928249292493024931249322493324934249352493624937249382493924940249412494224943249442494524946249472494824949249502495124952249532495424955249562495724958249592496024961249622496324964249652496624967249682496924970249712497224973249742497524976249772497824979249802498124982249832498424985249862498724988249892499024991249922499324994249952499624997249982499925000250012500225003250042500525006250072500825009250102501125012250132501425015250162501725018250192502025021250222502325024250252502625027250282502925030250312503225033250342503525036250372503825039250402504125042250432504425045250462504725048250492505025051250522505325054250552505625057250582505925060250612506225063250642506525066250672506825069250702507125072250732507425075250762507725078250792508025081250822508325084250852508625087250882508925090250912509225093250942509525096250972509825099251002510125102251032510425105251062510725108251092511025111251122511325114251152511625117251182511925120251212512225123251242512525126251272512825129251302513125132251332513425135251362513725138251392514025141251422514325144251452514625147251482514925150251512515225153251542515525156251572515825159251602516125162251632516425165251662516725168251692517025171251722517325174251752517625177251782517925180251812518225183251842518525186251872518825189251902519125192251932519425195251962519725198251992520025201252022520325204252052520625207252082520925210252112521225213252142521525216252172521825219252202522125222252232522425225252262522725228252292523025231252322523325234252352523625237252382523925240252412524225243252442524525246252472524825249252502525125252252532525425255252562525725258252592526025261252622526325264252652526625267252682526925270252712527225273252742527525276252772527825279252802528125282252832528425285252862528725288252892529025291252922529325294252952529625297252982529925300253012530225303253042530525306253072530825309253102531125312253132531425315253162531725318253192532025321253222532325324253252532625327253282532925330253312533225333253342533525336253372533825339253402534125342253432534425345253462534725348253492535025351253522535325354253552535625357253582535925360253612536225363253642536525366253672536825369253702537125372253732537425375253762537725378253792538025381253822538325384253852538625387253882538925390253912539225393253942539525396253972539825399254002540125402254032540425405254062540725408254092541025411254122541325414254152541625417254182541925420254212542225423254242542525426254272542825429254302543125432254332543425435254362543725438254392544025441254422544325444254452544625447254482544925450254512545225453254542545525456254572545825459254602546125462254632546425465254662546725468254692547025471254722547325474254752547625477254782547925480254812548225483254842548525486254872548825489254902549125492254932549425495254962549725498254992550025501255022550325504255052550625507255082550925510255112551225513255142551525516255172551825519255202552125522255232552425525255262552725528255292553025531255322553325534255352553625537255382553925540255412554225543255442554525546255472554825549255502555125552255532555425555255562555725558255592556025561255622556325564255652556625567255682556925570255712557225573255742557525576255772557825579255802558125582255832558425585255862558725588255892559025591255922559325594255952559625597255982559925600256012560225603256042560525606256072560825609256102561125612256132561425615256162561725618256192562025621256222562325624256252562625627256282562925630256312563225633256342563525636256372563825639256402564125642256432564425645256462564725648256492565025651256522565325654256552565625657256582565925660256612566225663256642566525666256672566825669256702567125672256732567425675256762567725678256792568025681256822568325684256852568625687256882568925690256912569225693256942569525696256972569825699257002570125702257032570425705257062570725708257092571025711257122571325714257152571625717257182571925720257212572225723257242572525726257272572825729257302573125732257332573425735257362573725738257392574025741257422574325744257452574625747257482574925750257512575225753257542575525756257572575825759257602576125762257632576425765257662576725768257692577025771257722577325774257752577625777257782577925780257812578225783257842578525786257872578825789257902579125792257932579425795257962579725798257992580025801258022580325804258052580625807258082580925810258112581225813258142581525816258172581825819258202582125822258232582425825258262582725828258292583025831258322583325834258352583625837258382583925840258412584225843258442584525846258472584825849258502585125852258532585425855258562585725858258592586025861258622586325864258652586625867258682586925870258712587225873258742587525876258772587825879258802588125882258832588425885258862588725888258892589025891258922589325894258952589625897258982589925900259012590225903259042590525906259072590825909259102591125912259132591425915259162591725918259192592025921259222592325924259252592625927259282592925930259312593225933259342593525936259372593825939259402594125942259432594425945259462594725948259492595025951259522595325954259552595625957259582595925960259612596225963259642596525966259672596825969259702597125972259732597425975259762597725978259792598025981259822598325984259852598625987259882598925990259912599225993259942599525996259972599825999260002600126002260032600426005260062600726008260092601026011260122601326014260152601626017260182601926020260212602226023260242602526026260272602826029260302603126032260332603426035260362603726038260392604026041260422604326044260452604626047260482604926050260512605226053260542605526056260572605826059260602606126062260632606426065260662606726068260692607026071260722607326074260752607626077260782607926080260812608226083260842608526086260872608826089260902609126092260932609426095260962609726098260992610026101261022610326104261052610626107261082610926110261112611226113261142611526116261172611826119261202612126122261232612426125261262612726128261292613026131261322613326134261352613626137261382613926140261412614226143261442614526146261472614826149261502615126152261532615426155261562615726158261592616026161261622616326164261652616626167261682616926170261712617226173261742617526176261772617826179261802618126182261832618426185261862618726188261892619026191261922619326194261952619626197261982619926200262012620226203262042620526206262072620826209262102621126212262132621426215262162621726218262192622026221262222622326224262252622626227262282622926230262312623226233262342623526236262372623826239262402624126242262432624426245262462624726248262492625026251262522625326254262552625626257262582625926260262612626226263262642626526266262672626826269262702627126272262732627426275262762627726278262792628026281262822628326284262852628626287262882628926290262912629226293262942629526296262972629826299263002630126302263032630426305263062630726308263092631026311263122631326314263152631626317263182631926320263212632226323263242632526326263272632826329263302633126332263332633426335263362633726338263392634026341263422634326344263452634626347263482634926350263512635226353263542635526356263572635826359263602636126362263632636426365263662636726368263692637026371263722637326374263752637626377263782637926380263812638226383263842638526386263872638826389263902639126392263932639426395263962639726398263992640026401264022640326404264052640626407264082640926410264112641226413264142641526416264172641826419264202642126422264232642426425264262642726428264292643026431264322643326434264352643626437264382643926440264412644226443264442644526446264472644826449264502645126452264532645426455264562645726458264592646026461264622646326464264652646626467264682646926470264712647226473264742647526476264772647826479264802648126482264832648426485264862648726488264892649026491264922649326494264952649626497264982649926500265012650226503265042650526506265072650826509265102651126512265132651426515265162651726518265192652026521265222652326524265252652626527265282652926530265312653226533265342653526536265372653826539265402654126542265432654426545265462654726548265492655026551265522655326554265552655626557265582655926560265612656226563265642656526566265672656826569265702657126572265732657426575265762657726578265792658026581265822658326584265852658626587265882658926590265912659226593265942659526596265972659826599266002660126602266032660426605266062660726608266092661026611266122661326614266152661626617266182661926620266212662226623266242662526626266272662826629266302663126632266332663426635266362663726638266392664026641266422664326644266452664626647266482664926650266512665226653266542665526656266572665826659266602666126662266632666426665266662666726668266692667026671266722667326674266752667626677266782667926680266812668226683266842668526686266872668826689266902669126692266932669426695266962669726698266992670026701267022670326704267052670626707267082670926710267112671226713267142671526716267172671826719267202672126722267232672426725267262672726728267292673026731267322673326734267352673626737267382673926740267412674226743267442674526746267472674826749267502675126752267532675426755267562675726758267592676026761267622676326764267652676626767267682676926770267712677226773267742677526776267772677826779267802678126782267832678426785267862678726788267892679026791267922679326794267952679626797267982679926800268012680226803268042680526806268072680826809268102681126812268132681426815268162681726818268192682026821268222682326824268252682626827268282682926830268312683226833268342683526836268372683826839268402684126842268432684426845268462684726848268492685026851268522685326854268552685626857268582685926860268612686226863268642686526866268672686826869268702687126872268732687426875268762687726878268792688026881268822688326884268852688626887268882688926890268912689226893268942689526896268972689826899269002690126902269032690426905269062690726908269092691026911269122691326914269152691626917269182691926920269212692226923269242692526926269272692826929269302693126932269332693426935269362693726938269392694026941269422694326944269452694626947269482694926950269512695226953269542695526956269572695826959269602696126962269632696426965269662696726968269692697026971269722697326974269752697626977269782697926980269812698226983269842698526986269872698826989269902699126992269932699426995269962699726998269992700027001270022700327004270052700627007270082700927010270112701227013270142701527016270172701827019270202702127022270232702427025270262702727028270292703027031270322703327034270352703627037270382703927040270412704227043270442704527046270472704827049270502705127052270532705427055270562705727058270592706027061270622706327064270652706627067270682706927070270712707227073270742707527076270772707827079270802708127082270832708427085270862708727088270892709027091270922709327094270952709627097270982709927100271012710227103271042710527106271072710827109271102711127112271132711427115271162711727118271192712027121271222712327124271252712627127271282712927130271312713227133271342713527136271372713827139271402714127142271432714427145271462714727148271492715027151271522715327154271552715627157271582715927160271612716227163271642716527166271672716827169271702717127172271732717427175271762717727178271792718027181271822718327184271852718627187271882718927190271912719227193271942719527196271972719827199272002720127202272032720427205272062720727208272092721027211272122721327214272152721627217272182721927220272212722227223272242722527226272272722827229272302723127232272332723427235272362723727238272392724027241272422724327244272452724627247272482724927250272512725227253272542725527256272572725827259272602726127262272632726427265272662726727268272692727027271272722727327274272752727627277272782727927280272812728227283272842728527286272872728827289272902729127292272932729427295272962729727298272992730027301273022730327304273052730627307273082730927310273112731227313273142731527316273172731827319273202732127322273232732427325273262732727328273292733027331273322733327334273352733627337273382733927340273412734227343273442734527346273472734827349273502735127352273532735427355273562735727358273592736027361273622736327364273652736627367273682736927370273712737227373273742737527376273772737827379273802738127382273832738427385273862738727388273892739027391273922739327394273952739627397273982739927400274012740227403274042740527406274072740827409274102741127412274132741427415274162741727418274192742027421274222742327424274252742627427274282742927430274312743227433274342743527436274372743827439274402744127442274432744427445274462744727448274492745027451274522745327454274552745627457274582745927460274612746227463274642746527466274672746827469274702747127472274732747427475274762747727478274792748027481274822748327484274852748627487274882748927490274912749227493274942749527496274972749827499275002750127502275032750427505275062750727508275092751027511275122751327514275152751627517275182751927520275212752227523275242752527526275272752827529275302753127532275332753427535275362753727538275392754027541275422754327544275452754627547275482754927550275512755227553275542755527556275572755827559275602756127562275632756427565275662756727568275692757027571275722757327574275752757627577275782757927580275812758227583275842758527586275872758827589275902759127592275932759427595275962759727598275992760027601276022760327604276052760627607276082760927610276112761227613276142761527616276172761827619276202762127622276232762427625276262762727628276292763027631276322763327634276352763627637276382763927640276412764227643276442764527646276472764827649276502765127652276532765427655276562765727658276592766027661276622766327664276652766627667276682766927670276712767227673276742767527676276772767827679276802768127682276832768427685276862768727688276892769027691276922769327694276952769627697276982769927700277012770227703277042770527706277072770827709277102771127712277132771427715277162771727718277192772027721277222772327724277252772627727277282772927730277312773227733277342773527736277372773827739277402774127742277432774427745277462774727748277492775027751277522775327754277552775627757277582775927760277612776227763277642776527766277672776827769277702777127772277732777427775277762777727778277792778027781277822778327784277852778627787277882778927790277912779227793277942779527796277972779827799278002780127802278032780427805278062780727808278092781027811278122781327814278152781627817278182781927820278212782227823278242782527826278272782827829278302783127832278332783427835278362783727838278392784027841278422784327844278452784627847278482784927850278512785227853278542785527856278572785827859278602786127862278632786427865278662786727868278692787027871278722787327874278752787627877278782787927880278812788227883278842788527886278872788827889278902789127892278932789427895278962789727898278992790027901279022790327904279052790627907279082790927910279112791227913279142791527916279172791827919279202792127922279232792427925279262792727928279292793027931279322793327934279352793627937279382793927940279412794227943279442794527946279472794827949279502795127952279532795427955279562795727958279592796027961279622796327964279652796627967279682796927970279712797227973279742797527976279772797827979279802798127982279832798427985279862798727988279892799027991279922799327994279952799627997279982799928000280012800228003280042800528006280072800828009280102801128012280132801428015280162801728018280192802028021280222802328024280252802628027280282802928030280312803228033280342803528036280372803828039280402804128042280432804428045280462804728048280492805028051280522805328054280552805628057280582805928060280612806228063280642806528066280672806828069280702807128072280732807428075280762807728078280792808028081280822808328084280852808628087280882808928090280912809228093280942809528096280972809828099281002810128102281032810428105281062810728108281092811028111281122811328114281152811628117281182811928120281212812228123281242812528126281272812828129281302813128132281332813428135281362813728138281392814028141281422814328144281452814628147281482814928150281512815228153281542815528156281572815828159281602816128162281632816428165281662816728168281692817028171281722817328174281752817628177281782817928180281812818228183281842818528186281872818828189281902819128192281932819428195281962819728198281992820028201282022820328204282052820628207282082820928210282112821228213282142821528216282172821828219282202822128222282232822428225282262822728228282292823028231282322823328234282352823628237282382823928240282412824228243282442824528246282472824828249282502825128252282532825428255282562825728258282592826028261282622826328264282652826628267282682826928270282712827228273282742827528276282772827828279282802828128282282832828428285282862828728288282892829028291282922829328294282952829628297282982829928300283012830228303283042830528306283072830828309283102831128312283132831428315283162831728318283192832028321283222832328324283252832628327283282832928330283312833228333283342833528336283372833828339283402834128342283432834428345283462834728348283492835028351283522835328354283552835628357283582835928360283612836228363283642836528366283672836828369283702837128372283732837428375283762837728378283792838028381283822838328384283852838628387283882838928390283912839228393283942839528396283972839828399284002840128402284032840428405284062840728408284092841028411284122841328414284152841628417284182841928420284212842228423284242842528426284272842828429284302843128432284332843428435284362843728438284392844028441284422844328444284452844628447284482844928450284512845228453284542845528456284572845828459284602846128462284632846428465284662846728468284692847028471284722847328474284752847628477284782847928480284812848228483284842848528486284872848828489284902849128492284932849428495284962849728498284992850028501285022850328504285052850628507285082850928510285112851228513285142851528516285172851828519285202852128522285232852428525285262852728528285292853028531285322853328534285352853628537285382853928540285412854228543285442854528546285472854828549285502855128552285532855428555285562855728558285592856028561285622856328564285652856628567285682856928570285712857228573285742857528576285772857828579285802858128582285832858428585285862858728588285892859028591285922859328594285952859628597285982859928600286012860228603286042860528606286072860828609286102861128612286132861428615286162861728618286192862028621286222862328624286252862628627286282862928630286312863228633286342863528636286372863828639286402864128642286432864428645286462864728648286492865028651286522865328654286552865628657286582865928660286612866228663286642866528666286672866828669286702867128672286732867428675286762867728678286792868028681286822868328684286852868628687286882868928690286912869228693286942869528696286972869828699287002870128702287032870428705287062870728708287092871028711287122871328714287152871628717287182871928720287212872228723287242872528726287272872828729287302873128732287332873428735287362873728738287392874028741287422874328744287452874628747287482874928750287512875228753287542875528756287572875828759287602876128762287632876428765287662876728768287692877028771287722877328774287752877628777287782877928780287812878228783287842878528786287872878828789287902879128792287932879428795287962879728798287992880028801288022880328804288052880628807288082880928810288112881228813288142881528816288172881828819288202882128822288232882428825288262882728828288292883028831288322883328834288352883628837288382883928840288412884228843288442884528846288472884828849288502885128852288532885428855288562885728858288592886028861288622886328864288652886628867288682886928870288712887228873288742887528876288772887828879288802888128882288832888428885288862888728888288892889028891288922889328894288952889628897288982889928900289012890228903289042890528906289072890828909289102891128912289132891428915289162891728918289192892028921289222892328924289252892628927289282892928930289312893228933289342893528936289372893828939289402894128942289432894428945289462894728948289492895028951289522895328954289552895628957289582895928960289612896228963289642896528966289672896828969289702897128972289732897428975289762897728978289792898028981289822898328984289852898628987289882898928990289912899228993289942899528996289972899828999290002900129002290032900429005290062900729008290092901029011290122901329014290152901629017290182901929020290212902229023290242902529026290272902829029290302903129032290332903429035290362903729038290392904029041290422904329044290452904629047290482904929050290512905229053290542905529056290572905829059290602906129062290632906429065290662906729068290692907029071290722907329074290752907629077290782907929080290812908229083290842908529086290872908829089290902909129092290932909429095290962909729098290992910029101291022910329104291052910629107291082910929110291112911229113291142911529116291172911829119291202912129122291232912429125291262912729128291292913029131291322913329134291352913629137291382913929140291412914229143291442914529146291472914829149291502915129152291532915429155291562915729158291592916029161291622916329164291652916629167291682916929170291712917229173291742917529176291772917829179291802918129182291832918429185291862918729188291892919029191291922919329194291952919629197291982919929200292012920229203292042920529206292072920829209292102921129212292132921429215292162921729218292192922029221292222922329224292252922629227292282922929230292312923229233292342923529236292372923829239292402924129242292432924429245292462924729248292492925029251292522925329254292552925629257292582925929260292612926229263292642926529266292672926829269292702927129272292732927429275292762927729278292792928029281292822928329284292852928629287292882928929290292912929229293292942929529296292972929829299293002930129302293032930429305293062930729308293092931029311293122931329314293152931629317293182931929320293212932229323293242932529326293272932829329293302933129332293332933429335293362933729338293392934029341293422934329344293452934629347293482934929350293512935229353293542935529356293572935829359293602936129362293632936429365293662936729368293692937029371293722937329374293752937629377293782937929380293812938229383293842938529386293872938829389293902939129392293932939429395293962939729398293992940029401294022940329404294052940629407294082940929410294112941229413294142941529416294172941829419294202942129422294232942429425294262942729428294292943029431294322943329434294352943629437294382943929440294412944229443294442944529446294472944829449294502945129452294532945429455294562945729458294592946029461294622946329464294652946629467294682946929470294712947229473294742947529476294772947829479294802948129482294832948429485294862948729488294892949029491294922949329494294952949629497294982949929500295012950229503295042950529506295072950829509295102951129512295132951429515295162951729518295192952029521295222952329524295252952629527295282952929530295312953229533295342953529536295372953829539295402954129542295432954429545295462954729548295492955029551295522955329554295552955629557295582955929560295612956229563295642956529566295672956829569295702957129572295732957429575295762957729578295792958029581295822958329584295852958629587295882958929590295912959229593295942959529596295972959829599296002960129602296032960429605296062960729608296092961029611296122961329614296152961629617296182961929620296212962229623296242962529626296272962829629296302963129632296332963429635296362963729638296392964029641296422964329644296452964629647296482964929650296512965229653296542965529656296572965829659296602966129662296632966429665296662966729668296692967029671296722967329674296752967629677296782967929680296812968229683296842968529686296872968829689296902969129692296932969429695296962969729698296992970029701297022970329704297052970629707297082970929710297112971229713297142971529716297172971829719297202972129722297232972429725297262972729728297292973029731297322973329734297352973629737297382973929740297412974229743297442974529746297472974829749297502975129752297532975429755297562975729758297592976029761297622976329764297652976629767297682976929770297712977229773297742977529776297772977829779297802978129782297832978429785297862978729788297892979029791297922979329794297952979629797297982979929800298012980229803298042980529806298072980829809298102981129812298132981429815298162981729818298192982029821298222982329824298252982629827298282982929830298312983229833298342983529836298372983829839298402984129842298432984429845298462984729848298492985029851298522985329854298552985629857298582985929860298612986229863298642986529866298672986829869298702987129872298732987429875298762987729878298792988029881298822988329884298852988629887298882988929890298912989229893298942989529896298972989829899299002990129902299032990429905299062990729908299092991029911299122991329914299152991629917299182991929920299212992229923299242992529926299272992829929299302993129932299332993429935299362993729938299392994029941299422994329944299452994629947299482994929950299512995229953299542995529956299572995829959299602996129962299632996429965299662996729968299692997029971299722997329974299752997629977299782997929980299812998229983299842998529986299872998829989299902999129992299932999429995299962999729998299993000030001300023000330004300053000630007300083000930010300113001230013300143001530016300173001830019300203002130022300233002430025300263002730028300293003030031300323003330034300353003630037300383003930040300413004230043300443004530046300473004830049300503005130052300533005430055300563005730058300593006030061300623006330064300653006630067300683006930070300713007230073300743007530076300773007830079300803008130082300833008430085300863008730088300893009030091300923009330094300953009630097300983009930100301013010230103301043010530106301073010830109301103011130112301133011430115301163011730118301193012030121301223012330124301253012630127301283012930130301313013230133301343013530136301373013830139301403014130142301433014430145301463014730148301493015030151301523015330154301553015630157301583015930160301613016230163301643016530166301673016830169301703017130172301733017430175301763017730178301793018030181301823018330184301853018630187301883018930190301913019230193301943019530196301973019830199302003020130202302033020430205302063020730208302093021030211302123021330214302153021630217302183021930220302213022230223302243022530226302273022830229302303023130232302333023430235302363023730238302393024030241302423024330244302453024630247302483024930250302513025230253302543025530256302573025830259302603026130262302633026430265302663026730268302693027030271302723027330274302753027630277302783027930280302813028230283302843028530286302873028830289302903029130292302933029430295302963029730298302993030030301303023030330304303053030630307303083030930310303113031230313303143031530316303173031830319303203032130322303233032430325303263032730328303293033030331303323033330334303353033630337303383033930340303413034230343303443034530346303473034830349303503035130352303533035430355303563035730358303593036030361303623036330364303653036630367303683036930370303713037230373303743037530376303773037830379303803038130382303833038430385303863038730388303893039030391303923039330394303953039630397303983039930400304013040230403304043040530406304073040830409304103041130412304133041430415304163041730418304193042030421304223042330424304253042630427304283042930430304313043230433304343043530436304373043830439304403044130442304433044430445304463044730448304493045030451304523045330454304553045630457304583045930460304613046230463304643046530466304673046830469304703047130472304733047430475304763047730478304793048030481304823048330484304853048630487304883048930490304913049230493304943049530496304973049830499305003050130502305033050430505305063050730508305093051030511305123051330514305153051630517305183051930520305213052230523305243052530526305273052830529305303053130532305333053430535305363053730538305393054030541305423054330544305453054630547305483054930550305513055230553305543055530556305573055830559305603056130562305633056430565305663056730568305693057030571305723057330574305753057630577305783057930580305813058230583305843058530586305873058830589305903059130592305933059430595305963059730598305993060030601306023060330604306053060630607306083060930610306113061230613306143061530616306173061830619306203062130622306233062430625306263062730628306293063030631306323063330634306353063630637306383063930640306413064230643306443064530646306473064830649306503065130652306533065430655306563065730658306593066030661306623066330664306653066630667306683066930670306713067230673306743067530676306773067830679306803068130682306833068430685306863068730688306893069030691306923069330694306953069630697306983069930700307013070230703307043070530706307073070830709307103071130712307133071430715307163071730718307193072030721307223072330724307253072630727307283072930730307313073230733307343073530736307373073830739307403074130742307433074430745307463074730748307493075030751307523075330754307553075630757307583075930760307613076230763307643076530766307673076830769307703077130772307733077430775307763077730778307793078030781307823078330784307853078630787307883078930790307913079230793307943079530796307973079830799308003080130802308033080430805308063080730808308093081030811308123081330814308153081630817308183081930820308213082230823308243082530826308273082830829308303083130832308333083430835308363083730838308393084030841308423084330844308453084630847308483084930850308513085230853308543085530856308573085830859308603086130862308633086430865308663086730868308693087030871308723087330874308753087630877308783087930880308813088230883308843088530886308873088830889308903089130892308933089430895308963089730898308993090030901309023090330904309053090630907309083090930910309113091230913309143091530916309173091830919309203092130922309233092430925309263092730928309293093030931309323093330934309353093630937309383093930940309413094230943309443094530946309473094830949309503095130952309533095430955309563095730958309593096030961309623096330964309653096630967309683096930970309713097230973309743097530976309773097830979309803098130982309833098430985309863098730988309893099030991309923099330994309953099630997309983099931000310013100231003310043100531006310073100831009310103101131012310133101431015310163101731018310193102031021310223102331024310253102631027310283102931030310313103231033310343103531036310373103831039310403104131042310433104431045310463104731048310493105031051310523105331054310553105631057310583105931060310613106231063310643106531066310673106831069310703107131072310733107431075310763107731078310793108031081310823108331084310853108631087310883108931090310913109231093310943109531096310973109831099311003110131102311033110431105311063110731108311093111031111311123111331114311153111631117311183111931120311213112231123311243112531126311273112831129311303113131132311333113431135311363113731138311393114031141311423114331144311453114631147311483114931150311513115231153311543115531156311573115831159311603116131162311633116431165311663116731168311693117031171311723117331174311753117631177311783117931180311813118231183311843118531186311873118831189311903119131192311933119431195311963119731198311993120031201312023120331204312053120631207312083120931210312113121231213312143121531216312173121831219312203122131222312233122431225312263122731228312293123031231312323123331234312353123631237312383123931240312413124231243312443124531246312473124831249312503125131252312533125431255312563125731258312593126031261312623126331264312653126631267312683126931270312713127231273312743127531276312773127831279312803128131282312833128431285312863128731288312893129031291312923129331294312953129631297312983129931300313013130231303313043130531306313073130831309313103131131312313133131431315313163131731318313193132031321313223132331324313253132631327313283132931330313313133231333313343133531336313373133831339313403134131342313433134431345313463134731348313493135031351313523135331354313553135631357313583135931360313613136231363313643136531366313673136831369313703137131372313733137431375313763137731378313793138031381313823138331384313853138631387313883138931390313913139231393313943139531396313973139831399314003140131402314033140431405314063140731408314093141031411314123141331414314153141631417314183141931420314213142231423314243142531426314273142831429314303143131432314333143431435314363143731438314393144031441314423144331444314453144631447314483144931450314513145231453314543145531456314573145831459314603146131462314633146431465314663146731468314693147031471314723147331474314753147631477314783147931480314813148231483314843148531486314873148831489314903149131492314933149431495314963149731498314993150031501315023150331504315053150631507315083150931510315113151231513315143151531516315173151831519315203152131522315233152431525315263152731528315293153031531315323153331534315353153631537315383153931540315413154231543315443154531546315473154831549315503155131552315533155431555315563155731558315593156031561315623156331564315653156631567315683156931570315713157231573315743157531576315773157831579315803158131582315833158431585315863158731588315893159031591315923159331594315953159631597315983159931600316013160231603316043160531606316073160831609316103161131612316133161431615316163161731618316193162031621316223162331624316253162631627316283162931630316313163231633316343163531636316373163831639316403164131642316433164431645316463164731648316493165031651316523165331654316553165631657316583165931660316613166231663316643166531666316673166831669316703167131672316733167431675316763167731678316793168031681316823168331684316853168631687316883168931690316913169231693316943169531696316973169831699317003170131702317033170431705317063170731708317093171031711317123171331714317153171631717317183171931720317213172231723317243172531726317273172831729317303173131732317333173431735317363173731738317393174031741317423174331744317453174631747317483174931750317513175231753317543175531756317573175831759317603176131762317633176431765317663176731768317693177031771317723177331774317753177631777317783177931780317813178231783317843178531786317873178831789317903179131792317933179431795317963179731798317993180031801318023180331804318053180631807318083180931810318113181231813318143181531816318173181831819318203182131822318233182431825318263182731828318293183031831318323183331834318353183631837318383183931840318413184231843318443184531846318473184831849318503185131852318533185431855318563185731858318593186031861318623186331864318653186631867318683186931870318713187231873318743187531876318773187831879318803188131882318833188431885318863188731888318893189031891318923189331894318953189631897318983189931900319013190231903319043190531906319073190831909319103191131912319133191431915319163191731918319193192031921319223192331924319253192631927319283192931930319313193231933319343193531936319373193831939319403194131942319433194431945319463194731948319493195031951319523195331954319553195631957319583195931960319613196231963319643196531966319673196831969319703197131972319733197431975319763197731978319793198031981319823198331984319853198631987319883198931990319913199231993319943199531996319973199831999320003200132002320033200432005320063200732008320093201032011320123201332014320153201632017320183201932020320213202232023320243202532026320273202832029320303203132032320333203432035320363203732038320393204032041320423204332044320453204632047320483204932050320513205232053320543205532056320573205832059320603206132062320633206432065320663206732068320693207032071320723207332074320753207632077320783207932080320813208232083320843208532086320873208832089320903209132092320933209432095320963209732098320993210032101321023210332104321053210632107321083210932110321113211232113321143211532116321173211832119321203212132122321233212432125321263212732128321293213032131321323213332134321353213632137321383213932140321413214232143321443214532146321473214832149321503215132152321533215432155321563215732158321593216032161321623216332164321653216632167321683216932170321713217232173321743217532176321773217832179321803218132182321833218432185321863218732188321893219032191321923219332194321953219632197321983219932200322013220232203322043220532206322073220832209322103221132212322133221432215322163221732218322193222032221322223222332224322253222632227322283222932230322313223232233322343223532236322373223832239322403224132242322433224432245322463224732248322493225032251322523225332254322553225632257322583225932260322613226232263322643226532266322673226832269322703227132272322733227432275322763227732278322793228032281322823228332284322853228632287322883228932290322913229232293322943229532296322973229832299323003230132302323033230432305323063230732308323093231032311323123231332314323153231632317323183231932320323213232232323323243232532326323273232832329323303233132332323333233432335323363233732338323393234032341323423234332344323453234632347323483234932350323513235232353323543235532356323573235832359323603236132362323633236432365323663236732368323693237032371323723237332374323753237632377323783237932380323813238232383323843238532386323873238832389323903239132392323933239432395323963239732398323993240032401324023240332404324053240632407324083240932410324113241232413324143241532416324173241832419324203242132422324233242432425324263242732428324293243032431324323243332434324353243632437324383243932440324413244232443324443244532446324473244832449324503245132452324533245432455324563245732458324593246032461324623246332464324653246632467324683246932470324713247232473324743247532476324773247832479324803248132482324833248432485324863248732488324893249032491324923249332494324953249632497324983249932500325013250232503325043250532506325073250832509325103251132512325133251432515325163251732518325193252032521325223252332524325253252632527325283252932530325313253232533325343253532536325373253832539325403254132542325433254432545325463254732548325493255032551325523255332554325553255632557325583255932560325613256232563325643256532566325673256832569325703257132572325733257432575325763257732578325793258032581325823258332584325853258632587325883258932590325913259232593325943259532596325973259832599326003260132602326033260432605326063260732608326093261032611326123261332614326153261632617326183261932620326213262232623326243262532626326273262832629326303263132632326333263432635326363263732638326393264032641326423264332644326453264632647326483264932650326513265232653326543265532656326573265832659326603266132662326633266432665326663266732668326693267032671326723267332674326753267632677326783267932680326813268232683326843268532686326873268832689326903269132692326933269432695326963269732698326993270032701327023270332704327053270632707327083270932710327113271232713327143271532716327173271832719327203272132722327233272432725327263272732728327293273032731327323273332734327353273632737327383273932740327413274232743327443274532746327473274832749327503275132752327533275432755327563275732758327593276032761327623276332764327653276632767327683276932770327713277232773327743277532776327773277832779327803278132782327833278432785327863278732788327893279032791327923279332794327953279632797327983279932800328013280232803328043280532806328073280832809328103281132812328133281432815328163281732818328193282032821328223282332824328253282632827328283282932830328313283232833328343283532836328373283832839328403284132842328433284432845328463284732848328493285032851328523285332854328553285632857328583285932860328613286232863328643286532866328673286832869328703287132872328733287432875328763287732878328793288032881328823288332884328853288632887328883288932890328913289232893328943289532896328973289832899329003290132902329033290432905329063290732908329093291032911329123291332914329153291632917329183291932920329213292232923329243292532926329273292832929329303293132932329333293432935329363293732938329393294032941329423294332944329453294632947329483294932950329513295232953329543295532956329573295832959329603296132962329633296432965329663296732968329693297032971329723297332974329753297632977329783297932980329813298232983329843298532986329873298832989329903299132992329933299432995329963299732998329993300033001330023300333004330053300633007330083300933010330113301233013330143301533016330173301833019330203302133022330233302433025330263302733028330293303033031330323303333034330353303633037330383303933040330413304233043330443304533046330473304833049330503305133052330533305433055330563305733058330593306033061330623306333064330653306633067330683306933070330713307233073330743307533076330773307833079330803308133082330833308433085330863308733088330893309033091330923309333094330953309633097330983309933100331013310233103331043310533106331073310833109331103311133112331133311433115331163311733118331193312033121331223312333124331253312633127331283312933130331313313233133331343313533136331373313833139331403314133142331433314433145331463314733148331493315033151331523315333154331553315633157331583315933160331613316233163331643316533166331673316833169331703317133172331733317433175331763317733178331793318033181331823318333184331853318633187331883318933190331913319233193331943319533196331973319833199332003320133202332033320433205332063320733208332093321033211332123321333214332153321633217332183321933220332213322233223332243322533226332273322833229332303323133232332333323433235332363323733238332393324033241332423324333244332453324633247332483324933250332513325233253332543325533256332573325833259332603326133262332633326433265332663326733268332693327033271332723327333274332753327633277332783327933280332813328233283332843328533286332873328833289332903329133292332933329433295332963329733298332993330033301333023330333304333053330633307333083330933310333113331233313333143331533316333173331833319333203332133322333233332433325333263332733328333293333033331333323333333334333353333633337333383333933340333413334233343333443334533346333473334833349333503335133352333533335433355333563335733358333593336033361333623336333364333653336633367333683336933370333713337233373333743337533376333773337833379333803338133382333833338433385333863338733388333893339033391333923339333394333953339633397333983339933400334013340233403334043340533406334073340833409334103341133412334133341433415334163341733418334193342033421334223342333424334253342633427334283342933430334313343233433334343343533436334373343833439334403344133442334433344433445334463344733448334493345033451334523345333454334553345633457334583345933460334613346233463334643346533466334673346833469334703347133472334733347433475334763347733478334793348033481334823348333484334853348633487334883348933490334913349233493334943349533496334973349833499335003350133502335033350433505335063350733508335093351033511335123351333514335153351633517335183351933520335213352233523335243352533526335273352833529335303353133532335333353433535335363353733538335393354033541335423354333544335453354633547335483354933550335513355233553335543355533556335573355833559335603356133562335633356433565335663356733568335693357033571335723357333574335753357633577335783357933580335813358233583335843358533586335873358833589335903359133592335933359433595335963359733598335993360033601336023360333604336053360633607336083360933610336113361233613336143361533616336173361833619336203362133622336233362433625336263362733628336293363033631336323363333634336353363633637336383363933640336413364233643336443364533646336473364833649336503365133652336533365433655336563365733658336593366033661336623366333664336653366633667336683366933670336713367233673336743367533676336773367833679336803368133682336833368433685336863368733688336893369033691336923369333694336953369633697336983369933700337013370233703337043370533706337073370833709337103371133712337133371433715337163371733718337193372033721337223372333724337253372633727337283372933730337313373233733337343373533736337373373833739337403374133742337433374433745337463374733748337493375033751337523375333754337553375633757337583375933760337613376233763337643376533766337673376833769337703377133772337733377433775337763377733778337793378033781337823378333784337853378633787337883378933790337913379233793337943379533796337973379833799338003380133802338033380433805338063380733808338093381033811338123381333814338153381633817338183381933820338213382233823338243382533826338273382833829338303383133832338333383433835338363383733838338393384033841338423384333844338453384633847338483384933850338513385233853338543385533856338573385833859338603386133862338633386433865338663386733868338693387033871338723387333874338753387633877338783387933880338813388233883338843388533886338873388833889338903389133892338933389433895338963389733898338993390033901339023390333904339053390633907339083390933910339113391233913339143391533916339173391833919339203392133922339233392433925339263392733928339293393033931339323393333934339353393633937339383393933940339413394233943339443394533946339473394833949339503395133952339533395433955339563395733958339593396033961339623396333964339653396633967339683396933970339713397233973339743397533976339773397833979339803398133982339833398433985339863398733988339893399033991339923399333994339953399633997339983399934000340013400234003340043400534006340073400834009340103401134012340133401434015340163401734018340193402034021340223402334024340253402634027340283402934030340313403234033340343403534036340373403834039340403404134042340433404434045340463404734048340493405034051340523405334054340553405634057340583405934060340613406234063340643406534066340673406834069340703407134072340733407434075340763407734078340793408034081340823408334084340853408634087340883408934090340913409234093340943409534096340973409834099341003410134102341033410434105341063410734108341093411034111341123411334114341153411634117341183411934120341213412234123341243412534126341273412834129341303413134132341333413434135341363413734138341393414034141341423414334144341453414634147341483414934150341513415234153341543415534156341573415834159341603416134162341633416434165341663416734168341693417034171341723417334174341753417634177341783417934180341813418234183341843418534186341873418834189341903419134192341933419434195341963419734198341993420034201342023420334204342053420634207342083420934210342113421234213342143421534216342173421834219342203422134222342233422434225342263422734228342293423034231342323423334234342353423634237342383423934240342413424234243342443424534246342473424834249342503425134252342533425434255342563425734258342593426034261342623426334264342653426634267342683426934270342713427234273342743427534276342773427834279342803428134282342833428434285342863428734288342893429034291342923429334294342953429634297342983429934300343013430234303343043430534306343073430834309343103431134312343133431434315343163431734318343193432034321343223432334324343253432634327343283432934330343313433234333343343433534336343373433834339343403434134342343433434434345343463434734348343493435034351343523435334354343553435634357343583435934360343613436234363343643436534366343673436834369343703437134372343733437434375343763437734378343793438034381343823438334384343853438634387343883438934390343913439234393343943439534396343973439834399344003440134402344033440434405344063440734408344093441034411344123441334414344153441634417344183441934420344213442234423344243442534426344273442834429344303443134432344333443434435344363443734438344393444034441344423444334444344453444634447344483444934450344513445234453344543445534456344573445834459344603446134462344633446434465344663446734468344693447034471344723447334474344753447634477344783447934480344813448234483344843448534486344873448834489344903449134492344933449434495344963449734498344993450034501345023450334504345053450634507345083450934510345113451234513345143451534516345173451834519345203452134522345233452434525345263452734528345293453034531345323453334534345353453634537345383453934540345413454234543345443454534546345473454834549345503455134552345533455434555345563455734558345593456034561345623456334564345653456634567345683456934570345713457234573345743457534576345773457834579345803458134582345833458434585345863458734588345893459034591345923459334594345953459634597345983459934600346013460234603346043460534606346073460834609346103461134612346133461434615346163461734618346193462034621346223462334624346253462634627346283462934630346313463234633346343463534636346373463834639346403464134642346433464434645346463464734648346493465034651346523465334654346553465634657346583465934660346613466234663346643466534666346673466834669346703467134672346733467434675346763467734678346793468034681346823468334684346853468634687346883468934690346913469234693346943469534696346973469834699347003470134702347033470434705347063470734708347093471034711347123471334714347153471634717347183471934720347213472234723347243472534726347273472834729347303473134732347333473434735347363473734738347393474034741347423474334744347453474634747347483474934750347513475234753347543475534756347573475834759347603476134762347633476434765347663476734768347693477034771347723477334774347753477634777347783477934780347813478234783347843478534786347873478834789347903479134792347933479434795347963479734798347993480034801348023480334804348053480634807348083480934810348113481234813348143481534816348173481834819348203482134822348233482434825348263482734828348293483034831348323483334834348353483634837348383483934840348413484234843348443484534846348473484834849348503485134852348533485434855348563485734858348593486034861348623486334864348653486634867348683486934870348713487234873348743487534876348773487834879348803488134882348833488434885348863488734888348893489034891348923489334894348953489634897348983489934900349013490234903349043490534906349073490834909349103491134912349133491434915349163491734918349193492034921349223492334924349253492634927349283492934930349313493234933349343493534936349373493834939349403494134942349433494434945349463494734948349493495034951349523495334954349553495634957349583495934960349613496234963349643496534966349673496834969349703497134972349733497434975349763497734978349793498034981349823498334984349853498634987349883498934990349913499234993349943499534996349973499834999350003500135002350033500435005350063500735008350093501035011350123501335014350153501635017350183501935020350213502235023350243502535026350273502835029350303503135032350333503435035350363503735038350393504035041350423504335044350453504635047350483504935050350513505235053350543505535056350573505835059350603506135062350633506435065350663506735068350693507035071350723507335074350753507635077350783507935080350813508235083350843508535086350873508835089350903509135092350933509435095350963509735098350993510035101351023510335104351053510635107351083510935110351113511235113351143511535116351173511835119351203512135122351233512435125351263512735128351293513035131351323513335134351353513635137351383513935140351413514235143351443514535146351473514835149351503515135152351533515435155351563515735158351593516035161351623516335164351653516635167351683516935170351713517235173351743517535176351773517835179351803518135182351833518435185351863518735188351893519035191351923519335194351953519635197351983519935200352013520235203352043520535206352073520835209352103521135212352133521435215352163521735218352193522035221352223522335224352253522635227352283522935230352313523235233352343523535236352373523835239352403524135242352433524435245352463524735248352493525035251352523525335254352553525635257352583525935260352613526235263352643526535266352673526835269352703527135272352733527435275352763527735278352793528035281352823528335284352853528635287352883528935290352913529235293352943529535296352973529835299353003530135302353033530435305353063530735308353093531035311353123531335314353153531635317353183531935320353213532235323353243532535326353273532835329353303533135332353333533435335353363533735338353393534035341353423534335344353453534635347353483534935350353513535235353353543535535356353573535835359353603536135362353633536435365353663536735368353693537035371353723537335374353753537635377353783537935380353813538235383353843538535386353873538835389353903539135392353933539435395353963539735398353993540035401354023540335404354053540635407354083540935410354113541235413354143541535416354173541835419354203542135422354233542435425354263542735428354293543035431354323543335434354353543635437354383543935440354413544235443354443544535446354473544835449354503545135452354533545435455354563545735458354593546035461354623546335464354653546635467354683546935470354713547235473354743547535476354773547835479354803548135482354833548435485354863548735488354893549035491354923549335494354953549635497354983549935500355013550235503355043550535506355073550835509355103551135512355133551435515355163551735518355193552035521355223552335524355253552635527355283552935530355313553235533355343553535536355373553835539355403554135542355433554435545355463554735548355493555035551355523555335554355553555635557355583555935560355613556235563355643556535566355673556835569355703557135572355733557435575355763557735578355793558035581355823558335584355853558635587355883558935590355913559235593355943559535596355973559835599356003560135602356033560435605356063560735608356093561035611356123561335614356153561635617356183561935620356213562235623356243562535626356273562835629356303563135632356333563435635356363563735638356393564035641356423564335644356453564635647356483564935650356513565235653356543565535656356573565835659356603566135662356633566435665356663566735668356693567035671356723567335674356753567635677356783567935680356813568235683356843568535686356873568835689356903569135692356933569435695356963569735698356993570035701357023570335704357053570635707357083570935710357113571235713357143571535716357173571835719357203572135722357233572435725357263572735728357293573035731357323573335734357353573635737357383573935740357413574235743357443574535746357473574835749357503575135752357533575435755357563575735758357593576035761357623576335764357653576635767357683576935770357713577235773357743577535776357773577835779357803578135782357833578435785357863578735788357893579035791357923579335794357953579635797357983579935800358013580235803358043580535806358073580835809358103581135812358133581435815358163581735818358193582035821358223582335824358253582635827358283582935830358313583235833358343583535836358373583835839358403584135842358433584435845358463584735848358493585035851358523585335854358553585635857358583585935860358613586235863358643586535866358673586835869358703587135872358733587435875358763587735878358793588035881358823588335884358853588635887358883588935890358913589235893358943589535896358973589835899359003590135902359033590435905359063590735908359093591035911359123591335914359153591635917359183591935920359213592235923359243592535926359273592835929359303593135932359333593435935359363593735938359393594035941359423594335944359453594635947359483594935950359513595235953359543595535956359573595835959359603596135962359633596435965359663596735968359693597035971359723597335974359753597635977359783597935980359813598235983359843598535986359873598835989359903599135992359933599435995359963599735998359993600036001360023600336004360053600636007360083600936010360113601236013360143601536016360173601836019360203602136022360233602436025360263602736028360293603036031360323603336034360353603636037360383603936040360413604236043360443604536046360473604836049360503605136052360533605436055360563605736058360593606036061360623606336064360653606636067360683606936070360713607236073360743607536076360773607836079360803608136082360833608436085360863608736088360893609036091360923609336094360953609636097360983609936100361013610236103361043610536106361073610836109361103611136112361133611436115361163611736118361193612036121361223612336124361253612636127361283612936130361313613236133361343613536136361373613836139361403614136142361433614436145361463614736148361493615036151361523615336154361553615636157361583615936160361613616236163361643616536166361673616836169361703617136172361733617436175361763617736178361793618036181361823618336184361853618636187361883618936190361913619236193361943619536196361973619836199362003620136202362033620436205362063620736208362093621036211362123621336214362153621636217362183621936220362213622236223362243622536226362273622836229362303623136232362333623436235362363623736238362393624036241362423624336244362453624636247362483624936250362513625236253362543625536256362573625836259362603626136262362633626436265362663626736268362693627036271362723627336274362753627636277362783627936280362813628236283362843628536286362873628836289362903629136292362933629436295362963629736298362993630036301363023630336304363053630636307363083630936310363113631236313363143631536316363173631836319363203632136322363233632436325363263632736328363293633036331363323633336334363353633636337363383633936340363413634236343363443634536346363473634836349363503635136352363533635436355363563635736358363593636036361363623636336364363653636636367363683636936370363713637236373363743637536376363773637836379363803638136382363833638436385363863638736388363893639036391363923639336394363953639636397363983639936400364013640236403364043640536406364073640836409364103641136412364133641436415364163641736418364193642036421364223642336424364253642636427364283642936430364313643236433364343643536436364373643836439364403644136442364433644436445364463644736448364493645036451364523645336454364553645636457364583645936460364613646236463364643646536466364673646836469364703647136472364733647436475364763647736478364793648036481364823648336484364853648636487364883648936490364913649236493364943649536496364973649836499365003650136502365033650436505365063650736508365093651036511365123651336514365153651636517365183651936520365213652236523365243652536526365273652836529365303653136532365333653436535365363653736538365393654036541365423654336544365453654636547365483654936550365513655236553365543655536556365573655836559365603656136562365633656436565365663656736568365693657036571365723657336574365753657636577365783657936580365813658236583365843658536586365873658836589365903659136592365933659436595365963659736598365993660036601366023660336604366053660636607366083660936610366113661236613366143661536616366173661836619366203662136622366233662436625366263662736628366293663036631366323663336634366353663636637366383663936640366413664236643366443664536646366473664836649366503665136652366533665436655366563665736658366593666036661366623666336664366653666636667366683666936670366713667236673366743667536676366773667836679366803668136682366833668436685366863668736688366893669036691366923669336694366953669636697366983669936700367013670236703367043670536706367073670836709367103671136712367133671436715367163671736718367193672036721367223672336724367253672636727367283672936730367313673236733367343673536736367373673836739367403674136742367433674436745367463674736748367493675036751367523675336754367553675636757367583675936760367613676236763367643676536766367673676836769367703677136772367733677436775367763677736778367793678036781367823678336784367853678636787367883678936790367913679236793367943679536796367973679836799368003680136802368033680436805368063680736808368093681036811368123681336814368153681636817368183681936820368213682236823368243682536826368273682836829368303683136832368333683436835368363683736838368393684036841368423684336844368453684636847368483684936850368513685236853368543685536856368573685836859368603686136862368633686436865368663686736868368693687036871368723687336874368753687636877368783687936880368813688236883368843688536886368873688836889368903689136892368933689436895368963689736898368993690036901369023690336904369053690636907369083690936910369113691236913369143691536916369173691836919369203692136922369233692436925369263692736928369293693036931369323693336934369353693636937369383693936940369413694236943369443694536946369473694836949369503695136952369533695436955369563695736958369593696036961369623696336964369653696636967369683696936970369713697236973369743697536976369773697836979369803698136982369833698436985369863698736988369893699036991369923699336994369953699636997369983699937000370013700237003370043700537006370073700837009370103701137012370133701437015370163701737018370193702037021370223702337024370253702637027370283702937030370313703237033370343703537036370373703837039370403704137042370433704437045370463704737048370493705037051370523705337054370553705637057370583705937060370613706237063370643706537066370673706837069370703707137072370733707437075370763707737078370793708037081370823708337084370853708637087370883708937090370913709237093370943709537096370973709837099371003710137102371033710437105371063710737108371093711037111371123711337114371153711637117371183711937120371213712237123371243712537126371273712837129371303713137132371333713437135371363713737138371393714037141371423714337144371453714637147371483714937150371513715237153371543715537156371573715837159371603716137162371633716437165371663716737168371693717037171371723717337174371753717637177371783717937180371813718237183371843718537186371873718837189371903719137192371933719437195371963719737198371993720037201372023720337204372053720637207372083720937210372113721237213372143721537216372173721837219372203722137222372233722437225372263722737228372293723037231372323723337234372353723637237372383723937240372413724237243372443724537246372473724837249372503725137252372533725437255372563725737258372593726037261372623726337264372653726637267372683726937270372713727237273372743727537276372773727837279372803728137282372833728437285372863728737288372893729037291372923729337294372953729637297372983729937300373013730237303373043730537306373073730837309373103731137312373133731437315373163731737318373193732037321373223732337324373253732637327373283732937330373313733237333373343733537336373373733837339373403734137342373433734437345373463734737348373493735037351373523735337354373553735637357373583735937360373613736237363373643736537366373673736837369373703737137372373733737437375373763737737378373793738037381373823738337384373853738637387373883738937390373913739237393373943739537396373973739837399374003740137402374033740437405374063740737408374093741037411374123741337414374153741637417374183741937420374213742237423374243742537426374273742837429374303743137432374333743437435374363743737438374393744037441374423744337444374453744637447374483744937450374513745237453374543745537456374573745837459374603746137462374633746437465374663746737468374693747037471374723747337474374753747637477374783747937480374813748237483374843748537486374873748837489374903749137492374933749437495374963749737498374993750037501375023750337504375053750637507375083750937510375113751237513375143751537516375173751837519375203752137522375233752437525375263752737528375293753037531375323753337534375353753637537375383753937540375413754237543375443754537546375473754837549375503755137552375533755437555375563755737558375593756037561375623756337564375653756637567375683756937570375713757237573375743757537576375773757837579375803758137582375833758437585375863758737588375893759037591375923759337594375953759637597375983759937600376013760237603376043760537606376073760837609376103761137612376133761437615376163761737618376193762037621376223762337624376253762637627376283762937630376313763237633376343763537636376373763837639376403764137642376433764437645376463764737648376493765037651376523765337654376553765637657376583765937660376613766237663376643766537666376673766837669376703767137672376733767437675376763767737678376793768037681376823768337684376853768637687376883768937690376913769237693376943769537696376973769837699377003770137702377033770437705377063770737708377093771037711377123771337714377153771637717377183771937720377213772237723377243772537726377273772837729377303773137732377333773437735377363773737738377393774037741377423774337744377453774637747377483774937750377513775237753377543775537756377573775837759377603776137762377633776437765377663776737768377693777037771377723777337774377753777637777377783777937780377813778237783377843778537786377873778837789377903779137792377933779437795377963779737798377993780037801378023780337804378053780637807378083780937810378113781237813378143781537816378173781837819378203782137822378233782437825378263782737828378293783037831378323783337834378353783637837378383783937840378413784237843378443784537846378473784837849378503785137852378533785437855378563785737858378593786037861378623786337864378653786637867378683786937870378713787237873378743787537876378773787837879378803788137882378833788437885378863788737888378893789037891378923789337894378953789637897378983789937900379013790237903379043790537906379073790837909379103791137912379133791437915379163791737918379193792037921379223792337924379253792637927379283792937930379313793237933379343793537936379373793837939379403794137942379433794437945379463794737948379493795037951379523795337954379553795637957379583795937960379613796237963379643796537966379673796837969379703797137972379733797437975379763797737978379793798037981379823798337984379853798637987379883798937990379913799237993379943799537996379973799837999380003800138002380033800438005380063800738008380093801038011380123801338014380153801638017380183801938020380213802238023380243802538026380273802838029380303803138032380333803438035380363803738038380393804038041380423804338044380453804638047380483804938050380513805238053380543805538056380573805838059380603806138062380633806438065380663806738068380693807038071380723807338074380753807638077380783807938080380813808238083380843808538086380873808838089380903809138092380933809438095380963809738098380993810038101381023810338104381053810638107381083810938110381113811238113381143811538116381173811838119381203812138122381233812438125381263812738128381293813038131381323813338134381353813638137381383813938140381413814238143381443814538146381473814838149381503815138152381533815438155381563815738158381593816038161381623816338164381653816638167381683816938170381713817238173381743817538176381773817838179381803818138182381833818438185381863818738188381893819038191381923819338194381953819638197381983819938200382013820238203382043820538206382073820838209382103821138212382133821438215382163821738218382193822038221382223822338224382253822638227382283822938230382313823238233382343823538236382373823838239382403824138242382433824438245382463824738248382493825038251382523825338254382553825638257382583825938260382613826238263382643826538266382673826838269382703827138272382733827438275382763827738278382793828038281382823828338284382853828638287382883828938290382913829238293382943829538296382973829838299383003830138302383033830438305383063830738308383093831038311383123831338314383153831638317383183831938320383213832238323383243832538326383273832838329383303833138332383333833438335383363833738338383393834038341383423834338344383453834638347383483834938350383513835238353383543835538356383573835838359383603836138362383633836438365383663836738368383693837038371383723837338374383753837638377383783837938380383813838238383383843838538386383873838838389383903839138392383933839438395383963839738398383993840038401384023840338404384053840638407384083840938410384113841238413384143841538416384173841838419384203842138422384233842438425384263842738428384293843038431384323843338434384353843638437384383843938440384413844238443384443844538446384473844838449384503845138452384533845438455384563845738458384593846038461384623846338464384653846638467384683846938470384713847238473384743847538476384773847838479384803848138482384833848438485384863848738488384893849038491384923849338494384953849638497384983849938500385013850238503385043850538506385073850838509385103851138512385133851438515385163851738518385193852038521385223852338524385253852638527385283852938530385313853238533385343853538536385373853838539385403854138542385433854438545385463854738548385493855038551385523855338554385553855638557385583855938560385613856238563385643856538566385673856838569385703857138572385733857438575385763857738578385793858038581385823858338584385853858638587385883858938590385913859238593385943859538596385973859838599386003860138602386033860438605386063860738608386093861038611386123861338614386153861638617386183861938620386213862238623386243862538626386273862838629386303863138632386333863438635386363863738638386393864038641386423864338644386453864638647386483864938650386513865238653386543865538656386573865838659386603866138662386633866438665386663866738668386693867038671386723867338674386753867638677386783867938680386813868238683386843868538686386873868838689386903869138692386933869438695386963869738698386993870038701387023870338704387053870638707387083870938710387113871238713387143871538716387173871838719387203872138722387233872438725387263872738728387293873038731387323873338734387353873638737387383873938740387413874238743387443874538746387473874838749387503875138752387533875438755387563875738758387593876038761387623876338764387653876638767387683876938770387713877238773387743877538776387773877838779387803878138782387833878438785387863878738788387893879038791387923879338794387953879638797387983879938800388013880238803388043880538806388073880838809388103881138812388133881438815388163881738818388193882038821388223882338824388253882638827388283882938830388313883238833388343883538836388373883838839388403884138842388433884438845388463884738848388493885038851388523885338854388553885638857388583885938860388613886238863388643886538866388673886838869388703887138872388733887438875388763887738878388793888038881388823888338884388853888638887388883888938890388913889238893388943889538896388973889838899389003890138902389033890438905389063890738908389093891038911389123891338914389153891638917389183891938920389213892238923389243892538926389273892838929389303893138932389333893438935389363893738938389393894038941389423894338944389453894638947389483894938950389513895238953389543895538956389573895838959389603896138962389633896438965389663896738968389693897038971389723897338974389753897638977389783897938980389813898238983389843898538986389873898838989389903899138992389933899438995389963899738998389993900039001390023900339004390053900639007390083900939010390113901239013390143901539016390173901839019390203902139022390233902439025390263902739028390293903039031390323903339034390353903639037390383903939040390413904239043390443904539046390473904839049390503905139052390533905439055390563905739058390593906039061390623906339064390653906639067390683906939070390713907239073390743907539076390773907839079390803908139082390833908439085390863908739088390893909039091390923909339094390953909639097390983909939100391013910239103391043910539106391073910839109391103911139112391133911439115391163911739118391193912039121391223912339124391253912639127391283912939130391313913239133391343913539136391373913839139391403914139142391433914439145391463914739148391493915039151391523915339154391553915639157391583915939160391613916239163391643916539166391673916839169391703917139172391733917439175391763917739178391793918039181391823918339184391853918639187391883918939190391913919239193391943919539196391973919839199392003920139202392033920439205392063920739208392093921039211392123921339214392153921639217392183921939220392213922239223392243922539226392273922839229392303923139232392333923439235392363923739238392393924039241392423924339244392453924639247392483924939250392513925239253392543925539256392573925839259392603926139262392633926439265392663926739268392693927039271392723927339274392753927639277392783927939280392813928239283392843928539286392873928839289392903929139292392933929439295392963929739298392993930039301393023930339304393053930639307393083930939310393113931239313393143931539316393173931839319393203932139322393233932439325393263932739328393293933039331393323933339334393353933639337393383933939340393413934239343393443934539346393473934839349393503935139352393533935439355393563935739358393593936039361393623936339364393653936639367393683936939370393713937239373393743937539376393773937839379393803938139382393833938439385393863938739388393893939039391393923939339394393953939639397393983939939400394013940239403394043940539406394073940839409394103941139412394133941439415394163941739418394193942039421394223942339424394253942639427394283942939430394313943239433394343943539436394373943839439394403944139442394433944439445394463944739448394493945039451394523945339454394553945639457394583945939460394613946239463394643946539466394673946839469394703947139472394733947439475394763947739478394793948039481394823948339484394853948639487394883948939490394913949239493394943949539496394973949839499395003950139502395033950439505395063950739508395093951039511395123951339514395153951639517395183951939520395213952239523395243952539526395273952839529395303953139532395333953439535395363953739538395393954039541395423954339544395453954639547395483954939550395513955239553395543955539556395573955839559395603956139562395633956439565395663956739568395693957039571395723957339574395753957639577395783957939580395813958239583395843958539586395873958839589395903959139592395933959439595395963959739598395993960039601396023960339604396053960639607396083960939610396113961239613396143961539616396173961839619396203962139622396233962439625396263962739628396293963039631396323963339634396353963639637396383963939640396413964239643396443964539646396473964839649396503965139652396533965439655396563965739658396593966039661396623966339664396653966639667396683966939670396713967239673396743967539676396773967839679396803968139682396833968439685396863968739688396893969039691396923969339694396953969639697396983969939700397013970239703397043970539706397073970839709397103971139712397133971439715397163971739718397193972039721397223972339724397253972639727397283972939730397313973239733397343973539736397373973839739397403974139742397433974439745397463974739748397493975039751397523975339754397553975639757397583975939760397613976239763397643976539766397673976839769397703977139772397733977439775397763977739778397793978039781397823978339784397853978639787397883978939790397913979239793397943979539796397973979839799398003980139802398033980439805398063980739808398093981039811398123981339814398153981639817398183981939820398213982239823398243982539826398273982839829398303983139832398333983439835398363983739838398393984039841398423984339844398453984639847398483984939850398513985239853398543985539856398573985839859398603986139862398633986439865398663986739868398693987039871398723987339874398753987639877398783987939880398813988239883398843988539886398873988839889398903989139892398933989439895398963989739898398993990039901399023990339904399053990639907399083990939910399113991239913399143991539916399173991839919399203992139922399233992439925399263992739928399293993039931399323993339934399353993639937399383993939940399413994239943399443994539946399473994839949399503995139952399533995439955399563995739958399593996039961399623996339964399653996639967399683996939970399713997239973399743997539976399773997839979399803998139982399833998439985399863998739988399893999039991399923999339994399953999639997399983999940000400014000240003400044000540006400074000840009400104001140012400134001440015400164001740018400194002040021400224002340024400254002640027400284002940030400314003240033400344003540036400374003840039400404004140042400434004440045400464004740048400494005040051400524005340054400554005640057400584005940060400614006240063400644006540066400674006840069400704007140072400734007440075400764007740078400794008040081400824008340084400854008640087400884008940090400914009240093400944009540096400974009840099401004010140102401034010440105401064010740108401094011040111401124011340114401154011640117401184011940120401214012240123401244012540126401274012840129401304013140132401334013440135401364013740138401394014040141401424014340144401454014640147401484014940150401514015240153401544015540156401574015840159401604016140162401634016440165401664016740168401694017040171401724017340174401754017640177401784017940180401814018240183401844018540186401874018840189401904019140192401934019440195401964019740198401994020040201402024020340204402054020640207402084020940210402114021240213402144021540216402174021840219402204022140222402234022440225402264022740228402294023040231402324023340234402354023640237402384023940240402414024240243402444024540246402474024840249402504025140252402534025440255402564025740258402594026040261402624026340264402654026640267402684026940270402714027240273402744027540276402774027840279402804028140282402834028440285402864028740288402894029040291402924029340294402954029640297402984029940300403014030240303403044030540306403074030840309403104031140312403134031440315403164031740318403194032040321403224032340324403254032640327403284032940330403314033240333403344033540336403374033840339403404034140342403434034440345403464034740348403494035040351403524035340354403554035640357403584035940360403614036240363403644036540366403674036840369403704037140372403734037440375403764037740378403794038040381403824038340384403854038640387403884038940390403914039240393403944039540396403974039840399404004040140402404034040440405404064040740408404094041040411404124041340414404154041640417404184041940420404214042240423404244042540426404274042840429404304043140432404334043440435404364043740438404394044040441404424044340444404454044640447404484044940450404514045240453404544045540456404574045840459404604046140462404634046440465404664046740468404694047040471404724047340474404754047640477404784047940480404814048240483404844048540486404874048840489404904049140492404934049440495404964049740498404994050040501405024050340504405054050640507405084050940510405114051240513405144051540516405174051840519405204052140522405234052440525405264052740528405294053040531405324053340534405354053640537405384053940540405414054240543405444054540546405474054840549405504055140552405534055440555405564055740558405594056040561405624056340564405654056640567405684056940570405714057240573405744057540576405774057840579405804058140582405834058440585405864058740588405894059040591405924059340594405954059640597405984059940600406014060240603406044060540606406074060840609406104061140612406134061440615406164061740618406194062040621406224062340624406254062640627406284062940630406314063240633406344063540636406374063840639406404064140642406434064440645406464064740648406494065040651406524065340654406554065640657406584065940660406614066240663406644066540666406674066840669406704067140672406734067440675406764067740678406794068040681406824068340684406854068640687406884068940690406914069240693406944069540696406974069840699407004070140702407034070440705407064070740708407094071040711407124071340714407154071640717407184071940720407214072240723407244072540726407274072840729407304073140732407334073440735407364073740738407394074040741407424074340744407454074640747407484074940750407514075240753407544075540756407574075840759407604076140762407634076440765407664076740768407694077040771407724077340774407754077640777407784077940780407814078240783407844078540786407874078840789407904079140792407934079440795407964079740798407994080040801408024080340804408054080640807408084080940810408114081240813408144081540816408174081840819408204082140822408234082440825408264082740828408294083040831408324083340834408354083640837408384083940840408414084240843408444084540846408474084840849408504085140852408534085440855408564085740858408594086040861408624086340864408654086640867408684086940870408714087240873408744087540876408774087840879408804088140882408834088440885408864088740888408894089040891408924089340894408954089640897408984089940900409014090240903409044090540906409074090840909409104091140912409134091440915409164091740918409194092040921409224092340924409254092640927409284092940930409314093240933409344093540936409374093840939409404094140942409434094440945409464094740948409494095040951409524095340954409554095640957409584095940960409614096240963409644096540966409674096840969409704097140972409734097440975409764097740978409794098040981409824098340984409854098640987409884098940990409914099240993409944099540996409974099840999410004100141002410034100441005410064100741008410094101041011410124101341014410154101641017410184101941020410214102241023410244102541026410274102841029410304103141032410334103441035410364103741038410394104041041410424104341044410454104641047410484104941050410514105241053410544105541056410574105841059410604106141062410634106441065410664106741068410694107041071410724107341074410754107641077410784107941080410814108241083410844108541086410874108841089410904109141092410934109441095410964109741098410994110041101411024110341104411054110641107411084110941110411114111241113411144111541116411174111841119411204112141122411234112441125411264112741128411294113041131411324113341134411354113641137411384113941140411414114241143411444114541146411474114841149411504115141152411534115441155411564115741158411594116041161411624116341164411654116641167411684116941170411714117241173411744117541176411774117841179411804118141182411834118441185411864118741188411894119041191411924119341194411954119641197411984119941200412014120241203412044120541206412074120841209412104121141212412134121441215412164121741218412194122041221412224122341224412254122641227412284122941230412314123241233412344123541236412374123841239412404124141242412434124441245412464124741248412494125041251412524125341254412554125641257412584125941260412614126241263412644126541266412674126841269412704127141272412734127441275412764127741278412794128041281412824128341284412854128641287412884128941290412914129241293412944129541296412974129841299413004130141302413034130441305413064130741308413094131041311413124131341314413154131641317413184131941320413214132241323413244132541326413274132841329413304133141332413334133441335413364133741338413394134041341413424134341344413454134641347413484134941350413514135241353413544135541356413574135841359413604136141362413634136441365413664136741368413694137041371413724137341374413754137641377413784137941380413814138241383413844138541386413874138841389413904139141392413934139441395413964139741398413994140041401414024140341404414054140641407414084140941410414114141241413414144141541416414174141841419414204142141422414234142441425414264142741428414294143041431414324143341434414354143641437414384143941440414414144241443414444144541446414474144841449414504145141452414534145441455414564145741458414594146041461414624146341464414654146641467414684146941470414714147241473414744147541476414774147841479414804148141482414834148441485414864148741488414894149041491414924149341494414954149641497414984149941500415014150241503415044150541506415074150841509415104151141512415134151441515415164151741518415194152041521415224152341524415254152641527415284152941530415314153241533415344153541536415374153841539415404154141542415434154441545415464154741548415494155041551415524155341554415554155641557415584155941560415614156241563415644156541566415674156841569415704157141572415734157441575415764157741578415794158041581415824158341584415854158641587415884158941590415914159241593415944159541596415974159841599416004160141602416034160441605416064160741608416094161041611416124161341614416154161641617416184161941620416214162241623416244162541626416274162841629416304163141632416334163441635416364163741638416394164041641416424164341644416454164641647416484164941650416514165241653416544165541656416574165841659416604166141662416634166441665416664166741668416694167041671416724167341674416754167641677416784167941680416814168241683416844168541686416874168841689416904169141692416934169441695416964169741698416994170041701417024170341704417054170641707417084170941710417114171241713417144171541716417174171841719417204172141722417234172441725417264172741728417294173041731417324173341734417354173641737417384173941740417414174241743417444174541746417474174841749417504175141752417534175441755417564175741758417594176041761417624176341764417654176641767417684176941770417714177241773417744177541776417774177841779417804178141782417834178441785417864178741788417894179041791417924179341794417954179641797417984179941800418014180241803418044180541806418074180841809418104181141812418134181441815418164181741818418194182041821418224182341824418254182641827418284182941830418314183241833418344183541836418374183841839418404184141842418434184441845418464184741848418494185041851418524185341854418554185641857418584185941860418614186241863418644186541866418674186841869418704187141872418734187441875418764187741878418794188041881418824188341884418854188641887418884188941890418914189241893418944189541896418974189841899419004190141902419034190441905419064190741908419094191041911419124191341914419154191641917419184191941920419214192241923419244192541926419274192841929419304193141932419334193441935419364193741938419394194041941419424194341944419454194641947419484194941950419514195241953419544195541956419574195841959419604196141962419634196441965419664196741968419694197041971419724197341974419754197641977419784197941980419814198241983419844198541986419874198841989419904199141992419934199441995419964199741998419994200042001420024200342004420054200642007420084200942010420114201242013420144201542016420174201842019420204202142022420234202442025420264202742028420294203042031420324203342034420354203642037420384203942040420414204242043420444204542046420474204842049420504205142052420534205442055420564205742058420594206042061420624206342064420654206642067420684206942070420714207242073420744207542076420774207842079420804208142082420834208442085420864208742088420894209042091420924209342094420954209642097420984209942100421014210242103421044210542106421074210842109421104211142112421134211442115421164211742118421194212042121421224212342124421254212642127421284212942130421314213242133421344213542136421374213842139421404214142142421434214442145421464214742148421494215042151421524215342154421554215642157421584215942160421614216242163421644216542166421674216842169421704217142172421734217442175421764217742178421794218042181421824218342184421854218642187421884218942190421914219242193421944219542196421974219842199422004220142202422034220442205422064220742208422094221042211422124221342214422154221642217422184221942220422214222242223422244222542226422274222842229422304223142232422334223442235422364223742238422394224042241422424224342244422454224642247422484224942250422514225242253422544225542256422574225842259422604226142262422634226442265422664226742268422694227042271422724227342274422754227642277422784227942280422814228242283422844228542286422874228842289422904229142292422934229442295422964229742298422994230042301423024230342304423054230642307423084230942310423114231242313423144231542316423174231842319423204232142322423234232442325423264232742328423294233042331423324233342334423354233642337423384233942340423414234242343423444234542346423474234842349423504235142352423534235442355423564235742358423594236042361423624236342364423654236642367423684236942370423714237242373423744237542376423774237842379423804238142382423834238442385423864238742388423894239042391423924239342394423954239642397423984239942400424014240242403424044240542406424074240842409424104241142412424134241442415424164241742418424194242042421424224242342424424254242642427424284242942430424314243242433424344243542436424374243842439424404244142442424434244442445424464244742448424494245042451424524245342454424554245642457424584245942460424614246242463424644246542466424674246842469424704247142472424734247442475424764247742478424794248042481424824248342484424854248642487424884248942490424914249242493424944249542496424974249842499425004250142502425034250442505425064250742508425094251042511425124251342514425154251642517425184251942520425214252242523425244252542526425274252842529425304253142532425334253442535425364253742538425394254042541425424254342544425454254642547425484254942550425514255242553425544255542556425574255842559425604256142562425634256442565425664256742568425694257042571425724257342574425754257642577425784257942580425814258242583425844258542586425874258842589425904259142592425934259442595425964259742598425994260042601426024260342604426054260642607426084260942610426114261242613426144261542616426174261842619426204262142622426234262442625426264262742628426294263042631426324263342634426354263642637426384263942640426414264242643426444264542646426474264842649426504265142652426534265442655426564265742658426594266042661426624266342664426654266642667426684266942670426714267242673426744267542676426774267842679426804268142682426834268442685426864268742688426894269042691426924269342694426954269642697426984269942700427014270242703427044270542706427074270842709427104271142712427134271442715427164271742718427194272042721427224272342724427254272642727427284272942730427314273242733427344273542736427374273842739427404274142742427434274442745427464274742748427494275042751427524275342754427554275642757427584275942760427614276242763427644276542766427674276842769427704277142772427734277442775427764277742778427794278042781427824278342784427854278642787427884278942790427914279242793427944279542796427974279842799428004280142802428034280442805428064280742808428094281042811428124281342814428154281642817428184281942820428214282242823428244282542826428274282842829428304283142832428334283442835428364283742838428394284042841428424284342844428454284642847428484284942850428514285242853428544285542856428574285842859428604286142862428634286442865428664286742868428694287042871428724287342874428754287642877428784287942880428814288242883428844288542886428874288842889428904289142892428934289442895428964289742898428994290042901429024290342904429054290642907429084290942910429114291242913429144291542916429174291842919429204292142922429234292442925429264292742928429294293042931429324293342934429354293642937429384293942940429414294242943429444294542946429474294842949429504295142952429534295442955429564295742958429594296042961429624296342964429654296642967429684296942970429714297242973429744297542976429774297842979429804298142982429834298442985429864298742988429894299042991429924299342994429954299642997429984299943000430014300243003430044300543006430074300843009430104301143012430134301443015430164301743018430194302043021430224302343024430254302643027430284302943030430314303243033430344303543036430374303843039430404304143042430434304443045430464304743048430494305043051430524305343054430554305643057430584305943060430614306243063430644306543066430674306843069430704307143072430734307443075430764307743078430794308043081430824308343084430854308643087430884308943090430914309243093430944309543096430974309843099431004310143102431034310443105431064310743108431094311043111431124311343114431154311643117431184311943120431214312243123431244312543126431274312843129431304313143132431334313443135431364313743138431394314043141431424314343144431454314643147431484314943150431514315243153431544315543156431574315843159431604316143162431634316443165431664316743168431694317043171431724317343174431754317643177431784317943180431814318243183431844318543186431874318843189431904319143192431934319443195431964319743198431994320043201432024320343204432054320643207432084320943210432114321243213432144321543216432174321843219432204322143222432234322443225432264322743228432294323043231432324323343234432354323643237432384323943240432414324243243432444324543246432474324843249432504325143252432534325443255432564325743258432594326043261432624326343264432654326643267432684326943270432714327243273432744327543276432774327843279432804328143282432834328443285432864328743288432894329043291432924329343294432954329643297432984329943300433014330243303433044330543306433074330843309433104331143312433134331443315433164331743318433194332043321433224332343324433254332643327433284332943330433314333243333433344333543336433374333843339433404334143342433434334443345433464334743348433494335043351433524335343354433554335643357433584335943360433614336243363433644336543366433674336843369433704337143372433734337443375433764337743378433794338043381433824338343384433854338643387433884338943390433914339243393433944339543396433974339843399434004340143402434034340443405434064340743408434094341043411434124341343414434154341643417434184341943420434214342243423434244342543426434274342843429434304343143432434334343443435434364343743438434394344043441434424344343444434454344643447434484344943450434514345243453434544345543456434574345843459434604346143462434634346443465434664346743468434694347043471434724347343474434754347643477434784347943480434814348243483434844348543486434874348843489434904349143492434934349443495434964349743498434994350043501435024350343504435054350643507435084350943510435114351243513435144351543516435174351843519435204352143522435234352443525435264352743528435294353043531435324353343534435354353643537435384353943540435414354243543435444354543546435474354843549435504355143552435534355443555435564355743558435594356043561435624356343564435654356643567435684356943570435714357243573435744357543576435774357843579435804358143582435834358443585435864358743588435894359043591435924359343594435954359643597435984359943600436014360243603436044360543606436074360843609436104361143612436134361443615436164361743618436194362043621436224362343624436254362643627436284362943630436314363243633436344363543636436374363843639436404364143642436434364443645436464364743648436494365043651436524365343654436554365643657436584365943660436614366243663436644366543666436674366843669436704367143672436734367443675436764367743678436794368043681436824368343684436854368643687436884368943690436914369243693436944369543696436974369843699437004370143702437034370443705437064370743708437094371043711437124371343714437154371643717437184371943720437214372243723437244372543726437274372843729437304373143732437334373443735437364373743738437394374043741437424374343744437454374643747437484374943750437514375243753437544375543756437574375843759437604376143762437634376443765437664376743768437694377043771437724377343774437754377643777437784377943780437814378243783437844378543786437874378843789437904379143792437934379443795437964379743798437994380043801438024380343804438054380643807438084380943810438114381243813438144381543816438174381843819438204382143822438234382443825438264382743828438294383043831438324383343834438354383643837438384383943840438414384243843438444384543846438474384843849438504385143852438534385443855438564385743858438594386043861438624386343864438654386643867438684386943870438714387243873438744387543876438774387843879438804388143882438834388443885438864388743888438894389043891438924389343894438954389643897438984389943900439014390243903439044390543906439074390843909439104391143912439134391443915439164391743918439194392043921439224392343924439254392643927439284392943930439314393243933439344393543936439374393843939439404394143942439434394443945439464394743948439494395043951439524395343954439554395643957439584395943960439614396243963439644396543966439674396843969439704397143972439734397443975439764397743978439794398043981439824398343984439854398643987439884398943990439914399243993439944399543996439974399843999440004400144002440034400444005440064400744008440094401044011440124401344014440154401644017440184401944020440214402244023440244402544026440274402844029440304403144032440334403444035440364403744038440394404044041440424404344044440454404644047440484404944050440514405244053440544405544056440574405844059440604406144062440634406444065440664406744068440694407044071440724407344074440754407644077440784407944080440814408244083440844408544086440874408844089440904409144092440934409444095440964409744098440994410044101441024410344104441054410644107441084410944110441114411244113441144411544116441174411844119441204412144122441234412444125441264412744128441294413044131441324413344134441354413644137441384413944140441414414244143441444414544146441474414844149441504415144152441534415444155441564415744158441594416044161441624416344164441654416644167441684416944170441714417244173441744417544176441774417844179441804418144182441834418444185441864418744188441894419044191441924419344194441954419644197441984419944200442014420244203442044420544206442074420844209442104421144212442134421444215442164421744218442194422044221442224422344224442254422644227442284422944230442314423244233442344423544236442374423844239442404424144242442434424444245442464424744248442494425044251442524425344254442554425644257442584425944260442614426244263442644426544266442674426844269442704427144272442734427444275442764427744278442794428044281442824428344284442854428644287442884428944290442914429244293442944429544296442974429844299443004430144302443034430444305443064430744308443094431044311443124431344314443154431644317443184431944320443214432244323443244432544326443274432844329443304433144332443334433444335443364433744338443394434044341443424434344344443454434644347443484434944350443514435244353443544435544356443574435844359443604436144362443634436444365443664436744368443694437044371443724437344374443754437644377443784437944380443814438244383443844438544386443874438844389443904439144392443934439444395443964439744398443994440044401444024440344404444054440644407444084440944410444114441244413444144441544416444174441844419444204442144422444234442444425444264442744428444294443044431444324443344434444354443644437444384443944440444414444244443444444444544446444474444844449444504445144452444534445444455444564445744458444594446044461444624446344464444654446644467444684446944470444714447244473444744447544476444774447844479444804448144482444834448444485444864448744488444894449044491444924449344494444954449644497444984449944500445014450244503445044450544506445074450844509445104451144512445134451444515445164451744518445194452044521445224452344524445254452644527445284452944530445314453244533445344453544536445374453844539445404454144542445434454444545445464454744548445494455044551445524455344554445554455644557445584455944560445614456244563445644456544566445674456844569445704457144572445734457444575445764457744578445794458044581445824458344584445854458644587445884458944590445914459244593445944459544596445974459844599446004460144602446034460444605446064460744608446094461044611446124461344614446154461644617446184461944620446214462244623446244462544626446274462844629446304463144632446334463444635446364463744638446394464044641446424464344644446454464644647446484464944650446514465244653446544465544656446574465844659446604466144662446634466444665446664466744668446694467044671446724467344674446754467644677446784467944680446814468244683446844468544686446874468844689446904469144692446934469444695446964469744698446994470044701447024470344704447054470644707447084470944710447114471244713447144471544716447174471844719447204472144722447234472444725447264472744728447294473044731447324473344734447354473644737447384473944740447414474244743447444474544746447474474844749447504475144752447534475444755447564475744758447594476044761447624476344764447654476644767447684476944770447714477244773447744477544776447774477844779447804478144782447834478444785447864478744788447894479044791447924479344794447954479644797447984479944800448014480244803448044480544806448074480844809448104481144812448134481444815448164481744818448194482044821448224482344824448254482644827448284482944830448314483244833448344483544836448374483844839448404484144842448434484444845448464484744848448494485044851448524485344854448554485644857448584485944860448614486244863448644486544866448674486844869448704487144872448734487444875448764487744878448794488044881448824488344884448854488644887448884488944890448914489244893448944489544896448974489844899449004490144902449034490444905449064490744908449094491044911449124491344914449154491644917449184491944920449214492244923449244492544926449274492844929449304493144932449334493444935449364493744938449394494044941449424494344944449454494644947449484494944950449514495244953449544495544956449574495844959449604496144962449634496444965449664496744968449694497044971449724497344974449754497644977449784497944980449814498244983449844498544986449874498844989449904499144992449934499444995449964499744998449994500045001450024500345004450054500645007450084500945010450114501245013450144501545016450174501845019450204502145022450234502445025450264502745028450294503045031450324503345034450354503645037450384503945040450414504245043450444504545046450474504845049450504505145052450534505445055450564505745058450594506045061450624506345064450654506645067450684506945070450714507245073450744507545076450774507845079450804508145082450834508445085450864508745088450894509045091450924509345094450954509645097450984509945100451014510245103451044510545106451074510845109451104511145112451134511445115451164511745118451194512045121451224512345124451254512645127451284512945130451314513245133451344513545136451374513845139451404514145142451434514445145451464514745148451494515045151451524515345154451554515645157451584515945160451614516245163451644516545166451674516845169451704517145172451734517445175451764517745178451794518045181451824518345184451854518645187451884518945190451914519245193451944519545196451974519845199452004520145202452034520445205452064520745208452094521045211452124521345214452154521645217452184521945220452214522245223452244522545226452274522845229452304523145232452334523445235452364523745238452394524045241452424524345244452454524645247452484524945250452514525245253452544525545256452574525845259452604526145262452634526445265452664526745268452694527045271452724527345274452754527645277452784527945280452814528245283452844528545286452874528845289452904529145292452934529445295452964529745298452994530045301453024530345304453054530645307453084530945310453114531245313453144531545316453174531845319453204532145322453234532445325453264532745328453294533045331453324533345334453354533645337453384533945340453414534245343453444534545346453474534845349453504535145352453534535445355453564535745358453594536045361453624536345364453654536645367453684536945370453714537245373453744537545376453774537845379453804538145382453834538445385453864538745388453894539045391453924539345394453954539645397453984539945400454014540245403454044540545406454074540845409454104541145412454134541445415454164541745418454194542045421454224542345424454254542645427454284542945430454314543245433454344543545436454374543845439454404544145442454434544445445454464544745448454494545045451454524545345454454554545645457454584545945460454614546245463454644546545466454674546845469454704547145472454734547445475454764547745478454794548045481454824548345484454854548645487454884548945490454914549245493454944549545496454974549845499455004550145502455034550445505455064550745508455094551045511455124551345514455154551645517455184551945520455214552245523455244552545526455274552845529455304553145532455334553445535455364553745538455394554045541455424554345544455454554645547455484554945550455514555245553455544555545556455574555845559455604556145562455634556445565455664556745568455694557045571455724557345574455754557645577455784557945580455814558245583455844558545586455874558845589455904559145592455934559445595455964559745598455994560045601456024560345604456054560645607456084560945610456114561245613456144561545616456174561845619456204562145622456234562445625456264562745628456294563045631456324563345634456354563645637456384563945640456414564245643456444564545646456474564845649456504565145652456534565445655456564565745658456594566045661456624566345664456654566645667456684566945670456714567245673456744567545676456774567845679456804568145682456834568445685456864568745688456894569045691456924569345694456954569645697456984569945700457014570245703457044570545706457074570845709457104571145712457134571445715457164571745718457194572045721457224572345724457254572645727457284572945730457314573245733457344573545736457374573845739457404574145742457434574445745457464574745748457494575045751457524575345754457554575645757457584575945760457614576245763457644576545766457674576845769457704577145772457734577445775457764577745778457794578045781457824578345784457854578645787457884578945790457914579245793457944579545796457974579845799458004580145802458034580445805458064580745808458094581045811458124581345814458154581645817458184581945820458214582245823458244582545826458274582845829458304583145832458334583445835458364583745838458394584045841458424584345844458454584645847458484584945850458514585245853458544585545856458574585845859458604586145862458634586445865458664586745868458694587045871458724587345874458754587645877458784587945880458814588245883458844588545886458874588845889458904589145892458934589445895458964589745898458994590045901459024590345904459054590645907459084590945910459114591245913459144591545916459174591845919459204592145922459234592445925459264592745928459294593045931459324593345934459354593645937459384593945940459414594245943459444594545946459474594845949459504595145952459534595445955459564595745958459594596045961459624596345964459654596645967459684596945970459714597245973459744597545976459774597845979459804598145982459834598445985459864598745988459894599045991459924599345994459954599645997459984599946000460014600246003460044600546006460074600846009460104601146012460134601446015460164601746018460194602046021460224602346024460254602646027460284602946030460314603246033460344603546036460374603846039460404604146042460434604446045460464604746048460494605046051460524605346054460554605646057460584605946060460614606246063460644606546066460674606846069460704607146072460734607446075460764607746078460794608046081460824608346084460854608646087460884608946090460914609246093460944609546096460974609846099461004610146102461034610446105461064610746108461094611046111461124611346114461154611646117461184611946120461214612246123461244612546126461274612846129461304613146132461334613446135461364613746138461394614046141461424614346144461454614646147461484614946150461514615246153461544615546156461574615846159461604616146162461634616446165461664616746168461694617046171461724617346174461754617646177461784617946180461814618246183461844618546186461874618846189461904619146192461934619446195461964619746198461994620046201462024620346204462054620646207462084620946210462114621246213462144621546216462174621846219462204622146222462234622446225462264622746228462294623046231462324623346234462354623646237462384623946240462414624246243462444624546246462474624846249462504625146252462534625446255462564625746258462594626046261462624626346264462654626646267462684626946270462714627246273462744627546276462774627846279462804628146282462834628446285462864628746288462894629046291462924629346294462954629646297462984629946300463014630246303463044630546306463074630846309463104631146312463134631446315463164631746318463194632046321463224632346324463254632646327463284632946330463314633246333463344633546336463374633846339463404634146342463434634446345463464634746348463494635046351463524635346354463554635646357463584635946360463614636246363463644636546366463674636846369463704637146372463734637446375463764637746378463794638046381463824638346384463854638646387463884638946390463914639246393463944639546396463974639846399464004640146402464034640446405464064640746408464094641046411464124641346414464154641646417464184641946420464214642246423464244642546426464274642846429464304643146432464334643446435464364643746438464394644046441464424644346444464454644646447464484644946450464514645246453464544645546456464574645846459464604646146462464634646446465464664646746468464694647046471464724647346474464754647646477464784647946480464814648246483464844648546486464874648846489464904649146492464934649446495464964649746498464994650046501465024650346504465054650646507465084650946510465114651246513465144651546516465174651846519465204652146522465234652446525465264652746528465294653046531465324653346534465354653646537465384653946540465414654246543465444654546546465474654846549465504655146552465534655446555465564655746558465594656046561465624656346564465654656646567465684656946570465714657246573465744657546576465774657846579465804658146582465834658446585465864658746588465894659046591465924659346594465954659646597465984659946600466014660246603466044660546606466074660846609466104661146612466134661446615466164661746618466194662046621466224662346624466254662646627466284662946630466314663246633466344663546636466374663846639466404664146642466434664446645466464664746648466494665046651466524665346654466554665646657466584665946660466614666246663466644666546666466674666846669466704667146672466734667446675466764667746678466794668046681466824668346684466854668646687466884668946690466914669246693466944669546696466974669846699467004670146702467034670446705467064670746708467094671046711467124671346714467154671646717467184671946720467214672246723467244672546726467274672846729467304673146732467334673446735467364673746738467394674046741467424674346744467454674646747467484674946750467514675246753467544675546756467574675846759467604676146762467634676446765467664676746768467694677046771467724677346774467754677646777467784677946780467814678246783467844678546786467874678846789467904679146792467934679446795467964679746798467994680046801468024680346804468054680646807468084680946810468114681246813468144681546816468174681846819468204682146822468234682446825468264682746828468294683046831468324683346834468354683646837468384683946840468414684246843468444684546846468474684846849468504685146852468534685446855468564685746858468594686046861468624686346864468654686646867468684686946870468714687246873468744687546876468774687846879468804688146882468834688446885468864688746888468894689046891468924689346894468954689646897468984689946900469014690246903469044690546906469074690846909469104691146912469134691446915469164691746918469194692046921469224692346924469254692646927469284692946930469314693246933469344693546936469374693846939469404694146942469434694446945469464694746948469494695046951469524695346954469554695646957469584695946960469614696246963469644696546966469674696846969469704697146972469734697446975469764697746978469794698046981469824698346984469854698646987469884698946990469914699246993469944699546996469974699846999470004700147002470034700447005470064700747008470094701047011470124701347014470154701647017470184701947020470214702247023470244702547026470274702847029470304703147032470334703447035470364703747038470394704047041470424704347044470454704647047470484704947050470514705247053470544705547056470574705847059470604706147062470634706447065470664706747068470694707047071470724707347074470754707647077470784707947080470814708247083470844708547086470874708847089470904709147092470934709447095470964709747098470994710047101471024710347104471054710647107471084710947110471114711247113471144711547116471174711847119471204712147122471234712447125471264712747128471294713047131471324713347134471354713647137471384713947140471414714247143471444714547146471474714847149471504715147152471534715447155471564715747158471594716047161471624716347164471654716647167471684716947170471714717247173471744717547176471774717847179471804718147182471834718447185471864718747188471894719047191471924719347194471954719647197471984719947200472014720247203472044720547206472074720847209472104721147212472134721447215472164721747218472194722047221472224722347224472254722647227472284722947230472314723247233472344723547236472374723847239472404724147242472434724447245472464724747248472494725047251472524725347254472554725647257472584725947260472614726247263472644726547266472674726847269472704727147272472734727447275472764727747278472794728047281472824728347284472854728647287472884728947290472914729247293472944729547296472974729847299473004730147302473034730447305473064730747308473094731047311473124731347314473154731647317473184731947320473214732247323473244732547326473274732847329473304733147332473334733447335473364733747338473394734047341473424734347344473454734647347473484734947350473514735247353473544735547356473574735847359473604736147362473634736447365473664736747368473694737047371473724737347374473754737647377473784737947380473814738247383473844738547386473874738847389473904739147392473934739447395473964739747398473994740047401474024740347404474054740647407474084740947410474114741247413474144741547416474174741847419474204742147422474234742447425474264742747428474294743047431474324743347434474354743647437474384743947440474414744247443474444744547446474474744847449474504745147452474534745447455474564745747458474594746047461474624746347464474654746647467474684746947470474714747247473474744747547476474774747847479474804748147482474834748447485474864748747488474894749047491474924749347494474954749647497474984749947500475014750247503475044750547506475074750847509475104751147512475134751447515475164751747518475194752047521475224752347524475254752647527475284752947530475314753247533475344753547536475374753847539475404754147542475434754447545475464754747548475494755047551475524755347554475554755647557475584755947560475614756247563475644756547566475674756847569475704757147572475734757447575475764757747578475794758047581475824758347584475854758647587475884758947590475914759247593475944759547596475974759847599476004760147602476034760447605476064760747608476094761047611476124761347614476154761647617476184761947620476214762247623476244762547626476274762847629476304763147632476334763447635476364763747638476394764047641476424764347644476454764647647476484764947650476514765247653476544765547656476574765847659476604766147662476634766447665476664766747668476694767047671476724767347674476754767647677476784767947680476814768247683476844768547686476874768847689476904769147692476934769447695476964769747698476994770047701477024770347704477054770647707477084770947710477114771247713477144771547716477174771847719477204772147722477234772447725477264772747728477294773047731477324773347734477354773647737477384773947740477414774247743477444774547746477474774847749477504775147752477534775447755477564775747758477594776047761477624776347764477654776647767477684776947770477714777247773477744777547776477774777847779477804778147782477834778447785477864778747788477894779047791477924779347794477954779647797477984779947800478014780247803478044780547806478074780847809478104781147812478134781447815478164781747818478194782047821478224782347824478254782647827478284782947830478314783247833478344783547836478374783847839478404784147842478434784447845478464784747848478494785047851478524785347854478554785647857478584785947860478614786247863478644786547866478674786847869478704787147872478734787447875478764787747878478794788047881478824788347884478854788647887478884788947890478914789247893478944789547896478974789847899479004790147902479034790447905479064790747908479094791047911479124791347914479154791647917479184791947920479214792247923479244792547926479274792847929479304793147932479334793447935479364793747938479394794047941479424794347944479454794647947479484794947950479514795247953479544795547956479574795847959479604796147962479634796447965479664796747968479694797047971479724797347974479754797647977479784797947980479814798247983479844798547986479874798847989479904799147992479934799447995479964799747998479994800048001480024800348004480054800648007480084800948010480114801248013480144801548016480174801848019480204802148022480234802448025480264802748028480294803048031480324803348034480354803648037480384803948040480414804248043480444804548046480474804848049480504805148052480534805448055480564805748058480594806048061480624806348064480654806648067480684806948070480714807248073480744807548076480774807848079480804808148082480834808448085480864808748088480894809048091480924809348094480954809648097480984809948100481014810248103481044810548106481074810848109481104811148112481134811448115481164811748118481194812048121481224812348124481254812648127481284812948130481314813248133481344813548136481374813848139481404814148142481434814448145481464814748148481494815048151481524815348154481554815648157481584815948160481614816248163481644816548166481674816848169481704817148172481734817448175481764817748178481794818048181481824818348184481854818648187481884818948190481914819248193481944819548196481974819848199482004820148202482034820448205482064820748208482094821048211482124821348214482154821648217482184821948220482214822248223482244822548226482274822848229482304823148232482334823448235482364823748238482394824048241482424824348244482454824648247482484824948250482514825248253482544825548256482574825848259482604826148262482634826448265482664826748268482694827048271482724827348274482754827648277482784827948280482814828248283482844828548286482874828848289482904829148292482934829448295482964829748298482994830048301483024830348304483054830648307483084830948310483114831248313483144831548316483174831848319483204832148322483234832448325483264832748328483294833048331483324833348334483354833648337483384833948340483414834248343483444834548346483474834848349483504835148352483534835448355483564835748358483594836048361483624836348364483654836648367483684836948370483714837248373483744837548376483774837848379483804838148382483834838448385483864838748388483894839048391483924839348394483954839648397483984839948400484014840248403484044840548406484074840848409484104841148412484134841448415484164841748418484194842048421484224842348424484254842648427484284842948430484314843248433484344843548436484374843848439484404844148442484434844448445484464844748448484494845048451484524845348454484554845648457484584845948460484614846248463484644846548466484674846848469484704847148472484734847448475484764847748478484794848048481484824848348484484854848648487484884848948490484914849248493484944849548496484974849848499485004850148502485034850448505485064850748508485094851048511485124851348514485154851648517485184851948520485214852248523485244852548526485274852848529485304853148532485334853448535485364853748538485394854048541485424854348544485454854648547485484854948550485514855248553485544855548556485574855848559485604856148562485634856448565485664856748568485694857048571485724857348574485754857648577485784857948580485814858248583485844858548586485874858848589485904859148592485934859448595485964859748598485994860048601486024860348604486054860648607486084860948610486114861248613486144861548616486174861848619486204862148622486234862448625486264862748628486294863048631486324863348634486354863648637486384863948640486414864248643486444864548646486474864848649486504865148652486534865448655486564865748658486594866048661486624866348664486654866648667486684866948670486714867248673486744867548676486774867848679486804868148682486834868448685486864868748688486894869048691486924869348694486954869648697486984869948700487014870248703487044870548706487074870848709487104871148712487134871448715487164871748718487194872048721487224872348724487254872648727487284872948730487314873248733487344873548736487374873848739487404874148742487434874448745487464874748748487494875048751487524875348754487554875648757487584875948760487614876248763487644876548766487674876848769487704877148772487734877448775487764877748778487794878048781487824878348784487854878648787487884878948790487914879248793487944879548796487974879848799488004880148802488034880448805488064880748808488094881048811488124881348814488154881648817488184881948820488214882248823488244882548826488274882848829488304883148832488334883448835488364883748838488394884048841488424884348844488454884648847488484884948850488514885248853488544885548856488574885848859488604886148862488634886448865488664886748868488694887048871488724887348874488754887648877488784887948880488814888248883488844888548886488874888848889488904889148892488934889448895488964889748898488994890048901489024890348904489054890648907489084890948910489114891248913489144891548916489174891848919489204892148922489234892448925489264892748928489294893048931489324893348934489354893648937489384893948940489414894248943489444894548946489474894848949489504895148952489534895448955489564895748958489594896048961489624896348964489654896648967489684896948970489714897248973489744897548976489774897848979489804898148982489834898448985489864898748988489894899048991489924899348994489954899648997489984899949000490014900249003490044900549006490074900849009490104901149012490134901449015490164901749018490194902049021490224902349024490254902649027490284902949030490314903249033490344903549036490374903849039490404904149042490434904449045490464904749048490494905049051490524905349054490554905649057490584905949060490614906249063490644906549066490674906849069490704907149072490734907449075490764907749078490794908049081490824908349084490854908649087490884908949090490914909249093490944909549096490974909849099491004910149102491034910449105491064910749108491094911049111491124911349114491154911649117491184911949120491214912249123491244912549126491274912849129491304913149132491334913449135491364913749138491394914049141491424914349144491454914649147491484914949150491514915249153491544915549156491574915849159491604916149162491634916449165491664916749168491694917049171491724917349174491754917649177491784917949180491814918249183491844918549186491874918849189491904919149192491934919449195491964919749198491994920049201492024920349204492054920649207492084920949210492114921249213492144921549216492174921849219492204922149222492234922449225492264922749228492294923049231492324923349234492354923649237492384923949240492414924249243492444924549246492474924849249492504925149252492534925449255492564925749258492594926049261492624926349264492654926649267492684926949270492714927249273492744927549276492774927849279492804928149282492834928449285492864928749288492894929049291492924929349294492954929649297492984929949300493014930249303493044930549306493074930849309493104931149312493134931449315493164931749318493194932049321493224932349324493254932649327493284932949330493314933249333493344933549336493374933849339493404934149342493434934449345493464934749348493494935049351493524935349354493554935649357493584935949360493614936249363493644936549366493674936849369493704937149372493734937449375493764937749378493794938049381493824938349384493854938649387493884938949390493914939249393493944939549396493974939849399494004940149402494034940449405494064940749408494094941049411494124941349414494154941649417494184941949420494214942249423494244942549426494274942849429494304943149432494334943449435494364943749438494394944049441494424944349444494454944649447494484944949450494514945249453494544945549456494574945849459494604946149462494634946449465494664946749468494694947049471494724947349474494754947649477494784947949480494814948249483494844948549486494874948849489494904949149492494934949449495494964949749498494994950049501495024950349504495054950649507495084950949510495114951249513495144951549516495174951849519495204952149522495234952449525495264952749528495294953049531495324953349534495354953649537495384953949540495414954249543495444954549546495474954849549495504955149552495534955449555495564955749558495594956049561495624956349564495654956649567495684956949570495714957249573495744957549576495774957849579495804958149582495834958449585495864958749588495894959049591495924959349594495954959649597495984959949600496014960249603496044960549606496074960849609496104961149612496134961449615496164961749618496194962049621496224962349624496254962649627496284962949630496314963249633496344963549636496374963849639496404964149642496434964449645496464964749648496494965049651496524965349654496554965649657496584965949660496614966249663496644966549666496674966849669496704967149672496734967449675496764967749678496794968049681496824968349684496854968649687496884968949690496914969249693496944969549696496974969849699497004970149702497034970449705497064970749708497094971049711497124971349714497154971649717497184971949720497214972249723497244972549726497274972849729497304973149732497334973449735497364973749738497394974049741497424974349744497454974649747497484974949750497514975249753497544975549756497574975849759497604976149762497634976449765497664976749768497694977049771497724977349774497754977649777497784977949780497814978249783497844978549786497874978849789497904979149792497934979449795497964979749798497994980049801498024980349804498054980649807498084980949810498114981249813498144981549816498174981849819498204982149822498234982449825498264982749828498294983049831498324983349834498354983649837498384983949840498414984249843498444984549846498474984849849498504985149852498534985449855498564985749858498594986049861498624986349864498654986649867498684986949870498714987249873498744987549876498774987849879498804988149882498834988449885498864988749888498894989049891498924989349894498954989649897498984989949900499014990249903499044990549906499074990849909499104991149912499134991449915499164991749918499194992049921499224992349924499254992649927499284992949930499314993249933499344993549936499374993849939499404994149942499434994449945499464994749948499494995049951499524995349954499554995649957499584995949960499614996249963499644996549966499674996849969499704997149972499734997449975499764997749978499794998049981499824998349984499854998649987499884998949990499914999249993499944999549996499974999849999500005000150002500035000450005500065000750008500095001050011500125001350014500155001650017500185001950020500215002250023500245002550026500275002850029500305003150032500335003450035500365003750038500395004050041500425004350044500455004650047500485004950050500515005250053500545005550056500575005850059500605006150062500635006450065500665006750068500695007050071500725007350074500755007650077500785007950080500815008250083500845008550086500875008850089500905009150092500935009450095500965009750098500995010050101501025010350104501055010650107501085010950110501115011250113501145011550116501175011850119501205012150122501235012450125501265012750128501295013050131501325013350134501355013650137501385013950140501415014250143501445014550146501475014850149501505015150152501535015450155501565015750158501595016050161501625016350164501655016650167501685016950170501715017250173501745017550176501775017850179501805018150182501835018450185501865018750188501895019050191501925019350194501955019650197501985019950200502015020250203502045020550206502075020850209502105021150212502135021450215502165021750218502195022050221502225022350224502255022650227502285022950230502315023250233502345023550236502375023850239502405024150242502435024450245502465024750248502495025050251502525025350254502555025650257502585025950260502615026250263502645026550266502675026850269502705027150272502735027450275502765027750278502795028050281502825028350284502855028650287502885028950290502915029250293502945029550296502975029850299503005030150302503035030450305503065030750308503095031050311503125031350314503155031650317503185031950320503215032250323503245032550326503275032850329503305033150332503335033450335503365033750338503395034050341503425034350344503455034650347503485034950350503515035250353503545035550356503575035850359503605036150362503635036450365503665036750368503695037050371503725037350374503755037650377503785037950380503815038250383503845038550386503875038850389503905039150392503935039450395503965039750398503995040050401504025040350404504055040650407504085040950410504115041250413504145041550416504175041850419504205042150422504235042450425504265042750428504295043050431504325043350434504355043650437504385043950440504415044250443504445044550446504475044850449504505045150452504535045450455504565045750458504595046050461504625046350464504655046650467504685046950470504715047250473504745047550476504775047850479504805048150482504835048450485504865048750488504895049050491504925049350494504955049650497504985049950500505015050250503505045050550506505075050850509505105051150512505135051450515505165051750518505195052050521505225052350524505255052650527505285052950530505315053250533505345053550536505375053850539505405054150542505435054450545505465054750548505495055050551505525055350554505555055650557505585055950560505615056250563505645056550566505675056850569505705057150572505735057450575505765057750578505795058050581505825058350584505855058650587505885058950590505915059250593505945059550596505975059850599506005060150602506035060450605506065060750608506095061050611506125061350614506155061650617506185061950620506215062250623506245062550626506275062850629506305063150632506335063450635506365063750638506395064050641506425064350644506455064650647506485064950650506515065250653506545065550656506575065850659506605066150662506635066450665506665066750668506695067050671506725067350674506755067650677506785067950680506815068250683506845068550686506875068850689506905069150692506935069450695506965069750698506995070050701507025070350704507055070650707507085070950710507115071250713507145071550716507175071850719507205072150722507235072450725507265072750728507295073050731507325073350734507355073650737507385073950740507415074250743507445074550746507475074850749507505075150752507535075450755507565075750758507595076050761507625076350764507655076650767507685076950770507715077250773507745077550776507775077850779507805078150782507835078450785507865078750788507895079050791507925079350794507955079650797507985079950800508015080250803508045080550806508075080850809508105081150812508135081450815508165081750818508195082050821508225082350824508255082650827508285082950830508315083250833508345083550836508375083850839508405084150842508435084450845508465084750848508495085050851508525085350854508555085650857508585085950860508615086250863508645086550866508675086850869508705087150872508735087450875508765087750878508795088050881508825088350884508855088650887508885088950890508915089250893508945089550896508975089850899509005090150902509035090450905509065090750908509095091050911509125091350914509155091650917509185091950920509215092250923509245092550926509275092850929509305093150932509335093450935509365093750938509395094050941509425094350944509455094650947509485094950950509515095250953509545095550956509575095850959509605096150962509635096450965509665096750968509695097050971509725097350974509755097650977509785097950980509815098250983509845098550986509875098850989509905099150992509935099450995509965099750998509995100051001510025100351004510055100651007510085100951010510115101251013510145101551016510175101851019510205102151022510235102451025510265102751028510295103051031510325103351034510355103651037510385103951040510415104251043510445104551046510475104851049510505105151052510535105451055510565105751058510595106051061510625106351064510655106651067510685106951070510715107251073510745107551076510775107851079510805108151082510835108451085510865108751088510895109051091510925109351094510955109651097510985109951100511015110251103511045110551106511075110851109511105111151112511135111451115511165111751118511195112051121511225112351124511255112651127511285112951130511315113251133511345113551136511375113851139511405114151142511435114451145511465114751148511495115051151511525115351154511555115651157511585115951160511615116251163511645116551166511675116851169511705117151172511735117451175511765117751178511795118051181511825118351184511855118651187511885118951190511915119251193511945119551196511975119851199512005120151202512035120451205512065120751208512095121051211512125121351214512155121651217512185121951220512215122251223512245122551226512275122851229512305123151232512335123451235512365123751238512395124051241512425124351244512455124651247512485124951250512515125251253512545125551256512575125851259512605126151262512635126451265512665126751268512695127051271512725127351274512755127651277512785127951280512815128251283512845128551286512875128851289512905129151292512935129451295512965129751298512995130051301513025130351304513055130651307513085130951310513115131251313513145131551316513175131851319513205132151322513235132451325513265132751328513295133051331513325133351334513355133651337513385133951340513415134251343513445134551346513475134851349513505135151352513535135451355513565135751358513595136051361513625136351364513655136651367513685136951370513715137251373513745137551376513775137851379513805138151382513835138451385513865138751388513895139051391513925139351394513955139651397513985139951400514015140251403514045140551406514075140851409514105141151412514135141451415514165141751418514195142051421514225142351424514255142651427514285142951430514315143251433514345143551436514375143851439514405144151442514435144451445514465144751448514495145051451514525145351454514555145651457514585145951460514615146251463514645146551466514675146851469514705147151472514735147451475514765147751478514795148051481514825148351484514855148651487514885148951490514915149251493514945149551496514975149851499515005150151502515035150451505515065150751508515095151051511515125151351514515155151651517515185151951520515215152251523515245152551526515275152851529515305153151532515335153451535515365153751538515395154051541515425154351544515455154651547515485154951550515515155251553515545155551556515575155851559515605156151562515635156451565515665156751568515695157051571515725157351574515755157651577515785157951580515815158251583515845158551586515875158851589515905159151592515935159451595515965159751598515995160051601516025160351604516055160651607516085160951610516115161251613516145161551616516175161851619516205162151622516235162451625516265162751628516295163051631516325163351634516355163651637516385163951640516415164251643516445164551646516475164851649516505165151652516535165451655516565165751658516595166051661516625166351664516655166651667516685166951670516715167251673516745167551676516775167851679516805168151682516835168451685516865168751688516895169051691516925169351694516955169651697516985169951700517015170251703517045170551706517075170851709517105171151712517135171451715517165171751718517195172051721517225172351724517255172651727517285172951730517315173251733517345173551736517375173851739517405174151742517435174451745517465174751748517495175051751517525175351754517555175651757517585175951760517615176251763517645176551766517675176851769517705177151772517735177451775517765177751778517795178051781517825178351784517855178651787517885178951790517915179251793517945179551796517975179851799518005180151802518035180451805518065180751808518095181051811518125181351814518155181651817518185181951820518215182251823518245182551826518275182851829518305183151832518335183451835518365183751838518395184051841518425184351844518455184651847518485184951850518515185251853518545185551856518575185851859518605186151862518635186451865518665186751868518695187051871518725187351874518755187651877518785187951880518815188251883518845188551886518875188851889518905189151892518935189451895518965189751898518995190051901519025190351904519055190651907519085190951910519115191251913519145191551916519175191851919519205192151922519235192451925519265192751928519295193051931519325193351934519355193651937519385193951940519415194251943519445194551946519475194851949519505195151952519535195451955519565195751958519595196051961519625196351964519655196651967519685196951970519715197251973519745197551976519775197851979519805198151982519835198451985519865198751988519895199051991519925199351994519955199651997519985199952000520015200252003520045200552006520075200852009520105201152012520135201452015520165201752018520195202052021520225202352024520255202652027520285202952030520315203252033520345203552036520375203852039520405204152042520435204452045520465204752048520495205052051520525205352054520555205652057520585205952060520615206252063520645206552066520675206852069520705207152072520735207452075520765207752078520795208052081520825208352084520855208652087520885208952090520915209252093520945209552096520975209852099521005210152102521035210452105521065210752108521095211052111521125211352114521155211652117521185211952120521215212252123521245212552126521275212852129521305213152132521335213452135521365213752138521395214052141521425214352144521455214652147521485214952150521515215252153521545215552156521575215852159521605216152162521635216452165521665216752168521695217052171521725217352174521755217652177521785217952180521815218252183521845218552186521875218852189521905219152192521935219452195521965219752198521995220052201522025220352204522055220652207522085220952210522115221252213522145221552216522175221852219522205222152222522235222452225522265222752228522295223052231522325223352234522355223652237522385223952240522415224252243522445224552246522475224852249522505225152252522535225452255522565225752258522595226052261522625226352264522655226652267522685226952270522715227252273522745227552276522775227852279522805228152282522835228452285522865228752288522895229052291522925229352294522955229652297522985229952300523015230252303523045230552306523075230852309523105231152312523135231452315523165231752318523195232052321523225232352324523255232652327523285232952330523315233252333523345233552336523375233852339523405234152342523435234452345523465234752348523495235052351523525235352354523555235652357523585235952360523615236252363523645236552366523675236852369523705237152372523735237452375523765237752378523795238052381523825238352384523855238652387523885238952390523915239252393523945239552396523975239852399524005240152402524035240452405524065240752408524095241052411524125241352414524155241652417524185241952420524215242252423524245242552426524275242852429524305243152432524335243452435524365243752438524395244052441524425244352444524455244652447524485244952450524515245252453524545245552456524575245852459524605246152462524635246452465524665246752468524695247052471524725247352474524755247652477524785247952480524815248252483524845248552486524875248852489524905249152492524935249452495524965249752498524995250052501525025250352504525055250652507525085250952510525115251252513525145251552516525175251852519525205252152522525235252452525525265252752528525295253052531525325253352534525355253652537525385253952540525415254252543525445254552546525475254852549525505255152552525535255452555525565255752558525595256052561525625256352564525655256652567525685256952570525715257252573525745257552576525775257852579525805258152582525835258452585525865258752588525895259052591525925259352594525955259652597525985259952600526015260252603526045260552606526075260852609526105261152612526135261452615526165261752618526195262052621526225262352624526255262652627526285262952630526315263252633526345263552636526375263852639526405264152642526435264452645526465264752648526495265052651526525265352654526555265652657526585265952660526615266252663526645266552666526675266852669526705267152672526735267452675526765267752678526795268052681526825268352684526855268652687526885268952690526915269252693526945269552696526975269852699527005270152702527035270452705527065270752708527095271052711527125271352714527155271652717527185271952720527215272252723527245272552726527275272852729527305273152732527335273452735527365273752738527395274052741527425274352744527455274652747527485274952750527515275252753527545275552756527575275852759527605276152762527635276452765527665276752768527695277052771527725277352774527755277652777527785277952780527815278252783527845278552786527875278852789527905279152792527935279452795527965279752798527995280052801528025280352804528055280652807528085280952810528115281252813528145281552816528175281852819528205282152822528235282452825528265282752828528295283052831528325283352834528355283652837528385283952840528415284252843528445284552846528475284852849528505285152852528535285452855528565285752858528595286052861528625286352864528655286652867528685286952870528715287252873528745287552876528775287852879528805288152882528835288452885528865288752888528895289052891528925289352894528955289652897528985289952900529015290252903529045290552906529075290852909529105291152912529135291452915529165291752918529195292052921529225292352924529255292652927529285292952930529315293252933529345293552936529375293852939529405294152942529435294452945529465294752948529495295052951529525295352954529555295652957529585295952960529615296252963529645296552966529675296852969529705297152972529735297452975529765297752978529795298052981529825298352984529855298652987529885298952990529915299252993529945299552996529975299852999530005300153002530035300453005530065300753008530095301053011530125301353014530155301653017530185301953020530215302253023530245302553026530275302853029530305303153032530335303453035530365303753038530395304053041530425304353044530455304653047530485304953050530515305253053530545305553056530575305853059530605306153062530635306453065530665306753068530695307053071530725307353074530755307653077530785307953080530815308253083530845308553086530875308853089530905309153092530935309453095530965309753098530995310053101531025310353104531055310653107531085310953110531115311253113531145311553116531175311853119531205312153122531235312453125531265312753128531295313053131531325313353134531355313653137531385313953140531415314253143531445314553146531475314853149531505315153152531535315453155531565315753158531595316053161531625316353164531655316653167531685316953170531715317253173531745317553176531775317853179531805318153182531835318453185531865318753188531895319053191531925319353194531955319653197531985319953200532015320253203532045320553206532075320853209532105321153212532135321453215532165321753218532195322053221532225322353224532255322653227532285322953230532315323253233532345323553236532375323853239532405324153242532435324453245532465324753248532495325053251532525325353254532555325653257532585325953260532615326253263532645326553266532675326853269532705327153272532735327453275532765327753278532795328053281532825328353284532855328653287532885328953290532915329253293532945329553296532975329853299533005330153302533035330453305533065330753308533095331053311533125331353314533155331653317533185331953320533215332253323533245332553326533275332853329533305333153332533335333453335533365333753338533395334053341533425334353344533455334653347533485334953350533515335253353533545335553356533575335853359533605336153362533635336453365533665336753368533695337053371533725337353374533755337653377533785337953380533815338253383533845338553386533875338853389533905339153392533935339453395533965339753398533995340053401534025340353404534055340653407534085340953410534115341253413534145341553416534175341853419534205342153422534235342453425534265342753428534295343053431534325343353434534355343653437534385343953440534415344253443534445344553446534475344853449534505345153452534535345453455534565345753458534595346053461534625346353464534655346653467534685346953470534715347253473534745347553476534775347853479534805348153482534835348453485534865348753488534895349053491534925349353494534955349653497534985349953500535015350253503535045350553506535075350853509535105351153512535135351453515535165351753518535195352053521535225352353524535255352653527535285352953530535315353253533535345353553536535375353853539535405354153542535435354453545535465354753548535495355053551535525355353554535555355653557535585355953560535615356253563535645356553566535675356853569535705357153572535735357453575535765357753578535795358053581535825358353584535855358653587535885358953590535915359253593535945359553596535975359853599536005360153602536035360453605536065360753608536095361053611536125361353614536155361653617536185361953620536215362253623536245362553626536275362853629536305363153632536335363453635536365363753638536395364053641536425364353644536455364653647536485364953650536515365253653536545365553656536575365853659536605366153662536635366453665536665366753668536695367053671536725367353674536755367653677536785367953680536815368253683536845368553686536875368853689536905369153692536935369453695536965369753698536995370053701537025370353704537055370653707537085370953710537115371253713537145371553716537175371853719537205372153722537235372453725537265372753728537295373053731537325373353734537355373653737537385373953740537415374253743537445374553746537475374853749537505375153752537535375453755537565375753758537595376053761537625376353764537655376653767537685376953770537715377253773537745377553776537775377853779537805378153782537835378453785537865378753788537895379053791537925379353794537955379653797537985379953800538015380253803538045380553806538075380853809538105381153812538135381453815538165381753818538195382053821538225382353824538255382653827538285382953830538315383253833538345383553836538375383853839538405384153842538435384453845538465384753848538495385053851538525385353854538555385653857538585385953860538615386253863538645386553866538675386853869538705387153872538735387453875538765387753878538795388053881538825388353884538855388653887538885388953890538915389253893538945389553896538975389853899539005390153902539035390453905539065390753908539095391053911539125391353914539155391653917539185391953920539215392253923539245392553926539275392853929539305393153932539335393453935539365393753938539395394053941539425394353944539455394653947539485394953950539515395253953539545395553956539575395853959539605396153962539635396453965539665396753968539695397053971539725397353974539755397653977539785397953980539815398253983539845398553986539875398853989539905399153992539935399453995539965399753998539995400054001540025400354004540055400654007540085400954010540115401254013540145401554016540175401854019540205402154022540235402454025540265402754028540295403054031540325403354034540355403654037540385403954040540415404254043540445404554046540475404854049540505405154052540535405454055540565405754058540595406054061540625406354064540655406654067540685406954070540715407254073540745407554076540775407854079540805408154082540835408454085540865408754088540895409054091540925409354094540955409654097540985409954100541015410254103541045410554106541075410854109541105411154112541135411454115541165411754118541195412054121541225412354124541255412654127541285412954130541315413254133541345413554136541375413854139541405414154142541435414454145541465414754148541495415054151541525415354154541555415654157541585415954160541615416254163541645416554166541675416854169541705417154172541735417454175541765417754178541795418054181541825418354184541855418654187541885418954190541915419254193541945419554196541975419854199542005420154202542035420454205542065420754208542095421054211542125421354214542155421654217542185421954220542215422254223542245422554226542275422854229542305423154232542335423454235542365423754238542395424054241542425424354244542455424654247542485424954250542515425254253542545425554256542575425854259542605426154262542635426454265542665426754268542695427054271542725427354274542755427654277542785427954280542815428254283542845428554286542875428854289542905429154292542935429454295542965429754298542995430054301543025430354304543055430654307543085430954310543115431254313543145431554316543175431854319543205432154322543235432454325543265432754328543295433054331543325433354334543355433654337543385433954340543415434254343543445434554346543475434854349543505435154352543535435454355543565435754358543595436054361543625436354364543655436654367543685436954370543715437254373543745437554376543775437854379543805438154382543835438454385543865438754388543895439054391543925439354394543955439654397543985439954400544015440254403544045440554406544075440854409544105441154412544135441454415544165441754418544195442054421544225442354424544255442654427544285442954430544315443254433544345443554436544375443854439544405444154442544435444454445544465444754448544495445054451544525445354454544555445654457544585445954460544615446254463544645446554466544675446854469544705447154472544735447454475544765447754478544795448054481544825448354484544855448654487544885448954490544915449254493544945449554496544975449854499545005450154502545035450454505545065450754508545095451054511545125451354514545155451654517545185451954520545215452254523545245452554526545275452854529545305453154532545335453454535545365453754538545395454054541545425454354544545455454654547545485454954550545515455254553545545455554556545575455854559545605456154562545635456454565545665456754568545695457054571545725457354574545755457654577545785457954580545815458254583545845458554586545875458854589545905459154592545935459454595545965459754598545995460054601546025460354604546055460654607546085460954610546115461254613546145461554616546175461854619546205462154622546235462454625546265462754628546295463054631546325463354634546355463654637546385463954640546415464254643546445464554646546475464854649546505465154652546535465454655546565465754658546595466054661546625466354664546655466654667546685466954670546715467254673546745467554676546775467854679546805468154682546835468454685546865468754688546895469054691546925469354694546955469654697546985469954700547015470254703547045470554706547075470854709547105471154712547135471454715547165471754718547195472054721547225472354724547255472654727547285472954730547315473254733547345473554736547375473854739547405474154742547435474454745547465474754748547495475054751547525475354754547555475654757547585475954760547615476254763547645476554766547675476854769547705477154772547735477454775547765477754778547795478054781547825478354784547855478654787547885478954790547915479254793547945479554796547975479854799548005480154802548035480454805548065480754808548095481054811548125481354814548155481654817548185481954820548215482254823548245482554826548275482854829548305483154832548335483454835548365483754838548395484054841548425484354844548455484654847548485484954850548515485254853548545485554856548575485854859548605486154862548635486454865548665486754868548695487054871548725487354874548755487654877548785487954880548815488254883548845488554886548875488854889548905489154892548935489454895548965489754898548995490054901549025490354904549055490654907549085490954910549115491254913549145491554916549175491854919549205492154922549235492454925549265492754928549295493054931549325493354934549355493654937549385493954940549415494254943549445494554946549475494854949549505495154952549535495454955549565495754958549595496054961549625496354964549655496654967549685496954970549715497254973549745497554976549775497854979549805498154982549835498454985549865498754988549895499054991549925499354994549955499654997549985499955000550015500255003550045500555006550075500855009550105501155012550135501455015550165501755018550195502055021550225502355024550255502655027550285502955030550315503255033550345503555036550375503855039550405504155042550435504455045550465504755048550495505055051550525505355054550555505655057550585505955060550615506255063550645506555066550675506855069550705507155072550735507455075550765507755078550795508055081550825508355084550855508655087550885508955090550915509255093550945509555096550975509855099551005510155102551035510455105551065510755108551095511055111551125511355114551155511655117551185511955120551215512255123551245512555126551275512855129551305513155132551335513455135551365513755138551395514055141551425514355144551455514655147551485514955150551515515255153551545515555156551575515855159551605516155162551635516455165551665516755168551695517055171551725517355174551755517655177551785517955180551815518255183551845518555186551875518855189551905519155192551935519455195551965519755198551995520055201552025520355204552055520655207552085520955210552115521255213552145521555216552175521855219552205522155222552235522455225552265522755228552295523055231552325523355234552355523655237552385523955240552415524255243552445524555246552475524855249552505525155252552535525455255552565525755258552595526055261552625526355264552655526655267552685526955270552715527255273552745527555276552775527855279552805528155282552835528455285552865528755288552895529055291552925529355294552955529655297552985529955300553015530255303553045530555306553075530855309553105531155312553135531455315553165531755318553195532055321553225532355324553255532655327553285532955330553315533255333553345533555336553375533855339553405534155342553435534455345553465534755348553495535055351553525535355354553555535655357553585535955360553615536255363553645536555366553675536855369553705537155372553735537455375553765537755378553795538055381553825538355384553855538655387553885538955390553915539255393553945539555396553975539855399554005540155402554035540455405554065540755408554095541055411554125541355414554155541655417554185541955420554215542255423554245542555426554275542855429554305543155432554335543455435554365543755438554395544055441554425544355444554455544655447554485544955450554515545255453554545545555456554575545855459554605546155462554635546455465554665546755468554695547055471554725547355474554755547655477554785547955480554815548255483554845548555486554875548855489554905549155492554935549455495554965549755498554995550055501555025550355504555055550655507555085550955510555115551255513555145551555516555175551855519555205552155522555235552455525555265552755528555295553055531555325553355534555355553655537555385553955540555415554255543555445554555546555475554855549555505555155552555535555455555555565555755558555595556055561555625556355564555655556655567555685556955570555715557255573555745557555576555775557855579555805558155582555835558455585555865558755588555895559055591555925559355594555955559655597555985559955600556015560255603556045560555606556075560855609556105561155612556135561455615556165561755618556195562055621556225562355624556255562655627556285562955630556315563255633556345563555636556375563855639556405564155642556435564455645556465564755648556495565055651556525565355654556555565655657556585565955660556615566255663556645566555666556675566855669556705567155672556735567455675556765567755678556795568055681556825568355684556855568655687556885568955690556915569255693556945569555696556975569855699557005570155702557035570455705557065570755708557095571055711557125571355714557155571655717557185571955720557215572255723557245572555726557275572855729557305573155732557335573455735557365573755738557395574055741557425574355744557455574655747557485574955750557515575255753557545575555756557575575855759557605576155762557635576455765557665576755768557695577055771557725577355774557755577655777557785577955780557815578255783557845578555786557875578855789557905579155792557935579455795557965579755798557995580055801558025580355804558055580655807558085580955810558115581255813558145581555816558175581855819558205582155822558235582455825558265582755828558295583055831558325583355834558355583655837558385583955840558415584255843558445584555846558475584855849558505585155852558535585455855558565585755858558595586055861558625586355864558655586655867558685586955870558715587255873558745587555876558775587855879558805588155882558835588455885558865588755888558895589055891558925589355894558955589655897558985589955900559015590255903559045590555906559075590855909559105591155912559135591455915559165591755918559195592055921559225592355924559255592655927559285592955930559315593255933559345593555936559375593855939559405594155942559435594455945559465594755948559495595055951559525595355954559555595655957559585595955960559615596255963559645596555966559675596855969559705597155972559735597455975559765597755978559795598055981559825598355984559855598655987559885598955990559915599255993559945599555996559975599855999560005600156002560035600456005560065600756008560095601056011560125601356014560155601656017560185601956020560215602256023560245602556026560275602856029560305603156032560335603456035560365603756038560395604056041560425604356044560455604656047560485604956050560515605256053560545605556056560575605856059560605606156062560635606456065560665606756068560695607056071560725607356074560755607656077560785607956080560815608256083560845608556086560875608856089560905609156092560935609456095560965609756098560995610056101561025610356104561055610656107561085610956110561115611256113561145611556116561175611856119561205612156122561235612456125561265612756128561295613056131561325613356134561355613656137561385613956140561415614256143561445614556146561475614856149561505615156152561535615456155561565615756158561595616056161561625616356164561655616656167561685616956170561715617256173561745617556176561775617856179561805618156182561835618456185561865618756188561895619056191561925619356194561955619656197561985619956200562015620256203562045620556206562075620856209562105621156212562135621456215562165621756218562195622056221562225622356224562255622656227562285622956230562315623256233562345623556236562375623856239562405624156242562435624456245562465624756248562495625056251562525625356254562555625656257562585625956260562615626256263562645626556266562675626856269562705627156272562735627456275562765627756278562795628056281562825628356284562855628656287562885628956290562915629256293562945629556296562975629856299563005630156302563035630456305563065630756308563095631056311563125631356314563155631656317563185631956320563215632256323563245632556326563275632856329563305633156332563335633456335563365633756338563395634056341563425634356344563455634656347563485634956350563515635256353563545635556356563575635856359563605636156362563635636456365563665636756368563695637056371563725637356374563755637656377563785637956380563815638256383563845638556386563875638856389563905639156392563935639456395563965639756398563995640056401564025640356404564055640656407564085640956410564115641256413564145641556416564175641856419564205642156422564235642456425564265642756428564295643056431564325643356434564355643656437564385643956440564415644256443564445644556446564475644856449564505645156452564535645456455564565645756458564595646056461564625646356464564655646656467564685646956470564715647256473564745647556476564775647856479564805648156482564835648456485564865648756488564895649056491564925649356494564955649656497564985649956500565015650256503565045650556506565075650856509565105651156512565135651456515565165651756518565195652056521565225652356524565255652656527565285652956530565315653256533565345653556536565375653856539565405654156542565435654456545565465654756548565495655056551565525655356554565555655656557565585655956560565615656256563565645656556566565675656856569565705657156572565735657456575565765657756578565795658056581565825658356584565855658656587565885658956590565915659256593565945659556596565975659856599566005660156602566035660456605566065660756608566095661056611566125661356614566155661656617566185661956620566215662256623566245662556626566275662856629566305663156632566335663456635566365663756638566395664056641566425664356644566455664656647566485664956650566515665256653566545665556656566575665856659566605666156662566635666456665566665666756668566695667056671566725667356674566755667656677566785667956680566815668256683566845668556686566875668856689566905669156692566935669456695566965669756698566995670056701567025670356704567055670656707567085670956710567115671256713567145671556716567175671856719567205672156722567235672456725567265672756728567295673056731567325673356734567355673656737567385673956740567415674256743567445674556746567475674856749567505675156752567535675456755567565675756758567595676056761567625676356764567655676656767567685676956770567715677256773567745677556776567775677856779567805678156782567835678456785567865678756788567895679056791567925679356794567955679656797567985679956800568015680256803568045680556806568075680856809568105681156812568135681456815568165681756818568195682056821568225682356824568255682656827568285682956830568315683256833568345683556836568375683856839568405684156842568435684456845568465684756848568495685056851568525685356854568555685656857568585685956860568615686256863568645686556866568675686856869568705687156872568735687456875568765687756878568795688056881568825688356884568855688656887568885688956890568915689256893568945689556896568975689856899569005690156902569035690456905569065690756908569095691056911569125691356914569155691656917569185691956920569215692256923569245692556926569275692856929569305693156932569335693456935569365693756938569395694056941569425694356944569455694656947569485694956950569515695256953569545695556956569575695856959569605696156962569635696456965569665696756968569695697056971569725697356974569755697656977569785697956980569815698256983569845698556986569875698856989569905699156992569935699456995569965699756998569995700057001570025700357004570055700657007570085700957010570115701257013570145701557016570175701857019570205702157022570235702457025570265702757028570295703057031570325703357034570355703657037570385703957040570415704257043570445704557046570475704857049570505705157052570535705457055570565705757058570595706057061570625706357064570655706657067570685706957070570715707257073570745707557076570775707857079570805708157082570835708457085570865708757088570895709057091570925709357094570955709657097570985709957100571015710257103571045710557106571075710857109571105711157112571135711457115571165711757118571195712057121571225712357124571255712657127571285712957130571315713257133571345713557136571375713857139571405714157142571435714457145571465714757148571495715057151571525715357154571555715657157571585715957160571615716257163571645716557166571675716857169571705717157172571735717457175571765717757178571795718057181571825718357184571855718657187571885718957190571915719257193571945719557196571975719857199572005720157202572035720457205572065720757208572095721057211572125721357214572155721657217572185721957220572215722257223572245722557226572275722857229572305723157232572335723457235572365723757238572395724057241572425724357244572455724657247572485724957250572515725257253572545725557256572575725857259572605726157262572635726457265572665726757268572695727057271572725727357274572755727657277572785727957280572815728257283572845728557286572875728857289572905729157292572935729457295572965729757298572995730057301573025730357304573055730657307573085730957310573115731257313573145731557316573175731857319573205732157322573235732457325573265732757328573295733057331573325733357334573355733657337573385733957340573415734257343573445734557346573475734857349573505735157352573535735457355573565735757358573595736057361573625736357364573655736657367573685736957370573715737257373573745737557376573775737857379573805738157382573835738457385573865738757388573895739057391573925739357394573955739657397573985739957400574015740257403574045740557406574075740857409574105741157412574135741457415574165741757418574195742057421574225742357424574255742657427574285742957430574315743257433574345743557436574375743857439574405744157442574435744457445574465744757448574495745057451574525745357454574555745657457574585745957460574615746257463574645746557466574675746857469574705747157472574735747457475574765747757478574795748057481574825748357484574855748657487574885748957490574915749257493574945749557496574975749857499575005750157502575035750457505575065750757508575095751057511575125751357514575155751657517575185751957520575215752257523575245752557526575275752857529575305753157532575335753457535575365753757538575395754057541575425754357544575455754657547575485754957550575515755257553575545755557556575575755857559575605756157562575635756457565575665756757568575695757057571575725757357574575755757657577575785757957580575815758257583575845758557586575875758857589575905759157592575935759457595575965759757598575995760057601576025760357604576055760657607576085760957610576115761257613576145761557616576175761857619576205762157622576235762457625576265762757628576295763057631576325763357634576355763657637576385763957640576415764257643576445764557646576475764857649576505765157652576535765457655576565765757658576595766057661576625766357664576655766657667576685766957670576715767257673576745767557676576775767857679576805768157682576835768457685576865768757688576895769057691576925769357694576955769657697576985769957700577015770257703577045770557706577075770857709577105771157712577135771457715577165771757718577195772057721577225772357724577255772657727577285772957730577315773257733577345773557736577375773857739577405774157742577435774457745577465774757748577495775057751577525775357754577555775657757577585775957760577615776257763577645776557766577675776857769577705777157772577735777457775577765777757778577795778057781577825778357784577855778657787577885778957790577915779257793577945779557796577975779857799578005780157802578035780457805578065780757808578095781057811578125781357814578155781657817578185781957820578215782257823578245782557826578275782857829578305783157832578335783457835578365783757838578395784057841578425784357844578455784657847578485784957850578515785257853578545785557856578575785857859578605786157862578635786457865578665786757868578695787057871578725787357874578755787657877578785787957880578815788257883578845788557886578875788857889578905789157892578935789457895578965789757898578995790057901579025790357904579055790657907579085790957910579115791257913579145791557916579175791857919579205792157922579235792457925579265792757928579295793057931579325793357934579355793657937579385793957940579415794257943579445794557946579475794857949579505795157952579535795457955579565795757958579595796057961579625796357964579655796657967579685796957970579715797257973579745797557976579775797857979579805798157982579835798457985579865798757988579895799057991579925799357994579955799657997579985799958000580015800258003580045800558006580075800858009580105801158012580135801458015580165801758018580195802058021580225802358024580255802658027580285802958030580315803258033580345803558036580375803858039580405804158042580435804458045580465804758048580495805058051580525805358054580555805658057580585805958060580615806258063580645806558066580675806858069580705807158072580735807458075580765807758078580795808058081580825808358084580855808658087580885808958090580915809258093580945809558096580975809858099581005810158102581035810458105581065810758108581095811058111581125811358114581155811658117581185811958120581215812258123581245812558126581275812858129581305813158132581335813458135581365813758138581395814058141581425814358144581455814658147581485814958150581515815258153581545815558156581575815858159581605816158162581635816458165581665816758168581695817058171581725817358174581755817658177581785817958180581815818258183581845818558186581875818858189581905819158192581935819458195581965819758198581995820058201582025820358204582055820658207582085820958210582115821258213582145821558216582175821858219582205822158222582235822458225582265822758228582295823058231582325823358234582355823658237582385823958240582415824258243582445824558246582475824858249582505825158252582535825458255582565825758258582595826058261582625826358264582655826658267582685826958270582715827258273582745827558276582775827858279582805828158282582835828458285582865828758288582895829058291582925829358294582955829658297582985829958300583015830258303583045830558306583075830858309583105831158312583135831458315583165831758318583195832058321583225832358324583255832658327583285832958330583315833258333583345833558336583375833858339583405834158342583435834458345583465834758348583495835058351583525835358354583555835658357583585835958360583615836258363583645836558366583675836858369583705837158372583735837458375583765837758378583795838058381583825838358384583855838658387583885838958390583915839258393583945839558396583975839858399584005840158402584035840458405584065840758408584095841058411584125841358414584155841658417584185841958420584215842258423584245842558426584275842858429584305843158432584335843458435584365843758438584395844058441584425844358444584455844658447584485844958450584515845258453584545845558456584575845858459584605846158462584635846458465584665846758468584695847058471584725847358474584755847658477584785847958480584815848258483584845848558486584875848858489584905849158492584935849458495584965849758498584995850058501585025850358504585055850658507585085850958510585115851258513585145851558516585175851858519585205852158522585235852458525585265852758528585295853058531585325853358534585355853658537585385853958540585415854258543585445854558546585475854858549585505855158552585535855458555585565855758558585595856058561585625856358564585655856658567585685856958570585715857258573585745857558576585775857858579585805858158582585835858458585585865858758588585895859058591585925859358594585955859658597585985859958600586015860258603586045860558606586075860858609586105861158612586135861458615586165861758618586195862058621586225862358624586255862658627586285862958630586315863258633586345863558636586375863858639586405864158642586435864458645586465864758648586495865058651586525865358654586555865658657586585865958660586615866258663586645866558666586675866858669586705867158672586735867458675586765867758678586795868058681586825868358684586855868658687586885868958690586915869258693586945869558696586975869858699587005870158702587035870458705587065870758708587095871058711587125871358714587155871658717587185871958720587215872258723587245872558726587275872858729587305873158732587335873458735587365873758738587395874058741587425874358744587455874658747587485874958750587515875258753587545875558756587575875858759587605876158762587635876458765587665876758768587695877058771587725877358774587755877658777587785877958780587815878258783587845878558786587875878858789587905879158792587935879458795587965879758798587995880058801588025880358804588055880658807588085880958810588115881258813588145881558816588175881858819588205882158822588235882458825588265882758828588295883058831588325883358834588355883658837588385883958840588415884258843588445884558846588475884858849588505885158852588535885458855588565885758858588595886058861588625886358864588655886658867588685886958870588715887258873588745887558876588775887858879588805888158882588835888458885588865888758888588895889058891588925889358894588955889658897588985889958900589015890258903589045890558906589075890858909589105891158912589135891458915589165891758918589195892058921589225892358924589255892658927589285892958930589315893258933589345893558936589375893858939589405894158942589435894458945589465894758948589495895058951589525895358954589555895658957589585895958960589615896258963589645896558966589675896858969589705897158972589735897458975589765897758978589795898058981589825898358984589855898658987589885898958990589915899258993589945899558996589975899858999590005900159002590035900459005590065900759008590095901059011590125901359014590155901659017590185901959020590215902259023590245902559026590275902859029590305903159032590335903459035590365903759038590395904059041590425904359044590455904659047590485904959050590515905259053590545905559056590575905859059590605906159062590635906459065590665906759068590695907059071590725907359074590755907659077590785907959080590815908259083590845908559086590875908859089590905909159092590935909459095590965909759098590995910059101591025910359104591055910659107591085910959110591115911259113591145911559116591175911859119591205912159122591235912459125591265912759128591295913059131591325913359134591355913659137591385913959140591415914259143591445914559146591475914859149591505915159152591535915459155591565915759158591595916059161591625916359164591655916659167591685916959170591715917259173591745917559176591775917859179591805918159182591835918459185591865918759188591895919059191591925919359194591955919659197591985919959200592015920259203592045920559206592075920859209592105921159212592135921459215592165921759218592195922059221592225922359224592255922659227592285922959230592315923259233592345923559236592375923859239592405924159242592435924459245592465924759248592495925059251592525925359254592555925659257592585925959260592615926259263592645926559266592675926859269592705927159272592735927459275592765927759278592795928059281592825928359284592855928659287592885928959290592915929259293592945929559296592975929859299593005930159302593035930459305593065930759308593095931059311593125931359314593155931659317593185931959320593215932259323593245932559326593275932859329593305933159332593335933459335593365933759338593395934059341593425934359344593455934659347593485934959350593515935259353593545935559356593575935859359593605936159362593635936459365593665936759368593695937059371593725937359374593755937659377593785937959380593815938259383593845938559386593875938859389593905939159392593935939459395593965939759398593995940059401594025940359404594055940659407594085940959410594115941259413594145941559416594175941859419594205942159422594235942459425594265942759428594295943059431594325943359434594355943659437594385943959440594415944259443594445944559446594475944859449594505945159452594535945459455594565945759458594595946059461594625946359464594655946659467594685946959470594715947259473594745947559476594775947859479594805948159482594835948459485594865948759488594895949059491594925949359494594955949659497594985949959500595015950259503595045950559506595075950859509595105951159512595135951459515595165951759518595195952059521595225952359524595255952659527595285952959530595315953259533595345953559536595375953859539595405954159542595435954459545595465954759548595495955059551595525955359554595555955659557595585955959560595615956259563595645956559566595675956859569595705957159572595735957459575595765957759578595795958059581595825958359584595855958659587595885958959590595915959259593595945959559596595975959859599596005960159602596035960459605596065960759608596095961059611596125961359614596155961659617596185961959620596215962259623596245962559626596275962859629596305963159632596335963459635596365963759638596395964059641596425964359644596455964659647596485964959650596515965259653596545965559656596575965859659596605966159662596635966459665596665966759668596695967059671596725967359674596755967659677596785967959680596815968259683596845968559686596875968859689596905969159692596935969459695596965969759698596995970059701597025970359704597055970659707597085970959710597115971259713597145971559716597175971859719597205972159722597235972459725597265972759728597295973059731597325973359734597355973659737597385973959740597415974259743597445974559746597475974859749597505975159752597535975459755597565975759758597595976059761597625976359764597655976659767597685976959770597715977259773597745977559776597775977859779597805978159782597835978459785597865978759788597895979059791597925979359794597955979659797597985979959800598015980259803598045980559806598075980859809598105981159812598135981459815598165981759818598195982059821598225982359824598255982659827598285982959830598315983259833598345983559836598375983859839598405984159842598435984459845598465984759848598495985059851598525985359854598555985659857598585985959860598615986259863598645986559866598675986859869598705987159872598735987459875598765987759878598795988059881598825988359884598855988659887598885988959890598915989259893598945989559896598975989859899599005990159902599035990459905599065990759908599095991059911599125991359914599155991659917599185991959920599215992259923599245992559926599275992859929599305993159932599335993459935599365993759938599395994059941599425994359944599455994659947599485994959950599515995259953599545995559956599575995859959599605996159962599635996459965599665996759968599695997059971599725997359974599755997659977599785997959980599815998259983599845998559986599875998859989599905999159992599935999459995599965999759998599996000060001600026000360004600056000660007600086000960010600116001260013600146001560016600176001860019600206002160022600236002460025600266002760028600296003060031600326003360034600356003660037600386003960040600416004260043600446004560046600476004860049600506005160052600536005460055600566005760058600596006060061600626006360064600656006660067600686006960070600716007260073600746007560076600776007860079600806008160082600836008460085600866008760088600896009060091600926009360094600956009660097600986009960100601016010260103601046010560106601076010860109601106011160112601136011460115601166011760118601196012060121601226012360124601256012660127601286012960130601316013260133601346013560136601376013860139601406014160142601436014460145601466014760148601496015060151601526015360154601556015660157601586015960160601616016260163601646016560166601676016860169601706017160172601736017460175601766017760178601796018060181601826018360184601856018660187601886018960190601916019260193601946019560196601976019860199602006020160202602036020460205602066020760208602096021060211602126021360214602156021660217602186021960220602216022260223602246022560226602276022860229602306023160232602336023460235602366023760238602396024060241602426024360244602456024660247602486024960250602516025260253602546025560256602576025860259602606026160262602636026460265602666026760268602696027060271602726027360274602756027660277602786027960280602816028260283602846028560286602876028860289602906029160292602936029460295602966029760298602996030060301603026030360304603056030660307603086030960310603116031260313603146031560316603176031860319603206032160322603236032460325603266032760328603296033060331603326033360334603356033660337603386033960340603416034260343603446034560346603476034860349603506035160352603536035460355603566035760358603596036060361603626036360364603656036660367603686036960370603716037260373603746037560376603776037860379603806038160382603836038460385603866038760388603896039060391603926039360394603956039660397603986039960400604016040260403604046040560406604076040860409604106041160412604136041460415604166041760418604196042060421604226042360424604256042660427604286042960430604316043260433604346043560436604376043860439604406044160442604436044460445604466044760448604496045060451604526045360454604556045660457604586045960460604616046260463604646046560466604676046860469604706047160472604736047460475604766047760478604796048060481604826048360484604856048660487604886048960490604916049260493604946049560496604976049860499605006050160502605036050460505605066050760508605096051060511605126051360514605156051660517605186051960520605216052260523605246052560526605276052860529605306053160532605336053460535605366053760538605396054060541605426054360544605456054660547605486054960550605516055260553605546055560556605576055860559605606056160562605636056460565605666056760568605696057060571605726057360574605756057660577605786057960580605816058260583605846058560586605876058860589605906059160592605936059460595605966059760598605996060060601606026060360604606056060660607606086060960610606116061260613606146061560616606176061860619606206062160622606236062460625606266062760628606296063060631606326063360634606356063660637606386063960640606416064260643606446064560646606476064860649606506065160652606536065460655606566065760658606596066060661606626066360664606656066660667606686066960670606716067260673606746067560676606776067860679606806068160682606836068460685606866068760688606896069060691606926069360694606956069660697606986069960700607016070260703607046070560706607076070860709607106071160712607136071460715607166071760718607196072060721607226072360724607256072660727607286072960730607316073260733607346073560736607376073860739607406074160742607436074460745607466074760748607496075060751607526075360754607556075660757607586075960760607616076260763607646076560766607676076860769607706077160772607736077460775607766077760778607796078060781607826078360784607856078660787607886078960790607916079260793607946079560796607976079860799608006080160802608036080460805608066080760808608096081060811608126081360814608156081660817608186081960820608216082260823608246082560826608276082860829608306083160832608336083460835608366083760838608396084060841608426084360844608456084660847608486084960850608516085260853608546085560856608576085860859608606086160862608636086460865608666086760868608696087060871608726087360874608756087660877608786087960880608816088260883608846088560886608876088860889608906089160892608936089460895608966089760898608996090060901609026090360904609056090660907609086090960910609116091260913609146091560916609176091860919609206092160922609236092460925609266092760928609296093060931609326093360934609356093660937609386093960940609416094260943609446094560946609476094860949609506095160952609536095460955609566095760958609596096060961609626096360964609656096660967609686096960970609716097260973609746097560976609776097860979609806098160982609836098460985609866098760988609896099060991609926099360994609956099660997609986099961000610016100261003610046100561006610076100861009610106101161012610136101461015610166101761018610196102061021610226102361024610256102661027610286102961030610316103261033610346103561036610376103861039610406104161042610436104461045610466104761048610496105061051610526105361054610556105661057610586105961060610616106261063610646106561066610676106861069610706107161072610736107461075610766107761078610796108061081610826108361084610856108661087610886108961090610916109261093610946109561096610976109861099611006110161102611036110461105611066110761108611096111061111611126111361114611156111661117611186111961120611216112261123611246112561126611276112861129611306113161132611336113461135611366113761138611396114061141611426114361144611456114661147611486114961150611516115261153611546115561156611576115861159611606116161162611636116461165611666116761168611696117061171611726117361174611756117661177611786117961180611816118261183611846118561186611876118861189611906119161192611936119461195611966119761198611996120061201612026120361204612056120661207612086120961210612116121261213612146121561216612176121861219612206122161222612236122461225612266122761228612296123061231612326123361234612356123661237612386123961240612416124261243612446124561246612476124861249612506125161252612536125461255612566125761258612596126061261612626126361264612656126661267612686126961270612716127261273612746127561276612776127861279612806128161282612836128461285612866128761288612896129061291612926129361294612956129661297612986129961300613016130261303613046130561306613076130861309613106131161312613136131461315613166131761318613196132061321613226132361324613256132661327613286132961330613316133261333613346133561336613376133861339613406134161342613436134461345613466134761348613496135061351613526135361354613556135661357613586135961360613616136261363613646136561366613676136861369613706137161372613736137461375613766137761378613796138061381613826138361384613856138661387613886138961390613916139261393613946139561396613976139861399614006140161402614036140461405614066140761408614096141061411614126141361414614156141661417614186141961420614216142261423614246142561426614276142861429614306143161432614336143461435614366143761438614396144061441614426144361444614456144661447614486144961450614516145261453614546145561456614576145861459614606146161462614636146461465614666146761468614696147061471614726147361474614756147661477614786147961480614816148261483614846148561486614876148861489614906149161492614936149461495614966149761498614996150061501615026150361504615056150661507615086150961510615116151261513615146151561516615176151861519615206152161522615236152461525615266152761528615296153061531615326153361534615356153661537615386153961540615416154261543615446154561546615476154861549615506155161552615536155461555615566155761558615596156061561615626156361564615656156661567615686156961570615716157261573615746157561576615776157861579615806158161582615836158461585615866158761588615896159061591615926159361594615956159661597615986159961600616016160261603616046160561606616076160861609616106161161612616136161461615616166161761618616196162061621616226162361624616256162661627616286162961630616316163261633616346163561636616376163861639616406164161642616436164461645616466164761648616496165061651616526165361654616556165661657616586165961660616616166261663616646166561666616676166861669616706167161672616736167461675616766167761678616796168061681616826168361684616856168661687616886168961690616916169261693616946169561696616976169861699617006170161702617036170461705617066170761708617096171061711617126171361714617156171661717617186171961720617216172261723617246172561726617276172861729617306173161732617336173461735617366173761738617396174061741617426174361744617456174661747617486174961750617516175261753617546175561756617576175861759617606176161762617636176461765617666176761768617696177061771617726177361774617756177661777617786177961780617816178261783617846178561786617876178861789617906179161792617936179461795617966179761798617996180061801618026180361804618056180661807618086180961810618116181261813618146181561816618176181861819618206182161822618236182461825618266182761828618296183061831618326183361834618356183661837618386183961840618416184261843618446184561846618476184861849618506185161852618536185461855618566185761858618596186061861618626186361864618656186661867618686186961870618716187261873618746187561876618776187861879618806188161882618836188461885618866188761888618896189061891618926189361894618956189661897618986189961900619016190261903619046190561906619076190861909619106191161912619136191461915619166191761918619196192061921619226192361924619256192661927619286192961930619316193261933619346193561936619376193861939619406194161942619436194461945619466194761948619496195061951619526195361954619556195661957619586195961960619616196261963619646196561966619676196861969619706197161972619736197461975619766197761978619796198061981619826198361984619856198661987619886198961990619916199261993619946199561996619976199861999620006200162002620036200462005620066200762008620096201062011620126201362014620156201662017620186201962020620216202262023620246202562026620276202862029620306203162032620336203462035620366203762038620396204062041620426204362044620456204662047620486204962050620516205262053620546205562056620576205862059620606206162062620636206462065620666206762068620696207062071620726207362074620756207662077620786207962080620816208262083620846208562086620876208862089620906209162092620936209462095620966209762098620996210062101621026210362104621056210662107621086210962110621116211262113621146211562116621176211862119621206212162122621236212462125621266212762128621296213062131621326213362134621356213662137621386213962140621416214262143621446214562146621476214862149621506215162152621536215462155621566215762158621596216062161621626216362164621656216662167621686216962170621716217262173621746217562176621776217862179621806218162182621836218462185621866218762188621896219062191621926219362194621956219662197621986219962200622016220262203622046220562206622076220862209622106221162212622136221462215622166221762218622196222062221622226222362224622256222662227622286222962230622316223262233622346223562236622376223862239622406224162242622436224462245622466224762248622496225062251622526225362254622556225662257622586225962260622616226262263622646226562266622676226862269622706227162272622736227462275622766227762278622796228062281622826228362284622856228662287622886228962290622916229262293622946229562296622976229862299623006230162302623036230462305623066230762308623096231062311623126231362314623156231662317623186231962320623216232262323623246232562326623276232862329623306233162332623336233462335623366233762338623396234062341623426234362344623456234662347623486234962350623516235262353623546235562356623576235862359623606236162362623636236462365623666236762368623696237062371623726237362374623756237662377623786237962380623816238262383623846238562386623876238862389623906239162392623936239462395623966239762398623996240062401624026240362404624056240662407624086240962410624116241262413624146241562416624176241862419624206242162422624236242462425624266242762428624296243062431624326243362434624356243662437624386243962440624416244262443624446244562446624476244862449624506245162452624536245462455624566245762458624596246062461624626246362464624656246662467624686246962470624716247262473624746247562476624776247862479624806248162482624836248462485624866248762488624896249062491624926249362494624956249662497624986249962500625016250262503625046250562506625076250862509625106251162512625136251462515625166251762518625196252062521625226252362524625256252662527625286252962530625316253262533625346253562536625376253862539625406254162542625436254462545625466254762548625496255062551625526255362554625556255662557625586255962560625616256262563625646256562566625676256862569625706257162572625736257462575625766257762578625796258062581625826258362584625856258662587625886258962590625916259262593625946259562596625976259862599626006260162602626036260462605626066260762608626096261062611626126261362614626156261662617626186261962620626216262262623626246262562626626276262862629626306263162632626336263462635626366263762638626396264062641626426264362644626456264662647626486264962650626516265262653626546265562656626576265862659626606266162662626636266462665626666266762668626696267062671626726267362674626756267662677626786267962680626816268262683626846268562686626876268862689626906269162692626936269462695626966269762698626996270062701627026270362704627056270662707627086270962710627116271262713627146271562716627176271862719627206272162722627236272462725627266272762728627296273062731627326273362734627356273662737627386273962740627416274262743627446274562746627476274862749627506275162752627536275462755627566275762758627596276062761627626276362764627656276662767627686276962770627716277262773627746277562776627776277862779627806278162782627836278462785627866278762788627896279062791627926279362794627956279662797627986279962800628016280262803628046280562806628076280862809628106281162812628136281462815628166281762818628196282062821628226282362824628256282662827628286282962830628316283262833628346283562836628376283862839628406284162842628436284462845628466284762848628496285062851628526285362854628556285662857628586285962860628616286262863628646286562866628676286862869628706287162872628736287462875628766287762878628796288062881628826288362884628856288662887628886288962890628916289262893628946289562896628976289862899629006290162902629036290462905629066290762908629096291062911629126291362914629156291662917629186291962920629216292262923629246292562926629276292862929629306293162932629336293462935629366293762938629396294062941629426294362944629456294662947629486294962950629516295262953629546295562956629576295862959629606296162962629636296462965629666296762968629696297062971629726297362974629756297662977629786297962980629816298262983629846298562986629876298862989629906299162992629936299462995629966299762998629996300063001630026300363004630056300663007630086300963010630116301263013630146301563016630176301863019630206302163022630236302463025630266302763028630296303063031630326303363034630356303663037630386303963040630416304263043630446304563046630476304863049630506305163052630536305463055630566305763058630596306063061630626306363064630656306663067630686306963070630716307263073630746307563076630776307863079630806308163082630836308463085630866308763088630896309063091630926309363094630956309663097630986309963100631016310263103631046310563106631076310863109631106311163112631136311463115631166311763118631196312063121631226312363124631256312663127631286312963130631316313263133631346313563136631376313863139631406314163142631436314463145631466314763148631496315063151631526315363154631556315663157631586315963160631616316263163631646316563166631676316863169631706317163172631736317463175631766317763178631796318063181631826318363184631856318663187631886318963190631916319263193631946319563196631976319863199632006320163202632036320463205632066320763208632096321063211632126321363214632156321663217632186321963220632216322263223632246322563226632276322863229632306323163232632336323463235632366323763238632396324063241632426324363244632456324663247632486324963250632516325263253632546325563256632576325863259632606326163262632636326463265632666326763268632696327063271632726327363274632756327663277632786327963280632816328263283632846328563286632876328863289632906329163292632936329463295632966329763298632996330063301633026330363304633056330663307633086330963310633116331263313633146331563316633176331863319633206332163322633236332463325633266332763328633296333063331633326333363334633356333663337633386333963340633416334263343633446334563346633476334863349633506335163352633536335463355633566335763358633596336063361633626336363364633656336663367633686336963370633716337263373633746337563376633776337863379633806338163382633836338463385633866338763388633896339063391633926339363394633956339663397633986339963400634016340263403634046340563406634076340863409634106341163412634136341463415634166341763418634196342063421634226342363424634256342663427634286342963430634316343263433634346343563436634376343863439634406344163442634436344463445634466344763448634496345063451634526345363454634556345663457634586345963460634616346263463634646346563466634676346863469634706347163472634736347463475634766347763478634796348063481634826348363484634856348663487634886348963490634916349263493634946349563496634976349863499635006350163502635036350463505635066350763508635096351063511635126351363514635156351663517635186351963520635216352263523635246352563526635276352863529635306353163532635336353463535635366353763538635396354063541635426354363544635456354663547635486354963550635516355263553635546355563556635576355863559635606356163562635636356463565635666356763568635696357063571635726357363574635756357663577635786357963580635816358263583635846358563586635876358863589635906359163592635936359463595635966359763598635996360063601636026360363604636056360663607636086360963610636116361263613636146361563616636176361863619636206362163622636236362463625636266362763628636296363063631636326363363634636356363663637636386363963640636416364263643636446364563646636476364863649636506365163652636536365463655636566365763658636596366063661636626366363664636656366663667636686366963670636716367263673636746367563676636776367863679636806368163682636836368463685636866368763688636896369063691636926369363694636956369663697636986369963700637016370263703637046370563706637076370863709637106371163712637136371463715637166371763718637196372063721637226372363724637256372663727637286372963730637316373263733637346373563736637376373863739637406374163742637436374463745637466374763748637496375063751637526375363754637556375663757637586375963760637616376263763637646376563766637676376863769637706377163772637736377463775637766377763778637796378063781637826378363784637856378663787637886378963790637916379263793637946379563796637976379863799638006380163802638036380463805638066380763808638096381063811638126381363814638156381663817638186381963820638216382263823638246382563826638276382863829638306383163832638336383463835638366383763838638396384063841638426384363844638456384663847638486384963850638516385263853638546385563856638576385863859638606386163862638636386463865638666386763868638696387063871638726387363874638756387663877638786387963880638816388263883638846388563886638876388863889638906389163892638936389463895638966389763898638996390063901639026390363904639056390663907639086390963910639116391263913639146391563916639176391863919639206392163922639236392463925639266392763928639296393063931639326393363934639356393663937639386393963940639416394263943639446394563946639476394863949639506395163952639536395463955639566395763958639596396063961639626396363964639656396663967639686396963970639716397263973639746397563976639776397863979639806398163982639836398463985639866398763988639896399063991639926399363994639956399663997639986399964000640016400264003640046400564006640076400864009640106401164012640136401464015640166401764018640196402064021640226402364024640256402664027640286402964030640316403264033640346403564036640376403864039640406404164042640436404464045640466404764048640496405064051640526405364054640556405664057640586405964060640616406264063640646406564066640676406864069640706407164072640736407464075640766407764078640796408064081640826408364084640856408664087640886408964090640916409264093640946409564096640976409864099641006410164102641036410464105641066410764108641096411064111641126411364114641156411664117641186411964120641216412264123641246412564126641276412864129641306413164132641336413464135641366413764138641396414064141641426414364144641456414664147641486414964150641516415264153641546415564156641576415864159641606416164162641636416464165641666416764168641696417064171641726417364174641756417664177641786417964180641816418264183641846418564186641876418864189641906419164192641936419464195641966419764198641996420064201642026420364204642056420664207642086420964210642116421264213642146421564216642176421864219642206422164222642236422464225642266422764228642296423064231642326423364234642356423664237642386423964240642416424264243642446424564246642476424864249642506425164252642536425464255642566425764258642596426064261642626426364264642656426664267642686426964270642716427264273642746427564276642776427864279642806428164282642836428464285642866428764288642896429064291642926429364294642956429664297642986429964300643016430264303643046430564306643076430864309643106431164312643136431464315643166431764318643196432064321643226432364324643256432664327643286432964330643316433264333643346433564336643376433864339643406434164342643436434464345643466434764348643496435064351643526435364354643556435664357643586435964360643616436264363643646436564366643676436864369643706437164372643736437464375643766437764378643796438064381643826438364384643856438664387643886438964390643916439264393643946439564396643976439864399644006440164402644036440464405644066440764408644096441064411644126441364414644156441664417644186441964420644216442264423644246442564426644276442864429644306443164432644336443464435644366443764438644396444064441644426444364444644456444664447644486444964450644516445264453644546445564456644576445864459644606446164462644636446464465644666446764468644696447064471644726447364474644756447664477644786447964480644816448264483644846448564486644876448864489644906449164492644936449464495644966449764498644996450064501645026450364504645056450664507645086450964510645116451264513645146451564516645176451864519645206452164522645236452464525645266452764528645296453064531645326453364534645356453664537645386453964540645416454264543645446454564546645476454864549645506455164552645536455464555645566455764558645596456064561645626456364564645656456664567645686456964570645716457264573645746457564576645776457864579645806458164582645836458464585645866458764588645896459064591645926459364594645956459664597645986459964600646016460264603646046460564606646076460864609646106461164612646136461464615646166461764618646196462064621646226462364624646256462664627646286462964630646316463264633646346463564636646376463864639646406464164642646436464464645646466464764648646496465064651646526465364654646556465664657646586465964660646616466264663646646466564666646676466864669646706467164672646736467464675646766467764678646796468064681646826468364684646856468664687646886468964690646916469264693646946469564696646976469864699647006470164702647036470464705647066470764708647096471064711647126471364714647156471664717647186471964720647216472264723647246472564726647276472864729647306473164732647336473464735647366473764738647396474064741647426474364744647456474664747647486474964750647516475264753647546475564756647576475864759647606476164762647636476464765647666476764768647696477064771647726477364774647756477664777647786477964780647816478264783647846478564786647876478864789647906479164792647936479464795647966479764798647996480064801648026480364804648056480664807648086480964810648116481264813648146481564816648176481864819648206482164822648236482464825648266482764828648296483064831648326483364834648356483664837648386483964840648416484264843648446484564846648476484864849648506485164852648536485464855648566485764858648596486064861648626486364864648656486664867648686486964870648716487264873648746487564876648776487864879648806488164882648836488464885648866488764888648896489064891648926489364894648956489664897648986489964900649016490264903649046490564906649076490864909649106491164912649136491464915649166491764918649196492064921649226492364924649256492664927649286492964930649316493264933649346493564936649376493864939649406494164942649436494464945649466494764948649496495064951649526495364954649556495664957649586495964960649616496264963649646496564966649676496864969649706497164972649736497464975649766497764978649796498064981649826498364984649856498664987649886498964990649916499264993649946499564996649976499864999650006500165002650036500465005650066500765008650096501065011650126501365014650156501665017650186501965020650216502265023650246502565026650276502865029650306503165032650336503465035650366503765038650396504065041650426504365044650456504665047650486504965050650516505265053650546505565056650576505865059650606506165062650636506465065650666506765068650696507065071650726507365074650756507665077650786507965080650816508265083650846508565086650876508865089650906509165092650936509465095650966509765098650996510065101651026510365104651056510665107651086510965110651116511265113651146511565116651176511865119651206512165122651236512465125651266512765128651296513065131651326513365134651356513665137651386513965140651416514265143651446514565146651476514865149651506515165152651536515465155651566515765158651596516065161651626516365164651656516665167651686516965170651716517265173651746517565176651776517865179651806518165182651836518465185651866518765188651896519065191651926519365194651956519665197651986519965200652016520265203652046520565206652076520865209652106521165212652136521465215652166521765218652196522065221652226522365224652256522665227652286522965230652316523265233652346523565236652376523865239652406524165242652436524465245652466524765248652496525065251652526525365254652556525665257652586525965260652616526265263652646526565266652676526865269652706527165272652736527465275652766527765278652796528065281652826528365284652856528665287652886528965290652916529265293652946529565296652976529865299653006530165302653036530465305653066530765308653096531065311653126531365314653156531665317653186531965320653216532265323653246532565326653276532865329653306533165332653336533465335653366533765338653396534065341653426534365344653456534665347653486534965350653516535265353653546535565356653576535865359653606536165362653636536465365653666536765368653696537065371653726537365374653756537665377653786537965380653816538265383653846538565386653876538865389653906539165392653936539465395653966539765398653996540065401654026540365404654056540665407654086540965410654116541265413654146541565416654176541865419654206542165422654236542465425654266542765428654296543065431654326543365434654356543665437654386543965440654416544265443654446544565446654476544865449654506545165452654536545465455654566545765458654596546065461654626546365464654656546665467654686546965470654716547265473654746547565476654776547865479654806548165482654836548465485654866548765488654896549065491654926549365494654956549665497654986549965500655016550265503655046550565506655076550865509655106551165512655136551465515655166551765518655196552065521655226552365524655256552665527655286552965530655316553265533655346553565536655376553865539655406554165542655436554465545655466554765548655496555065551655526555365554655556555665557655586555965560655616556265563655646556565566655676556865569655706557165572655736557465575655766557765578655796558065581655826558365584655856558665587655886558965590655916559265593655946559565596655976559865599656006560165602656036560465605656066560765608656096561065611656126561365614656156561665617656186561965620656216562265623656246562565626656276562865629656306563165632656336563465635656366563765638656396564065641656426564365644656456564665647656486564965650656516565265653656546565565656656576565865659656606566165662656636566465665656666566765668656696567065671656726567365674656756567665677656786567965680656816568265683656846568565686656876568865689656906569165692656936569465695656966569765698656996570065701657026570365704657056570665707657086570965710657116571265713657146571565716657176571865719657206572165722657236572465725657266572765728657296573065731657326573365734657356573665737657386573965740657416574265743657446574565746657476574865749657506575165752657536575465755657566575765758657596576065761657626576365764657656576665767657686576965770657716577265773657746577565776657776577865779657806578165782657836578465785657866578765788657896579065791657926579365794657956579665797657986579965800658016580265803658046580565806658076580865809658106581165812658136581465815658166581765818658196582065821658226582365824658256582665827658286582965830658316583265833658346583565836658376583865839658406584165842658436584465845658466584765848658496585065851658526585365854658556585665857658586585965860658616586265863658646586565866658676586865869658706587165872658736587465875658766587765878658796588065881658826588365884658856588665887658886588965890658916589265893658946589565896658976589865899659006590165902659036590465905659066590765908659096591065911659126591365914659156591665917659186591965920659216592265923659246592565926659276592865929659306593165932659336593465935659366593765938659396594065941659426594365944659456594665947659486594965950659516595265953659546595565956659576595865959659606596165962659636596465965659666596765968659696597065971659726597365974659756597665977659786597965980659816598265983659846598565986659876598865989659906599165992659936599465995659966599765998659996600066001660026600366004660056600666007660086600966010660116601266013660146601566016660176601866019660206602166022660236602466025660266602766028660296603066031660326603366034660356603666037660386603966040660416604266043660446604566046660476604866049660506605166052660536605466055660566605766058660596606066061660626606366064660656606666067660686606966070660716607266073660746607566076660776607866079660806608166082660836608466085660866608766088660896609066091660926609366094660956609666097660986609966100661016610266103661046610566106661076610866109661106611166112661136611466115661166611766118661196612066121661226612366124661256612666127661286612966130661316613266133661346613566136661376613866139661406614166142661436614466145661466614766148661496615066151661526615366154661556615666157661586615966160661616616266163661646616566166661676616866169661706617166172661736617466175661766617766178661796618066181661826618366184661856618666187661886618966190661916619266193661946619566196661976619866199662006620166202662036620466205662066620766208662096621066211662126621366214662156621666217662186621966220662216622266223662246622566226662276622866229662306623166232662336623466235662366623766238662396624066241662426624366244662456624666247662486624966250662516625266253662546625566256662576625866259662606626166262662636626466265662666626766268662696627066271662726627366274662756627666277662786627966280662816628266283662846628566286662876628866289662906629166292662936629466295662966629766298662996630066301663026630366304663056630666307663086630966310663116631266313663146631566316663176631866319663206632166322663236632466325663266632766328663296633066331663326633366334663356633666337663386633966340663416634266343663446634566346663476634866349663506635166352663536635466355663566635766358663596636066361663626636366364663656636666367663686636966370663716637266373663746637566376663776637866379663806638166382663836638466385663866638766388663896639066391663926639366394663956639666397663986639966400664016640266403664046640566406664076640866409664106641166412664136641466415664166641766418664196642066421664226642366424664256642666427664286642966430664316643266433664346643566436664376643866439664406644166442664436644466445664466644766448664496645066451664526645366454664556645666457664586645966460664616646266463664646646566466664676646866469664706647166472664736647466475664766647766478664796648066481664826648366484664856648666487664886648966490664916649266493664946649566496664976649866499665006650166502665036650466505665066650766508665096651066511665126651366514665156651666517665186651966520665216652266523665246652566526665276652866529665306653166532665336653466535665366653766538665396654066541665426654366544665456654666547665486654966550665516655266553665546655566556665576655866559665606656166562665636656466565665666656766568665696657066571665726657366574665756657666577665786657966580665816658266583665846658566586665876658866589665906659166592665936659466595665966659766598665996660066601666026660366604666056660666607666086660966610666116661266613666146661566616666176661866619666206662166622666236662466625666266662766628666296663066631666326663366634666356663666637666386663966640666416664266643666446664566646666476664866649666506665166652666536665466655666566665766658666596666066661666626666366664666656666666667666686666966670666716667266673666746667566676666776667866679666806668166682666836668466685666866668766688666896669066691666926669366694666956669666697666986669966700667016670266703667046670566706667076670866709667106671166712667136671466715667166671766718667196672066721667226672366724667256672666727667286672966730667316673266733667346673566736667376673866739667406674166742667436674466745667466674766748667496675066751667526675366754667556675666757667586675966760667616676266763667646676566766667676676866769667706677166772667736677466775667766677766778667796678066781667826678366784667856678666787667886678966790667916679266793667946679566796667976679866799668006680166802668036680466805668066680766808668096681066811668126681366814668156681666817668186681966820668216682266823668246682566826668276682866829668306683166832668336683466835668366683766838668396684066841668426684366844668456684666847668486684966850668516685266853668546685566856668576685866859668606686166862668636686466865668666686766868668696687066871668726687366874668756687666877668786687966880668816688266883668846688566886668876688866889668906689166892668936689466895668966689766898668996690066901669026690366904669056690666907669086690966910669116691266913669146691566916669176691866919669206692166922669236692466925669266692766928669296693066931669326693366934669356693666937669386693966940669416694266943669446694566946669476694866949669506695166952669536695466955669566695766958669596696066961669626696366964669656696666967669686696966970
  1. #!/usr/bin/env php
  2. <?php
  3. if (version_compare('7.3.0', PHP_VERSION, '>')) {
  4. fwrite(
  5. STDERR,
  6. sprintf(
  7. 'PHPUnit 9.2.5 by Sebastian Bergmann and contributors.' . PHP_EOL . PHP_EOL .
  8. 'This version of PHPUnit is supported on PHP 7.3 and PHP 7.4.' . PHP_EOL .
  9. 'You are using PHP %s (%s).' . PHP_EOL,
  10. PHP_VERSION,
  11. PHP_BINARY
  12. )
  13. );
  14. die(1);
  15. }
  16. if (__FILE__ === realpath($_SERVER['SCRIPT_NAME'])) {
  17. $execute = true;
  18. } else {
  19. $execute = false;
  20. }
  21. $options = getopt('', array('prepend:', 'manifest'));
  22. if (isset($options['prepend'])) {
  23. require $options['prepend'];
  24. }
  25. if (isset($options['manifest'])) {
  26. $printManifest = true;
  27. }
  28. unset($options);
  29. define('__PHPUNIT_PHAR__', str_replace(DIRECTORY_SEPARATOR, '/', __FILE__));
  30. define('__PHPUNIT_PHAR_ROOT__', 'phar://phpunit-9.2.5.phar');
  31. Phar::mapPhar('phpunit-9.2.5.phar');
  32. require 'phar://phpunit-9.2.5.phar' . '/myclabs-deep-copy/DeepCopy/DeepCopy.php';
  33. require 'phar://phpunit-9.2.5.phar' . '/myclabs-deep-copy/DeepCopy/Exception/CloneException.php';
  34. require 'phar://phpunit-9.2.5.phar' . '/myclabs-deep-copy/DeepCopy/Exception/PropertyException.php';
  35. require 'phar://phpunit-9.2.5.phar' . '/myclabs-deep-copy/DeepCopy/Filter/Filter.php';
  36. require 'phar://phpunit-9.2.5.phar' . '/myclabs-deep-copy/DeepCopy/Filter/Doctrine/DoctrineCollectionFilter.php';
  37. require 'phar://phpunit-9.2.5.phar' . '/myclabs-deep-copy/DeepCopy/Filter/Doctrine/DoctrineEmptyCollectionFilter.php';
  38. require 'phar://phpunit-9.2.5.phar' . '/myclabs-deep-copy/DeepCopy/Filter/Doctrine/DoctrineProxyFilter.php';
  39. require 'phar://phpunit-9.2.5.phar' . '/myclabs-deep-copy/DeepCopy/Filter/KeepFilter.php';
  40. require 'phar://phpunit-9.2.5.phar' . '/myclabs-deep-copy/DeepCopy/Filter/ReplaceFilter.php';
  41. require 'phar://phpunit-9.2.5.phar' . '/myclabs-deep-copy/DeepCopy/Filter/SetNullFilter.php';
  42. require 'phar://phpunit-9.2.5.phar' . '/myclabs-deep-copy/DeepCopy/Matcher/Matcher.php';
  43. require 'phar://phpunit-9.2.5.phar' . '/myclabs-deep-copy/DeepCopy/Matcher/Doctrine/DoctrineProxyMatcher.php';
  44. require 'phar://phpunit-9.2.5.phar' . '/myclabs-deep-copy/DeepCopy/Matcher/PropertyMatcher.php';
  45. require 'phar://phpunit-9.2.5.phar' . '/myclabs-deep-copy/DeepCopy/Matcher/PropertyNameMatcher.php';
  46. require 'phar://phpunit-9.2.5.phar' . '/myclabs-deep-copy/DeepCopy/Matcher/PropertyTypeMatcher.php';
  47. require 'phar://phpunit-9.2.5.phar' . '/myclabs-deep-copy/DeepCopy/Reflection/ReflectionHelper.php';
  48. require 'phar://phpunit-9.2.5.phar' . '/myclabs-deep-copy/DeepCopy/TypeFilter/TypeFilter.php';
  49. require 'phar://phpunit-9.2.5.phar' . '/myclabs-deep-copy/DeepCopy/TypeFilter/Date/DateIntervalFilter.php';
  50. require 'phar://phpunit-9.2.5.phar' . '/myclabs-deep-copy/DeepCopy/TypeFilter/ReplaceFilter.php';
  51. require 'phar://phpunit-9.2.5.phar' . '/myclabs-deep-copy/DeepCopy/TypeFilter/ShallowCopyFilter.php';
  52. require 'phar://phpunit-9.2.5.phar' . '/myclabs-deep-copy/DeepCopy/TypeFilter/Spl/ArrayObjectFilter.php';
  53. require 'phar://phpunit-9.2.5.phar' . '/myclabs-deep-copy/DeepCopy/TypeFilter/Spl/SplDoublyLinkedListFilter.php';
  54. require 'phar://phpunit-9.2.5.phar' . '/myclabs-deep-copy/DeepCopy/TypeFilter/Spl/SplDoublyLinkedList.php';
  55. require 'phar://phpunit-9.2.5.phar' . '/myclabs-deep-copy/DeepCopy/TypeMatcher/TypeMatcher.php';
  56. require 'phar://phpunit-9.2.5.phar' . '/doctrine-instantiator/Doctrine/Instantiator/Exception/ExceptionInterface.php';
  57. require 'phar://phpunit-9.2.5.phar' . '/doctrine-instantiator/Doctrine/Instantiator/Exception/InvalidArgumentException.php';
  58. require 'phar://phpunit-9.2.5.phar' . '/doctrine-instantiator/Doctrine/Instantiator/Exception/UnexpectedValueException.php';
  59. require 'phar://phpunit-9.2.5.phar' . '/doctrine-instantiator/Doctrine/Instantiator/InstantiatorInterface.php';
  60. require 'phar://phpunit-9.2.5.phar' . '/doctrine-instantiator/Doctrine/Instantiator/Instantiator.php';
  61. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Exception.php';
  62. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Framework/Assert.php';
  63. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Framework/SelfDescribing.php';
  64. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Framework/Exception/Exception.php';
  65. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Framework/Exception/AssertionFailedError.php';
  66. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Framework/Exception/CodeCoverageException.php';
  67. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Framework/Constraint/Constraint.php';
  68. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Framework/Constraint/ArrayHasKey.php';
  69. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Framework/Constraint/Callback.php';
  70. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Framework/Constraint/ClassHasAttribute.php';
  71. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Framework/Constraint/ClassHasStaticAttribute.php';
  72. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Framework/Constraint/Count.php';
  73. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Framework/Constraint/DirectoryExists.php';
  74. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Framework/Constraint/Exception.php';
  75. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Framework/Constraint/ExceptionCode.php';
  76. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Framework/Constraint/ExceptionMessage.php';
  77. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Framework/Constraint/ExceptionMessageRegularExpression.php';
  78. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Framework/Constraint/FileExists.php';
  79. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Framework/Constraint/GreaterThan.php';
  80. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Framework/Constraint/IsAnything.php';
  81. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Framework/Constraint/IsEmpty.php';
  82. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Framework/Constraint/IsEqual.php';
  83. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Framework/Constraint/IsEqualCanonicalizing.php';
  84. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Framework/Constraint/IsEqualIgnoringCase.php';
  85. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Framework/Constraint/IsEqualWithDelta.php';
  86. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Framework/Constraint/IsFalse.php';
  87. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Framework/Constraint/IsFinite.php';
  88. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Framework/Constraint/IsIdentical.php';
  89. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Framework/Constraint/IsInfinite.php';
  90. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Framework/Constraint/IsInstanceOf.php';
  91. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Framework/Constraint/IsJson.php';
  92. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Framework/Constraint/IsNan.php';
  93. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Framework/Constraint/IsNull.php';
  94. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Framework/Constraint/IsReadable.php';
  95. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Framework/Constraint/IsTrue.php';
  96. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Framework/Constraint/IsType.php';
  97. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Framework/Constraint/IsWritable.php';
  98. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Framework/Constraint/JsonMatches.php';
  99. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Framework/Constraint/JsonMatchesErrorMessageProvider.php';
  100. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Framework/Constraint/LessThan.php';
  101. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Framework/Constraint/LogicalAnd.php';
  102. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Framework/Constraint/LogicalNot.php';
  103. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Framework/Constraint/LogicalOr.php';
  104. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Framework/Constraint/LogicalXor.php';
  105. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Framework/Constraint/ObjectHasAttribute.php';
  106. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Framework/Constraint/RegularExpression.php';
  107. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Framework/Constraint/SameSize.php';
  108. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Framework/Constraint/StringContains.php';
  109. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Framework/Constraint/StringEndsWith.php';
  110. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Framework/Constraint/StringMatchesFormatDescription.php';
  111. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Framework/Constraint/StringStartsWith.php';
  112. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Framework/Constraint/TraversableContains.php';
  113. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Framework/Constraint/TraversableContainsEqual.php';
  114. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Framework/Constraint/TraversableContainsIdentical.php';
  115. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Framework/Constraint/TraversableContainsOnly.php';
  116. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Framework/Exception/RiskyTestError.php';
  117. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Framework/Exception/CoveredCodeNotExecutedException.php';
  118. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Framework/Test.php';
  119. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Framework/TestSuite.php';
  120. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Framework/DataProviderTestSuite.php';
  121. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Framework/Error/Error.php';
  122. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Framework/Error/Deprecated.php';
  123. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Framework/Error/Notice.php';
  124. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Framework/Error/Warning.php';
  125. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Framework/ExceptionWrapper.php';
  126. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Framework/Exception/ExpectationFailedException.php';
  127. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Framework/IncompleteTest.php';
  128. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Framework/TestCase.php';
  129. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Framework/IncompleteTestCase.php';
  130. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Framework/Exception/IncompleteTestError.php';
  131. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Framework/Exception/InvalidArgumentException.php';
  132. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Framework/Exception/InvalidCoversTargetException.php';
  133. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Framework/Exception/InvalidDataProviderException.php';
  134. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Framework/InvalidParameterGroupException.php';
  135. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Framework/Exception/MissingCoversAnnotationException.php';
  136. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Framework/MockObject/Api/Api.php';
  137. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Framework/MockObject/Exception/Exception.php';
  138. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Framework/MockObject/Exception/BadMethodCallException.php';
  139. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Framework/MockObject/Builder/Identity.php';
  140. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Framework/MockObject/Builder/InvocationStubber.php';
  141. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Framework/MockObject/Builder/Stub.php';
  142. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Framework/MockObject/Builder/Match.php';
  143. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Framework/MockObject/Builder/ParametersMatch.php';
  144. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Framework/MockObject/Builder/MethodNameMatch.php';
  145. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Framework/MockObject/Builder/InvocationMocker.php';
  146. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Framework/MockObject/ConfigurableMethod.php';
  147. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Framework/MockObject/Exception/ConfigurableMethodsAlreadyInitializedException.php';
  148. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Framework/MockObject/Generator.php';
  149. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Framework/MockObject/Exception/IncompatibleReturnValueException.php';
  150. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Framework/MockObject/Invocation.php';
  151. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Framework/MockObject/InvocationHandler.php';
  152. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Framework/MockObject/Matcher.php';
  153. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Framework/MockObject/Api/Method.php';
  154. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Framework/MockObject/MethodNameConstraint.php';
  155. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Framework/MockObject/MockBuilder.php';
  156. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Framework/MockObject/MockType.php';
  157. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Framework/MockObject/MockClass.php';
  158. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Framework/MockObject/MockMethod.php';
  159. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Framework/MockObject/MockMethodSet.php';
  160. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Framework/MockObject/Stub.php';
  161. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Framework/MockObject/MockObject.php';
  162. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Framework/MockObject/MockTrait.php';
  163. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Framework/MockObject/Api/MockedCloneMethod.php';
  164. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Framework/MockObject/Verifiable.php';
  165. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Framework/MockObject/Rule/InvocationOrder.php';
  166. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Framework/MockObject/Rule/AnyInvokedCount.php';
  167. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Framework/MockObject/Rule/ParametersRule.php';
  168. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Framework/MockObject/Rule/AnyParameters.php';
  169. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Framework/MockObject/Rule/ConsecutiveParameters.php';
  170. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Framework/MockObject/Rule/InvokedAtIndex.php';
  171. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Framework/MockObject/Rule/InvokedAtLeastCount.php';
  172. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Framework/MockObject/Rule/InvokedAtLeastOnce.php';
  173. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Framework/MockObject/Rule/InvokedAtMostCount.php';
  174. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Framework/MockObject/Rule/InvokedCount.php';
  175. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Framework/MockObject/Rule/MethodName.php';
  176. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Framework/MockObject/Rule/Parameters.php';
  177. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Framework/MockObject/Exception/RuntimeException.php';
  178. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Framework/MockObject/Stub/Stub.php';
  179. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Framework/MockObject/Stub/ConsecutiveCalls.php';
  180. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Framework/MockObject/Stub/Exception.php';
  181. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Framework/MockObject/Stub/ReturnArgument.php';
  182. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Framework/MockObject/Stub/ReturnCallback.php';
  183. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Framework/MockObject/Stub/ReturnReference.php';
  184. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Framework/MockObject/Stub/ReturnSelf.php';
  185. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Framework/MockObject/Stub/ReturnStub.php';
  186. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Framework/MockObject/Stub/ReturnValueMap.php';
  187. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Framework/MockObject/Api/UnmockedCloneMethod.php';
  188. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Framework/Exception/NoChildTestSuiteException.php';
  189. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Framework/Exception/OutputError.php';
  190. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Framework/Exception/SyntheticError.php';
  191. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Framework/Exception/PHPTAssertionFailedError.php';
  192. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Framework/SkippedTest.php';
  193. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Framework/SkippedTestCase.php';
  194. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Framework/Exception/SkippedTestError.php';
  195. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Framework/Exception/SkippedTestSuiteError.php';
  196. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Framework/Exception/SyntheticSkippedError.php';
  197. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Framework/TestBuilder.php';
  198. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Framework/TestFailure.php';
  199. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Framework/TestListener.php';
  200. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Framework/TestListenerDefaultImplementation.php';
  201. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Framework/TestResult.php';
  202. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Framework/TestSuiteIterator.php';
  203. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Framework/Exception/UnintentionallyCoveredCodeError.php';
  204. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Framework/Exception/Warning.php';
  205. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Framework/WarningTestCase.php';
  206. require 'phar://phpunit-9.2.5.phar' . '/php-token-stream/Token.php';
  207. require 'phar://phpunit-9.2.5.phar' . '/php-token-stream/Token/Stream.php';
  208. require 'phar://phpunit-9.2.5.phar' . '/php-token-stream/Token/Stream/CachingFactory.php';
  209. require 'phar://phpunit-9.2.5.phar' . '/php-token-stream/Token/Util.php';
  210. require 'phar://phpunit-9.2.5.phar' . '/phar-io-manifest/values/Type.php';
  211. require 'phar://phpunit-9.2.5.phar' . '/phar-io-manifest/values/Application.php';
  212. require 'phar://phpunit-9.2.5.phar' . '/phar-io-manifest/values/ApplicationName.php';
  213. require 'phar://phpunit-9.2.5.phar' . '/phar-io-manifest/values/Author.php';
  214. require 'phar://phpunit-9.2.5.phar' . '/phar-io-manifest/values/AuthorCollection.php';
  215. require 'phar://phpunit-9.2.5.phar' . '/phar-io-manifest/values/AuthorCollectionIterator.php';
  216. require 'phar://phpunit-9.2.5.phar' . '/phar-io-manifest/xml/ManifestElement.php';
  217. require 'phar://phpunit-9.2.5.phar' . '/phar-io-manifest/xml/AuthorElement.php';
  218. require 'phar://phpunit-9.2.5.phar' . '/phar-io-manifest/xml/ElementCollection.php';
  219. require 'phar://phpunit-9.2.5.phar' . '/phar-io-manifest/xml/AuthorElementCollection.php';
  220. require 'phar://phpunit-9.2.5.phar' . '/phar-io-manifest/values/BundledComponent.php';
  221. require 'phar://phpunit-9.2.5.phar' . '/phar-io-manifest/values/BundledComponentCollection.php';
  222. require 'phar://phpunit-9.2.5.phar' . '/phar-io-manifest/values/BundledComponentCollectionIterator.php';
  223. require 'phar://phpunit-9.2.5.phar' . '/phar-io-manifest/xml/BundlesElement.php';
  224. require 'phar://phpunit-9.2.5.phar' . '/phar-io-manifest/xml/ComponentElement.php';
  225. require 'phar://phpunit-9.2.5.phar' . '/phar-io-manifest/xml/ComponentElementCollection.php';
  226. require 'phar://phpunit-9.2.5.phar' . '/phar-io-manifest/xml/ContainsElement.php';
  227. require 'phar://phpunit-9.2.5.phar' . '/phar-io-manifest/xml/CopyrightElement.php';
  228. require 'phar://phpunit-9.2.5.phar' . '/phar-io-manifest/values/CopyrightInformation.php';
  229. require 'phar://phpunit-9.2.5.phar' . '/phar-io-manifest/values/Email.php';
  230. require 'phar://phpunit-9.2.5.phar' . '/phar-io-manifest/exceptions/Exception.php';
  231. require 'phar://phpunit-9.2.5.phar' . '/phar-io-manifest/xml/ExtElement.php';
  232. require 'phar://phpunit-9.2.5.phar' . '/phar-io-manifest/xml/ExtElementCollection.php';
  233. require 'phar://phpunit-9.2.5.phar' . '/phar-io-manifest/values/Extension.php';
  234. require 'phar://phpunit-9.2.5.phar' . '/phar-io-manifest/xml/ExtensionElement.php';
  235. require 'phar://phpunit-9.2.5.phar' . '/phar-io-manifest/exceptions/InvalidApplicationNameException.php';
  236. require 'phar://phpunit-9.2.5.phar' . '/phar-io-manifest/exceptions/InvalidEmailException.php';
  237. require 'phar://phpunit-9.2.5.phar' . '/phar-io-manifest/exceptions/InvalidUrlException.php';
  238. require 'phar://phpunit-9.2.5.phar' . '/phar-io-manifest/values/Library.php';
  239. require 'phar://phpunit-9.2.5.phar' . '/phar-io-manifest/values/License.php';
  240. require 'phar://phpunit-9.2.5.phar' . '/phar-io-manifest/xml/LicenseElement.php';
  241. require 'phar://phpunit-9.2.5.phar' . '/phar-io-manifest/values/Manifest.php';
  242. require 'phar://phpunit-9.2.5.phar' . '/phar-io-manifest/xml/ManifestDocument.php';
  243. require 'phar://phpunit-9.2.5.phar' . '/phar-io-manifest/exceptions/ManifestDocumentException.php';
  244. require 'phar://phpunit-9.2.5.phar' . '/phar-io-manifest/xml/ManifestDocumentLoadingException.php';
  245. require 'phar://phpunit-9.2.5.phar' . '/phar-io-manifest/ManifestDocumentMapper.php';
  246. require 'phar://phpunit-9.2.5.phar' . '/phar-io-manifest/exceptions/ManifestDocumentMapperException.php';
  247. require 'phar://phpunit-9.2.5.phar' . '/phar-io-manifest/exceptions/ManifestElementException.php';
  248. require 'phar://phpunit-9.2.5.phar' . '/phar-io-manifest/ManifestLoader.php';
  249. require 'phar://phpunit-9.2.5.phar' . '/phar-io-manifest/exceptions/ManifestLoaderException.php';
  250. require 'phar://phpunit-9.2.5.phar' . '/phar-io-manifest/ManifestSerializer.php';
  251. require 'phar://phpunit-9.2.5.phar' . '/phar-io-manifest/xml/PhpElement.php';
  252. require 'phar://phpunit-9.2.5.phar' . '/phar-io-manifest/values/Requirement.php';
  253. require 'phar://phpunit-9.2.5.phar' . '/phar-io-manifest/values/PhpExtensionRequirement.php';
  254. require 'phar://phpunit-9.2.5.phar' . '/phar-io-manifest/values/PhpVersionRequirement.php';
  255. require 'phar://phpunit-9.2.5.phar' . '/phar-io-manifest/values/RequirementCollection.php';
  256. require 'phar://phpunit-9.2.5.phar' . '/phar-io-manifest/values/RequirementCollectionIterator.php';
  257. require 'phar://phpunit-9.2.5.phar' . '/phar-io-manifest/xml/RequiresElement.php';
  258. require 'phar://phpunit-9.2.5.phar' . '/phar-io-manifest/values/Url.php';
  259. require 'phar://phpunit-9.2.5.phar' . '/phar-io-version/constraints/VersionConstraint.php';
  260. require 'phar://phpunit-9.2.5.phar' . '/phar-io-version/constraints/AbstractVersionConstraint.php';
  261. require 'phar://phpunit-9.2.5.phar' . '/phar-io-version/constraints/AndVersionConstraintGroup.php';
  262. require 'phar://phpunit-9.2.5.phar' . '/phar-io-version/constraints/AnyVersionConstraint.php';
  263. require 'phar://phpunit-9.2.5.phar' . '/phar-io-version/constraints/ExactVersionConstraint.php';
  264. require 'phar://phpunit-9.2.5.phar' . '/phar-io-version/exceptions/Exception.php';
  265. require 'phar://phpunit-9.2.5.phar' . '/phar-io-version/constraints/GreaterThanOrEqualToVersionConstraint.php';
  266. require 'phar://phpunit-9.2.5.phar' . '/phar-io-version/exceptions/InvalidPreReleaseSuffixException.php';
  267. require 'phar://phpunit-9.2.5.phar' . '/phar-io-version/exceptions/InvalidVersionException.php';
  268. require 'phar://phpunit-9.2.5.phar' . '/phar-io-version/constraints/OrVersionConstraintGroup.php';
  269. require 'phar://phpunit-9.2.5.phar' . '/phar-io-version/PreReleaseSuffix.php';
  270. require 'phar://phpunit-9.2.5.phar' . '/phar-io-version/constraints/SpecificMajorAndMinorVersionConstraint.php';
  271. require 'phar://phpunit-9.2.5.phar' . '/phar-io-version/constraints/SpecificMajorVersionConstraint.php';
  272. require 'phar://phpunit-9.2.5.phar' . '/phar-io-version/exceptions/UnsupportedVersionConstraintException.php';
  273. require 'phar://phpunit-9.2.5.phar' . '/phar-io-version/Version.php';
  274. require 'phar://phpunit-9.2.5.phar' . '/phar-io-version/VersionConstraintParser.php';
  275. require 'phar://phpunit-9.2.5.phar' . '/phar-io-version/VersionConstraintValue.php';
  276. require 'phar://phpunit-9.2.5.phar' . '/phar-io-version/VersionNumber.php';
  277. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Runner/Hook/Hook.php';
  278. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Runner/Hook/TestHook.php';
  279. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Runner/Hook/AfterIncompleteTestHook.php';
  280. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Runner/Hook/AfterLastTestHook.php';
  281. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Runner/Hook/AfterRiskyTestHook.php';
  282. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Runner/Hook/AfterSkippedTestHook.php';
  283. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Runner/Hook/AfterSuccessfulTestHook.php';
  284. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Runner/Hook/AfterTestErrorHook.php';
  285. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Runner/Hook/AfterTestFailureHook.php';
  286. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Runner/Hook/AfterTestHook.php';
  287. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Runner/Hook/AfterTestWarningHook.php';
  288. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Runner/BaseTestRunner.php';
  289. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Runner/Hook/BeforeFirstTestHook.php';
  290. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Runner/Hook/BeforeTestHook.php';
  291. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Runner/TestResultCache.php';
  292. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Runner/DefaultTestResultCache.php';
  293. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Runner/Exception.php';
  294. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Runner/Filter/GroupFilterIterator.php';
  295. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Runner/Filter/ExcludeGroupFilterIterator.php';
  296. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Runner/Filter/Factory.php';
  297. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Runner/Filter/IncludeGroupFilterIterator.php';
  298. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Runner/Filter/NameFilterIterator.php';
  299. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Runner/NullTestResultCache.php';
  300. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Runner/PhptTestCase.php';
  301. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Runner/ResultCacheExtension.php';
  302. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Runner/TestSuiteLoader.php';
  303. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Runner/StandardTestSuiteLoader.php';
  304. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Runner/Hook/TestListenerAdapter.php';
  305. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Runner/TestSuiteSorter.php';
  306. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Runner/Version.php';
  307. require 'phar://phpunit-9.2.5.phar' . '/php-code-coverage/CodeCoverage.php';
  308. require 'phar://phpunit-9.2.5.phar' . '/php-code-coverage/Exception/Exception.php';
  309. require 'phar://phpunit-9.2.5.phar' . '/php-code-coverage/Exception/RuntimeException.php';
  310. require 'phar://phpunit-9.2.5.phar' . '/php-code-coverage/Exception/CoveredCodeNotExecutedException.php';
  311. require 'phar://phpunit-9.2.5.phar' . '/php-code-coverage/Directory.php';
  312. require 'phar://phpunit-9.2.5.phar' . '/php-code-coverage/Exception/DirectoryCouldNotBeCreatedException.php';
  313. require 'phar://phpunit-9.2.5.phar' . '/php-code-coverage/Driver/Driver.php';
  314. require 'phar://phpunit-9.2.5.phar' . '/php-code-coverage/Driver/PCOV.php';
  315. require 'phar://phpunit-9.2.5.phar' . '/php-code-coverage/Driver/PHPDBG.php';
  316. require 'phar://phpunit-9.2.5.phar' . '/php-code-coverage/Driver/Xdebug.php';
  317. require 'phar://phpunit-9.2.5.phar' . '/php-code-coverage/Filter.php';
  318. require 'phar://phpunit-9.2.5.phar' . '/php-code-coverage/Exception/InvalidArgumentException.php';
  319. require 'phar://phpunit-9.2.5.phar' . '/php-code-coverage/Exception/MissingCoversAnnotationException.php';
  320. require 'phar://phpunit-9.2.5.phar' . '/php-code-coverage/Node/AbstractNode.php';
  321. require 'phar://phpunit-9.2.5.phar' . '/php-code-coverage/Node/Builder.php';
  322. require 'phar://phpunit-9.2.5.phar' . '/php-code-coverage/Node/Directory.php';
  323. require 'phar://phpunit-9.2.5.phar' . '/php-code-coverage/Node/File.php';
  324. require 'phar://phpunit-9.2.5.phar' . '/php-code-coverage/Node/Iterator.php';
  325. require 'phar://phpunit-9.2.5.phar' . '/php-code-coverage/Percentage.php';
  326. require 'phar://phpunit-9.2.5.phar' . '/php-code-coverage/Report/Clover.php';
  327. require 'phar://phpunit-9.2.5.phar' . '/php-code-coverage/Report/Crap4j.php';
  328. require 'phar://phpunit-9.2.5.phar' . '/php-code-coverage/Report/Html/Renderer.php';
  329. require 'phar://phpunit-9.2.5.phar' . '/php-code-coverage/Report/Html/Renderer/Dashboard.php';
  330. require 'phar://phpunit-9.2.5.phar' . '/php-code-coverage/Report/Html/Renderer/Directory.php';
  331. require 'phar://phpunit-9.2.5.phar' . '/php-code-coverage/Report/Html/Facade.php';
  332. require 'phar://phpunit-9.2.5.phar' . '/php-code-coverage/Report/Html/Renderer/File.php';
  333. require 'phar://phpunit-9.2.5.phar' . '/php-code-coverage/Report/PHP.php';
  334. require 'phar://phpunit-9.2.5.phar' . '/php-code-coverage/Report/Text.php';
  335. require 'phar://phpunit-9.2.5.phar' . '/php-code-coverage/Report/Xml/BuildInformation.php';
  336. require 'phar://phpunit-9.2.5.phar' . '/php-code-coverage/Report/Xml/Coverage.php';
  337. require 'phar://phpunit-9.2.5.phar' . '/php-code-coverage/Report/Xml/Node.php';
  338. require 'phar://phpunit-9.2.5.phar' . '/php-code-coverage/Report/Xml/Directory.php';
  339. require 'phar://phpunit-9.2.5.phar' . '/php-code-coverage/Report/Xml/Facade.php';
  340. require 'phar://phpunit-9.2.5.phar' . '/php-code-coverage/Report/Xml/File.php';
  341. require 'phar://phpunit-9.2.5.phar' . '/php-code-coverage/Report/Xml/Method.php';
  342. require 'phar://phpunit-9.2.5.phar' . '/php-code-coverage/Report/Xml/Project.php';
  343. require 'phar://phpunit-9.2.5.phar' . '/php-code-coverage/Report/Xml/Report.php';
  344. require 'phar://phpunit-9.2.5.phar' . '/php-code-coverage/Report/Xml/Source.php';
  345. require 'phar://phpunit-9.2.5.phar' . '/php-code-coverage/Report/Xml/Tests.php';
  346. require 'phar://phpunit-9.2.5.phar' . '/php-code-coverage/Report/Xml/Totals.php';
  347. require 'phar://phpunit-9.2.5.phar' . '/php-code-coverage/Report/Xml/Unit.php';
  348. require 'phar://phpunit-9.2.5.phar' . '/php-code-coverage/Exception/UnintentionallyCoveredCodeException.php';
  349. require 'phar://phpunit-9.2.5.phar' . '/php-code-coverage/Version.php';
  350. require 'phar://phpunit-9.2.5.phar' . '/sebastian-code-unit-reverse-lookup/Wizard.php';
  351. require 'phar://phpunit-9.2.5.phar' . '/sebastian-code-unit/CodeUnit.php';
  352. require 'phar://phpunit-9.2.5.phar' . '/sebastian-code-unit/ClassMethodUnit.php';
  353. require 'phar://phpunit-9.2.5.phar' . '/sebastian-code-unit/ClassUnit.php';
  354. require 'phar://phpunit-9.2.5.phar' . '/sebastian-code-unit/CodeUnitCollection.php';
  355. require 'phar://phpunit-9.2.5.phar' . '/sebastian-code-unit/CodeUnitCollectionIterator.php';
  356. require 'phar://phpunit-9.2.5.phar' . '/sebastian-code-unit/exceptions/Exception.php';
  357. require 'phar://phpunit-9.2.5.phar' . '/sebastian-code-unit/FunctionUnit.php';
  358. require 'phar://phpunit-9.2.5.phar' . '/sebastian-code-unit/InterfaceMethodUnit.php';
  359. require 'phar://phpunit-9.2.5.phar' . '/sebastian-code-unit/InterfaceUnit.php';
  360. require 'phar://phpunit-9.2.5.phar' . '/sebastian-code-unit/exceptions/InvalidCodeUnitException.php';
  361. require 'phar://phpunit-9.2.5.phar' . '/sebastian-code-unit/Mapper.php';
  362. require 'phar://phpunit-9.2.5.phar' . '/sebastian-code-unit/exceptions/NoTraitException.php';
  363. require 'phar://phpunit-9.2.5.phar' . '/sebastian-code-unit/exceptions/ReflectionException.php';
  364. require 'phar://phpunit-9.2.5.phar' . '/sebastian-code-unit/TraitMethodUnit.php';
  365. require 'phar://phpunit-9.2.5.phar' . '/sebastian-code-unit/TraitUnit.php';
  366. require 'phar://phpunit-9.2.5.phar' . '/sebastian-comparator/Comparator.php';
  367. require 'phar://phpunit-9.2.5.phar' . '/sebastian-comparator/ArrayComparator.php';
  368. require 'phar://phpunit-9.2.5.phar' . '/sebastian-comparator/ComparisonFailure.php';
  369. require 'phar://phpunit-9.2.5.phar' . '/sebastian-comparator/ObjectComparator.php';
  370. require 'phar://phpunit-9.2.5.phar' . '/sebastian-comparator/DOMNodeComparator.php';
  371. require 'phar://phpunit-9.2.5.phar' . '/sebastian-comparator/DateTimeComparator.php';
  372. require 'phar://phpunit-9.2.5.phar' . '/sebastian-comparator/ScalarComparator.php';
  373. require 'phar://phpunit-9.2.5.phar' . '/sebastian-comparator/NumericComparator.php';
  374. require 'phar://phpunit-9.2.5.phar' . '/sebastian-comparator/DoubleComparator.php';
  375. require 'phar://phpunit-9.2.5.phar' . '/sebastian-comparator/exceptions/Exception.php';
  376. require 'phar://phpunit-9.2.5.phar' . '/sebastian-comparator/ExceptionComparator.php';
  377. require 'phar://phpunit-9.2.5.phar' . '/sebastian-comparator/Factory.php';
  378. require 'phar://phpunit-9.2.5.phar' . '/sebastian-comparator/MockObjectComparator.php';
  379. require 'phar://phpunit-9.2.5.phar' . '/sebastian-comparator/ResourceComparator.php';
  380. require 'phar://phpunit-9.2.5.phar' . '/sebastian-comparator/exceptions/RuntimeException.php';
  381. require 'phar://phpunit-9.2.5.phar' . '/sebastian-comparator/SplObjectStorageComparator.php';
  382. require 'phar://phpunit-9.2.5.phar' . '/sebastian-comparator/TypeComparator.php';
  383. require 'phar://phpunit-9.2.5.phar' . '/sebastian-diff/Chunk.php';
  384. require 'phar://phpunit-9.2.5.phar' . '/sebastian-diff/Exception/Exception.php';
  385. require 'phar://phpunit-9.2.5.phar' . '/sebastian-diff/Exception/InvalidArgumentException.php';
  386. require 'phar://phpunit-9.2.5.phar' . '/sebastian-diff/Exception/ConfigurationException.php';
  387. require 'phar://phpunit-9.2.5.phar' . '/sebastian-diff/Diff.php';
  388. require 'phar://phpunit-9.2.5.phar' . '/sebastian-diff/Differ.php';
  389. require 'phar://phpunit-9.2.5.phar' . '/sebastian-diff/Line.php';
  390. require 'phar://phpunit-9.2.5.phar' . '/sebastian-diff/LongestCommonSubsequenceCalculator.php';
  391. require 'phar://phpunit-9.2.5.phar' . '/sebastian-diff/MemoryEfficientLongestCommonSubsequenceCalculator.php';
  392. require 'phar://phpunit-9.2.5.phar' . '/sebastian-diff/Output/DiffOutputBuilderInterface.php';
  393. require 'phar://phpunit-9.2.5.phar' . '/sebastian-diff/Output/AbstractChunkOutputBuilder.php';
  394. require 'phar://phpunit-9.2.5.phar' . '/sebastian-diff/Output/DiffOnlyOutputBuilder.php';
  395. require 'phar://phpunit-9.2.5.phar' . '/sebastian-diff/Output/StrictUnifiedDiffOutputBuilder.php';
  396. require 'phar://phpunit-9.2.5.phar' . '/sebastian-diff/Output/UnifiedDiffOutputBuilder.php';
  397. require 'phar://phpunit-9.2.5.phar' . '/sebastian-diff/Parser.php';
  398. require 'phar://phpunit-9.2.5.phar' . '/sebastian-diff/TimeEfficientLongestCommonSubsequenceCalculator.php';
  399. require 'phar://phpunit-9.2.5.phar' . '/sebastian-environment/Console.php';
  400. require 'phar://phpunit-9.2.5.phar' . '/sebastian-environment/OperatingSystem.php';
  401. require 'phar://phpunit-9.2.5.phar' . '/sebastian-environment/Runtime.php';
  402. require 'phar://phpunit-9.2.5.phar' . '/sebastian-exporter/Exporter.php';
  403. require 'phar://phpunit-9.2.5.phar' . '/php-file-iterator/Facade.php';
  404. require 'phar://phpunit-9.2.5.phar' . '/php-file-iterator/Factory.php';
  405. require 'phar://phpunit-9.2.5.phar' . '/php-file-iterator/Iterator.php';
  406. require 'phar://phpunit-9.2.5.phar' . '/sebastian-global-state/Blacklist.php';
  407. require 'phar://phpunit-9.2.5.phar' . '/sebastian-global-state/CodeExporter.php';
  408. require 'phar://phpunit-9.2.5.phar' . '/sebastian-global-state/exceptions/Exception.php';
  409. require 'phar://phpunit-9.2.5.phar' . '/sebastian-global-state/Restorer.php';
  410. require 'phar://phpunit-9.2.5.phar' . '/sebastian-global-state/exceptions/RuntimeException.php';
  411. require 'phar://phpunit-9.2.5.phar' . '/sebastian-global-state/Snapshot.php';
  412. require 'phar://phpunit-9.2.5.phar' . '/php-invoker/exceptions/Exception.php';
  413. require 'phar://phpunit-9.2.5.phar' . '/php-invoker/Invoker.php';
  414. require 'phar://phpunit-9.2.5.phar' . '/php-invoker/exceptions/ProcessControlExtensionNotLoadedException.php';
  415. require 'phar://phpunit-9.2.5.phar' . '/php-invoker/exceptions/TimeoutException.php';
  416. require 'phar://phpunit-9.2.5.phar' . '/sebastian-object-enumerator/Enumerator.php';
  417. require 'phar://phpunit-9.2.5.phar' . '/sebastian-object-enumerator/Exception.php';
  418. require 'phar://phpunit-9.2.5.phar' . '/sebastian-object-enumerator/InvalidArgumentException.php';
  419. require 'phar://phpunit-9.2.5.phar' . '/sebastian-object-reflector/Exception.php';
  420. require 'phar://phpunit-9.2.5.phar' . '/sebastian-object-reflector/InvalidArgumentException.php';
  421. require 'phar://phpunit-9.2.5.phar' . '/sebastian-object-reflector/ObjectReflector.php';
  422. require 'phar://phpunit-9.2.5.phar' . '/sebastian-recursion-context/Context.php';
  423. require 'phar://phpunit-9.2.5.phar' . '/sebastian-recursion-context/Exception.php';
  424. require 'phar://phpunit-9.2.5.phar' . '/sebastian-recursion-context/InvalidArgumentException.php';
  425. require 'phar://phpunit-9.2.5.phar' . '/sebastian-resource-operations/ResourceOperations.php';
  426. require 'phar://phpunit-9.2.5.phar' . '/php-text-template/exceptions/Exception.php';
  427. require 'phar://phpunit-9.2.5.phar' . '/php-text-template/exceptions/InvalidArgumentException.php';
  428. require 'phar://phpunit-9.2.5.phar' . '/php-text-template/exceptions/RuntimeException.php';
  429. require 'phar://phpunit-9.2.5.phar' . '/php-text-template/Template.php';
  430. require 'phar://phpunit-9.2.5.phar' . '/php-timer/Duration.php';
  431. require 'phar://phpunit-9.2.5.phar' . '/php-timer/exceptions/Exception.php';
  432. require 'phar://phpunit-9.2.5.phar' . '/php-timer/exceptions/NoActiveTimerException.php';
  433. require 'phar://phpunit-9.2.5.phar' . '/php-timer/ResourceUsageFormatter.php';
  434. require 'phar://phpunit-9.2.5.phar' . '/php-timer/exceptions/TimeSinceStartOfRequestNotAvailableException.php';
  435. require 'phar://phpunit-9.2.5.phar' . '/php-timer/Timer.php';
  436. require 'phar://phpunit-9.2.5.phar' . '/sebastian-type/Type.php';
  437. require 'phar://phpunit-9.2.5.phar' . '/sebastian-type/CallableType.php';
  438. require 'phar://phpunit-9.2.5.phar' . '/sebastian-type/exception/Exception.php';
  439. require 'phar://phpunit-9.2.5.phar' . '/sebastian-type/GenericObjectType.php';
  440. require 'phar://phpunit-9.2.5.phar' . '/sebastian-type/IterableType.php';
  441. require 'phar://phpunit-9.2.5.phar' . '/sebastian-type/NullType.php';
  442. require 'phar://phpunit-9.2.5.phar' . '/sebastian-type/ObjectType.php';
  443. require 'phar://phpunit-9.2.5.phar' . '/sebastian-type/ReflectionMapper.php';
  444. require 'phar://phpunit-9.2.5.phar' . '/sebastian-type/exception/RuntimeException.php';
  445. require 'phar://phpunit-9.2.5.phar' . '/sebastian-type/SimpleType.php';
  446. require 'phar://phpunit-9.2.5.phar' . '/sebastian-type/TypeName.php';
  447. require 'phar://phpunit-9.2.5.phar' . '/sebastian-type/UnionType.php';
  448. require 'phar://phpunit-9.2.5.phar' . '/sebastian-type/UnknownType.php';
  449. require 'phar://phpunit-9.2.5.phar' . '/sebastian-type/VoidType.php';
  450. require 'phar://phpunit-9.2.5.phar' . '/sebastian-version/Version.php';
  451. require 'phar://phpunit-9.2.5.phar' . '/symfony-polyfill-ctype/Ctype.php';
  452. require 'phar://phpunit-9.2.5.phar' . '/phpunit/TextUI/Arguments/Arguments.php';
  453. require 'phar://phpunit-9.2.5.phar' . '/phpunit/TextUI/Arguments/ArgumentsBuilder.php';
  454. require 'phar://phpunit-9.2.5.phar' . '/phpunit/TextUI/Arguments/ArgumentsMapper.php';
  455. require 'phar://phpunit-9.2.5.phar' . '/phpunit/TextUI/Arguments/Exception.php';
  456. require 'phar://phpunit-9.2.5.phar' . '/phpunit/TextUI/Command.php';
  457. require 'phar://phpunit-9.2.5.phar' . '/phpunit/TextUI/Configuration/Configuration.php';
  458. require 'phar://phpunit-9.2.5.phar' . '/phpunit/TextUI/Configuration/PHP/Constant.php';
  459. require 'phar://phpunit-9.2.5.phar' . '/phpunit/TextUI/Configuration/PHP/ConstantCollection.php';
  460. require 'phar://phpunit-9.2.5.phar' . '/phpunit/TextUI/Configuration/PHP/ConstantCollectionIterator.php';
  461. require 'phar://phpunit-9.2.5.phar' . '/phpunit/TextUI/Configuration/Filesystem/Directory.php';
  462. require 'phar://phpunit-9.2.5.phar' . '/phpunit/TextUI/Configuration/Filesystem/DirectoryCollection.php';
  463. require 'phar://phpunit-9.2.5.phar' . '/phpunit/TextUI/Configuration/Filesystem/DirectoryCollectionIterator.php';
  464. require 'phar://phpunit-9.2.5.phar' . '/phpunit/TextUI/Configuration/Exception.php';
  465. require 'phar://phpunit-9.2.5.phar' . '/phpunit/TextUI/Configuration/PHPUnit/Extension.php';
  466. require 'phar://phpunit-9.2.5.phar' . '/phpunit/TextUI/Configuration/PHPUnit/ExtensionCollection.php';
  467. require 'phar://phpunit-9.2.5.phar' . '/phpunit/TextUI/Configuration/PHPUnit/ExtensionCollectionIterator.php';
  468. require 'phar://phpunit-9.2.5.phar' . '/phpunit/TextUI/Configuration/PHPUnit/ExtensionHandler.php';
  469. require 'phar://phpunit-9.2.5.phar' . '/phpunit/TextUI/Configuration/Filesystem/File.php';
  470. require 'phar://phpunit-9.2.5.phar' . '/phpunit/TextUI/Configuration/Filesystem/FileCollection.php';
  471. require 'phar://phpunit-9.2.5.phar' . '/phpunit/TextUI/Configuration/Filesystem/FileCollectionIterator.php';
  472. require 'phar://phpunit-9.2.5.phar' . '/phpunit/TextUI/Configuration/Filter/Filter.php';
  473. require 'phar://phpunit-9.2.5.phar' . '/phpunit/TextUI/Configuration/Filter/FilterDirectory.php';
  474. require 'phar://phpunit-9.2.5.phar' . '/phpunit/TextUI/Configuration/Filter/FilterDirectoryCollection.php';
  475. require 'phar://phpunit-9.2.5.phar' . '/phpunit/TextUI/Configuration/Filter/FilterDirectoryCollectionIterator.php';
  476. require 'phar://phpunit-9.2.5.phar' . '/phpunit/TextUI/Configuration/Filter/FilterFile.php';
  477. require 'phar://phpunit-9.2.5.phar' . '/phpunit/TextUI/Configuration/Filter/FilterFileCollection.php';
  478. require 'phar://phpunit-9.2.5.phar' . '/phpunit/TextUI/Configuration/Filter/FilterFileCollectionIterator.php';
  479. require 'phar://phpunit-9.2.5.phar' . '/phpunit/TextUI/Configuration/Generator.php';
  480. require 'phar://phpunit-9.2.5.phar' . '/phpunit/TextUI/Configuration/Group/Group.php';
  481. require 'phar://phpunit-9.2.5.phar' . '/phpunit/TextUI/Configuration/Group/GroupCollection.php';
  482. require 'phar://phpunit-9.2.5.phar' . '/phpunit/TextUI/Configuration/Group/GroupCollectionIterator.php';
  483. require 'phar://phpunit-9.2.5.phar' . '/phpunit/TextUI/Configuration/Group/Groups.php';
  484. require 'phar://phpunit-9.2.5.phar' . '/phpunit/TextUI/Configuration/PHP/IniSetting.php';
  485. require 'phar://phpunit-9.2.5.phar' . '/phpunit/TextUI/Configuration/PHP/IniSettingCollection.php';
  486. require 'phar://phpunit-9.2.5.phar' . '/phpunit/TextUI/Configuration/PHP/IniSettingCollectionIterator.php';
  487. require 'phar://phpunit-9.2.5.phar' . '/phpunit/TextUI/Configuration/Loader.php';
  488. require 'phar://phpunit-9.2.5.phar' . '/phpunit/TextUI/Configuration/Logging/CodeCoverage/Clover.php';
  489. require 'phar://phpunit-9.2.5.phar' . '/phpunit/TextUI/Configuration/Logging/CodeCoverage/Crap4j.php';
  490. require 'phar://phpunit-9.2.5.phar' . '/phpunit/TextUI/Configuration/Logging/CodeCoverage/Html.php';
  491. require 'phar://phpunit-9.2.5.phar' . '/phpunit/TextUI/Configuration/Logging/CodeCoverage/Php.php';
  492. require 'phar://phpunit-9.2.5.phar' . '/phpunit/TextUI/Configuration/Logging/CodeCoverage/Text.php';
  493. require 'phar://phpunit-9.2.5.phar' . '/phpunit/TextUI/Configuration/Logging/CodeCoverage/Xml.php';
  494. require 'phar://phpunit-9.2.5.phar' . '/phpunit/TextUI/Configuration/Logging/Junit.php';
  495. require 'phar://phpunit-9.2.5.phar' . '/phpunit/TextUI/Configuration/Logging/Logging.php';
  496. require 'phar://phpunit-9.2.5.phar' . '/phpunit/TextUI/Configuration/Logging/PlainText.php';
  497. require 'phar://phpunit-9.2.5.phar' . '/phpunit/TextUI/Configuration/Logging/TeamCity.php';
  498. require 'phar://phpunit-9.2.5.phar' . '/phpunit/TextUI/Configuration/Logging/TestDox/Html.php';
  499. require 'phar://phpunit-9.2.5.phar' . '/phpunit/TextUI/Configuration/Logging/TestDox/Text.php';
  500. require 'phar://phpunit-9.2.5.phar' . '/phpunit/TextUI/Configuration/Logging/TestDox/Xml.php';
  501. require 'phar://phpunit-9.2.5.phar' . '/phpunit/TextUI/Configuration/PHPUnit/PHPUnit.php';
  502. require 'phar://phpunit-9.2.5.phar' . '/phpunit/TextUI/Configuration/PHP/Php.php';
  503. require 'phar://phpunit-9.2.5.phar' . '/phpunit/TextUI/Configuration/PHP/PhpHandler.php';
  504. require 'phar://phpunit-9.2.5.phar' . '/phpunit/TextUI/Configuration/Registry.php';
  505. require 'phar://phpunit-9.2.5.phar' . '/phpunit/TextUI/Configuration/TestSuite/TestDirectory.php';
  506. require 'phar://phpunit-9.2.5.phar' . '/phpunit/TextUI/Configuration/TestSuite/TestDirectoryCollection.php';
  507. require 'phar://phpunit-9.2.5.phar' . '/phpunit/TextUI/Configuration/TestSuite/TestDirectoryCollectionIterator.php';
  508. require 'phar://phpunit-9.2.5.phar' . '/phpunit/TextUI/Configuration/TestSuite/TestFile.php';
  509. require 'phar://phpunit-9.2.5.phar' . '/phpunit/TextUI/Configuration/TestSuite/TestFileCollection.php';
  510. require 'phar://phpunit-9.2.5.phar' . '/phpunit/TextUI/Configuration/TestSuite/TestFileCollectionIterator.php';
  511. require 'phar://phpunit-9.2.5.phar' . '/phpunit/TextUI/Configuration/TestSuite/TestSuite.php';
  512. require 'phar://phpunit-9.2.5.phar' . '/phpunit/TextUI/Configuration/TestSuite/TestSuiteCollection.php';
  513. require 'phar://phpunit-9.2.5.phar' . '/phpunit/TextUI/Configuration/TestSuite/TestSuiteCollectionIterator.php';
  514. require 'phar://phpunit-9.2.5.phar' . '/phpunit/TextUI/Configuration/TestSuite/TestSuiteMapper.php';
  515. require 'phar://phpunit-9.2.5.phar' . '/phpunit/TextUI/Configuration/PHP/Variable.php';
  516. require 'phar://phpunit-9.2.5.phar' . '/phpunit/TextUI/Configuration/PHP/VariableCollection.php';
  517. require 'phar://phpunit-9.2.5.phar' . '/phpunit/TextUI/Configuration/PHP/VariableCollectionIterator.php';
  518. require 'phar://phpunit-9.2.5.phar' . '/phpunit/TextUI/ResultPrinter.php';
  519. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Util/Printer.php';
  520. require 'phar://phpunit-9.2.5.phar' . '/phpunit/TextUI/DefaultResultPrinter.php';
  521. require 'phar://phpunit-9.2.5.phar' . '/phpunit/TextUI/Exception.php';
  522. require 'phar://phpunit-9.2.5.phar' . '/phpunit/TextUI/Help.php';
  523. require 'phar://phpunit-9.2.5.phar' . '/phpunit/TextUI/TestRunner.php';
  524. require 'phar://phpunit-9.2.5.phar' . '/theseer-tokenizer/Exception.php';
  525. require 'phar://phpunit-9.2.5.phar' . '/theseer-tokenizer/NamespaceUri.php';
  526. require 'phar://phpunit-9.2.5.phar' . '/theseer-tokenizer/NamespaceUriException.php';
  527. require 'phar://phpunit-9.2.5.phar' . '/theseer-tokenizer/Token.php';
  528. require 'phar://phpunit-9.2.5.phar' . '/theseer-tokenizer/TokenCollection.php';
  529. require 'phar://phpunit-9.2.5.phar' . '/theseer-tokenizer/TokenCollectionException.php';
  530. require 'phar://phpunit-9.2.5.phar' . '/theseer-tokenizer/Tokenizer.php';
  531. require 'phar://phpunit-9.2.5.phar' . '/theseer-tokenizer/XMLSerializer.php';
  532. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Util/Annotation/DocBlock.php';
  533. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Util/Annotation/Registry.php';
  534. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Util/Blacklist.php';
  535. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Util/Color.php';
  536. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Util/ErrorHandler.php';
  537. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Util/Exception.php';
  538. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Util/FileLoader.php';
  539. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Util/Filesystem.php';
  540. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Util/Filter.php';
  541. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Util/Getopt.php';
  542. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Util/GlobalState.php';
  543. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Util/InvalidDataSetException.php';
  544. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Util/Json.php';
  545. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Util/Log/JUnit.php';
  546. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Util/Log/TeamCity.php';
  547. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Util/PHP/AbstractPhpProcess.php';
  548. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Util/PHP/DefaultPhpProcess.php';
  549. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Util/PHP/WindowsPhpProcess.php';
  550. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Util/RegularExpression.php';
  551. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Util/Test.php';
  552. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Util/TestDox/TestDoxPrinter.php';
  553. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Util/TestDox/CliTestDoxPrinter.php';
  554. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Util/TestDox/ResultPrinter.php';
  555. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Util/TestDox/HtmlResultPrinter.php';
  556. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Util/TestDox/NamePrettifier.php';
  557. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Util/TestDox/TextResultPrinter.php';
  558. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Util/TestDox/XmlResultPrinter.php';
  559. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Util/TextTestListRenderer.php';
  560. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Util/Type.php';
  561. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Util/VersionComparisonOperator.php';
  562. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Util/XdebugFilterScriptGenerator.php';
  563. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Util/Xml.php';
  564. require 'phar://phpunit-9.2.5.phar' . '/phpunit/Util/XmlTestListRenderer.php';
  565. require 'phar://phpunit-9.2.5.phar' . '/webmozart-assert/Assert.php';
  566. require 'phar://phpunit-9.2.5.phar' . '/webmozart-assert/Mixin.php';
  567. require 'phar://phpunit-9.2.5.phar' . '/phpdocumentor-reflection-docblock/DocBlock.php';
  568. require 'phar://phpunit-9.2.5.phar' . '/phpdocumentor-reflection-docblock/DocBlockFactoryInterface.php';
  569. require 'phar://phpunit-9.2.5.phar' . '/phpdocumentor-reflection-docblock/DocBlockFactory.php';
  570. require 'phar://phpunit-9.2.5.phar' . '/phpdocumentor-reflection-docblock/DocBlock/Description.php';
  571. require 'phar://phpunit-9.2.5.phar' . '/phpdocumentor-reflection-docblock/DocBlock/DescriptionFactory.php';
  572. require 'phar://phpunit-9.2.5.phar' . '/phpdocumentor-reflection-docblock/DocBlock/ExampleFinder.php';
  573. require 'phar://phpunit-9.2.5.phar' . '/phpdocumentor-reflection-docblock/DocBlock/Serializer.php';
  574. require 'phar://phpunit-9.2.5.phar' . '/phpdocumentor-reflection-docblock/DocBlock/TagFactory.php';
  575. require 'phar://phpunit-9.2.5.phar' . '/phpdocumentor-reflection-docblock/DocBlock/StandardTagFactory.php';
  576. require 'phar://phpunit-9.2.5.phar' . '/phpdocumentor-reflection-docblock/DocBlock/Tag.php';
  577. require 'phar://phpunit-9.2.5.phar' . '/phpdocumentor-reflection-docblock/DocBlock/Tags/Factory/StaticMethod.php';
  578. require 'phar://phpunit-9.2.5.phar' . '/phpdocumentor-reflection-docblock/DocBlock/Tags/BaseTag.php';
  579. require 'phar://phpunit-9.2.5.phar' . '/phpdocumentor-reflection-docblock/DocBlock/Tags/Author.php';
  580. require 'phar://phpunit-9.2.5.phar' . '/phpdocumentor-reflection-docblock/DocBlock/Tags/Covers.php';
  581. require 'phar://phpunit-9.2.5.phar' . '/phpdocumentor-reflection-docblock/DocBlock/Tags/Deprecated.php';
  582. require 'phar://phpunit-9.2.5.phar' . '/phpdocumentor-reflection-docblock/DocBlock/Tags/Example.php';
  583. require 'phar://phpunit-9.2.5.phar' . '/phpdocumentor-reflection-docblock/DocBlock/Tags/Formatter.php';
  584. require 'phar://phpunit-9.2.5.phar' . '/phpdocumentor-reflection-docblock/DocBlock/Tags/Formatter/AlignFormatter.php';
  585. require 'phar://phpunit-9.2.5.phar' . '/phpdocumentor-reflection-docblock/DocBlock/Tags/Formatter/PassthroughFormatter.php';
  586. require 'phar://phpunit-9.2.5.phar' . '/phpdocumentor-reflection-docblock/DocBlock/Tags/Generic.php';
  587. require 'phar://phpunit-9.2.5.phar' . '/phpdocumentor-reflection-docblock/DocBlock/Tags/InvalidTag.php';
  588. require 'phar://phpunit-9.2.5.phar' . '/phpdocumentor-reflection-docblock/DocBlock/Tags/Link.php';
  589. require 'phar://phpunit-9.2.5.phar' . '/phpdocumentor-reflection-docblock/DocBlock/Tags/Method.php';
  590. require 'phar://phpunit-9.2.5.phar' . '/phpdocumentor-reflection-docblock/DocBlock/Tags/TagWithType.php';
  591. require 'phar://phpunit-9.2.5.phar' . '/phpdocumentor-reflection-docblock/DocBlock/Tags/Param.php';
  592. require 'phar://phpunit-9.2.5.phar' . '/phpdocumentor-reflection-docblock/DocBlock/Tags/Property.php';
  593. require 'phar://phpunit-9.2.5.phar' . '/phpdocumentor-reflection-docblock/DocBlock/Tags/PropertyRead.php';
  594. require 'phar://phpunit-9.2.5.phar' . '/phpdocumentor-reflection-docblock/DocBlock/Tags/PropertyWrite.php';
  595. require 'phar://phpunit-9.2.5.phar' . '/phpdocumentor-reflection-docblock/DocBlock/Tags/Reference/Reference.php';
  596. require 'phar://phpunit-9.2.5.phar' . '/phpdocumentor-reflection-docblock/DocBlock/Tags/Reference/Fqsen.php';
  597. require 'phar://phpunit-9.2.5.phar' . '/phpdocumentor-reflection-docblock/DocBlock/Tags/Reference/Url.php';
  598. require 'phar://phpunit-9.2.5.phar' . '/phpdocumentor-reflection-docblock/DocBlock/Tags/Return_.php';
  599. require 'phar://phpunit-9.2.5.phar' . '/phpdocumentor-reflection-docblock/DocBlock/Tags/See.php';
  600. require 'phar://phpunit-9.2.5.phar' . '/phpdocumentor-reflection-docblock/DocBlock/Tags/Since.php';
  601. require 'phar://phpunit-9.2.5.phar' . '/phpdocumentor-reflection-docblock/DocBlock/Tags/Source.php';
  602. require 'phar://phpunit-9.2.5.phar' . '/phpdocumentor-reflection-docblock/DocBlock/Tags/Throws.php';
  603. require 'phar://phpunit-9.2.5.phar' . '/phpdocumentor-reflection-docblock/DocBlock/Tags/Uses.php';
  604. require 'phar://phpunit-9.2.5.phar' . '/phpdocumentor-reflection-docblock/DocBlock/Tags/Var_.php';
  605. require 'phar://phpunit-9.2.5.phar' . '/phpdocumentor-reflection-docblock/DocBlock/Tags/Version.php';
  606. require 'phar://phpunit-9.2.5.phar' . '/phpdocumentor-reflection-common/Element.php';
  607. require 'phar://phpunit-9.2.5.phar' . '/phpdocumentor-reflection-common/File.php';
  608. require 'phar://phpunit-9.2.5.phar' . '/phpdocumentor-reflection-common/Fqsen.php';
  609. require 'phar://phpunit-9.2.5.phar' . '/phpdocumentor-type-resolver/FqsenResolver.php';
  610. require 'phar://phpunit-9.2.5.phar' . '/phpdocumentor-reflection-common/Location.php';
  611. require 'phar://phpunit-9.2.5.phar' . '/phpdocumentor-reflection-common/Project.php';
  612. require 'phar://phpunit-9.2.5.phar' . '/phpdocumentor-reflection-common/ProjectFactory.php';
  613. require 'phar://phpunit-9.2.5.phar' . '/phpdocumentor-type-resolver/Type.php';
  614. require 'phar://phpunit-9.2.5.phar' . '/phpdocumentor-type-resolver/TypeResolver.php';
  615. require 'phar://phpunit-9.2.5.phar' . '/phpdocumentor-type-resolver/Types/AbstractList.php';
  616. require 'phar://phpunit-9.2.5.phar' . '/phpdocumentor-type-resolver/Types/AggregatedType.php';
  617. require 'phar://phpunit-9.2.5.phar' . '/phpdocumentor-type-resolver/Types/Array_.php';
  618. require 'phar://phpunit-9.2.5.phar' . '/phpdocumentor-type-resolver/Types/Boolean.php';
  619. require 'phar://phpunit-9.2.5.phar' . '/phpdocumentor-type-resolver/Types/Callable_.php';
  620. require 'phar://phpunit-9.2.5.phar' . '/phpdocumentor-type-resolver/Types/ClassString.php';
  621. require 'phar://phpunit-9.2.5.phar' . '/phpdocumentor-type-resolver/Types/Collection.php';
  622. require 'phar://phpunit-9.2.5.phar' . '/phpdocumentor-type-resolver/Types/Compound.php';
  623. require 'phar://phpunit-9.2.5.phar' . '/phpdocumentor-type-resolver/Types/Context.php';
  624. require 'phar://phpunit-9.2.5.phar' . '/phpdocumentor-type-resolver/Types/ContextFactory.php';
  625. require 'phar://phpunit-9.2.5.phar' . '/phpdocumentor-type-resolver/Types/Expression.php';
  626. require 'phar://phpunit-9.2.5.phar' . '/phpdocumentor-type-resolver/Types/False_.php';
  627. require 'phar://phpunit-9.2.5.phar' . '/phpdocumentor-type-resolver/Types/Float_.php';
  628. require 'phar://phpunit-9.2.5.phar' . '/phpdocumentor-type-resolver/Types/Integer.php';
  629. require 'phar://phpunit-9.2.5.phar' . '/phpdocumentor-type-resolver/Types/Intersection.php';
  630. require 'phar://phpunit-9.2.5.phar' . '/phpdocumentor-type-resolver/Types/Iterable_.php';
  631. require 'phar://phpunit-9.2.5.phar' . '/phpdocumentor-type-resolver/Types/Mixed_.php';
  632. require 'phar://phpunit-9.2.5.phar' . '/phpdocumentor-type-resolver/Types/Null_.php';
  633. require 'phar://phpunit-9.2.5.phar' . '/phpdocumentor-type-resolver/Types/Nullable.php';
  634. require 'phar://phpunit-9.2.5.phar' . '/phpdocumentor-type-resolver/Types/Object_.php';
  635. require 'phar://phpunit-9.2.5.phar' . '/phpdocumentor-type-resolver/Types/Parent_.php';
  636. require 'phar://phpunit-9.2.5.phar' . '/phpdocumentor-type-resolver/Types/Resource_.php';
  637. require 'phar://phpunit-9.2.5.phar' . '/phpdocumentor-type-resolver/Types/Scalar.php';
  638. require 'phar://phpunit-9.2.5.phar' . '/phpdocumentor-type-resolver/Types/Self_.php';
  639. require 'phar://phpunit-9.2.5.phar' . '/phpdocumentor-type-resolver/Types/Static_.php';
  640. require 'phar://phpunit-9.2.5.phar' . '/phpdocumentor-type-resolver/Types/String_.php';
  641. require 'phar://phpunit-9.2.5.phar' . '/phpdocumentor-type-resolver/Types/This.php';
  642. require 'phar://phpunit-9.2.5.phar' . '/phpdocumentor-type-resolver/Types/True_.php';
  643. require 'phar://phpunit-9.2.5.phar' . '/phpdocumentor-type-resolver/Types/Void_.php';
  644. require 'phar://phpunit-9.2.5.phar' . '/phpspec-prophecy/Prophecy/Argument.php';
  645. require 'phar://phpunit-9.2.5.phar' . '/phpspec-prophecy/Prophecy/Argument/ArgumentsWildcard.php';
  646. require 'phar://phpunit-9.2.5.phar' . '/phpspec-prophecy/Prophecy/Argument/Token/TokenInterface.php';
  647. require 'phar://phpunit-9.2.5.phar' . '/phpspec-prophecy/Prophecy/Argument/Token/AnyValueToken.php';
  648. require 'phar://phpunit-9.2.5.phar' . '/phpspec-prophecy/Prophecy/Argument/Token/AnyValuesToken.php';
  649. require 'phar://phpunit-9.2.5.phar' . '/phpspec-prophecy/Prophecy/Argument/Token/ApproximateValueToken.php';
  650. require 'phar://phpunit-9.2.5.phar' . '/phpspec-prophecy/Prophecy/Argument/Token/ArrayCountToken.php';
  651. require 'phar://phpunit-9.2.5.phar' . '/phpspec-prophecy/Prophecy/Argument/Token/ArrayEntryToken.php';
  652. require 'phar://phpunit-9.2.5.phar' . '/phpspec-prophecy/Prophecy/Argument/Token/ArrayEveryEntryToken.php';
  653. require 'phar://phpunit-9.2.5.phar' . '/phpspec-prophecy/Prophecy/Argument/Token/CallbackToken.php';
  654. require 'phar://phpunit-9.2.5.phar' . '/phpspec-prophecy/Prophecy/Argument/Token/ExactValueToken.php';
  655. require 'phar://phpunit-9.2.5.phar' . '/phpspec-prophecy/Prophecy/Argument/Token/IdenticalValueToken.php';
  656. require 'phar://phpunit-9.2.5.phar' . '/phpspec-prophecy/Prophecy/Argument/Token/LogicalAndToken.php';
  657. require 'phar://phpunit-9.2.5.phar' . '/phpspec-prophecy/Prophecy/Argument/Token/LogicalNotToken.php';
  658. require 'phar://phpunit-9.2.5.phar' . '/phpspec-prophecy/Prophecy/Argument/Token/ObjectStateToken.php';
  659. require 'phar://phpunit-9.2.5.phar' . '/phpspec-prophecy/Prophecy/Argument/Token/StringContainsToken.php';
  660. require 'phar://phpunit-9.2.5.phar' . '/phpspec-prophecy/Prophecy/Argument/Token/TypeToken.php';
  661. require 'phar://phpunit-9.2.5.phar' . '/phpspec-prophecy/Prophecy/Call/Call.php';
  662. require 'phar://phpunit-9.2.5.phar' . '/phpspec-prophecy/Prophecy/Call/CallCenter.php';
  663. require 'phar://phpunit-9.2.5.phar' . '/phpspec-prophecy/Prophecy/Comparator/ClosureComparator.php';
  664. require 'phar://phpunit-9.2.5.phar' . '/phpspec-prophecy/Prophecy/Comparator/Factory.php';
  665. require 'phar://phpunit-9.2.5.phar' . '/phpspec-prophecy/Prophecy/Comparator/ProphecyComparator.php';
  666. require 'phar://phpunit-9.2.5.phar' . '/phpspec-prophecy/Prophecy/Doubler/Doubler.php';
  667. require 'phar://phpunit-9.2.5.phar' . '/phpspec-prophecy/Prophecy/Doubler/CachedDoubler.php';
  668. require 'phar://phpunit-9.2.5.phar' . '/phpspec-prophecy/Prophecy/Doubler/ClassPatch/ClassPatchInterface.php';
  669. require 'phar://phpunit-9.2.5.phar' . '/phpspec-prophecy/Prophecy/Doubler/ClassPatch/DisableConstructorPatch.php';
  670. require 'phar://phpunit-9.2.5.phar' . '/phpspec-prophecy/Prophecy/Doubler/ClassPatch/HhvmExceptionPatch.php';
  671. require 'phar://phpunit-9.2.5.phar' . '/phpspec-prophecy/Prophecy/Doubler/ClassPatch/KeywordPatch.php';
  672. require 'phar://phpunit-9.2.5.phar' . '/phpspec-prophecy/Prophecy/Doubler/ClassPatch/MagicCallPatch.php';
  673. require 'phar://phpunit-9.2.5.phar' . '/phpspec-prophecy/Prophecy/Doubler/ClassPatch/ProphecySubjectPatch.php';
  674. require 'phar://phpunit-9.2.5.phar' . '/phpspec-prophecy/Prophecy/Doubler/ClassPatch/ReflectionClassNewInstancePatch.php';
  675. require 'phar://phpunit-9.2.5.phar' . '/phpspec-prophecy/Prophecy/Doubler/ClassPatch/SplFileInfoPatch.php';
  676. require 'phar://phpunit-9.2.5.phar' . '/phpspec-prophecy/Prophecy/Doubler/ClassPatch/ThrowablePatch.php';
  677. require 'phar://phpunit-9.2.5.phar' . '/phpspec-prophecy/Prophecy/Doubler/ClassPatch/TraversablePatch.php';
  678. require 'phar://phpunit-9.2.5.phar' . '/phpspec-prophecy/Prophecy/Doubler/DoubleInterface.php';
  679. require 'phar://phpunit-9.2.5.phar' . '/phpspec-prophecy/Prophecy/Doubler/Generator/ClassCodeGenerator.php';
  680. require 'phar://phpunit-9.2.5.phar' . '/phpspec-prophecy/Prophecy/Doubler/Generator/ClassCreator.php';
  681. require 'phar://phpunit-9.2.5.phar' . '/phpspec-prophecy/Prophecy/Doubler/Generator/ClassMirror.php';
  682. require 'phar://phpunit-9.2.5.phar' . '/phpspec-prophecy/Prophecy/Doubler/Generator/Node/ArgumentNode.php';
  683. require 'phar://phpunit-9.2.5.phar' . '/phpspec-prophecy/Prophecy/Doubler/Generator/Node/ClassNode.php';
  684. require 'phar://phpunit-9.2.5.phar' . '/phpspec-prophecy/Prophecy/Doubler/Generator/Node/MethodNode.php';
  685. require 'phar://phpunit-9.2.5.phar' . '/phpspec-prophecy/Prophecy/Doubler/Generator/ReflectionInterface.php';
  686. require 'phar://phpunit-9.2.5.phar' . '/phpspec-prophecy/Prophecy/Doubler/Generator/TypeHintReference.php';
  687. require 'phar://phpunit-9.2.5.phar' . '/phpspec-prophecy/Prophecy/Doubler/LazyDouble.php';
  688. require 'phar://phpunit-9.2.5.phar' . '/phpspec-prophecy/Prophecy/Doubler/NameGenerator.php';
  689. require 'phar://phpunit-9.2.5.phar' . '/phpspec-prophecy/Prophecy/Exception/Exception.php';
  690. require 'phar://phpunit-9.2.5.phar' . '/phpspec-prophecy/Prophecy/Exception/Prophecy/ProphecyException.php';
  691. require 'phar://phpunit-9.2.5.phar' . '/phpspec-prophecy/Prophecy/Exception/Prophecy/ObjectProphecyException.php';
  692. require 'phar://phpunit-9.2.5.phar' . '/phpspec-prophecy/Prophecy/Exception/Call/UnexpectedCallException.php';
  693. require 'phar://phpunit-9.2.5.phar' . '/phpspec-prophecy/Prophecy/Exception/Doubler/DoublerException.php';
  694. require 'phar://phpunit-9.2.5.phar' . '/phpspec-prophecy/Prophecy/Exception/Doubler/ClassCreatorException.php';
  695. require 'phar://phpunit-9.2.5.phar' . '/phpspec-prophecy/Prophecy/Exception/Doubler/ClassMirrorException.php';
  696. require 'phar://phpunit-9.2.5.phar' . '/phpspec-prophecy/Prophecy/Exception/Doubler/DoubleException.php';
  697. require 'phar://phpunit-9.2.5.phar' . '/phpspec-prophecy/Prophecy/Exception/Doubler/ClassNotFoundException.php';
  698. require 'phar://phpunit-9.2.5.phar' . '/phpspec-prophecy/Prophecy/Exception/Doubler/InterfaceNotFoundException.php';
  699. require 'phar://phpunit-9.2.5.phar' . '/phpspec-prophecy/Prophecy/Exception/Doubler/MethodNotExtendableException.php';
  700. require 'phar://phpunit-9.2.5.phar' . '/phpspec-prophecy/Prophecy/Exception/Doubler/MethodNotFoundException.php';
  701. require 'phar://phpunit-9.2.5.phar' . '/phpspec-prophecy/Prophecy/Exception/Doubler/ReturnByReferenceException.php';
  702. require 'phar://phpunit-9.2.5.phar' . '/phpspec-prophecy/Prophecy/Exception/InvalidArgumentException.php';
  703. require 'phar://phpunit-9.2.5.phar' . '/phpspec-prophecy/Prophecy/Exception/Prediction/PredictionException.php';
  704. require 'phar://phpunit-9.2.5.phar' . '/phpspec-prophecy/Prophecy/Exception/Prediction/AggregateException.php';
  705. require 'phar://phpunit-9.2.5.phar' . '/phpspec-prophecy/Prophecy/Exception/Prediction/FailedPredictionException.php';
  706. require 'phar://phpunit-9.2.5.phar' . '/phpspec-prophecy/Prophecy/Exception/Prophecy/MethodProphecyException.php';
  707. require 'phar://phpunit-9.2.5.phar' . '/phpspec-prophecy/Prophecy/Exception/Prediction/NoCallsException.php';
  708. require 'phar://phpunit-9.2.5.phar' . '/phpspec-prophecy/Prophecy/Exception/Prediction/UnexpectedCallsException.php';
  709. require 'phar://phpunit-9.2.5.phar' . '/phpspec-prophecy/Prophecy/Exception/Prediction/UnexpectedCallsCountException.php';
  710. require 'phar://phpunit-9.2.5.phar' . '/phpspec-prophecy/Prophecy/PhpDocumentor/MethodTagRetrieverInterface.php';
  711. require 'phar://phpunit-9.2.5.phar' . '/phpspec-prophecy/Prophecy/PhpDocumentor/ClassAndInterfaceTagRetriever.php';
  712. require 'phar://phpunit-9.2.5.phar' . '/phpspec-prophecy/Prophecy/PhpDocumentor/ClassTagRetriever.php';
  713. require 'phar://phpunit-9.2.5.phar' . '/phpspec-prophecy/Prophecy/PhpDocumentor/LegacyClassTagRetriever.php';
  714. require 'phar://phpunit-9.2.5.phar' . '/phpspec-prophecy/Prophecy/Prediction/PredictionInterface.php';
  715. require 'phar://phpunit-9.2.5.phar' . '/phpspec-prophecy/Prophecy/Prediction/CallPrediction.php';
  716. require 'phar://phpunit-9.2.5.phar' . '/phpspec-prophecy/Prophecy/Prediction/CallTimesPrediction.php';
  717. require 'phar://phpunit-9.2.5.phar' . '/phpspec-prophecy/Prophecy/Prediction/CallbackPrediction.php';
  718. require 'phar://phpunit-9.2.5.phar' . '/phpspec-prophecy/Prophecy/Prediction/NoCallsPrediction.php';
  719. require 'phar://phpunit-9.2.5.phar' . '/phpspec-prophecy/Prophecy/Promise/PromiseInterface.php';
  720. require 'phar://phpunit-9.2.5.phar' . '/phpspec-prophecy/Prophecy/Promise/CallbackPromise.php';
  721. require 'phar://phpunit-9.2.5.phar' . '/phpspec-prophecy/Prophecy/Promise/ReturnArgumentPromise.php';
  722. require 'phar://phpunit-9.2.5.phar' . '/phpspec-prophecy/Prophecy/Promise/ReturnPromise.php';
  723. require 'phar://phpunit-9.2.5.phar' . '/phpspec-prophecy/Prophecy/Promise/ThrowPromise.php';
  724. require 'phar://phpunit-9.2.5.phar' . '/phpspec-prophecy/Prophecy/Prophecy/MethodProphecy.php';
  725. require 'phar://phpunit-9.2.5.phar' . '/phpspec-prophecy/Prophecy/Prophecy/ProphecyInterface.php';
  726. require 'phar://phpunit-9.2.5.phar' . '/phpspec-prophecy/Prophecy/Prophecy/ObjectProphecy.php';
  727. require 'phar://phpunit-9.2.5.phar' . '/phpspec-prophecy/Prophecy/Prophecy/ProphecySubjectInterface.php';
  728. require 'phar://phpunit-9.2.5.phar' . '/phpspec-prophecy/Prophecy/Prophecy/RevealerInterface.php';
  729. require 'phar://phpunit-9.2.5.phar' . '/phpspec-prophecy/Prophecy/Prophecy/Revealer.php';
  730. require 'phar://phpunit-9.2.5.phar' . '/phpspec-prophecy/Prophecy/Prophet.php';
  731. require 'phar://phpunit-9.2.5.phar' . '/phpspec-prophecy/Prophecy/Util/ExportUtil.php';
  732. require 'phar://phpunit-9.2.5.phar' . '/phpspec-prophecy/Prophecy/Util/StringUtil.php';
  733. require __PHPUNIT_PHAR_ROOT__ . '/phpunit/Framework/Assert/Functions.php';
  734. if ($execute) {
  735. if (isset($printManifest)) {
  736. print file_get_contents(__PHPUNIT_PHAR_ROOT__ . '/manifest.txt');
  737. exit;
  738. }
  739. unset($execute);
  740. PHPUnit\TextUI\Command::main();
  741. }
  742. __HALT_COMPILER(); ?>
  743. Íâ�����������phpunit-9.2.5.phar�������webmozart-assert/Assert.phpzÆ��¼Yð^zÆ��<bפ���������webmozart-assert/Mixin.phpÓÀ��¼Yð^ÓÀ��þ�]®¤���������webmozart-assert/LICENSE<��¼Yð^<��tØ}õ¤������)���phpdocumentor-reflection-common/Fqsen.phpÍ��¼Yð^Í��ÈáðR¤������2���phpdocumentor-reflection-common/ProjectFactory.php���¼Yð^���Aah¦¤������(���phpdocumentor-reflection-common/File.phpŸ��¼Yð^Ÿ��°ˆI)¤������,���phpdocumentor-reflection-common/Location.php‘��¼Yð^‘��=­(œ¤������+���phpdocumentor-reflection-common/Project.php��¼Yð^��¬¦J¤������+���phpdocumentor-reflection-common/Element.php+��¼Yð^+��ã_ë¤������'���phpdocumentor-reflection-common/LICENSE9��¼Yð^9��*2È�¤���������php-text-template/Template.phpÕ��¼Yð^Õ��,yO¿¤������1���php-text-template/exceptions/RuntimeException.php¼��¼Yð^¼��ŸëÈˤ������*���php-text-template/exceptions/Exception.phpX��¼Yð^X��d¤‹ë¤������9���php-text-template/exceptions/InvalidArgumentException.phpÄ��¼Yð^Ä��µ‹1ɤ���������php-text-template/LICENSE��¼Yð^��u¹¤������.���sebastian-object-reflector/ObjectReflector.phpª��¼Yð^ª��>}yC¤������(���sebastian-object-reflector/Exception.php`��¼Yð^`��ƒR*¤������7���sebastian-object-reflector/InvalidArgumentException.phpÍ��¼Yð^Í��jï{¤���������php-invoker/Invoker.phpá��¼Yð^á��ßï�¤������D���php-invoker/exceptions/ProcessControlExtensionNotLoadedException.phpÅ��¼Yð^Å��ë�£¤������+���php-invoker/exceptions/TimeoutException.php¬��¼Yð^¬��$
  744. ò1¤������$���php-invoker/exceptions/Exception.phpd��¼Yð^d��q¹,ç¤������8���phar-io-version/constraints/OrVersionConstraintGroup.phpf��¼Yð^f��1b)u¤������1���phar-io-version/constraints/VersionConstraint.phpT��¼Yð^T��%þÔø¤������6���phar-io-version/constraints/ExactVersionConstraint.php–��¼Yð^–�� Ô±.¤������4���phar-io-version/constraints/AnyVersionConstraint.phpÈ��¼Yð^È��"L�*¤������>���phar-io-version/constraints/SpecificMajorVersionConstraint.php²��¼Yð^²��ÛÉàš¤������F���phar-io-version/constraints/SpecificMajorAndMinorVersionConstraint.php—��¼Yð^—��6“4¤������E���phar-io-version/constraints/GreaterThanOrEqualToVersionConstraint.phpU��¼Yð^U��´h믤������9���phar-io-version/constraints/AbstractVersionConstraint.php��¼Yð^��lfææ¤������9���phar-io-version/constraints/AndVersionConstraintGroup.phph��¼Yð^h�� ZŽœ¤������!���phar-io-version/VersionNumber.php4��¼Yð^4��{ {¤������+���phar-io-version/VersionConstraintParser.php× ��¼Yð^× ��ÔÄÁ8¤���������phar-io-version/Version.php
  745. ��¼Yð^
  746. ��åË>¤������?���phar-io-version/exceptions/InvalidPreReleaseSuffixException.php•���¼Yð^•���‹…劤������D���phar-io-version/exceptions/UnsupportedVersionConstraintException.phpÙ��¼Yð^Ù��²0O™¤������(���phar-io-version/exceptions/Exception.phpt��¼Yð^t��9$ª4¤������6���phar-io-version/exceptions/InvalidVersionException.php›���¼Yð^›���’å²X¤������$���phar-io-version/PreReleaseSuffix.phpk��¼Yð^k��ëÀ‹¤���������phar-io-version/LICENSE1��¼Yð^1��>²»:¤������*���phar-io-version/VersionConstraintValue.phpx
  747. ��¼Yð^x
  748. ��~ðMU¤������*���sebastian-object-enumerator/Enumerator.php ��¼Yð^ ��!bÂƤ������)���sebastian-object-enumerator/Exception.phpb��¼Yð^b���{2»¤������8���sebastian-object-enumerator/InvalidArgumentException.phpÐ��¼Yð^Ð��¸XDÿ¤������ ���phpunit.xsdÕB��¼Yð^ÕB��I•*)¤���������php-timer/Timer.phpÁ��¼Yð^Á��Ý£â!¤������$���php-timer/ResourceUsageFormatter.phpÈ��¼Yð^È��2ž¤¤���������php-timer/Duration.phpø ��¼Yð^ø ��}/�¤������/���php-timer/exceptions/NoActiveTimerException.phpª��¼Yð^ª��¦ÚìƤ������E���php-timer/exceptions/TimeSinceStartOfRequestNotAvailableException.phpÂ��¼Yð^Â��›²ɤ������"���php-timer/exceptions/Exception.phpM��¼Yð^M��{ï^¤���������php-timer/LICENSE��¼Yð^��x™¸œ¤������$���sebastian-global-state/Blacklist.phpÇ
  749. ��¼Yð^Ç
  750. ��É"–Á¤������#���sebastian-global-state/Snapshot.php¥(��¼Yð^¥(��LÞ�¤������'���sebastian-global-state/CodeExporter.php ��¼Yð^ ��í?%œ¤������#���sebastian-global-state/Restorer.php‚��¼Yð^‚��³¿ ¤������6���sebastian-global-state/exceptions/RuntimeException.php·��¼Yð^·��Wþ¼y¤������/���sebastian-global-state/exceptions/Exception.phpX��¼Yð^X��2î²>¤���������sebastian-global-state/LICENSE��¼Yð^��a‡©¤������:���myclabs-deep-copy/DeepCopy/Matcher/PropertyNameMatcher.php��¼Yð^��¤(Z¤������6���myclabs-deep-copy/DeepCopy/Matcher/PropertyMatcher.phpÐ��¼Yð^Ð��öÌõŸ¤������.���myclabs-deep-copy/DeepCopy/Matcher/Matcher.phpÝ���¼Yð^Ý���º§³ê¤������D���myclabs-deep-copy/DeepCopy/Matcher/Doctrine/DoctrineProxyMatcher.phpÅ��¼Yð^Å��Bå§�¤������:���myclabs-deep-copy/DeepCopy/Matcher/PropertyTypeMatcher.phpk��¼Yð^k��r­•<¤������:���myclabs-deep-copy/DeepCopy/Exception/PropertyException.php€���¼Yð^€���–=œ€¤������7���myclabs-deep-copy/DeepCopy/Exception/CloneException.php‡���¼Yð^‡���ÖHŤ������(���myclabs-deep-copy/DeepCopy/deep_copy.php²��¼Yð^²��bÅSÙ¤������3���myclabs-deep-copy/DeepCopy/Filter/ReplaceFilter.phpÓ��¼Yð^Ó�� ‚™ò¤������3���myclabs-deep-copy/DeepCopy/Filter/SetNullFilter.php'��¼Yð^'��™©„L¤������0���myclabs-deep-copy/DeepCopy/Filter/KeepFilter.php(��¼Yð^(��9 [¼¤������,���myclabs-deep-copy/DeepCopy/Filter/Filter.phpd��¼Yð^d��³Mð¤������G���myclabs-deep-copy/DeepCopy/Filter/Doctrine/DoctrineCollectionFilter.php@��¼Yð^@��1 ,¤������L���myclabs-deep-copy/DeepCopy/Filter/Doctrine/DoctrineEmptyCollectionFilter.php;��¼Yð^;��K1d¤������B���myclabs-deep-copy/DeepCopy/Filter/Doctrine/DoctrineProxyFilter.php»��¼Yð^»��n)K¤������6���myclabs-deep-copy/DeepCopy/TypeMatcher/TypeMatcher.phpÝ��¼Yð^Ý��„QBŤ������7���myclabs-deep-copy/DeepCopy/TypeFilter/ReplaceFilter.php0��¼Yð^0��/ø²¤������4���myclabs-deep-copy/DeepCopy/TypeFilter/TypeFilter.phpÊ���¼Yð^Ê���’VDº¤������?���myclabs-deep-copy/DeepCopy/TypeFilter/Spl/ArrayObjectFilter.phpõ��¼Yð^õ��QṲ̈������A���myclabs-deep-copy/DeepCopy/TypeFilter/Spl/SplDoublyLinkedList.phpÙ���¼Yð^Ù��� n¥·¤������G���myclabs-deep-copy/DeepCopy/TypeFilter/Spl/SplDoublyLinkedListFilter.php`��¼Yð^`��#QKŸ¤������;���myclabs-deep-copy/DeepCopy/TypeFilter/ShallowCopyFilter.php��¼Yð^��ÕÞa7¤������A���myclabs-deep-copy/DeepCopy/TypeFilter/Date/DateIntervalFilter.php©��¼Yð^©��µN®¤������:���myclabs-deep-copy/DeepCopy/Reflection/ReflectionHelper.phpT��¼Yð^T��ÁÁª¦¤������'���myclabs-deep-copy/DeepCopy/DeepCopy.php`��¼Yð^`��I*”C¤���������myclabs-deep-copy/LICENSE5��¼Yð^5��Ê­Ë„¤���������sebastian-type/UnknownType.phpm��¼Yð^m��šlºV¤������$���sebastian-type/GenericObjectType.php(��¼Yð^(���*z¤���������sebastian-type/UnionType.phpu
  751. ��¼Yð^u
  752. ��M²Y·¤���������sebastian-type/CallableType.php«��¼Yð^«��™ªè¤���������sebastian-type/VoidType.php‘��¼Yð^‘���l¼ø¤���������sebastian-type/NullType.phpœ��¼Yð^œ��1¤K¤���������sebastian-type/ObjectType.phpC��¼Yð^C��l§€¤���������sebastian-type/SimpleType.phpì��¼Yð^ì��¥$µç¤���������sebastian-type/TypeName.php ��¼Yð^ ��?³™¤������#���sebastian-type/ReflectionMapper.php ��¼Yð^ ��ÿ–¤���������sebastian-type/IterableType.phpá��¼Yð^á��dDE¤���������sebastian-type/Type.phpÔ
  753. ��¼Yð^Ô
  754. ��$¤���������sebastian-type/LICENSE ��¼Yð^ �� +Τ������-���sebastian-type/exception/RuntimeException.php¡��¼Yð^¡�� rŒ¤������&���sebastian-type/exception/Exception.phpI��¼Yð^I��œ+bm¤���������sebastian-version/Version.php®��¼Yð^®�� ƪ�¤���������sebastian-version/LICENSE��¼Yð^��­ZÌù¤������A���phpdocumentor-reflection-docblock/DocBlock/StandardTagFactory.php6��¼Yð^6��Þ@T¤������9���phpdocumentor-reflection-docblock/DocBlock/Serializer.phpï��¼Yð^ï��ä^Ée¤������9���phpdocumentor-reflection-docblock/DocBlock/TagFactory.phpÕ��¼Yð^Õ��Ï–µ[¤������7���phpdocumentor-reflection-docblock/DocBlock/Tags/See.php‹ ��¼Yð^‹ ��—O~¤������;���phpdocumentor-reflection-docblock/DocBlock/Tags/Generic.phpH
  755. ��¼Yð^H
  756. ��ŒÉ¯w¤������>���phpdocumentor-reflection-docblock/DocBlock/Tags/InvalidTag.phpå��¼Yð^å��zúÅî¤������:���phpdocumentor-reflection-docblock/DocBlock/Tags/Source.php ��¼Yð^ ��wù¸¤������:���phpdocumentor-reflection-docblock/DocBlock/Tags/Method.php\ ��¼Yð^\ ��ða2y¤������=���phpdocumentor-reflection-docblock/DocBlock/Tags/Formatter.phpI��¼Yð^I��Œžãͤ������A���phpdocumentor-reflection-docblock/DocBlock/Tags/Reference/Url.php!��¼Yð^!��ëx&¤������C���phpdocumentor-reflection-docblock/DocBlock/Tags/Reference/Fqsen.php„��¼Yð^„��mQÒ>¤������G���phpdocumentor-reflection-docblock/DocBlock/Tags/Reference/Reference.phpÔ��¼Yð^Ô��ª ¢¤������;���phpdocumentor-reflection-docblock/DocBlock/Tags/BaseTag.php9��¼Yð^9��ù@ºØ¤������:���phpdocumentor-reflection-docblock/DocBlock/Tags/Author.php^ ��¼Yð^^ ��W[ýŸ¤������9���phpdocumentor-reflection-docblock/DocBlock/Tags/Since.php¯
  757. ��¼Yð^¯
  758. ��¦f³è¤������R���phpdocumentor-reflection-docblock/DocBlock/Tags/Formatter/PassthroughFormatter.php��¼Yð^��, ñG¤������L���phpdocumentor-reflection-docblock/DocBlock/Tags/Formatter/AlignFormatter.phpÐ��¼Yð^Ð��b0š¤������@���phpdocumentor-reflection-docblock/DocBlock/Tags/PropertyRead.php��¼Yð^��ò™X:¤������?���phpdocumentor-reflection-docblock/DocBlock/Tags/TagWithType.php��¼Yð^��‚•.̤������H���phpdocumentor-reflection-docblock/DocBlock/Tags/Factory/StaticMethod.php��¼Yð^��.ý·Í¤������A���phpdocumentor-reflection-docblock/DocBlock/Tags/PropertyWrite.php��¼Yð^��t쮤������;���phpdocumentor-reflection-docblock/DocBlock/Tags/Version.php' ��¼Yð^' ���ƒä
  759. ¤������>���phpdocumentor-reflection-docblock/DocBlock/Tags/Deprecated.phpC ��¼Yð^C ��áÄ ¡¤������8���phpdocumentor-reflection-docblock/DocBlock/Tags/Link.phpå��¼Yð^å��ˆý%¥¤������8���phpdocumentor-reflection-docblock/DocBlock/Tags/Var_.php��¼Yð^��ŒB@µ¤������;���phpdocumentor-reflection-docblock/DocBlock/Tags/Return_.php—��¼Yð^—��fç
  760. å¤������:���phpdocumentor-reflection-docblock/DocBlock/Tags/Covers.php[ ��¼Yð^[ ��Júù¤������;���phpdocumentor-reflection-docblock/DocBlock/Tags/Example.phpú��¼Yð^ú��bðj¤������9���phpdocumentor-reflection-docblock/DocBlock/Tags/Param.php^��¼Yð^^��2q.�¤������8���phpdocumentor-reflection-docblock/DocBlock/Tags/Uses.php> ��¼Yð^> ��>Ó‡Á¤������:���phpdocumentor-reflection-docblock/DocBlock/Tags/Throws.php’��¼Yð^’��$/%¤������<���phpdocumentor-reflection-docblock/DocBlock/Tags/Property.php ��¼Yð^ ��èü¦É¤������2���phpdocumentor-reflection-docblock/DocBlock/Tag.phpØ��¼Yð^Ø��–-5¤������<���phpdocumentor-reflection-docblock/DocBlock/ExampleFinder.phpn��¼Yð^n��/Ù…å¤������A���phpdocumentor-reflection-docblock/DocBlock/DescriptionFactory.php ��¼Yð^ ��Ìɽ¸¤������:���phpdocumentor-reflection-docblock/DocBlock/Description.phpA��¼Yð^A��ÀÒû¤������5���phpdocumentor-reflection-docblock/DocBlockFactory.php0'��¼Yð^0'��æ—šH¤������.���phpdocumentor-reflection-docblock/DocBlock.phpÄ��¼Yð^Ä��Y#Í/¤������)���phpdocumentor-reflection-docblock/LICENSE8��¼Yð^8��á‰Ê¤������>���phpdocumentor-reflection-docblock/DocBlockFactoryInterface.php ��¼Yð^ ��Žý±ß¤������/���phpdocumentor-type-resolver/Types/Resource_.php¡��¼Yð^¡��KWMg¤������.���phpdocumentor-type-resolver/Types/Compound.phpY��¼Yð^Y��^Ôþ¤������-���phpdocumentor-type-resolver/Types/Integer.php’��¼Yð^’��WÍÉ‹¤������+���phpdocumentor-type-resolver/Types/Null_.phpš��¼Yð^š�� Ô¤������-���phpdocumentor-type-resolver/Types/Parent_.php��¼Yð^��Q°—ͤ������+���phpdocumentor-type-resolver/Types/Void_.php)��¼Yð^)��ly@E¤������-���phpdocumentor-type-resolver/Types/Boolean.php���¼Yð^���š Kñ¤������4���phpdocumentor-type-resolver/Types/ContextFactory.phpž6��¼Yð^ž6��jY�ù¤������2���phpdocumentor-type-resolver/Types/AbstractList.php ��¼Yð^ ��N8,3¤������,���phpdocumentor-type-resolver/Types/False_.phps��¼Yð^s��çî^¤������-���phpdocumentor-type-resolver/Types/String_.php›��¼Yð^›��¼#K ¤������+���phpdocumentor-type-resolver/Types/True_.phpp��¼Yð^p��j~Üì¤������1���phpdocumentor-type-resolver/Types/ClassString.php ��¼Yð^ ��gEW³¤������+���phpdocumentor-type-resolver/Types/Self_.phpî��¼Yð^î��×ô�ü¤������,���phpdocumentor-type-resolver/Types/Float_.php���¼Yð^���dïW¤������-���phpdocumentor-type-resolver/Types/Static_.php'��¼Yð^'��¤ëçĤ������-���phpdocumentor-type-resolver/Types/Context.phpÞ ��¼Yð^Þ ��p÷}¤������,���phpdocumentor-type-resolver/Types/Array_.php��¼Yð^��­�5¤������-���phpdocumentor-type-resolver/Types/Object_.phpQ��¼Yð^Q��ÌêF­¤������/���phpdocumentor-type-resolver/Types/Callable_.php���¼Yð^���ª�g§¤������0���phpdocumentor-type-resolver/Types/Collection.phpP��¼Yð^P��™ó8v¤������,���phpdocumentor-type-resolver/Types/Scalar.phpÖ��¼Yð^Ö��Êt»¤������0���phpdocumentor-type-resolver/Types/Expression.phpž��¼Yð^ž��=òÖ̤������,���phpdocumentor-type-resolver/Types/Mixed_.php¢��¼Yð^¢��èSŸé¤������4���phpdocumentor-type-resolver/Types/AggregatedType.phpŠ ��¼Yð^Š ��q+*¤������/���phpdocumentor-type-resolver/Types/Iterable_.php���¼Yð^���Ñ•eÖ¤������2���phpdocumentor-type-resolver/Types/Intersection.phph��¼Yð^h��«kÈj¤������*���phpdocumentor-type-resolver/Types/This.php{��¼Yð^{��äØ6¤������.���phpdocumentor-type-resolver/Types/Nullable.php¸��¼Yð^¸��ùœ ï¤������-���phpdocumentor-type-resolver/FqsenResolver.php"
  761. ��¼Yð^"
  762. ��FåÁî¤������$���phpdocumentor-type-resolver/Type.phpÜ��¼Yð^Ü��’b¾&¤������#���phpdocumentor-type-resolver/LICENSE8��¼Yð^8��á‰Ê¤������,���phpdocumentor-type-resolver/TypeResolver.phpsL��¼Yð^sL��YOLõ¤������!���sebastian-environment/Console.php×��¼Yð^×��<â±W¤������)���sebastian-environment/OperatingSystem.phpŠ��¼Yð^Š��·ÎH>¤������!���sebastian-environment/Runtime.phpã��¼Yð^ã��ÚçϤ���������sebastian-environment/LICENSE��¼Yð^��lm|ð¤������*���sebastian-comparator/ComparisonFailure.phpü ��¼Yð^ü ���w˜ù¤������+���sebastian-comparator/ResourceComparator.phpP��¼Yð^P��j�Z¤������)���sebastian-comparator/DoubleComparator.php¾��¼Yð^¾��6uÓ5¤������*���sebastian-comparator/NumericComparator.phpA ��¼Yð^A ��œíj¤������ ���sebastian-comparator/Factory.php ��¼Yð^ ��ÙŠs¤������*���sebastian-comparator/DOMNodeComparator.phpì
  763. ��¼Yð^ì
  764. ��C™/r¤������)���sebastian-comparator/ObjectComparator.php‚ ��¼Yð^‚ ��Û3f¤������)���sebastian-comparator/ScalarComparator.phpÛ ��¼Yð^Û ��OØɤ������+���sebastian-comparator/DateTimeComparator.phpx ��¼Yð^x ��Î1‡é¤������'���sebastian-comparator/TypeComparator.php
  765. ��¼Yð^
  766. ��Ã/Q–¤������,���sebastian-comparator/ExceptionComparator.phpß��¼Yð^ß��€¤•¤������4���sebastian-comparator/exceptions/RuntimeException.php³��¼Yð^³��â8t¶¤������-���sebastian-comparator/exceptions/Exception.phpU��¼Yð^U��Æ›à^¤������3���sebastian-comparator/SplObjectStorageComparator.php[��¼Yð^[��¿�ž
  767. ¤������#���sebastian-comparator/Comparator.phpÏ��¼Yð^Ï��¶iÂ0¤������(���sebastian-comparator/ArrayComparator.phph��¼Yð^h��‹a«²¤���������sebastian-comparator/LICENSE ��¼Yð^ ��=(èã¤������-���sebastian-comparator/MockObjectComparator.php0��¼Yð^0��\îI¤������+���phar-io-manifest/ManifestDocumentMapper.phpP��¼Yð^P��I ¤������?���phar-io-manifest/exceptions/ManifestDocumentMapperException.php����¼Yð^����ÛÕ‘ç¤������3���phar-io-manifest/exceptions/InvalidUrlException.phpÌ��¼Yð^Ì��uqÁ6¤������?���phar-io-manifest/exceptions/InvalidApplicationNameException.php��¼Yð^��>ô› ¤������8���phar-io-manifest/exceptions/ManifestElementException.php–���¼Yð^–���]������7���phar-io-manifest/exceptions/ManifestLoaderException.phpŽ���¼Yð^Ž���³¾Æú¤������9���phar-io-manifest/exceptions/ManifestDocumentException.php—���¼Yð^—���"¤¦o¤������5���phar-io-manifest/exceptions/InvalidEmailException.phpÎ��¼Yð^Î��%Ïj›¤������)���phar-io-manifest/exceptions/Exception.phpv��¼Yð^v��4u_¤������'���phar-io-manifest/ManifestSerializer.phpé��¼Yð^é��6Ã^¤������#���phar-io-manifest/xml/ExtElement.phpÿ��¼Yð^ÿ���¹*¤������)���phar-io-manifest/xml/CopyrightElement.phpÙ��¼Yð^Ù��öc4¤������#���phar-io-manifest/xml/PhpElement.phpñ��¼Yð^ñ��([ôÕ¤������0���phar-io-manifest/xml/AuthorElementCollection.php4��¼Yð^4��je‘¤������*���phar-io-manifest/xml/ElementCollection.phpæ��¼Yð^æ��û»Oê¤������)���phar-io-manifest/xml/ExtensionElement.phpj��¼Yð^j��Ò/Âm¤������'���phar-io-manifest/xml/LicenseElement.php\��¼Yð^\��bb¼Ê¤������-���phar-io-manifest/xml/ExtElementCollection.php.��¼Yð^.��ìòÄ–¤������(���phar-io-manifest/xml/RequiresElement.php/��¼Yð^/��. TŽ¤������'���phar-io-manifest/xml/BundlesElement.phpN��¼Yð^N��Ô?¶†¤������(���phar-io-manifest/xml/ContainsElement.phpX��¼Yð^X��¹‰ä»¤������)���phar-io-manifest/xml/ManifestDocument.phpú ��¼Yð^ú ��7g½¤������)���phar-io-manifest/xml/ComponentElement.phpf��¼Yð^f��óò.û¤������(���phar-io-manifest/xml/ManifestElement.php= ��¼Yð^= ��'ì¤������&���phar-io-manifest/xml/AuthorElement.php_��¼Yð^_��¼9ݤ������9���phar-io-manifest/xml/ManifestDocumentLoadingException.phpK��¼Yð^K��¬ ‡N¤������3���phar-io-manifest/xml/ComponentElementCollection.php:��¼Yð^:��%º0ä¤���������phar-io-manifest/LICENSEQ��¼Yð^Q��$W0æ¤������$���phar-io-manifest/values/Manifest.phpx ��¼Yð^x ��üR ¤���������phar-io-manifest/values/Url.phpõ��¼Yð^õ��Ÿ¯ð¤������4���phar-io-manifest/values/AuthorCollectionIterator.php”��¼Yð^”��Ä"q1¤������"���phar-io-manifest/values/Author.php#��¼Yð^#��[Óš¤������+���phar-io-manifest/values/ApplicationName.php ��¼Yð^ ��ªú…¤������'���phar-io-manifest/values/Application.php��¼Yð^��ÌLa`¤������1���phar-io-manifest/values/PhpVersionRequirement.php\��¼Yð^\��¾ò�Þ¤������#���phar-io-manifest/values/License.php9��¼Yð^9��ßhe¤������#���phar-io-manifest/values/Library.phpü��¼Yð^ü��oȺ€¤������,���phar-io-manifest/values/AuthorCollection.phpí��¼Yð^í��°#h¤������'���phar-io-manifest/values/Requirement.phpx��¼Yð^x��ãDL¤������%���phar-io-manifest/values/Extension.php°��¼Yð^°��’[&E¤������>���phar-io-manifest/values/BundledComponentCollectionIterator.php��¼Yð^���ŸŸ]¤������1���phar-io-manifest/values/RequirementCollection.php.��¼Yð^.��į‘:¤������9���phar-io-manifest/values/RequirementCollectionIterator.phpË��¼Yð^Ë��~‚Ûÿ¤������!���phar-io-manifest/values/Email.php��¼Yð^��Id„r¤������ ���phar-io-manifest/values/Type.php˜��¼Yð^˜��E1'¤������6���phar-io-manifest/values/BundledComponentCollection.phpo��¼Yð^o��Дµ[¤������3���phar-io-manifest/values/PhpExtensionRequirement.phpî��¼Yð^î��{‰ƒR¤������,���phar-io-manifest/values/BundledComponent.phpÔ��¼Yð^Ô��ƒCã¤������0���phar-io-manifest/values/CopyrightInformation.phpº��¼Yð^º��¤¬0¤������#���phar-io-manifest/ManifestLoader.php«��¼Yð^«��.}æÙ¤������$���symfony-polyfill-ctype/bootstrap.php ��¼Yð^ ��ÿçg-¤������ ���symfony-polyfill-ctype/Ctype.php~��¼Yð^~��JÎÆÒ¤���������symfony-polyfill-ctype/LICENSE)��¼Yð^)��´`e0¤���������php-token-stream/Token.phpš��¼Yð^š��Ô÷—¤���������php-token-stream/Token/Util.php��¼Yð^��ܯ†¤������0���php-token-stream/Token/Stream/CachingFactory.phpp��¼Yð^p��¥0²r¤������!���php-token-stream/Token/Stream.phpÛ;��¼Yð^Û;��ˆL™¤���������php-token-stream/LICENSE��¼Yð^��ÎZ[{¤���������object-reflector/LICENSE��¼Yð^��¢9v¤������ ���manifest.txt™��¼Yð^™��Tµdh¤������R���doctrine-instantiator/Doctrine/Instantiator/Exception/UnexpectedValueException.phpŠ��¼Yð^Š��=8õé¤������L���doctrine-instantiator/Doctrine/Instantiator/Exception/ExceptionInterface.phpÈ���¼Yð^È���V®m̤������R���doctrine-instantiator/Doctrine/Instantiator/Exception/InvalidArgumentException.php×��¼Yð^×��—®eû¤������<���doctrine-instantiator/Doctrine/Instantiator/Instantiator.php���¼Yð^���ýPû¤������E���doctrine-instantiator/Doctrine/Instantiator/InstantiatorInterface.phpž��¼Yð^ž���‰m¤���������doctrine-instantiator/LICENSE$��¼Yð^$��
  768. Í‚å¤������4���sebastian-resource-operations/ResourceOperations.phpß²��¼Yð^ß²��·¦¤������%���sebastian-resource-operations/LICENSE��¼Yð^��]�<â¤������$���sebastian-code-unit/FunctionUnit.php2��¼Yð^2��ªÒ’Ÿ¤������2���sebastian-code-unit/CodeUnitCollectionIterator.phpn��¼Yð^n��¡‘YC¤���������sebastian-code-unit/Mapper.php$��¼Yð^$��ªª‚`¤������%���sebastian-code-unit/InterfaceUnit.php5��¼Yð^5��Ç÷ƒŽ¤������ ���sebastian-code-unit/CodeUnit.phpm)��¼Yð^m)��“¡<G¤������!���sebastian-code-unit/TraitUnit.php)��¼Yð^)��ð*ñ¤������+���sebastian-code-unit/InterfaceMethodUnit.phpC��¼Yð^C�� çÇX¤������'���sebastian-code-unit/ClassMethodUnit.php;��¼Yð^;��=ÃÐq¤������3���sebastian-code-unit/exceptions/NoTraitException.phpÄ��¼Yð^Ä��g€@\¤������6���sebastian-code-unit/exceptions/ReflectionException.phpÇ��¼Yð^Ç��¹Ë+2¤������,���sebastian-code-unit/exceptions/Exception.phpR��¼Yð^R��ºº‘¤������;���sebastian-code-unit/exceptions/InvalidCodeUnitException.phpÌ��¼Yð^Ì��(¸x¤������!���sebastian-code-unit/ClassUnit.php)��¼Yð^)��çFÒ¦¤������'���sebastian-code-unit/TraitMethodUnit.php;��¼Yð^;��LEؤ���������sebastian-code-unit/LICENSE ��¼Yð^ ��p”ˆð¤������*���sebastian-code-unit/CodeUnitCollection.php£��¼Yð^£��Á;‰¤���������.phpstorm.meta.phpí��¼Yð^í��’“Gó¤������?���php-code-coverage/Exception/CoveredCodeNotExecutedException.phpü��¼Yð^ü��ʼn⃤������C���php-code-coverage/Exception/DirectoryCouldNotBeCreatedException.php¹��¼Yð^¹��X¾í¤������@���php-code-coverage/Exception/MissingCoversAnnotationException.php���¼Yð^���6xì¤������0���php-code-coverage/Exception/RuntimeException.php¶��¼Yð^¶��Çy¬§¤������)���php-code-coverage/Exception/Exception.phpœ��¼Yð^œ��¿ŒD¤������C���php-code-coverage/Exception/UnintentionallyCoveredCodeException.phpw��¼Yð^w��`'wn¤������8���php-code-coverage/Exception/InvalidArgumentException.phpÄ��¼Yð^Ä��õªñ(¤������ ���php-code-coverage/Percentage.php��¼Yð^��ñWD¤���������php-code-coverage/Filter.php+��¼Yð^+��㔄c¤������#���php-code-coverage/Driver/Xdebug.php_ ��¼Yð^_ ��ö��E¤������#���php-code-coverage/Driver/PHPDBG.php½
  769. ��¼Yð^½
  770. ��⌛¤������#���php-code-coverage/Driver/Driver.php��¼Yð^��M©E¤������!���php-code-coverage/Driver/PCOV.phpå��¼Yð^å��T£:¤���������php-code-coverage/Version.phpå��¼Yð^å��Ø:'¤������"���php-code-coverage/CodeCoverage.php s��¼Yð^ s��ÔT6¤������#���php-code-coverage/Report/Crap4j.phpê��¼Yð^ê��σ'›¤������!���php-code-coverage/Report/Text.phpû��¼Yð^û��çí ¡¤������(���php-code-coverage/Report/Html/Facade.php&��¼Yð^&��ï×O�¤������*���php-code-coverage/Report/Html/Renderer.php_��¼Yð^_��F`±Œ¤������>���php-code-coverage/Report/Html/Renderer/Template/file.html.dist
  771. ��¼Yð^
  772. ��îf "¤������C���php-code-coverage/Report/Html/Renderer/Template/dashboard.html.distG��¼Yð^G��äÄl¤������C���php-code-coverage/Report/Html/Renderer/Template/directory.html.distÌ��¼Yð^Ì��GÉM³¤������?���php-code-coverage/Report/Html/Renderer/Template/js/nv.d3.min.jsÚR�¼Yð^ÚR�<Ms¤������:���php-code-coverage/Report/Html/Renderer/Template/js/file.jsù��¼Yð^ù��b�䆤������<���php-code-coverage/Report/Html/Renderer/Template/js/d3.min.js­P�¼Yð^­P�Åhéb¤������@���php-code-coverage/Report/Html/Renderer/Template/js/popper.min.jsªR��¼Yð^ªR��ZÉ\¤������@���php-code-coverage/Report/Html/Renderer/Template/js/jquery.min.jsQX�¼Yð^QX�Q†ä[¤������C���php-code-coverage/Report/Html/Renderer/Template/js/bootstrap.min.jsØâ��¼Yð^Øâ��'Ì^è¤������H���php-code-coverage/Report/Html/Renderer/Template/directory_item.html.distA��¼Yð^A��ds¤������F���php-code-coverage/Report/Html/Renderer/Template/coverage_bar.html.dist'��¼Yð^'��õO}¤������E���php-code-coverage/Report/Html/Renderer/Template/method_item.html.dist‚��¼Yð^‚��†îs:¤������>���php-code-coverage/Report/Html/Renderer/Template/css/custom.css����¼Yð^��������¤������E���php-code-coverage/Report/Html/Renderer/Template/css/bootstrap.min.cssn`�¼Yð^n`�ÑÿÓ¤������=���php-code-coverage/Report/Html/Renderer/Template/css/style.css¢��¼Yð^¢��”_æì¤������@���php-code-coverage/Report/Html/Renderer/Template/css/octicons.cssX���¼Yð^X���'#ï¤������A���php-code-coverage/Report/Html/Renderer/Template/css/nv.d3.min.cssX%��¼Yð^X%���0,¤������C���php-code-coverage/Report/Html/Renderer/Template/file_item.html.distt��¼Yð^t��Ø¿ê¤������C���php-code-coverage/Report/Html/Renderer/Template/icons/file-code.svg0��¼Yð^0��ÙQUU¤������H���php-code-coverage/Report/Html/Renderer/Template/icons/file-directory.svgê���¼Yð^ê���ýÚZÿ¤������/���php-code-coverage/Report/Html/Renderer/File.phpƒ@��¼Yð^ƒ@��‰„^³¤������4���php-code-coverage/Report/Html/Renderer/Dashboard.php ��¼Yð^ �� Xì¤������4���php-code-coverage/Report/Html/Renderer/Directory.phpû ��¼Yð^û ��æ)A¤������ ���php-code-coverage/Report/PHP.phpX��¼Yð^X��>wü(¤������1���php-code-coverage/Report/Xml/BuildInformation.phpT ��¼Yð^T ��O÷{g¤������'���php-code-coverage/Report/Xml/Source.phpJ��¼Yð^J��U§*(¤������'���php-code-coverage/Report/Xml/Facade.phpà ��¼Yð^à ��P ‘¤������'���php-code-coverage/Report/Xml/Method.phpÖ��¼Yð^Ö��è¯ö¤������'���php-code-coverage/Report/Xml/Report.php�
  773. ��¼Yð^�
  774. �� }!v¤������%���php-code-coverage/Report/Xml/File.php|��¼Yð^|��’H'L¤������'���php-code-coverage/Report/Xml/Totals.php5��¼Yð^5��v"¤������&���php-code-coverage/Report/Xml/Tests.php,��¼Yð^,��=Ce¤������%���php-code-coverage/Report/Xml/Node.phpò��¼Yð^ò��æŽ~ô¤������(���php-code-coverage/Report/Xml/Project.php ��¼Yð^ ��k�!(¤������)���php-code-coverage/Report/Xml/Coverage.php»��¼Yð^»��®Á¿Ä¤������*���php-code-coverage/Report/Xml/Directory.php©��¼Yð^©��ÄŠL¤������%���php-code-coverage/Report/Xml/Unit.phpç ��¼Yð^ç ��-ÁÒV¤������#���php-code-coverage/Report/Clover.php &��¼Yð^ &��/êb¤���������php-code-coverage/Node/File.phpå:��¼Yð^å:��„EQ“¤������"���php-code-coverage/Node/Builder.php¤��¼Yð^¤��Kg:¤������#���php-code-coverage/Node/Iterator.phpÆ��¼Yð^Æ��ßp²�¤������$���php-code-coverage/Node/Directory.php%$��¼Yð^%$�� hÿ ¤������'���php-code-coverage/Node/AbstractNode.phpÍ!��¼Yð^Í!��†v@w¤���������php-code-coverage/LICENSE��¼Yð^��½…@¤���������php-code-coverage/Directory.php��¼Yð^��é¡õ¡¤���������phpunit/Util/Xml.phpÝ��¼Yð^Ý��Ðya¤���������phpunit/Util/GlobalState.phpy��¼Yð^y��d´¤������(���phpunit/Util/InvalidDataSetException.phpÙ��¼Yð^Ù��}n™¨¤���������phpunit/Util/Log/JUnit.php$,��¼Yð^$,��lØì(¤���������phpunit/Util/Log/TeamCity.php|'��¼Yð^|'��Jç�ð¤���������phpunit/Util/Blacklist.phpÁ��¼Yð^Á��|Nr%¤���������phpunit/Util/Filter.phpJ ��¼Yð^J ��×t –¤���������phpunit/Util/Test.phpqX��¼Yð^qX��¹Éb|¤���������phpunit/Util/FileLoader.phpŽ��¼Yð^Ž���žÛ^¤���������phpunit/Util/Getopt.phpU��¼Yð^U��_Pm¤������$���phpunit/Util/XmlTestListRenderer.php¢ ��¼Yð^¢ ��ÀàÛ'¤������,���phpunit/Util/XdebugFilterScriptGenerator.phpà��¼Yð^à��†ÒÓˆ¤���������phpunit/Util/Filesystem.phpž��¼Yð^ž��æ¨[À¤������*���phpunit/Util/VersionComparisonOperator.phpW��¼Yð^W��Êž¥{¤���������phpunit/Util/Color.phpÅ ��¼Yð^Å ��·s¤������%���phpunit/Util/TextTestListRenderer.phpù��¼Yð^ù����™õ¤������"���phpunit/Util/RegularExpression.php5��¼Yð^5��üp­{¤���������phpunit/Util/ErrorHandler.phpñ��¼Yð^ñ��v™kΤ���������phpunit/Util/Exception.phpË��¼Yð^Ë��-¤������,���phpunit/Util/PHP/Template/TestCaseMethod.tplµ ��¼Yð^µ ��jw-�€������+���phpunit/Util/PHP/Template/TestCaseClass.tplf ��¼Yð^f ��¸g¶£€������*���phpunit/Util/PHP/Template/PhptTestCase.tplr��¼Yð^r��{ýø‚€������&���phpunit/Util/PHP/WindowsPhpProcess.phpi��¼Yð^i��•á´¤������&���phpunit/Util/PHP/DefaultPhpProcess.php!��¼Yð^!��nm™Æ¤������'���phpunit/Util/PHP/AbstractPhpProcess.php&��¼Yð^&��²ã@Š¤���������phpunit/Util/Printer.phpq��¼Yð^q��=º8j¤���������phpunit/Util/Type.php���¼Yð^���$Æ ¤���������phpunit/Util/Json.php/
  775. ��¼Yð^/
  776. ��$öìà¤������$���phpunit/Util/Annotation/DocBlock.php·@��¼Yð^·@��ÂV G¤������$���phpunit/Util/Annotation/Registry.php
  777. ��¼Yð^
  778. ��³Q¤������*���phpunit/Util/TestDox/TextResultPrinter.phpÀ��¼Yð^À��Šk†¤������'���phpunit/Util/TestDox/NamePrettifier.phpÜ!��¼Yð^Ü!��._Wõ¤������*���phpunit/Util/TestDox/CliTestDoxPrinter.phpE+��¼Yð^E+�� „T¤������&���phpunit/Util/TestDox/ResultPrinter.php[��¼Yð^[��gaˆÊ¤������)���phpunit/Util/TestDox/XmlResultPrinter.php£��¼Yð^£��„J)­¤������'���phpunit/Util/TestDox/TestDoxPrinter.phpÁ*��¼Yð^Á*��MÃλ¤������*���phpunit/Util/TestDox/HtmlResultPrinter.php�
  779. ��¼Yð^�
  780. ��/ÝƤ������*���phpunit/Runner/StandardTestSuiteLoader.php[ ��¼Yð^[ ��ù/Í6¤������"���phpunit/Runner/TestSuiteSorter.php4��¼Yð^4��5¶<v¤������"���phpunit/Runner/TestSuiteLoader.phpZ��¼Yð^Z��{zX=¤������"���phpunit/Runner/TestResultCache.phpÕ��¼Yð^Õ��ÏK¤������4���phpunit/Runner/Filter/ExcludeGroupFilterIterator.php]��¼Yð^]��’Ï û¤������4���phpunit/Runner/Filter/IncludeGroupFilterIterator.php\��¼Yð^\���šq€¤������!���phpunit/Runner/Filter/Factory.phpY��¼Yð^Y��4¼æ¯¤������-���phpunit/Runner/Filter/GroupFilterIterator.php=��¼Yð^=��ƒUþ•¤������,���phpunit/Runner/Filter/NameFilterIterator.php½ ��¼Yð^½ ��¬¹º ¤���������phpunit/Runner/Version.php;��¼Yð^;��ÉN¾Ÿ¤������)���phpunit/Runner/DefaultTestResultCache.phpS��¼Yð^S��j®Ô¤���������phpunit/Runner/Exception.phpÍ��¼Yð^Í��ðES¤������*���phpunit/Runner/Hook/AfterTestErrorHook.phpº��¼Yð^º��²›�é¤������,���phpunit/Runner/Hook/AfterTestWarningHook.php¾��¼Yð^¾��_˜A¤������,���phpunit/Runner/Hook/AfterTestFailureHook.php¾��¼Yð^¾��w� =¤������/���phpunit/Runner/Hook/AfterIncompleteTestHook.phpÄ��¼Yð^Ä��OÞ¤������,���phpunit/Runner/Hook/AfterSkippedTestHook.php¾��¼Yð^¾��ÉßÁA¤������+���phpunit/Runner/Hook/TestListenerAdapter.php ��¼Yð^ ��@†Að¤������*���phpunit/Runner/Hook/AfterRiskyTestHook.phpº��¼Yð^º��”QD¤������+���phpunit/Runner/Hook/BeforeFirstTestHook.phpŽ��¼Yð^Ž��Ž2:¤������/���phpunit/Runner/Hook/AfterSuccessfulTestHook.php³��¼Yð^³��wœjʤ������ ���phpunit/Runner/Hook/TestHook.phpN��¼Yð^N��BÚ¤������&���phpunit/Runner/Hook/BeforeTestHook.php”��¼Yð^”��¿Ã%q¤������%���phpunit/Runner/Hook/AfterTestHook.phph��¼Yð^h��@Ýæ¤���������phpunit/Runner/Hook/Hook.php-��¼Yð^-��g™jg¤������)���phpunit/Runner/Hook/AfterLastTestHook.phpŠ��¼Yð^Š��t"Ž¤������&���phpunit/Runner/NullTestResultCache.php™��¼Yð^™��¾W<ª¤���������phpunit/Runner/PhptTestCase.phpPK��¼Yð^PK��±'ý8¤������!���phpunit/Runner/BaseTestRunner.phpÛ ��¼Yð^Û ��ÆÛ_i¤������'���phpunit/Runner/ResultCacheExtension.php��¼Yð^��ù¹�]¤���������phpunit/TextUI/Help.phpŸ,��¼Yð^Ÿ,��ÝAWp¤���������phpunit/TextUI/TestRunner.php¼��¼Yð^¼��Û!*Z¤������ ���phpunit/TextUI/ResultPrinter.php%��¼Yð^%��]?,¤������'���phpunit/TextUI/DefaultResultPrinter.php¢8��¼Yð^¢8��46²”¤������>���phpunit/TextUI/Configuration/Group/GroupCollectionIterator.phpî��¼Yð^î��˜Õ ¤������6���phpunit/TextUI/Configuration/Group/GroupCollection.phpŸ��¼Yð^Ÿ��ñso1¤������-���phpunit/TextUI/Configuration/Group/Groups.phpÊ��¼Yð^Ê���¤������,���phpunit/TextUI/Configuration/Group/Group.phpŒ��¼Yð^Œ��'(¤������*���phpunit/TextUI/Configuration/Generator.phpž��¼Yð^ž��¯¤ˆ¤������.���phpunit/TextUI/Configuration/Logging/Junit.phpý��¼Yð^ý��Á�û(¤������0���phpunit/TextUI/Configuration/Logging/Logging.php ��¼Yð^ ��u>x¤������1���phpunit/TextUI/Configuration/Logging/TeamCity.php���¼Yð^���²±Ó¤������2���phpunit/TextUI/Configuration/Logging/PlainText.php��¼Yð^��%!¯§¤������9���phpunit/TextUI/Configuration/Logging/CodeCoverage/Xml.php��¼Yð^���œw¤������9���phpunit/TextUI/Configuration/Logging/CodeCoverage/Php.php��¼Yð^��6 åÛ¤������:���phpunit/TextUI/Configuration/Logging/CodeCoverage/Html.php×��¼Yð^×��˜ð=-¤������<���phpunit/TextUI/Configuration/Logging/CodeCoverage/Crap4j.phpÍ��¼Yð^Í���ùŤ������:���phpunit/TextUI/Configuration/Logging/CodeCoverage/Text.phpí��¼Yð^í��¾&yÔ¤������<���phpunit/TextUI/Configuration/Logging/CodeCoverage/Clover.php ��¼Yð^ ��`ª)±¤������4���phpunit/TextUI/Configuration/Logging/TestDox/Xml.php��¼Yð^��§½‡¤������5���phpunit/TextUI/Configuration/Logging/TestDox/Html.php��¼Yð^��£ŸÐ¤������5���phpunit/TextUI/Configuration/Logging/TestDox/Text.php��¼Yð^��„}e¤������G���phpunit/TextUI/Configuration/Filesystem/DirectoryCollectionIterator.php��¼Yð^��Ž{¤������?���phpunit/TextUI/Configuration/Filesystem/DirectoryCollection.phpY��¼Yð^Y��Bð×J¤������0���phpunit/TextUI/Configuration/Filesystem/File.php‹��¼Yð^‹��ÓáO¤������B���phpunit/TextUI/Configuration/Filesystem/FileCollectionIterator.phpä��¼Yð^ä��€Ó7q¤������:���phpunit/TextUI/Configuration/Filesystem/FileCollection.php���¼Yð^���Öõ½(¤������5���phpunit/TextUI/Configuration/Filesystem/Directory.php���¼Yð^���ׇ§·¤������'���phpunit/TextUI/Configuration/Loader.phpI|��¼Yð^I|��AwÖ¤������7���phpunit/TextUI/Configuration/Filter/FilterDirectory.php»��¼Yð^»��Ãwd.¤������D���phpunit/TextUI/Configuration/Filter/FilterFileCollectionIterator.phpü��¼Yð^ü��R#zñ¤������I���phpunit/TextUI/Configuration/Filter/FilterDirectoryCollectionIterator.php4��¼Yð^4���d/¤������.���phpunit/TextUI/Configuration/Filter/Filter.php%
  781. ��¼Yð^%
  782. ��YîiÚ¤������2���phpunit/TextUI/Configuration/Filter/FilterFile.php‘��¼Yð^‘�� é¤������A���phpunit/TextUI/Configuration/Filter/FilterDirectoryCollection.php-��¼Yð^-��C™ž(¤������<���phpunit/TextUI/Configuration/Filter/FilterFileCollection.phpÔ��¼Yð^Ô��ܸ„¤������.���phpunit/TextUI/Configuration/Configuration.phpG��¼Yð^G��“üÖ‚¤������0���phpunit/TextUI/Configuration/PHPUnit/PHPUnit.phpƒC��¼Yð^ƒC��Äàn•¤������9���phpunit/TextUI/Configuration/PHPUnit/ExtensionHandler.phpõ ��¼Yð^õ ��ÂV¤������2���phpunit/TextUI/Configuration/PHPUnit/Extension.php“��¼Yð^“��-‡=±¤������<���phpunit/TextUI/Configuration/PHPUnit/ExtensionCollection.php–��¼Yð^–��±m]¨¤������D���phpunit/TextUI/Configuration/PHPUnit/ExtensionCollectionIterator.php��¼Yð^��³ç=r¤������4���phpunit/TextUI/Configuration/TestSuite/TestSuite.phpü��¼Yð^ü��sPv¸¤������8���phpunit/TextUI/Configuration/TestSuite/TestDirectory.phpY��¼Yð^Y��ž£A®¤������F���phpunit/TextUI/Configuration/TestSuite/TestSuiteCollectionIterator.php��¼Yð^��΢ ¤������3���phpunit/TextUI/Configuration/TestSuite/TestFile.phpâ��¼Yð^â��"8wá¤������B���phpunit/TextUI/Configuration/TestSuite/TestDirectoryCollection.phpu��¼Yð^u��è‡a¨¤������>���phpunit/TextUI/Configuration/TestSuite/TestSuiteCollection.phpP��¼Yð^P��Ó¸ƒM¤������E���phpunit/TextUI/Configuration/TestSuite/TestFileCollectionIterator.phpô��¼Yð^ô��µrÞ`¤������=���phpunit/TextUI/Configuration/TestSuite/TestFileCollection.php��¼Yð^��ráB¤������J���phpunit/TextUI/Configuration/TestSuite/TestDirectoryCollectionIterator.php,��¼Yð^,��u±¤¤������:���phpunit/TextUI/Configuration/TestSuite/TestSuiteMapper.phpð��¼Yð^ð��;32¤������*���phpunit/TextUI/Configuration/Exception.phpÛ��¼Yð^Û��y䲤������(���phpunit/TextUI/Configuration/PHP/Php.phpÍ��¼Yð^Í��cž€„¤������7���phpunit/TextUI/Configuration/PHP/VariableCollection.phpê��¼Yð^ê��K<ùô¤������-���phpunit/TextUI/Configuration/PHP/Variable.phpÞ��¼Yð^Þ��mKÊz¤������?���phpunit/TextUI/Configuration/PHP/ConstantCollectionIterator.php ��¼Yð^ ��ÏÖüC¤������A���phpunit/TextUI/Configuration/PHP/IniSettingCollectionIterator.php ��¼Yð^ ��"œ�0¤������9���phpunit/TextUI/Configuration/PHP/IniSettingCollection.php
  783. ��¼Yð^
  784. ��î-3¤������/���phpunit/TextUI/Configuration/PHP/PhpHandler.phpæ��¼Yð^æ��Ó �Ô¤������-���phpunit/TextUI/Configuration/PHP/Constant.php1��¼Yð^1��ߺŒO¤������?���phpunit/TextUI/Configuration/PHP/VariableCollectionIterator.php ��¼Yð^ ��ž‰o…¤������7���phpunit/TextUI/Configuration/PHP/ConstantCollection.phpê��¼Yð^ê��3:Ö(¤������/���phpunit/TextUI/Configuration/PHP/IniSetting.phpD��¼Yð^D��¶–ð¤������)���phpunit/TextUI/Configuration/Registry.phpŽ��¼Yð^Ž��ôB-¤���������phpunit/TextUI/Exception.phpÍ��¼Yð^Í��1Õ¤���������phpunit/TextUI/Command.phpdW��¼Yð^dW��I()¤������&���phpunit/TextUI/Arguments/Arguments.phpM•��¼Yð^M•��\²¸ü¤������-���phpunit/TextUI/Arguments/ArgumentsBuilder.phpON��¼Yð^ON��¨Môá¤������&���phpunit/TextUI/Arguments/Exception.php×��¼Yð^×��ÂÂ<¤������,���phpunit/TextUI/Arguments/ArgumentsMapper.phpS(��¼Yð^S(��È>ÙȤ������!���phpunit/Framework/SkippedTest.php«��¼Yð^«��ÁÍn¤���������phpunit/Framework/TestSuite.php²X��¼Yð^²X��‹’½n¤������+���phpunit/Framework/DataProviderTestSuite.phpà��¼Yð^à���jͶ¤������$���phpunit/Framework/IncompleteTest.php®��¼Yð^®��îN ‡¤������!���phpunit/Framework/TestFailure.php`��¼Yð^`��VˆÇè¤������%���phpunit/Framework/SkippedTestCase.phpÎ��¼Yð^Î��3rð¤������8���phpunit/Framework/Exception/PHPTAssertionFailedError.php4��¼Yð^4��#M¤������5���phpunit/Framework/Exception/SyntheticSkippedError.phpø��¼Yð^ø��£�Ô—¤������+���phpunit/Framework/Exception/OutputError.phpÊ��¼Yð^Ê��©�¢¤������3���phpunit/Framework/Exception/IncompleteTestError.phpÿ��¼Yð^ÿ��×�’ܤ������5���phpunit/Framework/Exception/CodeCoverageException.phpÃ��¼Yð^Ã��µ£[è¤������.���phpunit/Framework/Exception/RiskyTestError.phpÇ��¼Yð^Ç��*Ãy¤������0���phpunit/Framework/Exception/SkippedTestError.phpù��¼Yð^ù�� O~¤������?���phpunit/Framework/Exception/CoveredCodeNotExecutedException.phpØ��¼Yð^Ø��8YÉФ������9���phpunit/Framework/Exception/NoChildTestSuiteException.phpÍ��¼Yð^Í��PÚ$¤������'���phpunit/Framework/Exception/Warning.phpŒ��¼Yð^Œ��ð8;«¤������:���phpunit/Framework/Exception/ExpectationFailedException.php ��¼Yð^ ��’p2¤������5���phpunit/Framework/Exception/SkippedTestSuiteError.phpþ��¼Yð^þ��x«Ž¤������@���phpunit/Framework/Exception/MissingCoversAnnotationException.phpÙ��¼Yð^Ù��|�î¤������.���phpunit/Framework/Exception/SyntheticError.php5��¼Yð^5��K‡Y¤������?���phpunit/Framework/Exception/UnintentionallyCoveredCodeError.phpØ��¼Yð^Ø��¼£¤������<���phpunit/Framework/Exception/InvalidDataProviderException.phpÐ��¼Yð^Ð��.ڜɤ������)���phpunit/Framework/Exception/Exception.phpi ��¼Yð^i ��u+�¤������4���phpunit/Framework/Exception/AssertionFailedError.php“��¼Yð^“��ÓÂà¤������<���phpunit/Framework/Exception/InvalidCoversTargetException.phpÜ��¼Yð^Ü��o–苤������8���phpunit/Framework/Exception/InvalidArgumentException.php¼��¼Yð^¼��ºeƒ3¤������&���phpunit/Framework/Assert/Functions.php �¼Yð^ �[2H•¤���������phpunit/Framework/Test.php5��¼Yð^5��Œ_A¤���������phpunit/Framework/Assert.php;b�¼Yð^;b�–tš¤������'���phpunit/Framework/TestSuiteIterator.phpÁ��¼Yð^Á��ðu‘"¤������%���phpunit/Framework/MockObject/Stub.php¨��¼Yð^¨��‘ß±¤������*���phpunit/Framework/MockObject/MockClass.php��¼Yð^��X]XǤ������)���phpunit/Framework/MockObject/MockType.phpÉ��¼Yð^É��¬Éž¤������8���phpunit/Framework/MockObject/Builder/MethodNameMatch.phpk��¼Yð^k��0-x¤������-���phpunit/Framework/MockObject/Builder/Stub.php0��¼Yð^0��Î:•l¤������:���phpunit/Framework/MockObject/Builder/InvocationStubber.phpx��¼Yð^x��Šƒß¤������1���phpunit/Framework/MockObject/Builder/Identity.php’��¼Yð^’��¨×¤������8���phpunit/Framework/MockObject/Builder/ParametersMatch.phpÖ��¼Yð^Ö��w”—/¤������.���phpunit/Framework/MockObject/Builder/Match.phpñ��¼Yð^ñ��yY=f¤������9���phpunit/Framework/MockObject/Builder/InvocationMocker.phpc ��¼Yð^c ��rÔSÙ¤������Y���phpunit/Framework/MockObject/Exception/ConfigurableMethodsAlreadyInitializedException.php ��¼Yð^ ��É…¢W¤������K���phpunit/Framework/MockObject/Exception/IncompatibleReturnValueException.php��¼Yð^��¹æY¤������;���phpunit/Framework/MockObject/Exception/RuntimeException.php÷��¼Yð^÷��ô¨_|¤������A���phpunit/Framework/MockObject/Exception/BadMethodCallException.php��¼Yð^��ΫýX¤������4���phpunit/Framework/MockObject/Exception/Exception.php´��¼Yð^´��-°C,¤������5���phpunit/Framework/MockObject/Stub/ReturnReference.php8��¼Yð^8��)…œ˜¤������*���phpunit/Framework/MockObject/Stub/Stub.phpd��¼Yð^d��¼÷qb¤������4���phpunit/Framework/MockObject/Stub/ReturnValueMap.phpÜ��¼Yð^Ü��œ[1z¤������4���phpunit/Framework/MockObject/Stub/ReturnCallback.phpŽ��¼Yð^Ž��òÚ¤®¤������0���phpunit/Framework/MockObject/Stub/ReturnSelf.phpR��¼Yð^R��-‹©Á¤������/���phpunit/Framework/MockObject/Stub/Exception.phpH��¼Yð^H��4›¤������4���phpunit/Framework/MockObject/Stub/ReturnArgument.php%��¼Yð^%��2Ìß#¤������0���phpunit/Framework/MockObject/Stub/ReturnStub.php��¼Yð^��£;¤������6���phpunit/Framework/MockObject/Stub/ConsecutiveCalls.php!��¼Yð^!��cÄJ†¤������*���phpunit/Framework/MockObject/Generator.phpn��¼Yð^n��@B ²¤������=���phpunit/Framework/MockObject/Generator/mocked_method_void.tpl��¼Yð^��ßpç¤������7���phpunit/Framework/MockObject/Generator/mocked_class.tpl����¼Yð^����‚wZ¤������8���phpunit/Framework/MockObject/Generator/mocked_method.tplF��¼Yð^F���ŒK¤������6���phpunit/Framework/MockObject/Generator/wsdl_method.tpl<���¼Yð^<���¾Ði‰¤������5���phpunit/Framework/MockObject/Generator/wsdl_class.tplÍ���¼Yð^Í���ô’±¤������9���phpunit/Framework/MockObject/Generator/proxied_method.tpl}��¼Yð^}��@üÄ—¤������>���phpunit/Framework/MockObject/Generator/proxied_method_void.tplv��¼Yð^v��ÖÃT¤������?���phpunit/Framework/MockObject/Generator/mocked_static_method.tplî���¼Yð^î��� 4éR¤������6���phpunit/Framework/MockObject/Generator/trait_class.tplQ���¼Yð^Q���÷<‹È¤������6���phpunit/Framework/MockObject/Generator/deprecation.tpl;���¼Yð^;���O5øs¤������,���phpunit/Framework/MockObject/MockBuilder.php)��¼Yð^)��\Ï.¤������.���phpunit/Framework/MockObject/MockMethodSet.phpé��¼Yð^é��î�a¤������+���phpunit/Framework/MockObject/Invocation.php7��¼Yð^7��É£D¤������+���phpunit/Framework/MockObject/MockMethod.php%��¼Yð^%��Ñäš"¤������5���phpunit/Framework/MockObject/MethodNameConstraint.phpå��¼Yð^å��é‚òñ¤������;���phpunit/Framework/MockObject/Rule/ConsecutiveParameters.phpC��¼Yð^C��âܤ������0���phpunit/Framework/MockObject/Rule/MethodName.php@��¼Yð^@��“Æ ¤������4���phpunit/Framework/MockObject/Rule/InvokedAtIndex.phpù��¼Yð^ù��Ÿe‘¤������3���phpunit/Framework/MockObject/Rule/AnyParameters.php��¼Yð^��{GÛ<¤������5���phpunit/Framework/MockObject/Rule/InvocationOrder.php5��¼Yð^5��4¸4¤������8���phpunit/Framework/MockObject/Rule/InvokedAtLeastOnce.phpt��¼Yð^t��=(½Z¤������8���phpunit/Framework/MockObject/Rule/InvokedAtMostCount.phpÒ��¼Yð^Ò��Iªa¤������9���phpunit/Framework/MockObject/Rule/InvokedAtLeastCount.phpÝ��¼Yð^Ý��§ß¤������5���phpunit/Framework/MockObject/Rule/AnyInvokedCount.phpž��¼Yð^ž��1Xo.¤������4���phpunit/Framework/MockObject/Rule/ParametersRule.php=��¼Yð^=��G{Ÿ¤������2���phpunit/Framework/MockObject/Rule/InvokedCount.phpì ��¼Yð^ì ��yþ ¤������0���phpunit/Framework/MockObject/Rule/Parameters.phpÇ��¼Yð^Ç��´Ý¯¤������*���phpunit/Framework/MockObject/MockTrait.phpù��¼Yð^ù��©�Ù¤������3���phpunit/Framework/MockObject/ConfigurableMethod.phpÈ��¼Yð^È��Ÿ¶ë
  785. ¤������+���phpunit/Framework/MockObject/Verifiable.phpÌ��¼Yð^Ì��Ì� s¤������+���phpunit/Framework/MockObject/Api/Method.php¥��¼Yð^¥��"+‚î¤������(���phpunit/Framework/MockObject/Api/Api.phpò ��¼Yð^ò ��U§€o¤������6���phpunit/Framework/MockObject/Api/MockedCloneMethod.php*��¼Yð^*��íô?z¤������8���phpunit/Framework/MockObject/Api/UnmockedCloneMethod.phpG��¼Yð^G��ÒÓ©¤������(���phpunit/Framework/MockObject/Matcher.phpš��¼Yð^š��<\T¤������2���phpunit/Framework/MockObject/InvocationHandler.phpù��¼Yð^ù��~Cë’¤������+���phpunit/Framework/MockObject/MockObject.phpm��¼Yð^m��(¤������$���phpunit/Framework/SelfDescribing.php
  786. ��¼Yð^
  787. ��ÀÎÂs¤���������phpunit/Framework/TestCase.php‘�¼Yð^‘�Q³Q®¤������%���phpunit/Framework/WarningTestCase.php•��¼Yð^•��J›¾¤������4���phpunit/Framework/InvalidParameterGroupException.phpÒ��¼Yð^Ò��†©€¤������?���phpunit/Framework/Constraint/StringMatchesFormatDescription.phpð ��¼Yð^ð ��3?É ¤������'���phpunit/Framework/Constraint/IsNull.phpN��¼Yð^N��Go‰Ì¤������'���phpunit/Framework/Constraint/IsJson.php"��¼Yð^"��kã"h¤������3���phpunit/Framework/Constraint/ObjectHasAttribute.phpm��¼Yð^m��²å8£¤������,���phpunit/Framework/Constraint/ArrayHasKey.php��¼Yð^��B¦ÿ'¤������=���phpunit/Framework/Constraint/TraversableContainsIdentical.php��¼Yð^��<\£9¤������&���phpunit/Framework/Constraint/IsNan.phpK��¼Yð^K���â4{¤������1���phpunit/Framework/Constraint/ExceptionMessage.php÷��¼Yð^÷��ÒÇÜZ¤������+���phpunit/Framework/Constraint/FileExists.phpZ��¼Yð^Z��cd€¤������'���phpunit/Framework/Constraint/IsType.phpÅ��¼Yð^Å��z_º<¤������6���phpunit/Framework/Constraint/IsEqualCanonicalizing.php:
  788. ��¼Yð^:
  789. ��óÞ¤������'���phpunit/Framework/Constraint/IsTrue.phpO��¼Yð^O��É}°Å¤������+���phpunit/Framework/Constraint/LogicalXor.phpœ ��¼Yð^œ ��s—Y ¤������+���phpunit/Framework/Constraint/LogicalNot.php²��¼Yð^²��Äiÿ̤������1���phpunit/Framework/Constraint/StringStartsWith.php"��¼Yð^"���õ³¤������4���phpunit/Framework/Constraint/TraversableContains.phpä��¼Yð^ä��Ï—ø¶¤������9���phpunit/Framework/Constraint/TraversableContainsEqual.php]��¼Yð^]��h*¤������.���phpunit/Framework/Constraint/ExceptionCode.php,��¼Yð^,��ÌV’œ¤������4���phpunit/Framework/Constraint/IsEqualIgnoringCase.php8
  790. ��¼Yð^8
  791. ��¨*_¤������)���phpunit/Framework/Constraint/Callback.php=��¼Yð^=��cdn¦¤������)���phpunit/Framework/Constraint/IsFinite.phpW��¼Yð^W��3§ý¤������+���phpunit/Framework/Constraint/IsAnything.phpH��¼Yð^H��GŸî¤������-���phpunit/Framework/Constraint/IsInstanceOf.php/��¼Yð^/��¨íø}¤������&���phpunit/Framework/Constraint/Count.phpT ��¼Yð^T ��Uz ù¤������B���phpunit/Framework/Constraint/ExceptionMessageRegularExpression.php8��¼Yð^8���£B#¤������,���phpunit/Framework/Constraint/GreaterThan.phpÚ��¼Yð^Ú��‚M_H¤������,���phpunit/Framework/Constraint/IsIdentical.php��¼Yð^��fä0¤������(���phpunit/Framework/Constraint/IsEmpty.php��¼Yð^��§O‰¤������*���phpunit/Framework/Constraint/LogicalOr.php+ ��¼Yð^+ ��È'µ¤������2���phpunit/Framework/Constraint/ClassHasAttribute.php9��¼Yð^9��-þÉä������)���phpunit/Framework/Constraint/LessThan.phpÑ��¼Yð^Ñ��ZƒU:¤������/���phpunit/Framework/Constraint/StringContains.php ��¼Yð^ ���óõ¤������(���phpunit/Framework/Constraint/IsFalse.phpS��¼Yð^S��”¤������1���phpunit/Framework/Constraint/IsEqualWithDelta.phpË ��¼Yð^Ë ��•[k¤������+���phpunit/Framework/Constraint/LogicalAnd.php� ��¼Yð^� ��õ-0:¤������8���phpunit/Framework/Constraint/ClassHasStaticAttribute.phpä��¼Yð^ä��©D�¤������8���phpunit/Framework/Constraint/TraversableContainsOnly.php ��¼Yð^ ��¡çÀc¤������+���phpunit/Framework/Constraint/IsWritable.phpc��¼Yð^c��µ‘ý¤������2���phpunit/Framework/Constraint/RegularExpression.php2��¼Yð^2��•k§ï¤������*���phpunit/Framework/Constraint/Exception.phpd��¼Yð^d��S-öñ¤������+���phpunit/Framework/Constraint/IsInfinite.php_��¼Yð^_���´ƒy¤������/���phpunit/Framework/Constraint/StringEndsWith.phpn��¼Yð^n��åÂþo¤������)���phpunit/Framework/Constraint/SameSize.phpî��¼Yð^î��d”^¤������+���phpunit/Framework/Constraint/Constraint.php²��¼Yð^²���¤å¤������(���phpunit/Framework/Constraint/IsEqual.php· ��¼Yð^· ��Á—U¤������@���phpunit/Framework/Constraint/JsonMatchesErrorMessageProvider.php?��¼Yð^?��¯n겤������,���phpunit/Framework/Constraint/JsonMatches.php¹ ��¼Yð^¹ ��Ñ­gý¤������0���phpunit/Framework/Constraint/DirectoryExists.phpi��¼Yð^i��@€œï¤������+���phpunit/Framework/Constraint/IsReadable.phpc��¼Yð^c��àñoǤ������"���phpunit/Framework/TestListener.phpT ��¼Yð^T ��¥î)g¤������!���phpunit/Framework/TestBuilder.php ��¼Yð^ ��=ö¹µ¤������ ���phpunit/Framework/TestResult.php#z��¼Yð^#z��!“™t¤������7���phpunit/Framework/TestListenerDefaultImplementation.php°��¼Yð^°��Û~¤������!���phpunit/Framework/Error/Error.php��¼Yð^��ÙB�¤������#���phpunit/Framework/Error/Warning.phpw��¼Yð^w��ÙãG¤������&���phpunit/Framework/Error/Deprecated.phpz��¼Yð^z��ñàV¤������"���phpunit/Framework/Error/Notice.phpv��¼Yð^v��¯úÂˤ������&���phpunit/Framework/ExceptionWrapper.phpV ��¼Yð^V ��[¸¤������(���phpunit/Framework/IncompleteTestCase.phpÔ��¼Yð^Ô��‹bôѤ���������phpunit/Exception.phpŸ��¼Yð^Ÿ��Í–öP¤���������sebastian-exporter/Exporter.php!��¼Yð^!��‡|Ÿ|¤���������sebastian-exporter/LICENSE��¼Yð^��螷ͤ���������php-file-iterator/Facade.phpˆ ��¼Yð^ˆ ��Eé[¤���������php-file-iterator/Factory.php��¼Yð^��KÛŸ¤���������php-file-iterator/Iterator.phpK
  792. ��¼Yð^K
  793. ��–ãìq¤���������php-file-iterator/LICENSE��¼Yð^��Ž†.¤������/���phpspec-prophecy/Prophecy/Prophecy/Revealer.phpµ��¼Yð^µ�� ”m€¤������5���phpspec-prophecy/Prophecy/Prophecy/MethodProphecy.phpÈ5��¼Yð^È5��âÃs­¤������8���phpspec-prophecy/Prophecy/Prophecy/RevealerInterface.phpG��¼Yð^G��§WnZ¤������?���phpspec-prophecy/Prophecy/Prophecy/ProphecySubjectInterface.phpð��¼Yð^ð��<�¤������8���phpspec-prophecy/Prophecy/Prophecy/ProphecyInterface.php+��¼Yð^+��´ãXì¤������5���phpspec-prophecy/Prophecy/Prophecy/ObjectProphecy.phpä��¼Yð^ä��ºµ× ¤������&���phpspec-prophecy/Prophecy/Argument.phpë��¼Yð^ë��_8D»¤������-���phpspec-prophecy/Prophecy/Util/StringUtil.php�
  794. ��¼Yð^�
  795. ��7‚¨Ý¤������-���phpspec-prophecy/Prophecy/Util/ExportUtil.phpŽ��¼Yð^Ž��ÞÚë¤������B���phpspec-prophecy/Prophecy/Exception/Prophecy/ProphecyException.php«��¼Yð^«��ÛȤ������H���phpspec-prophecy/Prophecy/Exception/Prophecy/MethodProphecyException.phpT��¼Yð^T��D׎¤������H���phpspec-prophecy/Prophecy/Exception/Prophecy/ObjectProphecyException.phpE��¼Yð^E��|.†¤������P���phpspec-prophecy/Prophecy/Exception/Prediction/UnexpectedCallsCountException.php6��¼Yð^6��²ýì@¤������K���phpspec-prophecy/Prophecy/Exception/Prediction/UnexpectedCallsException.phpv��¼Yð^v��¾ �ï¤������L���phpspec-prophecy/Prophecy/Exception/Prediction/FailedPredictionException.phph��¼Yð^h��¦²Vç¤������E���phpspec-prophecy/Prophecy/Exception/Prediction/AggregateException.phpK��¼Yð^K��²A—C¤������C���phpspec-prophecy/Prophecy/Exception/Prediction/NoCallsException.php��¼Yð^��úœs¤������F���phpspec-prophecy/Prophecy/Exception/Prediction/PredictionException.php¯��¼Yð^¯��î$ë¤������D���phpspec-prophecy/Prophecy/Exception/Call/UnexpectedCallException.phpà��¼Yð^à��eÛóN¤������1���phpspec-prophecy/Prophecy/Exception/Exception.php*��¼Yð^*��(òd‘¤������G���phpspec-prophecy/Prophecy/Exception/Doubler/MethodNotFoundException.php÷��¼Yð^÷��æe:°¤������F���phpspec-prophecy/Prophecy/Exception/Doubler/ClassNotFoundException.phpÝ��¼Yð^Ý��ï>Âí¤������D���phpspec-prophecy/Prophecy/Exception/Doubler/ClassMirrorException.phpÂ��¼Yð^Â��ñÐŽT¤������@���phpspec-prophecy/Prophecy/Exception/Doubler/DoublerException.php©��¼Yð^©��Èž¦¤������J���phpspec-prophecy/Prophecy/Exception/Doubler/InterfaceNotFoundException.phpû��¼Yð^û��&¾q¤������J���phpspec-prophecy/Prophecy/Exception/Doubler/ReturnByReferenceException.php£��¼Yð^£��0+5,¤������L���phpspec-prophecy/Prophecy/Exception/Doubler/MethodNotExtendableException.phpÝ��¼Yð^Ý��Ðã[–¤������?���phpspec-prophecy/Prophecy/Exception/Doubler/DoubleException.phpÄ��¼Yð^Ä��‡ŒC³¤������E���phpspec-prophecy/Prophecy/Exception/Doubler/ClassCreatorException.phpí��¼Yð^í��� ¤������@���phpspec-prophecy/Prophecy/Exception/InvalidArgumentException.php¨��¼Yð^¨��õ󱙤������6���phpspec-prophecy/Prophecy/Promise/PromiseInterface.phpo��¼Yð^o��‰ì”v¤������2���phpspec-prophecy/Prophecy/Promise/ThrowPromise.php“ ��¼Yð^“ ��K~/¤������3���phpspec-prophecy/Prophecy/Promise/ReturnPromise.phpK��¼Yð^K��¶×³÷¤������;���phpspec-prophecy/Prophecy/Promise/ReturnArgumentPromise.phpD��¼Yð^D��˜7¤������5���phpspec-prophecy/Prophecy/Promise/CallbackPromise.php«��¼Yð^«��-µ“¤������;���phpspec-prophecy/Prophecy/Prediction/CallbackPrediction.php´��¼Yð^´���†—„¤������7���phpspec-prophecy/Prophecy/Prediction/CallPrediction.php ��¼Yð^ ��öSHߤ������<���phpspec-prophecy/Prophecy/Prediction/CallTimesPrediction.phpV ��¼Yð^V ��SËsΤ������<���phpspec-prophecy/Prophecy/Prediction/PredictionInterface.phpÃ��¼Yð^Ã��PÝøœ¤������:���phpspec-prophecy/Prophecy/Prediction/NoCallsPrediction.phpê��¼Yð^ê��þÅ覤������C���phpspec-prophecy/Prophecy/PhpDocumentor/LegacyClassTagRetriever.php¶��¼Yð^¶��Ùä¾°¤������G���phpspec-prophecy/Prophecy/PhpDocumentor/MethodTagRetrieverInterface.phpí��¼Yð^í��®’³1¤������=���phpspec-prophecy/Prophecy/PhpDocumentor/ClassTagRetriever.phpy��¼Yð^y��âNi¤������I���phpspec-prophecy/Prophecy/PhpDocumentor/ClassAndInterfaceTagRetriever.php¸��¼Yð^¸��—ŠùƤ������-���phpspec-prophecy/Prophecy/Call/CallCenter.php��¼Yð^��*àš¥¤������'���phpspec-prophecy/Prophecy/Call/Call.phpŠ ��¼Yð^Š ��3Õ3Õ¤������;���phpspec-prophecy/Prophecy/Comparator/ProphecyComparator.phpµ��¼Yð^µ��QHg¤������0���phpspec-prophecy/Prophecy/Comparator/Factory.php9��¼Yð^9��b€ï[¤������:���phpspec-prophecy/Prophecy/Comparator/ClosureComparator.php��¼Yð^��ªYu‘¤������%���phpspec-prophecy/Prophecy/Prophet.phpÁ��¼Yð^Á��FÉ}²¤������3���phpspec-prophecy/Prophecy/Doubler/NameGenerator.phpŠ��¼Yð^Š��8SÖˆ¤������0���phpspec-prophecy/Prophecy/Doubler/LazyDouble.phpB ��¼Yð^B ��Ï=þ¤������3���phpspec-prophecy/Prophecy/Doubler/CachedDoubler.php…��¼Yð^…��L4œ•¤������5���phpspec-prophecy/Prophecy/Doubler/DoubleInterface.phpá��¼Yð^á��Bÿ�Û¤������A���phpspec-prophecy/Prophecy/Doubler/Generator/TypeHintReference.phpí��¼Yð^í��àçhö¤������B���phpspec-prophecy/Prophecy/Doubler/Generator/ClassCodeGenerator.php��¼Yð^��cÍ7Õ¤������<���phpspec-prophecy/Prophecy/Doubler/Generator/ClassCreator.phpù��¼Yð^ù��!1ú¤������>���phpspec-prophecy/Prophecy/Doubler/Generator/Node/ClassNode.php¯��¼Yð^¯��‚<éC¤������?���phpspec-prophecy/Prophecy/Doubler/Generator/Node/MethodNode.phpù��¼Yð^ù��BåYÓ¤������A���phpspec-prophecy/Prophecy/Doubler/Generator/Node/ArgumentNode.php³��¼Yð^³�� Yûö¤������;���phpspec-prophecy/Prophecy/Doubler/Generator/ClassMirror.php¿��¼Yð^¿��É™¤������C���phpspec-prophecy/Prophecy/Doubler/Generator/ReflectionInterface.phpñ��¼Yð^ñ�� Y¤������-���phpspec-prophecy/Prophecy/Doubler/Doubler.php3��¼Yð^3��íR'$¤������?���phpspec-prophecy/Prophecy/Doubler/ClassPatch/ThrowablePatch.phpö ��¼Yð^ö ��£ä£ ¤������H���phpspec-prophecy/Prophecy/Doubler/ClassPatch/DisableConstructorPatch.phpU��¼Yð^U��•{Ÿ¤������?���phpspec-prophecy/Prophecy/Doubler/ClassPatch/MagicCallPatch.phpÂ
  796. ��¼Yð^Â
  797. ��»Hö\¤������D���phpspec-prophecy/Prophecy/Doubler/ClassPatch/ClassPatchInterface.phpª��¼Yð^ª��ã ÇŸ¤������E���phpspec-prophecy/Prophecy/Doubler/ClassPatch/ProphecySubjectPatch.php# ��¼Yð^# ��Ô§è¤������A���phpspec-prophecy/Prophecy/Doubler/ClassPatch/SplFileInfoPatch.php/ ��¼Yð^/ ��ßË «¤������=���phpspec-prophecy/Prophecy/Doubler/ClassPatch/KeywordPatch.phpQ ��¼Yð^Q ��J-*¤������C���phpspec-prophecy/Prophecy/Doubler/ClassPatch/HhvmExceptionPatch.php.��¼Yð^.��«¼Y¦¤������A���phpspec-prophecy/Prophecy/Doubler/ClassPatch/TraversablePatch.php
  798. ��¼Yð^
  799. ��úIŤ������P���phpspec-prophecy/Prophecy/Doubler/ClassPatch/ReflectionClassNewInstancePatch.phpË��¼Yð^Ë��À£Hv¤������<���phpspec-prophecy/Prophecy/Argument/Token/LogicalNotToken.phpX��¼Yð^X��Ê5)ð¤������A���phpspec-prophecy/Prophecy/Argument/Token/ArrayEveryEntryToken.phpÝ��¼Yð^Ý��²‘ª#¤������<���phpspec-prophecy/Prophecy/Argument/Token/LogicalAndToken.phpD��¼Yð^D��(bL‘¤������<���phpspec-prophecy/Prophecy/Argument/Token/ArrayEntryToken.phpÑ��¼Yð^Ñ��$Eiʤ������@���phpspec-prophecy/Prophecy/Argument/Token/IdenticalValueToken.php��¼Yð^��+Ý£¤������6���phpspec-prophecy/Prophecy/Argument/Token/TypeToken.php¶��¼Yð^¶��4Ø7|¤������=���phpspec-prophecy/Prophecy/Argument/Token/ObjectStateToken.phpR
  800. ��¼Yð^R
  801. ��‹qe7¤������:���phpspec-prophecy/Prophecy/Argument/Token/AnyValueToken.phpÂ��¼Yð^Â��Í{ƒÜ¤������B���phpspec-prophecy/Prophecy/Argument/Token/ApproximateValueToken.php¡��¼Yð^¡��õ�¡¤������;���phpspec-prophecy/Prophecy/Argument/Token/AnyValuesToken.phpñ��¼Yð^ñ��Ã'Þ`¤������<���phpspec-prophecy/Prophecy/Argument/Token/ExactValueToken.php. ��¼Yð^. ��ÙŽ–œ¤������<���phpspec-prophecy/Prophecy/Argument/Token/ArrayCountToken.phpõ��¼Yð^õ��»/*2¤������@���phpspec-prophecy/Prophecy/Argument/Token/StringContainsToken.php-��¼Yð^-��3xÖD¤������;���phpspec-prophecy/Prophecy/Argument/Token/TokenInterface.php���¼Yð^���(nGw¤������:���phpspec-prophecy/Prophecy/Argument/Token/CallbackToken.php*��¼Yð^*��Yÿd¤������8���phpspec-prophecy/Prophecy/Argument/ArgumentsWildcard.phpY ��¼Yð^Y ��¸0?Š¤���������phpspec-prophecy/LICENSE}��¼Yð^}��òÅ6¤������/���sebastian-diff/Output/DiffOnlyOutputBuilder.php—��¼Yð^—��)ï‚ä������4���sebastian-diff/Output/DiffOutputBuilderInterface.php��¼Yð^��VŽáå¤������2���sebastian-diff/Output/UnifiedDiffOutputBuilder.phpÄ��¼Yð^Ä��Ö¬º¤������8���sebastian-diff/Output/StrictUnifiedDiffOutputBuilder.phpU)��¼Yð^U)��z,£;¤������4���sebastian-diff/Output/AbstractChunkOutputBuilder.php
  802. ��¼Yð^
  803. ��ÖJI´¤������3���sebastian-diff/Exception/ConfigurationException.php÷��¼Yð^÷�� éH<¤������&���sebastian-diff/Exception/Exception.phpI��¼Yð^I��n:mê¤������5���sebastian-diff/Exception/InvalidArgumentException.php«��¼Yð^«��"�bà¤������B���sebastian-diff/TimeEfficientLongestCommonSubsequenceCalculator.phpÅ��¼Yð^Å��?¸ƒ[¤������D���sebastian-diff/MemoryEfficientLongestCommonSubsequenceCalculator.php(��¼Yð^(��1U㞤���������sebastian-diff/Chunk.phpŸ��¼Yð^Ÿ��#Iëã¤���������sebastian-diff/Diff.phpj��¼Yð^j��bXØA¤������5���sebastian-diff/LongestCommonSubsequenceCalculator.phpñ��¼Yð^ñ��}e7z¤���������sebastian-diff/Differ.phpâ#��¼Yð^â#��ŸUØä¤���������sebastian-diff/Parser.php ��¼Yð^ ��&q\ä���������sebastian-diff/Line.phpL��¼Yð^L��
  804. óq¤���������sebastian-diff/LICENSE ��¼Yð^ ��a¸©1¤���������theseer-tokenizer/Token.php‚��¼Yð^‚��ÏC’Ϥ���������theseer-tokenizer/Tokenizer.php��¼Yð^��¬M9Š¤������+���theseer-tokenizer/NamespaceUriException.php”���¼Yð^”���>J†D¤������.���theseer-tokenizer/TokenCollectionException.php—���¼Yð^—���¼'pÞ¤���������theseer-tokenizer/Exception.phpn���¼Yð^n���¹'Ǥ������#���theseer-tokenizer/XMLSerializer.phpd
  805. ��¼Yð^d
  806. ��ÉBwN¤������"���theseer-tokenizer/NamespaceUri.phpˆ��¼Yð^ˆ��Å� ¤���������theseer-tokenizer/LICENSEü��¼Yð^ü��ïR (¤������%���theseer-tokenizer/TokenCollection.php 
  807. ��¼Yð^ 
  808. ��ŒÒ¤���������object-enumerator/LICENSE��¼Yð^��×y{¤������-���sebastian-code-unit-reverse-lookup/Wizard.phpÅ ��¼Yð^Å ��š®¢¤������*���sebastian-code-unit-reverse-lookup/LICENSE��¼Yð^��3G (¤������'���sebastian-recursion-context/Context.php£��¼Yð^£��ùO 2¤������)���sebastian-recursion-context/Exception.phpd��¼Yð^d��f"p¤������#���sebastian-recursion-context/LICENSE��¼Yð^��`Äó¤������8���sebastian-recursion-context/InvalidArgumentException.phpØ��¼Yð^Ø��‰ž³I¤������<?php
  809. /*
  810. * This file is part of the webmozart/assert package.
  811. *
  812. * (c) Bernhard Schussek <bschussek@gmail.com>
  813. *
  814. * For the full copyright and license information, please view the LICENSE
  815. * file that was distributed with this source code.
  816. */
  817. namespace PHPUnit\Webmozart\Assert;
  818. use ArrayAccess;
  819. use BadMethodCallException;
  820. use Closure;
  821. use Countable;
  822. use DateTime;
  823. use DateTimeImmutable;
  824. use Exception;
  825. use InvalidArgumentException;
  826. use ResourceBundle;
  827. use SimpleXMLElement;
  828. use Throwable;
  829. use Traversable;
  830. /**
  831. * Efficient assertions to validate the input/output of your methods.
  832. *
  833. * @mixin Mixin
  834. *
  835. * @since 1.0
  836. *
  837. * @author Bernhard Schussek <bschussek@gmail.com>
  838. */
  839. class Assert
  840. {
  841. /**
  842. * @psalm-pure
  843. * @psalm-assert string $value
  844. *
  845. * @param mixed $value
  846. * @param string $message
  847. *
  848. * @throws InvalidArgumentException
  849. */
  850. public static function string($value, $message = '')
  851. {
  852. if (!\is_string($value)) {
  853. static::reportInvalidArgument(\sprintf($message ?: 'Expected a string. Got: %s', static::typeToString($value)));
  854. }
  855. }
  856. /**
  857. * @psalm-pure
  858. * @psalm-assert non-empty-string $value
  859. *
  860. * @param mixed $value
  861. * @param string $message
  862. *
  863. * @throws InvalidArgumentException
  864. */
  865. public static function stringNotEmpty($value, $message = '')
  866. {
  867. static::string($value, $message);
  868. static::notEq($value, '', $message);
  869. }
  870. /**
  871. * @psalm-pure
  872. * @psalm-assert int $value
  873. *
  874. * @param mixed $value
  875. * @param string $message
  876. *
  877. * @throws InvalidArgumentException
  878. */
  879. public static function integer($value, $message = '')
  880. {
  881. if (!\is_int($value)) {
  882. static::reportInvalidArgument(\sprintf($message ?: 'Expected an integer. Got: %s', static::typeToString($value)));
  883. }
  884. }
  885. /**
  886. * @psalm-pure
  887. * @psalm-assert numeric $value
  888. *
  889. * @param mixed $value
  890. * @param string $message
  891. *
  892. * @throws InvalidArgumentException
  893. */
  894. public static function integerish($value, $message = '')
  895. {
  896. if (!\is_numeric($value) || $value != (int) $value) {
  897. static::reportInvalidArgument(\sprintf($message ?: 'Expected an integerish value. Got: %s', static::typeToString($value)));
  898. }
  899. }
  900. /**
  901. * @psalm-pure
  902. * @psalm-assert float $value
  903. *
  904. * @param mixed $value
  905. * @param string $message
  906. *
  907. * @throws InvalidArgumentException
  908. */
  909. public static function float($value, $message = '')
  910. {
  911. if (!\is_float($value)) {
  912. static::reportInvalidArgument(\sprintf($message ?: 'Expected a float. Got: %s', static::typeToString($value)));
  913. }
  914. }
  915. /**
  916. * @psalm-pure
  917. * @psalm-assert numeric $value
  918. *
  919. * @param mixed $value
  920. * @param string $message
  921. *
  922. * @throws InvalidArgumentException
  923. */
  924. public static function numeric($value, $message = '')
  925. {
  926. if (!\is_numeric($value)) {
  927. static::reportInvalidArgument(\sprintf($message ?: 'Expected a numeric. Got: %s', static::typeToString($value)));
  928. }
  929. }
  930. /**
  931. * @psalm-pure
  932. * @psalm-assert int $value
  933. *
  934. * @param mixed $value
  935. * @param string $message
  936. *
  937. * @throws InvalidArgumentException
  938. */
  939. public static function natural($value, $message = '')
  940. {
  941. if (!\is_int($value) || $value < 0) {
  942. static::reportInvalidArgument(\sprintf($message ?: 'Expected a non-negative integer. Got: %s', static::valueToString($value)));
  943. }
  944. }
  945. /**
  946. * @psalm-pure
  947. * @psalm-assert bool $value
  948. *
  949. * @param mixed $value
  950. * @param string $message
  951. *
  952. * @throws InvalidArgumentException
  953. */
  954. public static function boolean($value, $message = '')
  955. {
  956. if (!\is_bool($value)) {
  957. static::reportInvalidArgument(\sprintf($message ?: 'Expected a boolean. Got: %s', static::typeToString($value)));
  958. }
  959. }
  960. /**
  961. * @psalm-pure
  962. * @psalm-assert scalar $value
  963. *
  964. * @param mixed $value
  965. * @param string $message
  966. *
  967. * @throws InvalidArgumentException
  968. */
  969. public static function scalar($value, $message = '')
  970. {
  971. if (!\is_scalar($value)) {
  972. static::reportInvalidArgument(\sprintf($message ?: 'Expected a scalar. Got: %s', static::typeToString($value)));
  973. }
  974. }
  975. /**
  976. * @psalm-pure
  977. * @psalm-assert object $value
  978. *
  979. * @param mixed $value
  980. * @param string $message
  981. *
  982. * @throws InvalidArgumentException
  983. */
  984. public static function object($value, $message = '')
  985. {
  986. if (!\is_object($value)) {
  987. static::reportInvalidArgument(\sprintf($message ?: 'Expected an object. Got: %s', static::typeToString($value)));
  988. }
  989. }
  990. /**
  991. * @psalm-pure
  992. * @psalm-assert resource $value
  993. *
  994. * @param mixed $value
  995. * @param string|null $type type of resource this should be. @see https://www.php.net/manual/en/function.get-resource-type.php
  996. * @param string $message
  997. *
  998. * @throws InvalidArgumentException
  999. */
  1000. public static function resource($value, $type = null, $message = '')
  1001. {
  1002. if (!\is_resource($value)) {
  1003. static::reportInvalidArgument(\sprintf($message ?: 'Expected a resource. Got: %s', static::typeToString($value)));
  1004. }
  1005. if ($type && $type !== \get_resource_type($value)) {
  1006. static::reportInvalidArgument(\sprintf($message ?: 'Expected a resource of type %2$s. Got: %s', static::typeToString($value), $type));
  1007. }
  1008. }
  1009. /**
  1010. * @psalm-pure
  1011. * @psalm-assert callable $value
  1012. *
  1013. * @param mixed $value
  1014. * @param string $message
  1015. *
  1016. * @throws InvalidArgumentException
  1017. */
  1018. public static function isCallable($value, $message = '')
  1019. {
  1020. if (!\is_callable($value)) {
  1021. static::reportInvalidArgument(\sprintf($message ?: 'Expected a callable. Got: %s', static::typeToString($value)));
  1022. }
  1023. }
  1024. /**
  1025. * @psalm-pure
  1026. * @psalm-assert array $value
  1027. *
  1028. * @param mixed $value
  1029. * @param string $message
  1030. *
  1031. * @throws InvalidArgumentException
  1032. */
  1033. public static function isArray($value, $message = '')
  1034. {
  1035. if (!\is_array($value)) {
  1036. static::reportInvalidArgument(\sprintf($message ?: 'Expected an array. Got: %s', static::typeToString($value)));
  1037. }
  1038. }
  1039. /**
  1040. * @psalm-pure
  1041. * @psalm-assert iterable $value
  1042. *
  1043. * @deprecated use "isIterable" or "isInstanceOf" instead
  1044. *
  1045. * @param mixed $value
  1046. * @param string $message
  1047. *
  1048. * @throws InvalidArgumentException
  1049. */
  1050. public static function isTraversable($value, $message = '')
  1051. {
  1052. @\trigger_error(\sprintf('The "%s" assertion is deprecated. You should stop using it, as it will soon be removed in 2.0 version. Use "isIterable" or "isInstanceOf" instead.', __METHOD__), \E_USER_DEPRECATED);
  1053. if (!\is_array($value) && !$value instanceof \Traversable) {
  1054. static::reportInvalidArgument(\sprintf($message ?: 'Expected a traversable. Got: %s', static::typeToString($value)));
  1055. }
  1056. }
  1057. /**
  1058. * @psalm-pure
  1059. * @psalm-assert array|ArrayAccess $value
  1060. *
  1061. * @param mixed $value
  1062. * @param string $message
  1063. *
  1064. * @throws InvalidArgumentException
  1065. */
  1066. public static function isArrayAccessible($value, $message = '')
  1067. {
  1068. if (!\is_array($value) && !$value instanceof \ArrayAccess) {
  1069. static::reportInvalidArgument(\sprintf($message ?: 'Expected an array accessible. Got: %s', static::typeToString($value)));
  1070. }
  1071. }
  1072. /**
  1073. * @psalm-pure
  1074. * @psalm-assert countable $value
  1075. *
  1076. * @param mixed $value
  1077. * @param string $message
  1078. *
  1079. * @throws InvalidArgumentException
  1080. */
  1081. public static function isCountable($value, $message = '')
  1082. {
  1083. if (!\is_array($value) && !$value instanceof \Countable && !$value instanceof \ResourceBundle && !$value instanceof \SimpleXMLElement) {
  1084. static::reportInvalidArgument(\sprintf($message ?: 'Expected a countable. Got: %s', static::typeToString($value)));
  1085. }
  1086. }
  1087. /**
  1088. * @psalm-pure
  1089. * @psalm-assert iterable $value
  1090. *
  1091. * @param mixed $value
  1092. * @param string $message
  1093. *
  1094. * @throws InvalidArgumentException
  1095. */
  1096. public static function isIterable($value, $message = '')
  1097. {
  1098. if (!\is_array($value) && !$value instanceof \Traversable) {
  1099. static::reportInvalidArgument(\sprintf($message ?: 'Expected an iterable. Got: %s', static::typeToString($value)));
  1100. }
  1101. }
  1102. /**
  1103. * @psalm-pure
  1104. * @psalm-template ExpectedType of object
  1105. * @psalm-param class-string<ExpectedType> $class
  1106. * @psalm-assert ExpectedType $value
  1107. *
  1108. * @param mixed $value
  1109. * @param string|object $class
  1110. * @param string $message
  1111. *
  1112. * @throws InvalidArgumentException
  1113. */
  1114. public static function isInstanceOf($value, $class, $message = '')
  1115. {
  1116. if (!$value instanceof $class) {
  1117. static::reportInvalidArgument(\sprintf($message ?: 'Expected an instance of %2$s. Got: %s', static::typeToString($value), $class));
  1118. }
  1119. }
  1120. /**
  1121. * @psalm-pure
  1122. * @psalm-template ExpectedType of object
  1123. * @psalm-param class-string<ExpectedType> $class
  1124. * @psalm-assert !ExpectedType $value
  1125. *
  1126. * @param mixed $value
  1127. * @param string|object $class
  1128. * @param string $message
  1129. *
  1130. * @throws InvalidArgumentException
  1131. */
  1132. public static function notInstanceOf($value, $class, $message = '')
  1133. {
  1134. if ($value instanceof $class) {
  1135. static::reportInvalidArgument(\sprintf($message ?: 'Expected an instance other than %2$s. Got: %s', static::typeToString($value), $class));
  1136. }
  1137. }
  1138. /**
  1139. * @psalm-pure
  1140. * @psalm-param array<class-string> $classes
  1141. *
  1142. * @param mixed $value
  1143. * @param array<object|string> $classes
  1144. * @param string $message
  1145. *
  1146. * @throws InvalidArgumentException
  1147. */
  1148. public static function isInstanceOfAny($value, array $classes, $message = '')
  1149. {
  1150. foreach ($classes as $class) {
  1151. if ($value instanceof $class) {
  1152. return;
  1153. }
  1154. }
  1155. static::reportInvalidArgument(\sprintf($message ?: 'Expected an instance of any of %2$s. Got: %s', static::typeToString($value), \implode(', ', \array_map(array('static', 'valueToString'), $classes))));
  1156. }
  1157. /**
  1158. * @psalm-pure
  1159. * @psalm-template ExpectedType of object
  1160. * @psalm-param class-string<ExpectedType> $class
  1161. * @psalm-assert ExpectedType|class-string<ExpectedType> $value
  1162. *
  1163. * @param object|string $value
  1164. * @param string $class
  1165. * @param string $message
  1166. *
  1167. * @throws InvalidArgumentException
  1168. */
  1169. public static function isAOf($value, $class, $message = '')
  1170. {
  1171. static::string($class, 'Expected class as a string. Got: %s');
  1172. if (!\is_a($value, $class, \is_string($value))) {
  1173. static::reportInvalidArgument(\sprintf($message ?: 'Expected an instance of this class or to this class among his parents %2$s. Got: %s', static::typeToString($value), $class));
  1174. }
  1175. }
  1176. /**
  1177. * @psalm-pure
  1178. * @psalm-template UnexpectedType of object
  1179. * @psalm-param class-string<UnexpectedType> $class
  1180. * @psalm-assert !UnexpectedType $value
  1181. * @psalm-assert !class-string<UnexpectedType> $value
  1182. *
  1183. * @param object|string $value
  1184. * @param string $class
  1185. * @param string $message
  1186. *
  1187. * @throws InvalidArgumentException
  1188. */
  1189. public static function isNotA($value, $class, $message = '')
  1190. {
  1191. static::string($class, 'Expected class as a string. Got: %s');
  1192. if (\is_a($value, $class, \is_string($value))) {
  1193. static::reportInvalidArgument(\sprintf($message ?: 'Expected an instance of this class or to this class among his parents other than %2$s. Got: %s', static::typeToString($value), $class));
  1194. }
  1195. }
  1196. /**
  1197. * @psalm-pure
  1198. * @psalm-param array<class-string> $classes
  1199. *
  1200. * @param object|string $value
  1201. * @param string[] $classes
  1202. * @param string $message
  1203. *
  1204. * @throws InvalidArgumentException
  1205. */
  1206. public static function isAnyOf($value, array $classes, $message = '')
  1207. {
  1208. foreach ($classes as $class) {
  1209. static::string($class, 'Expected class as a string. Got: %s');
  1210. if (\is_a($value, $class, \is_string($value))) {
  1211. return;
  1212. }
  1213. }
  1214. static::reportInvalidArgument(\sprintf($message ?: 'Expected an any of instance of this class or to this class among his parents other than %2$s. Got: %s', static::typeToString($value), \implode(', ', \array_map(array('static', 'valueToString'), $classes))));
  1215. }
  1216. /**
  1217. * @psalm-pure
  1218. * @psalm-assert empty $value
  1219. *
  1220. * @param mixed $value
  1221. * @param string $message
  1222. *
  1223. * @throws InvalidArgumentException
  1224. */
  1225. public static function isEmpty($value, $message = '')
  1226. {
  1227. if (!empty($value)) {
  1228. static::reportInvalidArgument(\sprintf($message ?: 'Expected an empty value. Got: %s', static::valueToString($value)));
  1229. }
  1230. }
  1231. /**
  1232. * @psalm-pure
  1233. * @psalm-assert !empty $value
  1234. *
  1235. * @param mixed $value
  1236. * @param string $message
  1237. *
  1238. * @throws InvalidArgumentException
  1239. */
  1240. public static function notEmpty($value, $message = '')
  1241. {
  1242. if (empty($value)) {
  1243. static::reportInvalidArgument(\sprintf($message ?: 'Expected a non-empty value. Got: %s', static::valueToString($value)));
  1244. }
  1245. }
  1246. /**
  1247. * @psalm-pure
  1248. * @psalm-assert null $value
  1249. *
  1250. * @param mixed $value
  1251. * @param string $message
  1252. *
  1253. * @throws InvalidArgumentException
  1254. */
  1255. public static function null($value, $message = '')
  1256. {
  1257. if (null !== $value) {
  1258. static::reportInvalidArgument(\sprintf($message ?: 'Expected null. Got: %s', static::valueToString($value)));
  1259. }
  1260. }
  1261. /**
  1262. * @psalm-pure
  1263. * @psalm-assert !null $value
  1264. *
  1265. * @param mixed $value
  1266. * @param string $message
  1267. *
  1268. * @throws InvalidArgumentException
  1269. */
  1270. public static function notNull($value, $message = '')
  1271. {
  1272. if (null === $value) {
  1273. static::reportInvalidArgument($message ?: 'Expected a value other than null.');
  1274. }
  1275. }
  1276. /**
  1277. * @psalm-pure
  1278. * @psalm-assert true $value
  1279. *
  1280. * @param mixed $value
  1281. * @param string $message
  1282. *
  1283. * @throws InvalidArgumentException
  1284. */
  1285. public static function true($value, $message = '')
  1286. {
  1287. if (\true !== $value) {
  1288. static::reportInvalidArgument(\sprintf($message ?: 'Expected a value to be true. Got: %s', static::valueToString($value)));
  1289. }
  1290. }
  1291. /**
  1292. * @psalm-pure
  1293. * @psalm-assert false $value
  1294. *
  1295. * @param mixed $value
  1296. * @param string $message
  1297. *
  1298. * @throws InvalidArgumentException
  1299. */
  1300. public static function false($value, $message = '')
  1301. {
  1302. if (\false !== $value) {
  1303. static::reportInvalidArgument(\sprintf($message ?: 'Expected a value to be false. Got: %s', static::valueToString($value)));
  1304. }
  1305. }
  1306. /**
  1307. * @psalm-pure
  1308. * @psalm-assert !false $value
  1309. *
  1310. * @param mixed $value
  1311. * @param string $message
  1312. *
  1313. * @throws InvalidArgumentException
  1314. */
  1315. public static function notFalse($value, $message = '')
  1316. {
  1317. if (\false === $value) {
  1318. static::reportInvalidArgument($message ?: 'Expected a value other than false.');
  1319. }
  1320. }
  1321. /**
  1322. * @param mixed $value
  1323. * @param string $message
  1324. *
  1325. * @throws InvalidArgumentException
  1326. */
  1327. public static function ip($value, $message = '')
  1328. {
  1329. if (\false === \filter_var($value, \FILTER_VALIDATE_IP)) {
  1330. static::reportInvalidArgument(\sprintf($message ?: 'Expected a value to be an IP. Got: %s', static::valueToString($value)));
  1331. }
  1332. }
  1333. /**
  1334. * @param mixed $value
  1335. * @param string $message
  1336. *
  1337. * @throws InvalidArgumentException
  1338. */
  1339. public static function ipv4($value, $message = '')
  1340. {
  1341. if (\false === \filter_var($value, \FILTER_VALIDATE_IP, \FILTER_FLAG_IPV4)) {
  1342. static::reportInvalidArgument(\sprintf($message ?: 'Expected a value to be an IPv4. Got: %s', static::valueToString($value)));
  1343. }
  1344. }
  1345. /**
  1346. * @param mixed $value
  1347. * @param string $message
  1348. *
  1349. * @throws InvalidArgumentException
  1350. */
  1351. public static function ipv6($value, $message = '')
  1352. {
  1353. if (\false === \filter_var($value, \FILTER_VALIDATE_IP, \FILTER_FLAG_IPV6)) {
  1354. static::reportInvalidArgument(\sprintf($message ?: 'Expected a value to be an IPv6. Got: %s', static::valueToString($value)));
  1355. }
  1356. }
  1357. /**
  1358. * @param mixed $value
  1359. * @param string $message
  1360. *
  1361. * @throws InvalidArgumentException
  1362. */
  1363. public static function email($value, $message = '')
  1364. {
  1365. if (\false === \filter_var($value, \FILTER_VALIDATE_EMAIL)) {
  1366. static::reportInvalidArgument(\sprintf($message ?: 'Expected a value to be a valid e-mail address. Got: %s', static::valueToString($value)));
  1367. }
  1368. }
  1369. /**
  1370. * Does non strict comparisons on the items, so ['3', 3] will not pass the assertion.
  1371. *
  1372. * @param array $values
  1373. * @param string $message
  1374. *
  1375. * @throws InvalidArgumentException
  1376. */
  1377. public static function uniqueValues(array $values, $message = '')
  1378. {
  1379. $allValues = \count($values);
  1380. $uniqueValues = \count(\array_unique($values));
  1381. if ($allValues !== $uniqueValues) {
  1382. $difference = $allValues - $uniqueValues;
  1383. static::reportInvalidArgument(\sprintf($message ?: 'Expected an array of unique values, but %s of them %s duplicated', $difference, 1 === $difference ? 'is' : 'are'));
  1384. }
  1385. }
  1386. /**
  1387. * @param mixed $value
  1388. * @param mixed $expect
  1389. * @param string $message
  1390. *
  1391. * @throws InvalidArgumentException
  1392. */
  1393. public static function eq($value, $expect, $message = '')
  1394. {
  1395. if ($expect != $value) {
  1396. static::reportInvalidArgument(\sprintf($message ?: 'Expected a value equal to %2$s. Got: %s', static::valueToString($value), static::valueToString($expect)));
  1397. }
  1398. }
  1399. /**
  1400. * @param mixed $value
  1401. * @param mixed $expect
  1402. * @param string $message
  1403. *
  1404. * @throws InvalidArgumentException
  1405. */
  1406. public static function notEq($value, $expect, $message = '')
  1407. {
  1408. if ($expect == $value) {
  1409. static::reportInvalidArgument(\sprintf($message ?: 'Expected a different value than %s.', static::valueToString($expect)));
  1410. }
  1411. }
  1412. /**
  1413. * @psalm-pure
  1414. *
  1415. * @param mixed $value
  1416. * @param mixed $expect
  1417. * @param string $message
  1418. *
  1419. * @throws InvalidArgumentException
  1420. */
  1421. public static function same($value, $expect, $message = '')
  1422. {
  1423. if ($expect !== $value) {
  1424. static::reportInvalidArgument(\sprintf($message ?: 'Expected a value identical to %2$s. Got: %s', static::valueToString($value), static::valueToString($expect)));
  1425. }
  1426. }
  1427. /**
  1428. * @psalm-pure
  1429. *
  1430. * @param mixed $value
  1431. * @param mixed $expect
  1432. * @param string $message
  1433. *
  1434. * @throws InvalidArgumentException
  1435. */
  1436. public static function notSame($value, $expect, $message = '')
  1437. {
  1438. if ($expect === $value) {
  1439. static::reportInvalidArgument(\sprintf($message ?: 'Expected a value not identical to %s.', static::valueToString($expect)));
  1440. }
  1441. }
  1442. /**
  1443. * @psalm-pure
  1444. *
  1445. * @param mixed $value
  1446. * @param mixed $limit
  1447. * @param string $message
  1448. *
  1449. * @throws InvalidArgumentException
  1450. */
  1451. public static function greaterThan($value, $limit, $message = '')
  1452. {
  1453. if ($value <= $limit) {
  1454. static::reportInvalidArgument(\sprintf($message ?: 'Expected a value greater than %2$s. Got: %s', static::valueToString($value), static::valueToString($limit)));
  1455. }
  1456. }
  1457. /**
  1458. * @psalm-pure
  1459. *
  1460. * @param mixed $value
  1461. * @param mixed $limit
  1462. * @param string $message
  1463. *
  1464. * @throws InvalidArgumentException
  1465. */
  1466. public static function greaterThanEq($value, $limit, $message = '')
  1467. {
  1468. if ($value < $limit) {
  1469. static::reportInvalidArgument(\sprintf($message ?: 'Expected a value greater than or equal to %2$s. Got: %s', static::valueToString($value), static::valueToString($limit)));
  1470. }
  1471. }
  1472. /**
  1473. * @psalm-pure
  1474. *
  1475. * @param mixed $value
  1476. * @param mixed $limit
  1477. * @param string $message
  1478. *
  1479. * @throws InvalidArgumentException
  1480. */
  1481. public static function lessThan($value, $limit, $message = '')
  1482. {
  1483. if ($value >= $limit) {
  1484. static::reportInvalidArgument(\sprintf($message ?: 'Expected a value less than %2$s. Got: %s', static::valueToString($value), static::valueToString($limit)));
  1485. }
  1486. }
  1487. /**
  1488. * @psalm-pure
  1489. *
  1490. * @param mixed $value
  1491. * @param mixed $limit
  1492. * @param string $message
  1493. *
  1494. * @throws InvalidArgumentException
  1495. */
  1496. public static function lessThanEq($value, $limit, $message = '')
  1497. {
  1498. if ($value > $limit) {
  1499. static::reportInvalidArgument(\sprintf($message ?: 'Expected a value less than or equal to %2$s. Got: %s', static::valueToString($value), static::valueToString($limit)));
  1500. }
  1501. }
  1502. /**
  1503. * Inclusive range, so Assert::(3, 3, 5) passes.
  1504. *
  1505. * @psalm-pure
  1506. *
  1507. * @param mixed $value
  1508. * @param mixed $min
  1509. * @param mixed $max
  1510. * @param string $message
  1511. *
  1512. * @throws InvalidArgumentException
  1513. */
  1514. public static function range($value, $min, $max, $message = '')
  1515. {
  1516. if ($value < $min || $value > $max) {
  1517. static::reportInvalidArgument(\sprintf($message ?: 'Expected a value between %2$s and %3$s. Got: %s', static::valueToString($value), static::valueToString($min), static::valueToString($max)));
  1518. }
  1519. }
  1520. /**
  1521. * A more human-readable alias of Assert::inArray().
  1522. *
  1523. * @psalm-pure
  1524. *
  1525. * @param mixed $value
  1526. * @param array $values
  1527. * @param string $message
  1528. *
  1529. * @throws InvalidArgumentException
  1530. */
  1531. public static function oneOf($value, array $values, $message = '')
  1532. {
  1533. static::inArray($value, $values, $message);
  1534. }
  1535. /**
  1536. * Does strict comparison, so Assert::inArray(3, ['3']) does not pass the assertion.
  1537. *
  1538. * @psalm-pure
  1539. *
  1540. * @param mixed $value
  1541. * @param array $values
  1542. * @param string $message
  1543. *
  1544. * @throws InvalidArgumentException
  1545. */
  1546. public static function inArray($value, array $values, $message = '')
  1547. {
  1548. if (!\in_array($value, $values, \true)) {
  1549. static::reportInvalidArgument(\sprintf($message ?: 'Expected one of: %2$s. Got: %s', static::valueToString($value), \implode(', ', \array_map(array('static', 'valueToString'), $values))));
  1550. }
  1551. }
  1552. /**
  1553. * @psalm-pure
  1554. *
  1555. * @param string $value
  1556. * @param string $subString
  1557. * @param string $message
  1558. *
  1559. * @throws InvalidArgumentException
  1560. */
  1561. public static function contains($value, $subString, $message = '')
  1562. {
  1563. if (\false === \strpos($value, $subString)) {
  1564. static::reportInvalidArgument(\sprintf($message ?: 'Expected a value to contain %2$s. Got: %s', static::valueToString($value), static::valueToString($subString)));
  1565. }
  1566. }
  1567. /**
  1568. * @psalm-pure
  1569. *
  1570. * @param string $value
  1571. * @param string $subString
  1572. * @param string $message
  1573. *
  1574. * @throws InvalidArgumentException
  1575. */
  1576. public static function notContains($value, $subString, $message = '')
  1577. {
  1578. if (\false !== \strpos($value, $subString)) {
  1579. static::reportInvalidArgument(\sprintf($message ?: '%2$s was not expected to be contained in a value. Got: %s', static::valueToString($value), static::valueToString($subString)));
  1580. }
  1581. }
  1582. /**
  1583. * @psalm-pure
  1584. *
  1585. * @param string $value
  1586. * @param string $message
  1587. *
  1588. * @throws InvalidArgumentException
  1589. */
  1590. public static function notWhitespaceOnly($value, $message = '')
  1591. {
  1592. if (\preg_match('/^\\s*$/', $value)) {
  1593. static::reportInvalidArgument(\sprintf($message ?: 'Expected a non-whitespace string. Got: %s', static::valueToString($value)));
  1594. }
  1595. }
  1596. /**
  1597. * @psalm-pure
  1598. *
  1599. * @param string $value
  1600. * @param string $prefix
  1601. * @param string $message
  1602. *
  1603. * @throws InvalidArgumentException
  1604. */
  1605. public static function startsWith($value, $prefix, $message = '')
  1606. {
  1607. if (0 !== \strpos($value, $prefix)) {
  1608. static::reportInvalidArgument(\sprintf($message ?: 'Expected a value to start with %2$s. Got: %s', static::valueToString($value), static::valueToString($prefix)));
  1609. }
  1610. }
  1611. /**
  1612. * @psalm-pure
  1613. *
  1614. * @param string $value
  1615. * @param string $prefix
  1616. * @param string $message
  1617. *
  1618. * @throws InvalidArgumentException
  1619. */
  1620. public static function notStartsWith($value, $prefix, $message = '')
  1621. {
  1622. if (0 === \strpos($value, $prefix)) {
  1623. static::reportInvalidArgument(\sprintf($message ?: 'Expected a value not to start with %2$s. Got: %s', static::valueToString($value), static::valueToString($prefix)));
  1624. }
  1625. }
  1626. /**
  1627. * @psalm-pure
  1628. *
  1629. * @param mixed $value
  1630. * @param string $message
  1631. *
  1632. * @throws InvalidArgumentException
  1633. */
  1634. public static function startsWithLetter($value, $message = '')
  1635. {
  1636. static::string($value);
  1637. $valid = isset($value[0]);
  1638. if ($valid) {
  1639. $locale = \setlocale(\LC_CTYPE, 0);
  1640. \setlocale(\LC_CTYPE, 'C');
  1641. $valid = \ctype_alpha($value[0]);
  1642. \setlocale(\LC_CTYPE, $locale);
  1643. }
  1644. if (!$valid) {
  1645. static::reportInvalidArgument(\sprintf($message ?: 'Expected a value to start with a letter. Got: %s', static::valueToString($value)));
  1646. }
  1647. }
  1648. /**
  1649. * @psalm-pure
  1650. *
  1651. * @param string $value
  1652. * @param string $suffix
  1653. * @param string $message
  1654. *
  1655. * @throws InvalidArgumentException
  1656. */
  1657. public static function endsWith($value, $suffix, $message = '')
  1658. {
  1659. if ($suffix !== \substr($value, -\strlen($suffix))) {
  1660. static::reportInvalidArgument(\sprintf($message ?: 'Expected a value to end with %2$s. Got: %s', static::valueToString($value), static::valueToString($suffix)));
  1661. }
  1662. }
  1663. /**
  1664. * @psalm-pure
  1665. *
  1666. * @param string $value
  1667. * @param string $suffix
  1668. * @param string $message
  1669. *
  1670. * @throws InvalidArgumentException
  1671. */
  1672. public static function notEndsWith($value, $suffix, $message = '')
  1673. {
  1674. if ($suffix === \substr($value, -\strlen($suffix))) {
  1675. static::reportInvalidArgument(\sprintf($message ?: 'Expected a value not to end with %2$s. Got: %s', static::valueToString($value), static::valueToString($suffix)));
  1676. }
  1677. }
  1678. /**
  1679. * @psalm-pure
  1680. *
  1681. * @param string $value
  1682. * @param string $pattern
  1683. * @param string $message
  1684. *
  1685. * @throws InvalidArgumentException
  1686. */
  1687. public static function regex($value, $pattern, $message = '')
  1688. {
  1689. if (!\preg_match($pattern, $value)) {
  1690. static::reportInvalidArgument(\sprintf($message ?: 'The value %s does not match the expected pattern.', static::valueToString($value)));
  1691. }
  1692. }
  1693. /**
  1694. * @psalm-pure
  1695. *
  1696. * @param string $value
  1697. * @param string $pattern
  1698. * @param string $message
  1699. *
  1700. * @throws InvalidArgumentException
  1701. */
  1702. public static function notRegex($value, $pattern, $message = '')
  1703. {
  1704. if (\preg_match($pattern, $value, $matches, \PREG_OFFSET_CAPTURE)) {
  1705. static::reportInvalidArgument(\sprintf($message ?: 'The value %s matches the pattern %s (at offset %d).', static::valueToString($value), static::valueToString($pattern), $matches[0][1]));
  1706. }
  1707. }
  1708. /**
  1709. * @psalm-pure
  1710. *
  1711. * @param mixed $value
  1712. * @param string $message
  1713. *
  1714. * @throws InvalidArgumentException
  1715. */
  1716. public static function unicodeLetters($value, $message = '')
  1717. {
  1718. static::string($value);
  1719. if (!\preg_match('/^\\p{L}+$/u', $value)) {
  1720. static::reportInvalidArgument(\sprintf($message ?: 'Expected a value to contain only Unicode letters. Got: %s', static::valueToString($value)));
  1721. }
  1722. }
  1723. /**
  1724. * @psalm-pure
  1725. *
  1726. * @param mixed $value
  1727. * @param string $message
  1728. *
  1729. * @throws InvalidArgumentException
  1730. */
  1731. public static function alpha($value, $message = '')
  1732. {
  1733. static::string($value);
  1734. $locale = \setlocale(\LC_CTYPE, 0);
  1735. \setlocale(\LC_CTYPE, 'C');
  1736. $valid = !\ctype_alpha($value);
  1737. \setlocale(\LC_CTYPE, $locale);
  1738. if ($valid) {
  1739. static::reportInvalidArgument(\sprintf($message ?: 'Expected a value to contain only letters. Got: %s', static::valueToString($value)));
  1740. }
  1741. }
  1742. /**
  1743. * @psalm-pure
  1744. *
  1745. * @param string $value
  1746. * @param string $message
  1747. *
  1748. * @throws InvalidArgumentException
  1749. */
  1750. public static function digits($value, $message = '')
  1751. {
  1752. $locale = \setlocale(\LC_CTYPE, 0);
  1753. \setlocale(\LC_CTYPE, 'C');
  1754. $valid = !\ctype_digit($value);
  1755. \setlocale(\LC_CTYPE, $locale);
  1756. if ($valid) {
  1757. static::reportInvalidArgument(\sprintf($message ?: 'Expected a value to contain digits only. Got: %s', static::valueToString($value)));
  1758. }
  1759. }
  1760. /**
  1761. * @psalm-pure
  1762. *
  1763. * @param string $value
  1764. * @param string $message
  1765. *
  1766. * @throws InvalidArgumentException
  1767. */
  1768. public static function alnum($value, $message = '')
  1769. {
  1770. $locale = \setlocale(\LC_CTYPE, 0);
  1771. \setlocale(\LC_CTYPE, 'C');
  1772. $valid = !\ctype_alnum($value);
  1773. \setlocale(\LC_CTYPE, $locale);
  1774. if ($valid) {
  1775. static::reportInvalidArgument(\sprintf($message ?: 'Expected a value to contain letters and digits only. Got: %s', static::valueToString($value)));
  1776. }
  1777. }
  1778. /**
  1779. * @psalm-pure
  1780. * @psalm-assert lowercase-string $value
  1781. *
  1782. * @param string $value
  1783. * @param string $message
  1784. *
  1785. * @throws InvalidArgumentException
  1786. */
  1787. public static function lower($value, $message = '')
  1788. {
  1789. $locale = \setlocale(\LC_CTYPE, 0);
  1790. \setlocale(\LC_CTYPE, 'C');
  1791. $valid = !\ctype_lower($value);
  1792. \setlocale(\LC_CTYPE, $locale);
  1793. if ($valid) {
  1794. static::reportInvalidArgument(\sprintf($message ?: 'Expected a value to contain lowercase characters only. Got: %s', static::valueToString($value)));
  1795. }
  1796. }
  1797. /**
  1798. * @psalm-pure
  1799. * @psalm-assert !lowercase-string $value
  1800. *
  1801. * @param string $value
  1802. * @param string $message
  1803. *
  1804. * @throws InvalidArgumentException
  1805. */
  1806. public static function upper($value, $message = '')
  1807. {
  1808. $locale = \setlocale(\LC_CTYPE, 0);
  1809. \setlocale(\LC_CTYPE, 'C');
  1810. $valid = !\ctype_upper($value);
  1811. \setlocale(\LC_CTYPE, $locale);
  1812. if ($valid) {
  1813. static::reportInvalidArgument(\sprintf($message ?: 'Expected a value to contain uppercase characters only. Got: %s', static::valueToString($value)));
  1814. }
  1815. }
  1816. /**
  1817. * @psalm-pure
  1818. *
  1819. * @param string $value
  1820. * @param int $length
  1821. * @param string $message
  1822. *
  1823. * @throws InvalidArgumentException
  1824. */
  1825. public static function length($value, $length, $message = '')
  1826. {
  1827. if ($length !== static::strlen($value)) {
  1828. static::reportInvalidArgument(\sprintf($message ?: 'Expected a value to contain %2$s characters. Got: %s', static::valueToString($value), $length));
  1829. }
  1830. }
  1831. /**
  1832. * Inclusive min.
  1833. *
  1834. * @psalm-pure
  1835. *
  1836. * @param string $value
  1837. * @param int|float $min
  1838. * @param string $message
  1839. *
  1840. * @throws InvalidArgumentException
  1841. */
  1842. public static function minLength($value, $min, $message = '')
  1843. {
  1844. if (static::strlen($value) < $min) {
  1845. static::reportInvalidArgument(\sprintf($message ?: 'Expected a value to contain at least %2$s characters. Got: %s', static::valueToString($value), $min));
  1846. }
  1847. }
  1848. /**
  1849. * Inclusive max.
  1850. *
  1851. * @psalm-pure
  1852. *
  1853. * @param string $value
  1854. * @param int|float $max
  1855. * @param string $message
  1856. *
  1857. * @throws InvalidArgumentException
  1858. */
  1859. public static function maxLength($value, $max, $message = '')
  1860. {
  1861. if (static::strlen($value) > $max) {
  1862. static::reportInvalidArgument(\sprintf($message ?: 'Expected a value to contain at most %2$s characters. Got: %s', static::valueToString($value), $max));
  1863. }
  1864. }
  1865. /**
  1866. * Inclusive , so Assert::lengthBetween('asd', 3, 5); passes the assertion.
  1867. *
  1868. * @psalm-pure
  1869. *
  1870. * @param string $value
  1871. * @param int|float $min
  1872. * @param int|float $max
  1873. * @param string $message
  1874. *
  1875. * @throws InvalidArgumentException
  1876. */
  1877. public static function lengthBetween($value, $min, $max, $message = '')
  1878. {
  1879. $length = static::strlen($value);
  1880. if ($length < $min || $length > $max) {
  1881. static::reportInvalidArgument(\sprintf($message ?: 'Expected a value to contain between %2$s and %3$s characters. Got: %s', static::valueToString($value), $min, $max));
  1882. }
  1883. }
  1884. /**
  1885. * Will also pass if $value is a directory, use Assert::file() instead if you need to be sure it is a file.
  1886. *
  1887. * @param mixed $value
  1888. * @param string $message
  1889. *
  1890. * @throws InvalidArgumentException
  1891. */
  1892. public static function fileExists($value, $message = '')
  1893. {
  1894. static::string($value);
  1895. if (!\file_exists($value)) {
  1896. static::reportInvalidArgument(\sprintf($message ?: 'The file %s does not exist.', static::valueToString($value)));
  1897. }
  1898. }
  1899. /**
  1900. * @param mixed $value
  1901. * @param string $message
  1902. *
  1903. * @throws InvalidArgumentException
  1904. */
  1905. public static function file($value, $message = '')
  1906. {
  1907. static::fileExists($value, $message);
  1908. if (!\is_file($value)) {
  1909. static::reportInvalidArgument(\sprintf($message ?: 'The path %s is not a file.', static::valueToString($value)));
  1910. }
  1911. }
  1912. /**
  1913. * @param mixed $value
  1914. * @param string $message
  1915. *
  1916. * @throws InvalidArgumentException
  1917. */
  1918. public static function directory($value, $message = '')
  1919. {
  1920. static::fileExists($value, $message);
  1921. if (!\is_dir($value)) {
  1922. static::reportInvalidArgument(\sprintf($message ?: 'The path %s is no directory.', static::valueToString($value)));
  1923. }
  1924. }
  1925. /**
  1926. * @param string $value
  1927. * @param string $message
  1928. *
  1929. * @throws InvalidArgumentException
  1930. */
  1931. public static function readable($value, $message = '')
  1932. {
  1933. if (!\is_readable($value)) {
  1934. static::reportInvalidArgument(\sprintf($message ?: 'The path %s is not readable.', static::valueToString($value)));
  1935. }
  1936. }
  1937. /**
  1938. * @param string $value
  1939. * @param string $message
  1940. *
  1941. * @throws InvalidArgumentException
  1942. */
  1943. public static function writable($value, $message = '')
  1944. {
  1945. if (!\is_writable($value)) {
  1946. static::reportInvalidArgument(\sprintf($message ?: 'The path %s is not writable.', static::valueToString($value)));
  1947. }
  1948. }
  1949. /**
  1950. * @psalm-assert class-string $value
  1951. *
  1952. * @param mixed $value
  1953. * @param string $message
  1954. *
  1955. * @throws InvalidArgumentException
  1956. */
  1957. public static function classExists($value, $message = '')
  1958. {
  1959. if (!\class_exists($value)) {
  1960. static::reportInvalidArgument(\sprintf($message ?: 'Expected an existing class name. Got: %s', static::valueToString($value)));
  1961. }
  1962. }
  1963. /**
  1964. * @psalm-pure
  1965. * @psalm-template ExpectedType of object
  1966. * @psalm-param class-string<ExpectedType> $class
  1967. * @psalm-assert class-string<ExpectedType>|ExpectedType $value
  1968. *
  1969. * @param mixed $value
  1970. * @param string|object $class
  1971. * @param string $message
  1972. *
  1973. * @throws InvalidArgumentException
  1974. */
  1975. public static function subclassOf($value, $class, $message = '')
  1976. {
  1977. if (!\is_subclass_of($value, $class)) {
  1978. static::reportInvalidArgument(\sprintf($message ?: 'Expected a sub-class of %2$s. Got: %s', static::valueToString($value), static::valueToString($class)));
  1979. }
  1980. }
  1981. /**
  1982. * @psalm-assert class-string $value
  1983. *
  1984. * @param mixed $value
  1985. * @param string $message
  1986. *
  1987. * @throws InvalidArgumentException
  1988. */
  1989. public static function interfaceExists($value, $message = '')
  1990. {
  1991. if (!\interface_exists($value)) {
  1992. static::reportInvalidArgument(\sprintf($message ?: 'Expected an existing interface name. got %s', static::valueToString($value)));
  1993. }
  1994. }
  1995. /**
  1996. * @psalm-pure
  1997. * @psalm-template ExpectedType of object
  1998. * @psalm-param class-string<ExpectedType> $interface
  1999. * @psalm-assert class-string<ExpectedType> $value
  2000. *
  2001. * @param mixed $value
  2002. * @param mixed $interface
  2003. * @param string $message
  2004. *
  2005. * @throws InvalidArgumentException
  2006. */
  2007. public static function implementsInterface($value, $interface, $message = '')
  2008. {
  2009. if (!\in_array($interface, \class_implements($value))) {
  2010. static::reportInvalidArgument(\sprintf($message ?: 'Expected an implementation of %2$s. Got: %s', static::valueToString($value), static::valueToString($interface)));
  2011. }
  2012. }
  2013. /**
  2014. * @psalm-pure
  2015. * @psalm-param class-string|object $classOrObject
  2016. *
  2017. * @param string|object $classOrObject
  2018. * @param mixed $property
  2019. * @param string $message
  2020. *
  2021. * @throws InvalidArgumentException
  2022. */
  2023. public static function propertyExists($classOrObject, $property, $message = '')
  2024. {
  2025. if (!\property_exists($classOrObject, $property)) {
  2026. static::reportInvalidArgument(\sprintf($message ?: 'Expected the property %s to exist.', static::valueToString($property)));
  2027. }
  2028. }
  2029. /**
  2030. * @psalm-pure
  2031. * @psalm-param class-string|object $classOrObject
  2032. *
  2033. * @param string|object $classOrObject
  2034. * @param mixed $property
  2035. * @param string $message
  2036. *
  2037. * @throws InvalidArgumentException
  2038. */
  2039. public static function propertyNotExists($classOrObject, $property, $message = '')
  2040. {
  2041. if (\property_exists($classOrObject, $property)) {
  2042. static::reportInvalidArgument(\sprintf($message ?: 'Expected the property %s to not exist.', static::valueToString($property)));
  2043. }
  2044. }
  2045. /**
  2046. * @psalm-pure
  2047. * @psalm-param class-string|object $classOrObject
  2048. *
  2049. * @param string|object $classOrObject
  2050. * @param mixed $method
  2051. * @param string $message
  2052. *
  2053. * @throws InvalidArgumentException
  2054. */
  2055. public static function methodExists($classOrObject, $method, $message = '')
  2056. {
  2057. if (!\method_exists($classOrObject, $method)) {
  2058. static::reportInvalidArgument(\sprintf($message ?: 'Expected the method %s to exist.', static::valueToString($method)));
  2059. }
  2060. }
  2061. /**
  2062. * @psalm-pure
  2063. * @psalm-param class-string|object $classOrObject
  2064. *
  2065. * @param string|object $classOrObject
  2066. * @param mixed $method
  2067. * @param string $message
  2068. *
  2069. * @throws InvalidArgumentException
  2070. */
  2071. public static function methodNotExists($classOrObject, $method, $message = '')
  2072. {
  2073. if (\method_exists($classOrObject, $method)) {
  2074. static::reportInvalidArgument(\sprintf($message ?: 'Expected the method %s to not exist.', static::valueToString($method)));
  2075. }
  2076. }
  2077. /**
  2078. * @psalm-pure
  2079. *
  2080. * @param array $array
  2081. * @param string|int $key
  2082. * @param string $message
  2083. *
  2084. * @throws InvalidArgumentException
  2085. */
  2086. public static function keyExists($array, $key, $message = '')
  2087. {
  2088. if (!(isset($array[$key]) || \array_key_exists($key, $array))) {
  2089. static::reportInvalidArgument(\sprintf($message ?: 'Expected the key %s to exist.', static::valueToString($key)));
  2090. }
  2091. }
  2092. /**
  2093. * @psalm-pure
  2094. *
  2095. * @param array $array
  2096. * @param string|int $key
  2097. * @param string $message
  2098. *
  2099. * @throws InvalidArgumentException
  2100. */
  2101. public static function keyNotExists($array, $key, $message = '')
  2102. {
  2103. if (isset($array[$key]) || \array_key_exists($key, $array)) {
  2104. static::reportInvalidArgument(\sprintf($message ?: 'Expected the key %s to not exist.', static::valueToString($key)));
  2105. }
  2106. }
  2107. /**
  2108. * Checks if a value is a valid array key (int or string).
  2109. *
  2110. * @psalm-pure
  2111. * @psalm-assert array-key $value
  2112. *
  2113. * @param mixed $value
  2114. * @param string $message
  2115. *
  2116. * @throws InvalidArgumentException
  2117. */
  2118. public static function validArrayKey($value, $message = '')
  2119. {
  2120. if (!(\is_int($value) || \is_string($value))) {
  2121. static::reportInvalidArgument(\sprintf($message ?: 'Expected string or integer. Got: %s', static::typeToString($value)));
  2122. }
  2123. }
  2124. /**
  2125. * Does not check if $array is countable, this can generate a warning on php versions after 7.2.
  2126. *
  2127. * @param Countable|array $array
  2128. * @param int $number
  2129. * @param string $message
  2130. *
  2131. * @throws InvalidArgumentException
  2132. */
  2133. public static function count($array, $number, $message = '')
  2134. {
  2135. static::eq(\count($array), $number, \sprintf($message ?: 'Expected an array to contain %d elements. Got: %d.', $number, \count($array)));
  2136. }
  2137. /**
  2138. * Does not check if $array is countable, this can generate a warning on php versions after 7.2.
  2139. *
  2140. * @param Countable|array $array
  2141. * @param int|float $min
  2142. * @param string $message
  2143. *
  2144. * @throws InvalidArgumentException
  2145. */
  2146. public static function minCount($array, $min, $message = '')
  2147. {
  2148. if (\count($array) < $min) {
  2149. static::reportInvalidArgument(\sprintf($message ?: 'Expected an array to contain at least %2$d elements. Got: %d', \count($array), $min));
  2150. }
  2151. }
  2152. /**
  2153. * Does not check if $array is countable, this can generate a warning on php versions after 7.2.
  2154. *
  2155. * @param Countable|array $array
  2156. * @param int|float $max
  2157. * @param string $message
  2158. *
  2159. * @throws InvalidArgumentException
  2160. */
  2161. public static function maxCount($array, $max, $message = '')
  2162. {
  2163. if (\count($array) > $max) {
  2164. static::reportInvalidArgument(\sprintf($message ?: 'Expected an array to contain at most %2$d elements. Got: %d', \count($array), $max));
  2165. }
  2166. }
  2167. /**
  2168. * Does not check if $array is countable, this can generate a warning on php versions after 7.2.
  2169. *
  2170. * @param Countable|array $array
  2171. * @param int|float $min
  2172. * @param int|float $max
  2173. * @param string $message
  2174. *
  2175. * @throws InvalidArgumentException
  2176. */
  2177. public static function countBetween($array, $min, $max, $message = '')
  2178. {
  2179. $count = \count($array);
  2180. if ($count < $min || $count > $max) {
  2181. static::reportInvalidArgument(\sprintf($message ?: 'Expected an array to contain between %2$d and %3$d elements. Got: %d', $count, $min, $max));
  2182. }
  2183. }
  2184. /**
  2185. * @psalm-pure
  2186. * @psalm-assert list $array
  2187. *
  2188. * @param mixed $array
  2189. * @param string $message
  2190. *
  2191. * @throws InvalidArgumentException
  2192. */
  2193. public static function isList($array, $message = '')
  2194. {
  2195. if (!\is_array($array) || $array !== \array_values($array)) {
  2196. static::reportInvalidArgument($message ?: 'Expected list - non-associative array.');
  2197. }
  2198. }
  2199. /**
  2200. * @psalm-pure
  2201. * @psalm-assert non-empty-list $array
  2202. *
  2203. * @param mixed $array
  2204. * @param string $message
  2205. *
  2206. * @throws InvalidArgumentException
  2207. */
  2208. public static function isNonEmptyList($array, $message = '')
  2209. {
  2210. static::isList($array, $message);
  2211. static::notEmpty($array, $message);
  2212. }
  2213. /**
  2214. * @psalm-pure
  2215. * @psalm-template T
  2216. * @psalm-param mixed|array<T> $array
  2217. * @psalm-assert array<string, T> $array
  2218. *
  2219. * @param mixed $array
  2220. * @param string $message
  2221. *
  2222. * @throws InvalidArgumentException
  2223. */
  2224. public static function isMap($array, $message = '')
  2225. {
  2226. if (!\is_array($array) || \array_keys($array) !== \array_filter(\array_keys($array), '\\is_string')) {
  2227. static::reportInvalidArgument($message ?: 'Expected map - associative array with string keys.');
  2228. }
  2229. }
  2230. /**
  2231. * @psalm-pure
  2232. * @psalm-template T
  2233. * @psalm-param mixed|array<T> $array
  2234. * @psalm-assert array<string, T> $array
  2235. * @psalm-assert !empty $array
  2236. *
  2237. * @param mixed $array
  2238. * @param string $message
  2239. *
  2240. * @throws InvalidArgumentException
  2241. */
  2242. public static function isNonEmptyMap($array, $message = '')
  2243. {
  2244. static::isMap($array, $message);
  2245. static::notEmpty($array, $message);
  2246. }
  2247. /**
  2248. * @psalm-pure
  2249. *
  2250. * @param string $value
  2251. * @param string $message
  2252. *
  2253. * @throws InvalidArgumentException
  2254. */
  2255. public static function uuid($value, $message = '')
  2256. {
  2257. $value = \str_replace(array('urn:', 'uuid:', '{', '}'), '', $value);
  2258. // The nil UUID is special form of UUID that is specified to have all
  2259. // 128 bits set to zero.
  2260. if ('00000000-0000-0000-0000-000000000000' === $value) {
  2261. return;
  2262. }
  2263. if (!\preg_match('/^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{12}$/', $value)) {
  2264. static::reportInvalidArgument(\sprintf($message ?: 'Value %s is not a valid UUID.', static::valueToString($value)));
  2265. }
  2266. }
  2267. /**
  2268. * @psalm-param class-string<Throwable> $class
  2269. *
  2270. * @param Closure $expression
  2271. * @param string $class
  2272. * @param string $message
  2273. *
  2274. * @throws InvalidArgumentException
  2275. */
  2276. public static function throws(\Closure $expression, $class = 'Exception', $message = '')
  2277. {
  2278. static::string($class);
  2279. $actual = 'none';
  2280. try {
  2281. $expression();
  2282. } catch (\Exception $e) {
  2283. $actual = \get_class($e);
  2284. if ($e instanceof $class) {
  2285. return;
  2286. }
  2287. } catch (\Throwable $e) {
  2288. $actual = \get_class($e);
  2289. if ($e instanceof $class) {
  2290. return;
  2291. }
  2292. }
  2293. static::reportInvalidArgument($message ?: \sprintf('Expected to throw "%s", got "%s"', $class, $actual));
  2294. }
  2295. /**
  2296. * @throws BadMethodCallException
  2297. */
  2298. public static function __callStatic($name, $arguments)
  2299. {
  2300. if ('nullOr' === \substr($name, 0, 6)) {
  2301. if (null !== $arguments[0]) {
  2302. $method = \lcfirst(\substr($name, 6));
  2303. \call_user_func_array(array('static', $method), $arguments);
  2304. }
  2305. return;
  2306. }
  2307. if ('all' === \substr($name, 0, 3)) {
  2308. static::isIterable($arguments[0]);
  2309. $method = \lcfirst(\substr($name, 3));
  2310. $args = $arguments;
  2311. foreach ($arguments[0] as $entry) {
  2312. $args[0] = $entry;
  2313. \call_user_func_array(array('static', $method), $args);
  2314. }
  2315. return;
  2316. }
  2317. throw new \BadMethodCallException('No such method: ' . $name);
  2318. }
  2319. /**
  2320. * @param mixed $value
  2321. *
  2322. * @return string
  2323. */
  2324. protected static function valueToString($value)
  2325. {
  2326. if (null === $value) {
  2327. return 'null';
  2328. }
  2329. if (\true === $value) {
  2330. return 'true';
  2331. }
  2332. if (\false === $value) {
  2333. return 'false';
  2334. }
  2335. if (\is_array($value)) {
  2336. return 'array';
  2337. }
  2338. if (\is_object($value)) {
  2339. if (\method_exists($value, '__toString')) {
  2340. return \get_class($value) . ': ' . self::valueToString($value->__toString());
  2341. }
  2342. if ($value instanceof \DateTime || $value instanceof \DateTimeImmutable) {
  2343. return \get_class($value) . ': ' . self::valueToString($value->format('c'));
  2344. }
  2345. return \get_class($value);
  2346. }
  2347. if (\is_resource($value)) {
  2348. return 'resource';
  2349. }
  2350. if (\is_string($value)) {
  2351. return '"' . $value . '"';
  2352. }
  2353. return (string) $value;
  2354. }
  2355. /**
  2356. * @param mixed $value
  2357. *
  2358. * @return string
  2359. */
  2360. protected static function typeToString($value)
  2361. {
  2362. return \is_object($value) ? \get_class($value) : \gettype($value);
  2363. }
  2364. protected static function strlen($value)
  2365. {
  2366. if (!\function_exists('mb_detect_encoding')) {
  2367. return \strlen($value);
  2368. }
  2369. if (\false === ($encoding = \mb_detect_encoding($value))) {
  2370. return \strlen($value);
  2371. }
  2372. return \mb_strlen($value, $encoding);
  2373. }
  2374. /**
  2375. * @param string $message
  2376. *
  2377. * @throws InvalidArgumentException
  2378. *
  2379. * @psalm-pure this method is not supposed to perform side-effects
  2380. */
  2381. protected static function reportInvalidArgument($message)
  2382. {
  2383. throw new \InvalidArgumentException($message);
  2384. }
  2385. private function __construct()
  2386. {
  2387. }
  2388. }
  2389. <?php
  2390. /**
  2391. * provides type inference and auto-completion for magic static methods of Assert.
  2392. */
  2393. namespace PHPUnit\Webmozart\Assert;
  2394. use ArrayAccess;
  2395. use Closure;
  2396. use Countable;
  2397. use InvalidArgumentException;
  2398. use Throwable;
  2399. interface Mixin
  2400. {
  2401. /**
  2402. * @psalm-pure
  2403. * @psalm-assert null|string $value
  2404. *
  2405. * @param mixed $value
  2406. * @param string $message
  2407. *
  2408. * @throws InvalidArgumentException
  2409. */
  2410. public static function nullOrString($value, $message = '');
  2411. /**
  2412. * @psalm-pure
  2413. * @psalm-assert iterable<string> $value
  2414. *
  2415. * @param mixed $value
  2416. * @param string $message
  2417. *
  2418. * @throws InvalidArgumentException
  2419. */
  2420. public static function allString($value, $message = '');
  2421. /**
  2422. * @psalm-pure
  2423. * @psalm-assert null|non-empty-string $value
  2424. *
  2425. * @param mixed $value
  2426. * @param string $message
  2427. *
  2428. * @throws InvalidArgumentException
  2429. */
  2430. public static function nullOrStringNotEmpty($value, $message = '');
  2431. /**
  2432. * @psalm-pure
  2433. * @psalm-assert iterable<non-empty-string> $value
  2434. *
  2435. * @param mixed $value
  2436. * @param string $message
  2437. *
  2438. * @throws InvalidArgumentException
  2439. */
  2440. public static function allStringNotEmpty($value, $message = '');
  2441. /**
  2442. * @psalm-pure
  2443. * @psalm-assert null|int $value
  2444. *
  2445. * @param mixed $value
  2446. * @param string $message
  2447. *
  2448. * @throws InvalidArgumentException
  2449. */
  2450. public static function nullOrInteger($value, $message = '');
  2451. /**
  2452. * @psalm-pure
  2453. * @psalm-assert iterable<int> $value
  2454. *
  2455. * @param mixed $value
  2456. * @param string $message
  2457. *
  2458. * @throws InvalidArgumentException
  2459. */
  2460. public static function allInteger($value, $message = '');
  2461. /**
  2462. * @psalm-pure
  2463. * @psalm-assert null|numeric $value
  2464. *
  2465. * @param mixed $value
  2466. * @param string $message
  2467. *
  2468. * @throws InvalidArgumentException
  2469. */
  2470. public static function nullOrIntegerish($value, $message = '');
  2471. /**
  2472. * @psalm-pure
  2473. * @psalm-assert iterable<numeric> $value
  2474. *
  2475. * @param mixed $value
  2476. * @param string $message
  2477. *
  2478. * @throws InvalidArgumentException
  2479. */
  2480. public static function allIntegerish($value, $message = '');
  2481. /**
  2482. * @psalm-pure
  2483. * @psalm-assert null|float $value
  2484. *
  2485. * @param mixed $value
  2486. * @param string $message
  2487. *
  2488. * @throws InvalidArgumentException
  2489. */
  2490. public static function nullOrFloat($value, $message = '');
  2491. /**
  2492. * @psalm-pure
  2493. * @psalm-assert iterable<float> $value
  2494. *
  2495. * @param mixed $value
  2496. * @param string $message
  2497. *
  2498. * @throws InvalidArgumentException
  2499. */
  2500. public static function allFloat($value, $message = '');
  2501. /**
  2502. * @psalm-pure
  2503. * @psalm-assert null|numeric $value
  2504. *
  2505. * @param mixed $value
  2506. * @param string $message
  2507. *
  2508. * @throws InvalidArgumentException
  2509. */
  2510. public static function nullOrNumeric($value, $message = '');
  2511. /**
  2512. * @psalm-pure
  2513. * @psalm-assert iterable<numeric> $value
  2514. *
  2515. * @param mixed $value
  2516. * @param string $message
  2517. *
  2518. * @throws InvalidArgumentException
  2519. */
  2520. public static function allNumeric($value, $message = '');
  2521. /**
  2522. * @psalm-pure
  2523. * @psalm-assert null|int $value
  2524. *
  2525. * @param mixed $value
  2526. * @param string $message
  2527. *
  2528. * @throws InvalidArgumentException
  2529. */
  2530. public static function nullOrNatural($value, $message = '');
  2531. /**
  2532. * @psalm-pure
  2533. * @psalm-assert iterable<int> $value
  2534. *
  2535. * @param mixed $value
  2536. * @param string $message
  2537. *
  2538. * @throws InvalidArgumentException
  2539. */
  2540. public static function allNatural($value, $message = '');
  2541. /**
  2542. * @psalm-pure
  2543. * @psalm-assert null|bool $value
  2544. *
  2545. * @param mixed $value
  2546. * @param string $message
  2547. *
  2548. * @throws InvalidArgumentException
  2549. */
  2550. public static function nullOrBoolean($value, $message = '');
  2551. /**
  2552. * @psalm-pure
  2553. * @psalm-assert iterable<bool> $value
  2554. *
  2555. * @param mixed $value
  2556. * @param string $message
  2557. *
  2558. * @throws InvalidArgumentException
  2559. */
  2560. public static function allBoolean($value, $message = '');
  2561. /**
  2562. * @psalm-pure
  2563. * @psalm-assert null|scalar $value
  2564. *
  2565. * @param mixed $value
  2566. * @param string $message
  2567. *
  2568. * @throws InvalidArgumentException
  2569. */
  2570. public static function nullOrScalar($value, $message = '');
  2571. /**
  2572. * @psalm-pure
  2573. * @psalm-assert iterable<scalar> $value
  2574. *
  2575. * @param mixed $value
  2576. * @param string $message
  2577. *
  2578. * @throws InvalidArgumentException
  2579. */
  2580. public static function allScalar($value, $message = '');
  2581. /**
  2582. * @psalm-pure
  2583. * @psalm-assert null|object $value
  2584. *
  2585. * @param mixed $value
  2586. * @param string $message
  2587. *
  2588. * @throws InvalidArgumentException
  2589. */
  2590. public static function nullOrObject($value, $message = '');
  2591. /**
  2592. * @psalm-pure
  2593. * @psalm-assert iterable<object> $value
  2594. *
  2595. * @param mixed $value
  2596. * @param string $message
  2597. *
  2598. * @throws InvalidArgumentException
  2599. */
  2600. public static function allObject($value, $message = '');
  2601. /**
  2602. * @psalm-pure
  2603. * @psalm-assert null|resource $value
  2604. *
  2605. * @param mixed $value
  2606. * @param string|null $type type of resource this should be. @see https://www.php.net/manual/en/function.get-resource-type.php
  2607. * @param string $message
  2608. *
  2609. * @throws InvalidArgumentException
  2610. */
  2611. public static function nullOrResource($value, $type = null, $message = '');
  2612. /**
  2613. * @psalm-pure
  2614. * @psalm-assert iterable<resource> $value
  2615. *
  2616. * @param mixed $value
  2617. * @param string|null $type type of resource this should be. @see https://www.php.net/manual/en/function.get-resource-type.php
  2618. * @param string $message
  2619. *
  2620. * @throws InvalidArgumentException
  2621. */
  2622. public static function allResource($value, $type = null, $message = '');
  2623. /**
  2624. * @psalm-pure
  2625. * @psalm-assert null|callable $value
  2626. *
  2627. * @param mixed $value
  2628. * @param string $message
  2629. *
  2630. * @throws InvalidArgumentException
  2631. */
  2632. public static function nullOrIsCallable($value, $message = '');
  2633. /**
  2634. * @psalm-pure
  2635. * @psalm-assert iterable<callable> $value
  2636. *
  2637. * @param mixed $value
  2638. * @param string $message
  2639. *
  2640. * @throws InvalidArgumentException
  2641. */
  2642. public static function allIsCallable($value, $message = '');
  2643. /**
  2644. * @psalm-pure
  2645. * @psalm-assert null|array $value
  2646. *
  2647. * @param mixed $value
  2648. * @param string $message
  2649. *
  2650. * @throws InvalidArgumentException
  2651. */
  2652. public static function nullOrIsArray($value, $message = '');
  2653. /**
  2654. * @psalm-pure
  2655. * @psalm-assert iterable<array> $value
  2656. *
  2657. * @param mixed $value
  2658. * @param string $message
  2659. *
  2660. * @throws InvalidArgumentException
  2661. */
  2662. public static function allIsArray($value, $message = '');
  2663. /**
  2664. * @psalm-pure
  2665. * @psalm-assert null|iterable $value
  2666. *
  2667. * @deprecated use "isIterable" or "isInstanceOf" instead
  2668. *
  2669. * @param mixed $value
  2670. * @param string $message
  2671. *
  2672. * @throws InvalidArgumentException
  2673. */
  2674. public static function nullOrIsTraversable($value, $message = '');
  2675. /**
  2676. * @psalm-pure
  2677. * @psalm-assert iterable<iterable> $value
  2678. *
  2679. * @deprecated use "isIterable" or "isInstanceOf" instead
  2680. *
  2681. * @param mixed $value
  2682. * @param string $message
  2683. *
  2684. * @throws InvalidArgumentException
  2685. */
  2686. public static function allIsTraversable($value, $message = '');
  2687. /**
  2688. * @psalm-pure
  2689. * @psalm-assert null|array|ArrayAccess $value
  2690. *
  2691. * @param mixed $value
  2692. * @param string $message
  2693. *
  2694. * @throws InvalidArgumentException
  2695. */
  2696. public static function nullOrIsArrayAccessible($value, $message = '');
  2697. /**
  2698. * @psalm-pure
  2699. * @psalm-assert iterable<array|ArrayAccess> $value
  2700. *
  2701. * @param mixed $value
  2702. * @param string $message
  2703. *
  2704. * @throws InvalidArgumentException
  2705. */
  2706. public static function allIsArrayAccessible($value, $message = '');
  2707. /**
  2708. * @psalm-pure
  2709. * @psalm-assert null|countable $value
  2710. *
  2711. * @param mixed $value
  2712. * @param string $message
  2713. *
  2714. * @throws InvalidArgumentException
  2715. */
  2716. public static function nullOrIsCountable($value, $message = '');
  2717. /**
  2718. * @psalm-pure
  2719. * @psalm-assert iterable<countable> $value
  2720. *
  2721. * @param mixed $value
  2722. * @param string $message
  2723. *
  2724. * @throws InvalidArgumentException
  2725. */
  2726. public static function allIsCountable($value, $message = '');
  2727. /**
  2728. * @psalm-pure
  2729. * @psalm-assert null|iterable $value
  2730. *
  2731. * @param mixed $value
  2732. * @param string $message
  2733. *
  2734. * @throws InvalidArgumentException
  2735. */
  2736. public static function nullOrIsIterable($value, $message = '');
  2737. /**
  2738. * @psalm-pure
  2739. * @psalm-assert iterable<iterable> $value
  2740. *
  2741. * @param mixed $value
  2742. * @param string $message
  2743. *
  2744. * @throws InvalidArgumentException
  2745. */
  2746. public static function allIsIterable($value, $message = '');
  2747. /**
  2748. * @psalm-pure
  2749. * @psalm-template ExpectedType of object
  2750. * @psalm-param class-string<ExpectedType> $class
  2751. * @psalm-assert null|ExpectedType $value
  2752. *
  2753. * @param mixed $value
  2754. * @param string|object $class
  2755. * @param string $message
  2756. *
  2757. * @throws InvalidArgumentException
  2758. */
  2759. public static function nullOrIsInstanceOf($value, $class, $message = '');
  2760. /**
  2761. * @psalm-pure
  2762. * @psalm-template ExpectedType of object
  2763. * @psalm-param class-string<ExpectedType> $class
  2764. * @psalm-assert iterable<ExpectedType> $value
  2765. *
  2766. * @param mixed $value
  2767. * @param string|object $class
  2768. * @param string $message
  2769. *
  2770. * @throws InvalidArgumentException
  2771. */
  2772. public static function allIsInstanceOf($value, $class, $message = '');
  2773. /**
  2774. * @psalm-pure
  2775. * @psalm-template ExpectedType of object
  2776. * @psalm-param class-string<ExpectedType> $class
  2777. *
  2778. * @param mixed $value
  2779. * @param string|object $class
  2780. * @param string $message
  2781. *
  2782. * @throws InvalidArgumentException
  2783. */
  2784. public static function nullOrNotInstanceOf($value, $class, $message = '');
  2785. /**
  2786. * @psalm-pure
  2787. * @psalm-template ExpectedType of object
  2788. * @psalm-param class-string<ExpectedType> $class
  2789. *
  2790. * @param mixed $value
  2791. * @param string|object $class
  2792. * @param string $message
  2793. *
  2794. * @throws InvalidArgumentException
  2795. */
  2796. public static function allNotInstanceOf($value, $class, $message = '');
  2797. /**
  2798. * @psalm-pure
  2799. * @psalm-param array<class-string> $classes
  2800. *
  2801. * @param mixed $value
  2802. * @param array<object|string> $classes
  2803. * @param string $message
  2804. *
  2805. * @throws InvalidArgumentException
  2806. */
  2807. public static function nullOrIsInstanceOfAny($value, $classes, $message = '');
  2808. /**
  2809. * @psalm-pure
  2810. * @psalm-param array<class-string> $classes
  2811. *
  2812. * @param mixed $value
  2813. * @param array<object|string> $classes
  2814. * @param string $message
  2815. *
  2816. * @throws InvalidArgumentException
  2817. */
  2818. public static function allIsInstanceOfAny($value, $classes, $message = '');
  2819. /**
  2820. * @psalm-pure
  2821. * @psalm-template ExpectedType of object
  2822. * @psalm-param class-string<ExpectedType> $class
  2823. * @psalm-assert null|ExpectedType|class-string<ExpectedType> $value
  2824. *
  2825. * @param null|object|string $value
  2826. * @param string $class
  2827. * @param string $message
  2828. *
  2829. * @throws InvalidArgumentException
  2830. */
  2831. public static function nullOrIsAOf($value, $class, $message = '');
  2832. /**
  2833. * @psalm-pure
  2834. * @psalm-template ExpectedType of object
  2835. * @psalm-param class-string<ExpectedType> $class
  2836. * @psalm-assert iterable<ExpectedType|class-string<ExpectedType>> $value
  2837. *
  2838. * @param iterable<object|string> $value
  2839. * @param string $class
  2840. * @param string $message
  2841. *
  2842. * @throws InvalidArgumentException
  2843. */
  2844. public static function allIsAOf($value, $class, $message = '');
  2845. /**
  2846. * @psalm-pure
  2847. * @psalm-template UnexpectedType of object
  2848. * @psalm-param class-string<UnexpectedType> $class
  2849. *
  2850. * @param null|object|string $value
  2851. * @param string $class
  2852. * @param string $message
  2853. *
  2854. * @throws InvalidArgumentException
  2855. */
  2856. public static function nullOrIsNotA($value, $class, $message = '');
  2857. /**
  2858. * @psalm-pure
  2859. * @psalm-template UnexpectedType of object
  2860. * @psalm-param class-string<UnexpectedType> $class
  2861. *
  2862. * @param iterable<object|string> $value
  2863. * @param string $class
  2864. * @param string $message
  2865. *
  2866. * @throws InvalidArgumentException
  2867. */
  2868. public static function allIsNotA($value, $class, $message = '');
  2869. /**
  2870. * @psalm-pure
  2871. * @psalm-param array<class-string> $classes
  2872. *
  2873. * @param null|object|string $value
  2874. * @param string[] $classes
  2875. * @param string $message
  2876. *
  2877. * @throws InvalidArgumentException
  2878. */
  2879. public static function nullOrIsAnyOf($value, $classes, $message = '');
  2880. /**
  2881. * @psalm-pure
  2882. * @psalm-param array<class-string> $classes
  2883. *
  2884. * @param iterable<object|string> $value
  2885. * @param string[] $classes
  2886. * @param string $message
  2887. *
  2888. * @throws InvalidArgumentException
  2889. */
  2890. public static function allIsAnyOf($value, $classes, $message = '');
  2891. /**
  2892. * @psalm-pure
  2893. * @psalm-assert empty $value
  2894. *
  2895. * @param mixed $value
  2896. * @param string $message
  2897. *
  2898. * @throws InvalidArgumentException
  2899. */
  2900. public static function nullOrIsEmpty($value, $message = '');
  2901. /**
  2902. * @psalm-pure
  2903. * @psalm-assert iterable<empty> $value
  2904. *
  2905. * @param mixed $value
  2906. * @param string $message
  2907. *
  2908. * @throws InvalidArgumentException
  2909. */
  2910. public static function allIsEmpty($value, $message = '');
  2911. /**
  2912. * @psalm-pure
  2913. *
  2914. * @param mixed $value
  2915. * @param string $message
  2916. *
  2917. * @throws InvalidArgumentException
  2918. */
  2919. public static function nullOrNotEmpty($value, $message = '');
  2920. /**
  2921. * @psalm-pure
  2922. *
  2923. * @param mixed $value
  2924. * @param string $message
  2925. *
  2926. * @throws InvalidArgumentException
  2927. */
  2928. public static function allNotEmpty($value, $message = '');
  2929. /**
  2930. * @psalm-pure
  2931. * @psalm-assert iterable<null> $value
  2932. *
  2933. * @param mixed $value
  2934. * @param string $message
  2935. *
  2936. * @throws InvalidArgumentException
  2937. */
  2938. public static function allNull($value, $message = '');
  2939. /**
  2940. * @psalm-pure
  2941. *
  2942. * @param mixed $value
  2943. * @param string $message
  2944. *
  2945. * @throws InvalidArgumentException
  2946. */
  2947. public static function allNotNull($value, $message = '');
  2948. /**
  2949. * @psalm-pure
  2950. * @psalm-assert null|true $value
  2951. *
  2952. * @param mixed $value
  2953. * @param string $message
  2954. *
  2955. * @throws InvalidArgumentException
  2956. */
  2957. public static function nullOrTrue($value, $message = '');
  2958. /**
  2959. * @psalm-pure
  2960. * @psalm-assert iterable<true> $value
  2961. *
  2962. * @param mixed $value
  2963. * @param string $message
  2964. *
  2965. * @throws InvalidArgumentException
  2966. */
  2967. public static function allTrue($value, $message = '');
  2968. /**
  2969. * @psalm-pure
  2970. * @psalm-assert null|false $value
  2971. *
  2972. * @param mixed $value
  2973. * @param string $message
  2974. *
  2975. * @throws InvalidArgumentException
  2976. */
  2977. public static function nullOrFalse($value, $message = '');
  2978. /**
  2979. * @psalm-pure
  2980. * @psalm-assert iterable<false> $value
  2981. *
  2982. * @param mixed $value
  2983. * @param string $message
  2984. *
  2985. * @throws InvalidArgumentException
  2986. */
  2987. public static function allFalse($value, $message = '');
  2988. /**
  2989. * @psalm-pure
  2990. *
  2991. * @param mixed $value
  2992. * @param string $message
  2993. *
  2994. * @throws InvalidArgumentException
  2995. */
  2996. public static function nullOrNotFalse($value, $message = '');
  2997. /**
  2998. * @psalm-pure
  2999. *
  3000. * @param mixed $value
  3001. * @param string $message
  3002. *
  3003. * @throws InvalidArgumentException
  3004. */
  3005. public static function allNotFalse($value, $message = '');
  3006. /**
  3007. * @param mixed $value
  3008. * @param string $message
  3009. *
  3010. * @throws InvalidArgumentException
  3011. */
  3012. public static function nullOrIp($value, $message = '');
  3013. /**
  3014. * @param mixed $value
  3015. * @param string $message
  3016. *
  3017. * @throws InvalidArgumentException
  3018. */
  3019. public static function allIp($value, $message = '');
  3020. /**
  3021. * @param mixed $value
  3022. * @param string $message
  3023. *
  3024. * @throws InvalidArgumentException
  3025. */
  3026. public static function nullOrIpv4($value, $message = '');
  3027. /**
  3028. * @param mixed $value
  3029. * @param string $message
  3030. *
  3031. * @throws InvalidArgumentException
  3032. */
  3033. public static function allIpv4($value, $message = '');
  3034. /**
  3035. * @param mixed $value
  3036. * @param string $message
  3037. *
  3038. * @throws InvalidArgumentException
  3039. */
  3040. public static function nullOrIpv6($value, $message = '');
  3041. /**
  3042. * @param mixed $value
  3043. * @param string $message
  3044. *
  3045. * @throws InvalidArgumentException
  3046. */
  3047. public static function allIpv6($value, $message = '');
  3048. /**
  3049. * @param mixed $value
  3050. * @param string $message
  3051. *
  3052. * @throws InvalidArgumentException
  3053. */
  3054. public static function nullOrEmail($value, $message = '');
  3055. /**
  3056. * @param mixed $value
  3057. * @param string $message
  3058. *
  3059. * @throws InvalidArgumentException
  3060. */
  3061. public static function allEmail($value, $message = '');
  3062. /**
  3063. * @param null|array $values
  3064. * @param string $message
  3065. *
  3066. * @throws InvalidArgumentException
  3067. */
  3068. public static function nullOrUniqueValues($values, $message = '');
  3069. /**
  3070. * @param iterable<array> $values
  3071. * @param string $message
  3072. *
  3073. * @throws InvalidArgumentException
  3074. */
  3075. public static function allUniqueValues($values, $message = '');
  3076. /**
  3077. * @param mixed $value
  3078. * @param mixed $expect
  3079. * @param string $message
  3080. *
  3081. * @throws InvalidArgumentException
  3082. */
  3083. public static function nullOrEq($value, $expect, $message = '');
  3084. /**
  3085. * @param mixed $value
  3086. * @param mixed $expect
  3087. * @param string $message
  3088. *
  3089. * @throws InvalidArgumentException
  3090. */
  3091. public static function allEq($value, $expect, $message = '');
  3092. /**
  3093. * @param mixed $value
  3094. * @param mixed $expect
  3095. * @param string $message
  3096. *
  3097. * @throws InvalidArgumentException
  3098. */
  3099. public static function nullOrNotEq($value, $expect, $message = '');
  3100. /**
  3101. * @param mixed $value
  3102. * @param mixed $expect
  3103. * @param string $message
  3104. *
  3105. * @throws InvalidArgumentException
  3106. */
  3107. public static function allNotEq($value, $expect, $message = '');
  3108. /**
  3109. * @psalm-pure
  3110. *
  3111. * @param mixed $value
  3112. * @param mixed $expect
  3113. * @param string $message
  3114. *
  3115. * @throws InvalidArgumentException
  3116. */
  3117. public static function nullOrSame($value, $expect, $message = '');
  3118. /**
  3119. * @psalm-pure
  3120. *
  3121. * @param mixed $value
  3122. * @param mixed $expect
  3123. * @param string $message
  3124. *
  3125. * @throws InvalidArgumentException
  3126. */
  3127. public static function allSame($value, $expect, $message = '');
  3128. /**
  3129. * @psalm-pure
  3130. *
  3131. * @param mixed $value
  3132. * @param mixed $expect
  3133. * @param string $message
  3134. *
  3135. * @throws InvalidArgumentException
  3136. */
  3137. public static function nullOrNotSame($value, $expect, $message = '');
  3138. /**
  3139. * @psalm-pure
  3140. *
  3141. * @param mixed $value
  3142. * @param mixed $expect
  3143. * @param string $message
  3144. *
  3145. * @throws InvalidArgumentException
  3146. */
  3147. public static function allNotSame($value, $expect, $message = '');
  3148. /**
  3149. * @psalm-pure
  3150. *
  3151. * @param mixed $value
  3152. * @param mixed $limit
  3153. * @param string $message
  3154. *
  3155. * @throws InvalidArgumentException
  3156. */
  3157. public static function nullOrGreaterThan($value, $limit, $message = '');
  3158. /**
  3159. * @psalm-pure
  3160. *
  3161. * @param mixed $value
  3162. * @param mixed $limit
  3163. * @param string $message
  3164. *
  3165. * @throws InvalidArgumentException
  3166. */
  3167. public static function allGreaterThan($value, $limit, $message = '');
  3168. /**
  3169. * @psalm-pure
  3170. *
  3171. * @param mixed $value
  3172. * @param mixed $limit
  3173. * @param string $message
  3174. *
  3175. * @throws InvalidArgumentException
  3176. */
  3177. public static function nullOrGreaterThanEq($value, $limit, $message = '');
  3178. /**
  3179. * @psalm-pure
  3180. *
  3181. * @param mixed $value
  3182. * @param mixed $limit
  3183. * @param string $message
  3184. *
  3185. * @throws InvalidArgumentException
  3186. */
  3187. public static function allGreaterThanEq($value, $limit, $message = '');
  3188. /**
  3189. * @psalm-pure
  3190. *
  3191. * @param mixed $value
  3192. * @param mixed $limit
  3193. * @param string $message
  3194. *
  3195. * @throws InvalidArgumentException
  3196. */
  3197. public static function nullOrLessThan($value, $limit, $message = '');
  3198. /**
  3199. * @psalm-pure
  3200. *
  3201. * @param mixed $value
  3202. * @param mixed $limit
  3203. * @param string $message
  3204. *
  3205. * @throws InvalidArgumentException
  3206. */
  3207. public static function allLessThan($value, $limit, $message = '');
  3208. /**
  3209. * @psalm-pure
  3210. *
  3211. * @param mixed $value
  3212. * @param mixed $limit
  3213. * @param string $message
  3214. *
  3215. * @throws InvalidArgumentException
  3216. */
  3217. public static function nullOrLessThanEq($value, $limit, $message = '');
  3218. /**
  3219. * @psalm-pure
  3220. *
  3221. * @param mixed $value
  3222. * @param mixed $limit
  3223. * @param string $message
  3224. *
  3225. * @throws InvalidArgumentException
  3226. */
  3227. public static function allLessThanEq($value, $limit, $message = '');
  3228. /**
  3229. * @psalm-pure
  3230. *
  3231. * @param mixed $value
  3232. * @param mixed $min
  3233. * @param mixed $max
  3234. * @param string $message
  3235. *
  3236. * @throws InvalidArgumentException
  3237. */
  3238. public static function nullOrRange($value, $min, $max, $message = '');
  3239. /**
  3240. * @psalm-pure
  3241. *
  3242. * @param mixed $value
  3243. * @param mixed $min
  3244. * @param mixed $max
  3245. * @param string $message
  3246. *
  3247. * @throws InvalidArgumentException
  3248. */
  3249. public static function allRange($value, $min, $max, $message = '');
  3250. /**
  3251. * @psalm-pure
  3252. *
  3253. * @param mixed $value
  3254. * @param array $values
  3255. * @param string $message
  3256. *
  3257. * @throws InvalidArgumentException
  3258. */
  3259. public static function nullOrOneOf($value, $values, $message = '');
  3260. /**
  3261. * @psalm-pure
  3262. *
  3263. * @param mixed $value
  3264. * @param array $values
  3265. * @param string $message
  3266. *
  3267. * @throws InvalidArgumentException
  3268. */
  3269. public static function allOneOf($value, $values, $message = '');
  3270. /**
  3271. * @psalm-pure
  3272. *
  3273. * @param mixed $value
  3274. * @param array $values
  3275. * @param string $message
  3276. *
  3277. * @throws InvalidArgumentException
  3278. */
  3279. public static function nullOrInArray($value, $values, $message = '');
  3280. /**
  3281. * @psalm-pure
  3282. *
  3283. * @param mixed $value
  3284. * @param array $values
  3285. * @param string $message
  3286. *
  3287. * @throws InvalidArgumentException
  3288. */
  3289. public static function allInArray($value, $values, $message = '');
  3290. /**
  3291. * @psalm-pure
  3292. *
  3293. * @param null|string $value
  3294. * @param string $subString
  3295. * @param string $message
  3296. *
  3297. * @throws InvalidArgumentException
  3298. */
  3299. public static function nullOrContains($value, $subString, $message = '');
  3300. /**
  3301. * @psalm-pure
  3302. *
  3303. * @param iterable<string> $value
  3304. * @param string $subString
  3305. * @param string $message
  3306. *
  3307. * @throws InvalidArgumentException
  3308. */
  3309. public static function allContains($value, $subString, $message = '');
  3310. /**
  3311. * @psalm-pure
  3312. *
  3313. * @param null|string $value
  3314. * @param string $subString
  3315. * @param string $message
  3316. *
  3317. * @throws InvalidArgumentException
  3318. */
  3319. public static function nullOrNotContains($value, $subString, $message = '');
  3320. /**
  3321. * @psalm-pure
  3322. *
  3323. * @param iterable<string> $value
  3324. * @param string $subString
  3325. * @param string $message
  3326. *
  3327. * @throws InvalidArgumentException
  3328. */
  3329. public static function allNotContains($value, $subString, $message = '');
  3330. /**
  3331. * @psalm-pure
  3332. *
  3333. * @param null|string $value
  3334. * @param string $message
  3335. *
  3336. * @throws InvalidArgumentException
  3337. */
  3338. public static function nullOrNotWhitespaceOnly($value, $message = '');
  3339. /**
  3340. * @psalm-pure
  3341. *
  3342. * @param iterable<string> $value
  3343. * @param string $message
  3344. *
  3345. * @throws InvalidArgumentException
  3346. */
  3347. public static function allNotWhitespaceOnly($value, $message = '');
  3348. /**
  3349. * @psalm-pure
  3350. *
  3351. * @param null|string $value
  3352. * @param string $prefix
  3353. * @param string $message
  3354. *
  3355. * @throws InvalidArgumentException
  3356. */
  3357. public static function nullOrStartsWith($value, $prefix, $message = '');
  3358. /**
  3359. * @psalm-pure
  3360. *
  3361. * @param iterable<string> $value
  3362. * @param string $prefix
  3363. * @param string $message
  3364. *
  3365. * @throws InvalidArgumentException
  3366. */
  3367. public static function allStartsWith($value, $prefix, $message = '');
  3368. /**
  3369. * @psalm-pure
  3370. *
  3371. * @param null|string $value
  3372. * @param string $prefix
  3373. * @param string $message
  3374. *
  3375. * @throws InvalidArgumentException
  3376. */
  3377. public static function nullOrNotStartsWith($value, $prefix, $message = '');
  3378. /**
  3379. * @psalm-pure
  3380. *
  3381. * @param iterable<string> $value
  3382. * @param string $prefix
  3383. * @param string $message
  3384. *
  3385. * @throws InvalidArgumentException
  3386. */
  3387. public static function allNotStartsWith($value, $prefix, $message = '');
  3388. /**
  3389. * @psalm-pure
  3390. *
  3391. * @param mixed $value
  3392. * @param string $message
  3393. *
  3394. * @throws InvalidArgumentException
  3395. */
  3396. public static function nullOrStartsWithLetter($value, $message = '');
  3397. /**
  3398. * @psalm-pure
  3399. *
  3400. * @param mixed $value
  3401. * @param string $message
  3402. *
  3403. * @throws InvalidArgumentException
  3404. */
  3405. public static function allStartsWithLetter($value, $message = '');
  3406. /**
  3407. * @psalm-pure
  3408. *
  3409. * @param null|string $value
  3410. * @param string $suffix
  3411. * @param string $message
  3412. *
  3413. * @throws InvalidArgumentException
  3414. */
  3415. public static function nullOrEndsWith($value, $suffix, $message = '');
  3416. /**
  3417. * @psalm-pure
  3418. *
  3419. * @param iterable<string> $value
  3420. * @param string $suffix
  3421. * @param string $message
  3422. *
  3423. * @throws InvalidArgumentException
  3424. */
  3425. public static function allEndsWith($value, $suffix, $message = '');
  3426. /**
  3427. * @psalm-pure
  3428. *
  3429. * @param null|string $value
  3430. * @param string $suffix
  3431. * @param string $message
  3432. *
  3433. * @throws InvalidArgumentException
  3434. */
  3435. public static function nullOrNotEndsWith($value, $suffix, $message = '');
  3436. /**
  3437. * @psalm-pure
  3438. *
  3439. * @param iterable<string> $value
  3440. * @param string $suffix
  3441. * @param string $message
  3442. *
  3443. * @throws InvalidArgumentException
  3444. */
  3445. public static function allNotEndsWith($value, $suffix, $message = '');
  3446. /**
  3447. * @psalm-pure
  3448. *
  3449. * @param null|string $value
  3450. * @param string $pattern
  3451. * @param string $message
  3452. *
  3453. * @throws InvalidArgumentException
  3454. */
  3455. public static function nullOrRegex($value, $pattern, $message = '');
  3456. /**
  3457. * @psalm-pure
  3458. *
  3459. * @param iterable<string> $value
  3460. * @param string $pattern
  3461. * @param string $message
  3462. *
  3463. * @throws InvalidArgumentException
  3464. */
  3465. public static function allRegex($value, $pattern, $message = '');
  3466. /**
  3467. * @psalm-pure
  3468. *
  3469. * @param null|string $value
  3470. * @param string $pattern
  3471. * @param string $message
  3472. *
  3473. * @throws InvalidArgumentException
  3474. */
  3475. public static function nullOrNotRegex($value, $pattern, $message = '');
  3476. /**
  3477. * @psalm-pure
  3478. *
  3479. * @param iterable<string> $value
  3480. * @param string $pattern
  3481. * @param string $message
  3482. *
  3483. * @throws InvalidArgumentException
  3484. */
  3485. public static function allNotRegex($value, $pattern, $message = '');
  3486. /**
  3487. * @psalm-pure
  3488. *
  3489. * @param mixed $value
  3490. * @param string $message
  3491. *
  3492. * @throws InvalidArgumentException
  3493. */
  3494. public static function nullOrUnicodeLetters($value, $message = '');
  3495. /**
  3496. * @psalm-pure
  3497. *
  3498. * @param mixed $value
  3499. * @param string $message
  3500. *
  3501. * @throws InvalidArgumentException
  3502. */
  3503. public static function allUnicodeLetters($value, $message = '');
  3504. /**
  3505. * @psalm-pure
  3506. *
  3507. * @param mixed $value
  3508. * @param string $message
  3509. *
  3510. * @throws InvalidArgumentException
  3511. */
  3512. public static function nullOrAlpha($value, $message = '');
  3513. /**
  3514. * @psalm-pure
  3515. *
  3516. * @param mixed $value
  3517. * @param string $message
  3518. *
  3519. * @throws InvalidArgumentException
  3520. */
  3521. public static function allAlpha($value, $message = '');
  3522. /**
  3523. * @psalm-pure
  3524. *
  3525. * @param null|string $value
  3526. * @param string $message
  3527. *
  3528. * @throws InvalidArgumentException
  3529. */
  3530. public static function nullOrDigits($value, $message = '');
  3531. /**
  3532. * @psalm-pure
  3533. *
  3534. * @param iterable<string> $value
  3535. * @param string $message
  3536. *
  3537. * @throws InvalidArgumentException
  3538. */
  3539. public static function allDigits($value, $message = '');
  3540. /**
  3541. * @psalm-pure
  3542. *
  3543. * @param null|string $value
  3544. * @param string $message
  3545. *
  3546. * @throws InvalidArgumentException
  3547. */
  3548. public static function nullOrAlnum($value, $message = '');
  3549. /**
  3550. * @psalm-pure
  3551. *
  3552. * @param iterable<string> $value
  3553. * @param string $message
  3554. *
  3555. * @throws InvalidArgumentException
  3556. */
  3557. public static function allAlnum($value, $message = '');
  3558. /**
  3559. * @psalm-pure
  3560. * @psalm-assert null|lowercase-string $value
  3561. *
  3562. * @param null|string $value
  3563. * @param string $message
  3564. *
  3565. * @throws InvalidArgumentException
  3566. */
  3567. public static function nullOrLower($value, $message = '');
  3568. /**
  3569. * @psalm-pure
  3570. * @psalm-assert iterable<lowercase-string> $value
  3571. *
  3572. * @param iterable<string> $value
  3573. * @param string $message
  3574. *
  3575. * @throws InvalidArgumentException
  3576. */
  3577. public static function allLower($value, $message = '');
  3578. /**
  3579. * @psalm-pure
  3580. *
  3581. * @param null|string $value
  3582. * @param string $message
  3583. *
  3584. * @throws InvalidArgumentException
  3585. */
  3586. public static function nullOrUpper($value, $message = '');
  3587. /**
  3588. * @psalm-pure
  3589. *
  3590. * @param iterable<string> $value
  3591. * @param string $message
  3592. *
  3593. * @throws InvalidArgumentException
  3594. */
  3595. public static function allUpper($value, $message = '');
  3596. /**
  3597. * @psalm-pure
  3598. *
  3599. * @param null|string $value
  3600. * @param int $length
  3601. * @param string $message
  3602. *
  3603. * @throws InvalidArgumentException
  3604. */
  3605. public static function nullOrLength($value, $length, $message = '');
  3606. /**
  3607. * @psalm-pure
  3608. *
  3609. * @param iterable<string> $value
  3610. * @param int $length
  3611. * @param string $message
  3612. *
  3613. * @throws InvalidArgumentException
  3614. */
  3615. public static function allLength($value, $length, $message = '');
  3616. /**
  3617. * @psalm-pure
  3618. *
  3619. * @param null|string $value
  3620. * @param int|float $min
  3621. * @param string $message
  3622. *
  3623. * @throws InvalidArgumentException
  3624. */
  3625. public static function nullOrMinLength($value, $min, $message = '');
  3626. /**
  3627. * @psalm-pure
  3628. *
  3629. * @param iterable<string> $value
  3630. * @param int|float $min
  3631. * @param string $message
  3632. *
  3633. * @throws InvalidArgumentException
  3634. */
  3635. public static function allMinLength($value, $min, $message = '');
  3636. /**
  3637. * @psalm-pure
  3638. *
  3639. * @param null|string $value
  3640. * @param int|float $max
  3641. * @param string $message
  3642. *
  3643. * @throws InvalidArgumentException
  3644. */
  3645. public static function nullOrMaxLength($value, $max, $message = '');
  3646. /**
  3647. * @psalm-pure
  3648. *
  3649. * @param iterable<string> $value
  3650. * @param int|float $max
  3651. * @param string $message
  3652. *
  3653. * @throws InvalidArgumentException
  3654. */
  3655. public static function allMaxLength($value, $max, $message = '');
  3656. /**
  3657. * @psalm-pure
  3658. *
  3659. * @param null|string $value
  3660. * @param int|float $min
  3661. * @param int|float $max
  3662. * @param string $message
  3663. *
  3664. * @throws InvalidArgumentException
  3665. */
  3666. public static function nullOrLengthBetween($value, $min, $max, $message = '');
  3667. /**
  3668. * @psalm-pure
  3669. *
  3670. * @param iterable<string> $value
  3671. * @param int|float $min
  3672. * @param int|float $max
  3673. * @param string $message
  3674. *
  3675. * @throws InvalidArgumentException
  3676. */
  3677. public static function allLengthBetween($value, $min, $max, $message = '');
  3678. /**
  3679. * @param mixed $value
  3680. * @param string $message
  3681. *
  3682. * @throws InvalidArgumentException
  3683. */
  3684. public static function nullOrFileExists($value, $message = '');
  3685. /**
  3686. * @param mixed $value
  3687. * @param string $message
  3688. *
  3689. * @throws InvalidArgumentException
  3690. */
  3691. public static function allFileExists($value, $message = '');
  3692. /**
  3693. * @param mixed $value
  3694. * @param string $message
  3695. *
  3696. * @throws InvalidArgumentException
  3697. */
  3698. public static function nullOrFile($value, $message = '');
  3699. /**
  3700. * @param mixed $value
  3701. * @param string $message
  3702. *
  3703. * @throws InvalidArgumentException
  3704. */
  3705. public static function allFile($value, $message = '');
  3706. /**
  3707. * @param mixed $value
  3708. * @param string $message
  3709. *
  3710. * @throws InvalidArgumentException
  3711. */
  3712. public static function nullOrDirectory($value, $message = '');
  3713. /**
  3714. * @param mixed $value
  3715. * @param string $message
  3716. *
  3717. * @throws InvalidArgumentException
  3718. */
  3719. public static function allDirectory($value, $message = '');
  3720. /**
  3721. * @param null|string $value
  3722. * @param string $message
  3723. *
  3724. * @throws InvalidArgumentException
  3725. */
  3726. public static function nullOrReadable($value, $message = '');
  3727. /**
  3728. * @param iterable<string> $value
  3729. * @param string $message
  3730. *
  3731. * @throws InvalidArgumentException
  3732. */
  3733. public static function allReadable($value, $message = '');
  3734. /**
  3735. * @param null|string $value
  3736. * @param string $message
  3737. *
  3738. * @throws InvalidArgumentException
  3739. */
  3740. public static function nullOrWritable($value, $message = '');
  3741. /**
  3742. * @param iterable<string> $value
  3743. * @param string $message
  3744. *
  3745. * @throws InvalidArgumentException
  3746. */
  3747. public static function allWritable($value, $message = '');
  3748. /**
  3749. * @psalm-assert null|class-string $value
  3750. *
  3751. * @param mixed $value
  3752. * @param string $message
  3753. *
  3754. * @throws InvalidArgumentException
  3755. */
  3756. public static function nullOrClassExists($value, $message = '');
  3757. /**
  3758. * @psalm-assert iterable<class-string> $value
  3759. *
  3760. * @param mixed $value
  3761. * @param string $message
  3762. *
  3763. * @throws InvalidArgumentException
  3764. */
  3765. public static function allClassExists($value, $message = '');
  3766. /**
  3767. * @psalm-pure
  3768. * @psalm-template ExpectedType of object
  3769. * @psalm-param class-string<ExpectedType> $class
  3770. * @psalm-assert null|class-string<ExpectedType>|ExpectedType $value
  3771. *
  3772. * @param mixed $value
  3773. * @param string|object $class
  3774. * @param string $message
  3775. *
  3776. * @throws InvalidArgumentException
  3777. */
  3778. public static function nullOrSubclassOf($value, $class, $message = '');
  3779. /**
  3780. * @psalm-pure
  3781. * @psalm-template ExpectedType of object
  3782. * @psalm-param class-string<ExpectedType> $class
  3783. * @psalm-assert iterable<class-string<ExpectedType>|ExpectedType> $value
  3784. *
  3785. * @param mixed $value
  3786. * @param string|object $class
  3787. * @param string $message
  3788. *
  3789. * @throws InvalidArgumentException
  3790. */
  3791. public static function allSubclassOf($value, $class, $message = '');
  3792. /**
  3793. * @psalm-assert null|class-string $value
  3794. *
  3795. * @param mixed $value
  3796. * @param string $message
  3797. *
  3798. * @throws InvalidArgumentException
  3799. */
  3800. public static function nullOrInterfaceExists($value, $message = '');
  3801. /**
  3802. * @psalm-assert iterable<class-string> $value
  3803. *
  3804. * @param mixed $value
  3805. * @param string $message
  3806. *
  3807. * @throws InvalidArgumentException
  3808. */
  3809. public static function allInterfaceExists($value, $message = '');
  3810. /**
  3811. * @psalm-pure
  3812. * @psalm-template ExpectedType of object
  3813. * @psalm-param class-string<ExpectedType> $interface
  3814. * @psalm-assert null|class-string<ExpectedType> $value
  3815. *
  3816. * @param mixed $value
  3817. * @param mixed $interface
  3818. * @param string $message
  3819. *
  3820. * @throws InvalidArgumentException
  3821. */
  3822. public static function nullOrImplementsInterface($value, $interface, $message = '');
  3823. /**
  3824. * @psalm-pure
  3825. * @psalm-template ExpectedType of object
  3826. * @psalm-param class-string<ExpectedType> $interface
  3827. * @psalm-assert iterable<class-string<ExpectedType>> $value
  3828. *
  3829. * @param mixed $value
  3830. * @param mixed $interface
  3831. * @param string $message
  3832. *
  3833. * @throws InvalidArgumentException
  3834. */
  3835. public static function allImplementsInterface($value, $interface, $message = '');
  3836. /**
  3837. * @psalm-pure
  3838. * @psalm-param null|class-string|object $classOrObject
  3839. *
  3840. * @param null|string|object $classOrObject
  3841. * @param mixed $property
  3842. * @param string $message
  3843. *
  3844. * @throws InvalidArgumentException
  3845. */
  3846. public static function nullOrPropertyExists($classOrObject, $property, $message = '');
  3847. /**
  3848. * @psalm-pure
  3849. * @psalm-param iterable<class-string|object> $classOrObject
  3850. *
  3851. * @param iterable<string|object> $classOrObject
  3852. * @param mixed $property
  3853. * @param string $message
  3854. *
  3855. * @throws InvalidArgumentException
  3856. */
  3857. public static function allPropertyExists($classOrObject, $property, $message = '');
  3858. /**
  3859. * @psalm-pure
  3860. * @psalm-param null|class-string|object $classOrObject
  3861. *
  3862. * @param null|string|object $classOrObject
  3863. * @param mixed $property
  3864. * @param string $message
  3865. *
  3866. * @throws InvalidArgumentException
  3867. */
  3868. public static function nullOrPropertyNotExists($classOrObject, $property, $message = '');
  3869. /**
  3870. * @psalm-pure
  3871. * @psalm-param iterable<class-string|object> $classOrObject
  3872. *
  3873. * @param iterable<string|object> $classOrObject
  3874. * @param mixed $property
  3875. * @param string $message
  3876. *
  3877. * @throws InvalidArgumentException
  3878. */
  3879. public static function allPropertyNotExists($classOrObject, $property, $message = '');
  3880. /**
  3881. * @psalm-pure
  3882. * @psalm-param null|class-string|object $classOrObject
  3883. *
  3884. * @param null|string|object $classOrObject
  3885. * @param mixed $method
  3886. * @param string $message
  3887. *
  3888. * @throws InvalidArgumentException
  3889. */
  3890. public static function nullOrMethodExists($classOrObject, $method, $message = '');
  3891. /**
  3892. * @psalm-pure
  3893. * @psalm-param iterable<class-string|object> $classOrObject
  3894. *
  3895. * @param iterable<string|object> $classOrObject
  3896. * @param mixed $method
  3897. * @param string $message
  3898. *
  3899. * @throws InvalidArgumentException
  3900. */
  3901. public static function allMethodExists($classOrObject, $method, $message = '');
  3902. /**
  3903. * @psalm-pure
  3904. * @psalm-param null|class-string|object $classOrObject
  3905. *
  3906. * @param null|string|object $classOrObject
  3907. * @param mixed $method
  3908. * @param string $message
  3909. *
  3910. * @throws InvalidArgumentException
  3911. */
  3912. public static function nullOrMethodNotExists($classOrObject, $method, $message = '');
  3913. /**
  3914. * @psalm-pure
  3915. * @psalm-param iterable<class-string|object> $classOrObject
  3916. *
  3917. * @param iterable<string|object> $classOrObject
  3918. * @param mixed $method
  3919. * @param string $message
  3920. *
  3921. * @throws InvalidArgumentException
  3922. */
  3923. public static function allMethodNotExists($classOrObject, $method, $message = '');
  3924. /**
  3925. * @psalm-pure
  3926. *
  3927. * @param null|array $array
  3928. * @param string|int $key
  3929. * @param string $message
  3930. *
  3931. * @throws InvalidArgumentException
  3932. */
  3933. public static function nullOrKeyExists($array, $key, $message = '');
  3934. /**
  3935. * @psalm-pure
  3936. *
  3937. * @param iterable<array> $array
  3938. * @param string|int $key
  3939. * @param string $message
  3940. *
  3941. * @throws InvalidArgumentException
  3942. */
  3943. public static function allKeyExists($array, $key, $message = '');
  3944. /**
  3945. * @psalm-pure
  3946. *
  3947. * @param null|array $array
  3948. * @param string|int $key
  3949. * @param string $message
  3950. *
  3951. * @throws InvalidArgumentException
  3952. */
  3953. public static function nullOrKeyNotExists($array, $key, $message = '');
  3954. /**
  3955. * @psalm-pure
  3956. *
  3957. * @param iterable<array> $array
  3958. * @param string|int $key
  3959. * @param string $message
  3960. *
  3961. * @throws InvalidArgumentException
  3962. */
  3963. public static function allKeyNotExists($array, $key, $message = '');
  3964. /**
  3965. * @psalm-pure
  3966. * @psalm-assert null|array-key $value
  3967. *
  3968. * @param mixed $value
  3969. * @param string $message
  3970. *
  3971. * @throws InvalidArgumentException
  3972. */
  3973. public static function nullOrValidArrayKey($value, $message = '');
  3974. /**
  3975. * @psalm-pure
  3976. * @psalm-assert iterable<array-key> $value
  3977. *
  3978. * @param mixed $value
  3979. * @param string $message
  3980. *
  3981. * @throws InvalidArgumentException
  3982. */
  3983. public static function allValidArrayKey($value, $message = '');
  3984. /**
  3985. * @param null|Countable|array $array
  3986. * @param int $number
  3987. * @param string $message
  3988. *
  3989. * @throws InvalidArgumentException
  3990. */
  3991. public static function nullOrCount($array, $number, $message = '');
  3992. /**
  3993. * @param iterable<Countable|array> $array
  3994. * @param int $number
  3995. * @param string $message
  3996. *
  3997. * @throws InvalidArgumentException
  3998. */
  3999. public static function allCount($array, $number, $message = '');
  4000. /**
  4001. * @param null|Countable|array $array
  4002. * @param int|float $min
  4003. * @param string $message
  4004. *
  4005. * @throws InvalidArgumentException
  4006. */
  4007. public static function nullOrMinCount($array, $min, $message = '');
  4008. /**
  4009. * @param iterable<Countable|array> $array
  4010. * @param int|float $min
  4011. * @param string $message
  4012. *
  4013. * @throws InvalidArgumentException
  4014. */
  4015. public static function allMinCount($array, $min, $message = '');
  4016. /**
  4017. * @param null|Countable|array $array
  4018. * @param int|float $max
  4019. * @param string $message
  4020. *
  4021. * @throws InvalidArgumentException
  4022. */
  4023. public static function nullOrMaxCount($array, $max, $message = '');
  4024. /**
  4025. * @param iterable<Countable|array> $array
  4026. * @param int|float $max
  4027. * @param string $message
  4028. *
  4029. * @throws InvalidArgumentException
  4030. */
  4031. public static function allMaxCount($array, $max, $message = '');
  4032. /**
  4033. * @param null|Countable|array $array
  4034. * @param int|float $min
  4035. * @param int|float $max
  4036. * @param string $message
  4037. *
  4038. * @throws InvalidArgumentException
  4039. */
  4040. public static function nullOrCountBetween($array, $min, $max, $message = '');
  4041. /**
  4042. * @param iterable<Countable|array> $array
  4043. * @param int|float $min
  4044. * @param int|float $max
  4045. * @param string $message
  4046. *
  4047. * @throws InvalidArgumentException
  4048. */
  4049. public static function allCountBetween($array, $min, $max, $message = '');
  4050. /**
  4051. * @psalm-pure
  4052. * @psalm-assert null|list $array
  4053. *
  4054. * @param mixed $array
  4055. * @param string $message
  4056. *
  4057. * @throws InvalidArgumentException
  4058. */
  4059. public static function nullOrIsList($array, $message = '');
  4060. /**
  4061. * @psalm-pure
  4062. * @psalm-assert iterable<list> $array
  4063. *
  4064. * @param mixed $array
  4065. * @param string $message
  4066. *
  4067. * @throws InvalidArgumentException
  4068. */
  4069. public static function allIsList($array, $message = '');
  4070. /**
  4071. * @psalm-pure
  4072. * @psalm-assert null|non-empty-list $array
  4073. *
  4074. * @param mixed $array
  4075. * @param string $message
  4076. *
  4077. * @throws InvalidArgumentException
  4078. */
  4079. public static function nullOrIsNonEmptyList($array, $message = '');
  4080. /**
  4081. * @psalm-pure
  4082. * @psalm-assert iterable<non-empty-list> $array
  4083. *
  4084. * @param mixed $array
  4085. * @param string $message
  4086. *
  4087. * @throws InvalidArgumentException
  4088. */
  4089. public static function allIsNonEmptyList($array, $message = '');
  4090. /**
  4091. * @psalm-pure
  4092. * @psalm-template T
  4093. * @psalm-param null|mixed|array<T> $array
  4094. * @psalm-assert null|array<string, T> $array
  4095. *
  4096. * @param mixed $array
  4097. * @param string $message
  4098. *
  4099. * @throws InvalidArgumentException
  4100. */
  4101. public static function nullOrIsMap($array, $message = '');
  4102. /**
  4103. * @psalm-pure
  4104. * @psalm-template T
  4105. * @psalm-param iterable<mixed|array<T>> $array
  4106. * @psalm-assert iterable<array<string, T>> $array
  4107. *
  4108. * @param mixed $array
  4109. * @param string $message
  4110. *
  4111. * @throws InvalidArgumentException
  4112. */
  4113. public static function allIsMap($array, $message = '');
  4114. /**
  4115. * @psalm-pure
  4116. * @psalm-template T
  4117. * @psalm-param null|mixed|array<T> $array
  4118. *
  4119. * @param mixed $array
  4120. * @param string $message
  4121. *
  4122. * @throws InvalidArgumentException
  4123. */
  4124. public static function nullOrIsNonEmptyMap($array, $message = '');
  4125. /**
  4126. * @psalm-pure
  4127. * @psalm-template T
  4128. * @psalm-param iterable<mixed|array<T>> $array
  4129. *
  4130. * @param mixed $array
  4131. * @param string $message
  4132. *
  4133. * @throws InvalidArgumentException
  4134. */
  4135. public static function allIsNonEmptyMap($array, $message = '');
  4136. /**
  4137. * @psalm-pure
  4138. *
  4139. * @param null|string $value
  4140. * @param string $message
  4141. *
  4142. * @throws InvalidArgumentException
  4143. */
  4144. public static function nullOrUuid($value, $message = '');
  4145. /**
  4146. * @psalm-pure
  4147. *
  4148. * @param iterable<string> $value
  4149. * @param string $message
  4150. *
  4151. * @throws InvalidArgumentException
  4152. */
  4153. public static function allUuid($value, $message = '');
  4154. /**
  4155. * @psalm-param class-string<Throwable> $class
  4156. *
  4157. * @param null|Closure $expression
  4158. * @param string $class
  4159. * @param string $message
  4160. *
  4161. * @throws InvalidArgumentException
  4162. */
  4163. public static function nullOrThrows($expression, $class = 'Exception', $message = '');
  4164. /**
  4165. * @psalm-param class-string<Throwable> $class
  4166. *
  4167. * @param iterable<Closure> $expression
  4168. * @param string $class
  4169. * @param string $message
  4170. *
  4171. * @throws InvalidArgumentException
  4172. */
  4173. public static function allThrows($expression, $class = 'Exception', $message = '');
  4174. }
  4175. The MIT License (MIT)
  4176. Copyright (c) 2014 Bernhard Schussek
  4177. Permission is hereby granted, free of charge, to any person obtaining a copy of
  4178. this software and associated documentation files (the "Software"), to deal in
  4179. the Software without restriction, including without limitation the rights to
  4180. use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
  4181. the Software, and to permit persons to whom the Software is furnished to do so,
  4182. subject to the following conditions:
  4183. The above copyright notice and this permission notice shall be included in all
  4184. copies or substantial portions of the Software.
  4185. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  4186. IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
  4187. FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
  4188. COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
  4189. IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  4190. CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  4191. <?php
  4192. declare (strict_types=1);
  4193. /**
  4194. * phpDocumentor
  4195. *
  4196. * For the full copyright and license information, please view the LICENSE
  4197. * file that was distributed with this source code.
  4198. *
  4199. * @link http://phpdoc.org
  4200. */
  4201. namespace PHPUnit\phpDocumentor\Reflection;
  4202. use InvalidArgumentException;
  4203. use function assert;
  4204. use function end;
  4205. use function explode;
  4206. use function is_string;
  4207. use function preg_match;
  4208. use function sprintf;
  4209. use function trim;
  4210. /**
  4211. * Value Object for Fqsen.
  4212. *
  4213. * @link https://github.com/phpDocumentor/fig-standards/blob/master/proposed/phpdoc-meta.md
  4214. *
  4215. * @psalm-immutable
  4216. */
  4217. final class Fqsen
  4218. {
  4219. /** @var string full quallified class name */
  4220. private $fqsen;
  4221. /** @var string name of the element without path. */
  4222. private $name;
  4223. /**
  4224. * Initializes the object.
  4225. *
  4226. * @throws InvalidArgumentException when $fqsen is not matching the format.
  4227. */
  4228. public function __construct(string $fqsen)
  4229. {
  4230. $matches = [];
  4231. $result = \preg_match(
  4232. //phpcs:ignore Generic.Files.LineLength.TooLong
  4233. '/^\\\\([a-zA-Z_\\x7f-\\xff][a-zA-Z0-9_\\x7f-\\xff\\\\]*)?(?:[:]{2}\\$?([a-zA-Z_\\x7f-\\xff][a-zA-Z0-9_\\x7f-\\xff]*))?(?:\\(\\))?$/',
  4234. $fqsen,
  4235. $matches
  4236. );
  4237. if ($result === 0) {
  4238. throw new \InvalidArgumentException(\sprintf('"%s" is not a valid Fqsen.', $fqsen));
  4239. }
  4240. $this->fqsen = $fqsen;
  4241. if (isset($matches[2])) {
  4242. $this->name = $matches[2];
  4243. } else {
  4244. $matches = \explode('\\', $fqsen);
  4245. $name = \end($matches);
  4246. \assert(\is_string($name));
  4247. $this->name = \trim($name, '()');
  4248. }
  4249. }
  4250. /**
  4251. * converts this class to string.
  4252. */
  4253. public function __toString() : string
  4254. {
  4255. return $this->fqsen;
  4256. }
  4257. /**
  4258. * Returns the name of the element without path.
  4259. */
  4260. public function getName() : string
  4261. {
  4262. return $this->name;
  4263. }
  4264. }
  4265. <?php
  4266. declare (strict_types=1);
  4267. /**
  4268. * phpDocumentor
  4269. *
  4270. * For the full copyright and license information, please view the LICENSE
  4271. * file that was distributed with this source code.
  4272. *
  4273. * @link http://phpdoc.org
  4274. */
  4275. namespace PHPUnit\phpDocumentor\Reflection;
  4276. /**
  4277. * Interface for project factories. A project factory shall convert a set of files
  4278. * into an object implementing the Project interface.
  4279. */
  4280. interface ProjectFactory
  4281. {
  4282. /**
  4283. * Creates a project from the set of files.
  4284. *
  4285. * @param File[] $files
  4286. */
  4287. public function create(string $name, array $files) : \PHPUnit\phpDocumentor\Reflection\Project;
  4288. }
  4289. <?php
  4290. declare (strict_types=1);
  4291. /**
  4292. * This file is part of phpDocumentor.
  4293. *
  4294. * For the full copyright and license information, please view the LICENSE
  4295. * file that was distributed with this source code.
  4296. *
  4297. * @link http://phpdoc.org
  4298. */
  4299. namespace PHPUnit\phpDocumentor\Reflection;
  4300. /**
  4301. * Interface for files processed by the ProjectFactory
  4302. */
  4303. interface File
  4304. {
  4305. /**
  4306. * Returns the content of the file as a string.
  4307. */
  4308. public function getContents() : string;
  4309. /**
  4310. * Returns md5 hash of the file.
  4311. */
  4312. public function md5() : string;
  4313. /**
  4314. * Returns an relative path to the file.
  4315. */
  4316. public function path() : string;
  4317. }
  4318. <?php
  4319. declare (strict_types=1);
  4320. /**
  4321. * This file is part of phpDocumentor.
  4322. *
  4323. * For the full copyright and license information, please view the LICENSE
  4324. * file that was distributed with this source code.
  4325. *
  4326. * @link http://phpdoc.org
  4327. */
  4328. namespace PHPUnit\phpDocumentor\Reflection;
  4329. /**
  4330. * The location where an element occurs within a file.
  4331. *
  4332. * @psalm-immutable
  4333. */
  4334. final class Location
  4335. {
  4336. /** @var int */
  4337. private $lineNumber = 0;
  4338. /** @var int */
  4339. private $columnNumber = 0;
  4340. /**
  4341. * Initializes the location for an element using its line number in the file and optionally the column number.
  4342. */
  4343. public function __construct(int $lineNumber, int $columnNumber = 0)
  4344. {
  4345. $this->lineNumber = $lineNumber;
  4346. $this->columnNumber = $columnNumber;
  4347. }
  4348. /**
  4349. * Returns the line number that is covered by this location.
  4350. */
  4351. public function getLineNumber() : int
  4352. {
  4353. return $this->lineNumber;
  4354. }
  4355. /**
  4356. * Returns the column number (character position on a line) for this location object.
  4357. */
  4358. public function getColumnNumber() : int
  4359. {
  4360. return $this->columnNumber;
  4361. }
  4362. }
  4363. <?php
  4364. declare (strict_types=1);
  4365. /**
  4366. * phpDocumentor
  4367. *
  4368. * For the full copyright and license information, please view the LICENSE
  4369. * file that was distributed with this source code.
  4370. *
  4371. * @link http://phpdoc.org
  4372. */
  4373. namespace PHPUnit\phpDocumentor\Reflection;
  4374. /**
  4375. * Interface for project. Since the definition of a project can be different per factory this interface will be small.
  4376. */
  4377. interface Project
  4378. {
  4379. /**
  4380. * Returns the name of the project.
  4381. */
  4382. public function getName() : string;
  4383. }
  4384. <?php
  4385. declare (strict_types=1);
  4386. /**
  4387. * phpDocumentor
  4388. *
  4389. * For the full copyright and license information, please view the LICENSE
  4390. * file that was distributed with this source code.
  4391. *
  4392. * @link http://phpdoc.org
  4393. */
  4394. namespace PHPUnit\phpDocumentor\Reflection;
  4395. /**
  4396. * Interface for Api Elements
  4397. */
  4398. interface Element
  4399. {
  4400. /**
  4401. * Returns the Fqsen of the element.
  4402. */
  4403. public function getFqsen() : \PHPUnit\phpDocumentor\Reflection\Fqsen;
  4404. /**
  4405. * Returns the name of the element.
  4406. */
  4407. public function getName() : string;
  4408. }
  4409. The MIT License (MIT)
  4410. Copyright (c) 2015 phpDocumentor
  4411. Permission is hereby granted, free of charge, to any person obtaining a copy
  4412. of this software and associated documentation files (the "Software"), to deal
  4413. in the Software without restriction, including without limitation the rights
  4414. to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  4415. copies of the Software, and to permit persons to whom the Software is
  4416. furnished to do so, subject to the following conditions:
  4417. The above copyright notice and this permission notice shall be included in all
  4418. copies or substantial portions of the Software.
  4419. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  4420. IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  4421. FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  4422. AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  4423. LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  4424. OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  4425. SOFTWARE.
  4426. <?php
  4427. declare (strict_types=1);
  4428. /*
  4429. * This file is part of phpunit/php-text-template.
  4430. *
  4431. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  4432. *
  4433. * For the full copyright and license information, please view the LICENSE
  4434. * file that was distributed with this source code.
  4435. */
  4436. namespace PHPUnit\SebastianBergmann\Template;
  4437. final class Template
  4438. {
  4439. /**
  4440. * @var string
  4441. */
  4442. private $template = '';
  4443. /**
  4444. * @var string
  4445. */
  4446. private $openDelimiter;
  4447. /**
  4448. * @var string
  4449. */
  4450. private $closeDelimiter;
  4451. /**
  4452. * @var array
  4453. */
  4454. private $values = [];
  4455. /**
  4456. * @throws InvalidArgumentException
  4457. */
  4458. public function __construct(string $file = '', string $openDelimiter = '{', string $closeDelimiter = '}')
  4459. {
  4460. $this->setFile($file);
  4461. $this->openDelimiter = $openDelimiter;
  4462. $this->closeDelimiter = $closeDelimiter;
  4463. }
  4464. /**
  4465. * @throws InvalidArgumentException
  4466. */
  4467. public function setFile(string $file) : void
  4468. {
  4469. $distFile = $file . '.dist';
  4470. if (\file_exists($file)) {
  4471. $this->template = \file_get_contents($file);
  4472. } elseif (\file_exists($distFile)) {
  4473. $this->template = \file_get_contents($distFile);
  4474. } else {
  4475. throw new \PHPUnit\SebastianBergmann\Template\InvalidArgumentException(\sprintf('Failed to load template "%s"', $file));
  4476. }
  4477. }
  4478. public function setVar(array $values, bool $merge = \true) : void
  4479. {
  4480. if (!$merge || empty($this->values)) {
  4481. $this->values = $values;
  4482. } else {
  4483. $this->values = \array_merge($this->values, $values);
  4484. }
  4485. }
  4486. public function render() : string
  4487. {
  4488. $keys = [];
  4489. foreach ($this->values as $key => $value) {
  4490. $keys[] = $this->openDelimiter . $key . $this->closeDelimiter;
  4491. }
  4492. return \str_replace($keys, $this->values, $this->template);
  4493. }
  4494. /**
  4495. * @codeCoverageIgnore
  4496. */
  4497. public function renderTo(string $target) : void
  4498. {
  4499. if (!\file_put_contents($target, $this->render())) {
  4500. throw new \PHPUnit\SebastianBergmann\Template\RuntimeException(\sprintf('Writing rendered result to "%s" failed', $target));
  4501. }
  4502. }
  4503. }
  4504. <?php
  4505. declare (strict_types=1);
  4506. /*
  4507. * This file is part of phpunit/php-text-template.
  4508. *
  4509. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  4510. *
  4511. * For the full copyright and license information, please view the LICENSE
  4512. * file that was distributed with this source code.
  4513. */
  4514. namespace PHPUnit\SebastianBergmann\Template;
  4515. final class RuntimeException extends \InvalidArgumentException implements \PHPUnit\SebastianBergmann\Template\Exception
  4516. {
  4517. }
  4518. <?php
  4519. declare (strict_types=1);
  4520. /*
  4521. * This file is part of phpunit/php-text-template.
  4522. *
  4523. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  4524. *
  4525. * For the full copyright and license information, please view the LICENSE
  4526. * file that was distributed with this source code.
  4527. */
  4528. namespace PHPUnit\SebastianBergmann\Template;
  4529. interface Exception
  4530. {
  4531. }
  4532. <?php
  4533. declare (strict_types=1);
  4534. /*
  4535. * This file is part of phpunit/php-text-template.
  4536. *
  4537. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  4538. *
  4539. * For the full copyright and license information, please view the LICENSE
  4540. * file that was distributed with this source code.
  4541. */
  4542. namespace PHPUnit\SebastianBergmann\Template;
  4543. final class InvalidArgumentException extends \InvalidArgumentException implements \PHPUnit\SebastianBergmann\Template\Exception
  4544. {
  4545. }
  4546. phpunit/php-text-template
  4547. Copyright (c) 2009-2020, Sebastian Bergmann <sebastian@phpunit.de>.
  4548. All rights reserved.
  4549. Redistribution and use in source and binary forms, with or without
  4550. modification, are permitted provided that the following conditions
  4551. are met:
  4552. * Redistributions of source code must retain the above copyright
  4553. notice, this list of conditions and the following disclaimer.
  4554. * Redistributions in binary form must reproduce the above copyright
  4555. notice, this list of conditions and the following disclaimer in
  4556. the documentation and/or other materials provided with the
  4557. distribution.
  4558. * Neither the name of Sebastian Bergmann nor the names of his
  4559. contributors may be used to endorse or promote products derived
  4560. from this software without specific prior written permission.
  4561. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  4562. "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  4563. LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  4564. FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  4565. COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  4566. INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  4567. BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  4568. LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  4569. CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  4570. LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
  4571. ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  4572. POSSIBILITY OF SUCH DAMAGE.
  4573. <?php
  4574. declare (strict_types=1);
  4575. /*
  4576. * This file is part of sebastian/object-reflector.
  4577. *
  4578. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  4579. *
  4580. * For the full copyright and license information, please view the LICENSE
  4581. * file that was distributed with this source code.
  4582. */
  4583. namespace PHPUnit\SebastianBergmann\ObjectReflector;
  4584. class ObjectReflector
  4585. {
  4586. /**
  4587. * @param object $object
  4588. *
  4589. * @throws InvalidArgumentException
  4590. */
  4591. public function getAttributes($object) : array
  4592. {
  4593. if (!\is_object($object)) {
  4594. throw new \PHPUnit\SebastianBergmann\ObjectReflector\InvalidArgumentException();
  4595. }
  4596. $attributes = [];
  4597. $className = \get_class($object);
  4598. foreach ((array) $object as $name => $value) {
  4599. $name = \explode("\0", (string) $name);
  4600. if (\count($name) === 1) {
  4601. $name = $name[0];
  4602. } else {
  4603. if ($name[1] !== $className) {
  4604. $name = $name[1] . '::' . $name[2];
  4605. } else {
  4606. $name = $name[2];
  4607. }
  4608. }
  4609. $attributes[$name] = $value;
  4610. }
  4611. return $attributes;
  4612. }
  4613. }
  4614. <?php
  4615. declare (strict_types=1);
  4616. /*
  4617. * This file is part of sebastian/object-reflector.
  4618. *
  4619. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  4620. *
  4621. * For the full copyright and license information, please view the LICENSE
  4622. * file that was distributed with this source code.
  4623. */
  4624. namespace PHPUnit\SebastianBergmann\ObjectReflector;
  4625. interface Exception
  4626. {
  4627. }
  4628. <?php
  4629. declare (strict_types=1);
  4630. /*
  4631. * This file is part of sebastian/object-reflector.
  4632. *
  4633. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  4634. *
  4635. * For the full copyright and license information, please view the LICENSE
  4636. * file that was distributed with this source code.
  4637. */
  4638. namespace PHPUnit\SebastianBergmann\ObjectReflector;
  4639. class InvalidArgumentException extends \InvalidArgumentException implements \PHPUnit\SebastianBergmann\ObjectReflector\Exception
  4640. {
  4641. }
  4642. <?php
  4643. declare (strict_types=1);
  4644. /*
  4645. * This file is part of phpunit/php-invoker.
  4646. *
  4647. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  4648. *
  4649. * For the full copyright and license information, please view the LICENSE
  4650. * file that was distributed with this source code.
  4651. */
  4652. namespace PHPUnit\SebastianBergmann\Invoker;
  4653. final class Invoker
  4654. {
  4655. /**
  4656. * @var int
  4657. */
  4658. private $timeout;
  4659. /**
  4660. * @throws \Throwable
  4661. */
  4662. public function invoke(callable $callable, array $arguments, int $timeout)
  4663. {
  4664. if (!$this->canInvokeWithTimeout()) {
  4665. throw new \PHPUnit\SebastianBergmann\Invoker\ProcessControlExtensionNotLoadedException('The pcntl (process control) extension for PHP is required');
  4666. }
  4667. \pcntl_signal(\SIGALRM, function () : void {
  4668. throw new \PHPUnit\SebastianBergmann\Invoker\TimeoutException(\sprintf('Execution aborted after %d second%s', $this->timeout, $this->timeout === 1 ? '' : 's'));
  4669. }, \true);
  4670. $this->timeout = $timeout;
  4671. \pcntl_async_signals(\true);
  4672. \pcntl_alarm($timeout);
  4673. try {
  4674. $result = \call_user_func_array($callable, $arguments);
  4675. } catch (\Throwable $t) {
  4676. \pcntl_alarm(0);
  4677. throw $t;
  4678. }
  4679. \pcntl_alarm(0);
  4680. return $result;
  4681. }
  4682. public function canInvokeWithTimeout() : bool
  4683. {
  4684. return \function_exists('pcntl_signal') && \function_exists('pcntl_async_signals') && \function_exists('pcntl_alarm');
  4685. }
  4686. }
  4687. <?php
  4688. declare (strict_types=1);
  4689. /*
  4690. * This file is part of phpunit/php-invoker.
  4691. *
  4692. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  4693. *
  4694. * For the full copyright and license information, please view the LICENSE
  4695. * file that was distributed with this source code.
  4696. */
  4697. namespace PHPUnit\SebastianBergmann\Invoker;
  4698. final class ProcessControlExtensionNotLoadedException extends \RuntimeException implements \PHPUnit\SebastianBergmann\Invoker\Exception
  4699. {
  4700. }
  4701. <?php
  4702. declare (strict_types=1);
  4703. /*
  4704. * This file is part of phpunit/php-invoker.
  4705. *
  4706. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  4707. *
  4708. * For the full copyright and license information, please view the LICENSE
  4709. * file that was distributed with this source code.
  4710. */
  4711. namespace PHPUnit\SebastianBergmann\Invoker;
  4712. final class TimeoutException extends \RuntimeException implements \PHPUnit\SebastianBergmann\Invoker\Exception
  4713. {
  4714. }
  4715. <?php
  4716. declare (strict_types=1);
  4717. /*
  4718. * This file is part of phpunit/php-invoker.
  4719. *
  4720. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  4721. *
  4722. * For the full copyright and license information, please view the LICENSE
  4723. * file that was distributed with this source code.
  4724. */
  4725. namespace PHPUnit\SebastianBergmann\Invoker;
  4726. interface Exception extends \Throwable
  4727. {
  4728. }
  4729. <?php
  4730. /*
  4731. * This file is part of PharIo\Version.
  4732. *
  4733. * (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>
  4734. *
  4735. * For the full copyright and license information, please view the LICENSE
  4736. * file that was distributed with this source code.
  4737. */
  4738. namespace PHPUnit\PharIo\Version;
  4739. class OrVersionConstraintGroup extends \PHPUnit\PharIo\Version\AbstractVersionConstraint
  4740. {
  4741. /**
  4742. * @var VersionConstraint[]
  4743. */
  4744. private $constraints = [];
  4745. /**
  4746. * @param string $originalValue
  4747. * @param VersionConstraint[] $constraints
  4748. */
  4749. public function __construct($originalValue, array $constraints)
  4750. {
  4751. parent::__construct($originalValue);
  4752. $this->constraints = $constraints;
  4753. }
  4754. /**
  4755. * @param Version $version
  4756. *
  4757. * @return bool
  4758. */
  4759. public function complies(\PHPUnit\PharIo\Version\Version $version)
  4760. {
  4761. foreach ($this->constraints as $constraint) {
  4762. if ($constraint->complies($version)) {
  4763. return \true;
  4764. }
  4765. }
  4766. return \false;
  4767. }
  4768. }
  4769. <?php
  4770. /*
  4771. * This file is part of PharIo\Version.
  4772. *
  4773. * (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>
  4774. *
  4775. * For the full copyright and license information, please view the LICENSE
  4776. * file that was distributed with this source code.
  4777. */
  4778. namespace PHPUnit\PharIo\Version;
  4779. interface VersionConstraint
  4780. {
  4781. /**
  4782. * @param Version $version
  4783. *
  4784. * @return bool
  4785. */
  4786. public function complies(\PHPUnit\PharIo\Version\Version $version);
  4787. /**
  4788. * @return string
  4789. */
  4790. public function asString();
  4791. }
  4792. <?php
  4793. /*
  4794. * This file is part of PharIo\Version.
  4795. *
  4796. * (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>
  4797. *
  4798. * For the full copyright and license information, please view the LICENSE
  4799. * file that was distributed with this source code.
  4800. */
  4801. namespace PHPUnit\PharIo\Version;
  4802. class ExactVersionConstraint extends \PHPUnit\PharIo\Version\AbstractVersionConstraint
  4803. {
  4804. /**
  4805. * @param Version $version
  4806. *
  4807. * @return bool
  4808. */
  4809. public function complies(\PHPUnit\PharIo\Version\Version $version)
  4810. {
  4811. return $this->asString() == $version->getVersionString();
  4812. }
  4813. }
  4814. <?php
  4815. /*
  4816. * This file is part of PharIo\Version.
  4817. *
  4818. * (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>
  4819. *
  4820. * For the full copyright and license information, please view the LICENSE
  4821. * file that was distributed with this source code.
  4822. */
  4823. namespace PHPUnit\PharIo\Version;
  4824. class AnyVersionConstraint implements \PHPUnit\PharIo\Version\VersionConstraint
  4825. {
  4826. /**
  4827. * @param Version $version
  4828. *
  4829. * @return bool
  4830. */
  4831. public function complies(\PHPUnit\PharIo\Version\Version $version)
  4832. {
  4833. return \true;
  4834. }
  4835. /**
  4836. * @return string
  4837. */
  4838. public function asString()
  4839. {
  4840. return '*';
  4841. }
  4842. }
  4843. <?php
  4844. /*
  4845. * This file is part of PharIo\Version.
  4846. *
  4847. * (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>
  4848. *
  4849. * For the full copyright and license information, please view the LICENSE
  4850. * file that was distributed with this source code.
  4851. */
  4852. namespace PHPUnit\PharIo\Version;
  4853. class SpecificMajorVersionConstraint extends \PHPUnit\PharIo\Version\AbstractVersionConstraint
  4854. {
  4855. /**
  4856. * @var int
  4857. */
  4858. private $major = 0;
  4859. /**
  4860. * @param string $originalValue
  4861. * @param int $major
  4862. */
  4863. public function __construct($originalValue, $major)
  4864. {
  4865. parent::__construct($originalValue);
  4866. $this->major = $major;
  4867. }
  4868. /**
  4869. * @param Version $version
  4870. *
  4871. * @return bool
  4872. */
  4873. public function complies(\PHPUnit\PharIo\Version\Version $version)
  4874. {
  4875. return $version->getMajor()->getValue() == $this->major;
  4876. }
  4877. }
  4878. <?php
  4879. /*
  4880. * This file is part of PharIo\Version.
  4881. *
  4882. * (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>
  4883. *
  4884. * For the full copyright and license information, please view the LICENSE
  4885. * file that was distributed with this source code.
  4886. */
  4887. namespace PHPUnit\PharIo\Version;
  4888. class SpecificMajorAndMinorVersionConstraint extends \PHPUnit\PharIo\Version\AbstractVersionConstraint
  4889. {
  4890. /**
  4891. * @var int
  4892. */
  4893. private $major = 0;
  4894. /**
  4895. * @var int
  4896. */
  4897. private $minor = 0;
  4898. /**
  4899. * @param string $originalValue
  4900. * @param int $major
  4901. * @param int $minor
  4902. */
  4903. public function __construct($originalValue, $major, $minor)
  4904. {
  4905. parent::__construct($originalValue);
  4906. $this->major = $major;
  4907. $this->minor = $minor;
  4908. }
  4909. /**
  4910. * @param Version $version
  4911. *
  4912. * @return bool
  4913. */
  4914. public function complies(\PHPUnit\PharIo\Version\Version $version)
  4915. {
  4916. if ($version->getMajor()->getValue() != $this->major) {
  4917. return \false;
  4918. }
  4919. return $version->getMinor()->getValue() == $this->minor;
  4920. }
  4921. }
  4922. <?php
  4923. /*
  4924. * This file is part of PharIo\Version.
  4925. *
  4926. * (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>
  4927. *
  4928. * For the full copyright and license information, please view the LICENSE
  4929. * file that was distributed with this source code.
  4930. */
  4931. namespace PHPUnit\PharIo\Version;
  4932. class GreaterThanOrEqualToVersionConstraint extends \PHPUnit\PharIo\Version\AbstractVersionConstraint
  4933. {
  4934. /**
  4935. * @var Version
  4936. */
  4937. private $minimalVersion;
  4938. /**
  4939. * @param string $originalValue
  4940. * @param Version $minimalVersion
  4941. */
  4942. public function __construct($originalValue, \PHPUnit\PharIo\Version\Version $minimalVersion)
  4943. {
  4944. parent::__construct($originalValue);
  4945. $this->minimalVersion = $minimalVersion;
  4946. }
  4947. /**
  4948. * @param Version $version
  4949. *
  4950. * @return bool
  4951. */
  4952. public function complies(\PHPUnit\PharIo\Version\Version $version)
  4953. {
  4954. return $version->getVersionString() == $this->minimalVersion->getVersionString() || $version->isGreaterThan($this->minimalVersion);
  4955. }
  4956. }
  4957. <?php
  4958. /*
  4959. * This file is part of PharIo\Version.
  4960. *
  4961. * (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>
  4962. *
  4963. * For the full copyright and license information, please view the LICENSE
  4964. * file that was distributed with this source code.
  4965. */
  4966. namespace PHPUnit\PharIo\Version;
  4967. abstract class AbstractVersionConstraint implements \PHPUnit\PharIo\Version\VersionConstraint
  4968. {
  4969. /**
  4970. * @var string
  4971. */
  4972. private $originalValue = '';
  4973. /**
  4974. * @param string $originalValue
  4975. */
  4976. public function __construct($originalValue)
  4977. {
  4978. $this->originalValue = $originalValue;
  4979. }
  4980. /**
  4981. * @return string
  4982. */
  4983. public function asString()
  4984. {
  4985. return $this->originalValue;
  4986. }
  4987. }
  4988. <?php
  4989. /*
  4990. * This file is part of PharIo\Version.
  4991. *
  4992. * (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>
  4993. *
  4994. * For the full copyright and license information, please view the LICENSE
  4995. * file that was distributed with this source code.
  4996. */
  4997. namespace PHPUnit\PharIo\Version;
  4998. class AndVersionConstraintGroup extends \PHPUnit\PharIo\Version\AbstractVersionConstraint
  4999. {
  5000. /**
  5001. * @var VersionConstraint[]
  5002. */
  5003. private $constraints = [];
  5004. /**
  5005. * @param string $originalValue
  5006. * @param VersionConstraint[] $constraints
  5007. */
  5008. public function __construct($originalValue, array $constraints)
  5009. {
  5010. parent::__construct($originalValue);
  5011. $this->constraints = $constraints;
  5012. }
  5013. /**
  5014. * @param Version $version
  5015. *
  5016. * @return bool
  5017. */
  5018. public function complies(\PHPUnit\PharIo\Version\Version $version)
  5019. {
  5020. foreach ($this->constraints as $constraint) {
  5021. if (!$constraint->complies($version)) {
  5022. return \false;
  5023. }
  5024. }
  5025. return \true;
  5026. }
  5027. }
  5028. <?php
  5029. /*
  5030. * This file is part of PharIo\Version.
  5031. *
  5032. * (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>
  5033. *
  5034. * For the full copyright and license information, please view the LICENSE
  5035. * file that was distributed with this source code.
  5036. */
  5037. namespace PHPUnit\PharIo\Version;
  5038. class VersionNumber
  5039. {
  5040. /**
  5041. * @var int
  5042. */
  5043. private $value;
  5044. /**
  5045. * @param mixed $value
  5046. */
  5047. public function __construct($value)
  5048. {
  5049. if (\is_numeric($value)) {
  5050. $this->value = $value;
  5051. }
  5052. }
  5053. /**
  5054. * @return bool
  5055. */
  5056. public function isAny()
  5057. {
  5058. return $this->value === null;
  5059. }
  5060. /**
  5061. * @return int
  5062. */
  5063. public function getValue()
  5064. {
  5065. return $this->value;
  5066. }
  5067. }
  5068. <?php
  5069. /*
  5070. * This file is part of PharIo\Version.
  5071. *
  5072. * (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>
  5073. *
  5074. * For the full copyright and license information, please view the LICENSE
  5075. * file that was distributed with this source code.
  5076. */
  5077. namespace PHPUnit\PharIo\Version;
  5078. class VersionConstraintParser
  5079. {
  5080. /**
  5081. * @param string $value
  5082. *
  5083. * @return VersionConstraint
  5084. *
  5085. * @throws UnsupportedVersionConstraintException
  5086. */
  5087. public function parse($value)
  5088. {
  5089. if (\strpos($value, '||') !== \false) {
  5090. return $this->handleOrGroup($value);
  5091. }
  5092. if (!\preg_match('/^[\\^~\\*]?[\\d.\\*]+(?:-.*)?$/', $value)) {
  5093. throw new \PHPUnit\PharIo\Version\UnsupportedVersionConstraintException(\sprintf('Version constraint %s is not supported.', $value));
  5094. }
  5095. switch ($value[0]) {
  5096. case '~':
  5097. return $this->handleTildeOperator($value);
  5098. case '^':
  5099. return $this->handleCaretOperator($value);
  5100. }
  5101. $version = new \PHPUnit\PharIo\Version\VersionConstraintValue($value);
  5102. if ($version->getMajor()->isAny()) {
  5103. return new \PHPUnit\PharIo\Version\AnyVersionConstraint();
  5104. }
  5105. if ($version->getMinor()->isAny()) {
  5106. return new \PHPUnit\PharIo\Version\SpecificMajorVersionConstraint($version->getVersionString(), $version->getMajor()->getValue());
  5107. }
  5108. if ($version->getPatch()->isAny()) {
  5109. return new \PHPUnit\PharIo\Version\SpecificMajorAndMinorVersionConstraint($version->getVersionString(), $version->getMajor()->getValue(), $version->getMinor()->getValue());
  5110. }
  5111. return new \PHPUnit\PharIo\Version\ExactVersionConstraint($version->getVersionString());
  5112. }
  5113. /**
  5114. * @param $value
  5115. *
  5116. * @return OrVersionConstraintGroup
  5117. */
  5118. private function handleOrGroup($value)
  5119. {
  5120. $constraints = [];
  5121. foreach (\explode('||', $value) as $groupSegment) {
  5122. $constraints[] = $this->parse(\trim($groupSegment));
  5123. }
  5124. return new \PHPUnit\PharIo\Version\OrVersionConstraintGroup($value, $constraints);
  5125. }
  5126. /**
  5127. * @param string $value
  5128. *
  5129. * @return AndVersionConstraintGroup
  5130. */
  5131. private function handleTildeOperator($value)
  5132. {
  5133. $version = new \PHPUnit\PharIo\Version\Version(\substr($value, 1));
  5134. $constraints = [new \PHPUnit\PharIo\Version\GreaterThanOrEqualToVersionConstraint($value, $version)];
  5135. if ($version->getPatch()->isAny()) {
  5136. $constraints[] = new \PHPUnit\PharIo\Version\SpecificMajorVersionConstraint($value, $version->getMajor()->getValue());
  5137. } else {
  5138. $constraints[] = new \PHPUnit\PharIo\Version\SpecificMajorAndMinorVersionConstraint($value, $version->getMajor()->getValue(), $version->getMinor()->getValue());
  5139. }
  5140. return new \PHPUnit\PharIo\Version\AndVersionConstraintGroup($value, $constraints);
  5141. }
  5142. /**
  5143. * @param string $value
  5144. *
  5145. * @return AndVersionConstraintGroup
  5146. */
  5147. private function handleCaretOperator($value)
  5148. {
  5149. $version = new \PHPUnit\PharIo\Version\Version(\substr($value, 1));
  5150. return new \PHPUnit\PharIo\Version\AndVersionConstraintGroup($value, [new \PHPUnit\PharIo\Version\GreaterThanOrEqualToVersionConstraint($value, $version), new \PHPUnit\PharIo\Version\SpecificMajorVersionConstraint($value, $version->getMajor()->getValue())]);
  5151. }
  5152. }
  5153. <?php
  5154. /*
  5155. * This file is part of PharIo\Version.
  5156. *
  5157. * (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>
  5158. *
  5159. * For the full copyright and license information, please view the LICENSE
  5160. * file that was distributed with this source code.
  5161. */
  5162. namespace PHPUnit\PharIo\Version;
  5163. class Version
  5164. {
  5165. /**
  5166. * @var VersionNumber
  5167. */
  5168. private $major;
  5169. /**
  5170. * @var VersionNumber
  5171. */
  5172. private $minor;
  5173. /**
  5174. * @var VersionNumber
  5175. */
  5176. private $patch;
  5177. /**
  5178. * @var PreReleaseSuffix
  5179. */
  5180. private $preReleaseSuffix;
  5181. /**
  5182. * @var string
  5183. */
  5184. private $versionString = '';
  5185. /**
  5186. * @param string $versionString
  5187. */
  5188. public function __construct($versionString)
  5189. {
  5190. $this->ensureVersionStringIsValid($versionString);
  5191. $this->versionString = $versionString;
  5192. }
  5193. /**
  5194. * @return PreReleaseSuffix
  5195. */
  5196. public function getPreReleaseSuffix()
  5197. {
  5198. return $this->preReleaseSuffix;
  5199. }
  5200. /**
  5201. * @return string
  5202. */
  5203. public function getVersionString()
  5204. {
  5205. return $this->versionString;
  5206. }
  5207. /**
  5208. * @return bool
  5209. */
  5210. public function hasPreReleaseSuffix()
  5211. {
  5212. return $this->preReleaseSuffix !== null;
  5213. }
  5214. /**
  5215. * @param Version $version
  5216. *
  5217. * @return bool
  5218. */
  5219. public function isGreaterThan(\PHPUnit\PharIo\Version\Version $version)
  5220. {
  5221. if ($version->getMajor()->getValue() > $this->getMajor()->getValue()) {
  5222. return \false;
  5223. }
  5224. if ($version->getMajor()->getValue() < $this->getMajor()->getValue()) {
  5225. return \true;
  5226. }
  5227. if ($version->getMinor()->getValue() > $this->getMinor()->getValue()) {
  5228. return \false;
  5229. }
  5230. if ($version->getMinor()->getValue() < $this->getMinor()->getValue()) {
  5231. return \true;
  5232. }
  5233. if ($version->getPatch()->getValue() > $this->getPatch()->getValue()) {
  5234. return \false;
  5235. }
  5236. if ($version->getPatch()->getValue() < $this->getPatch()->getValue()) {
  5237. return \true;
  5238. }
  5239. if (!$version->hasPreReleaseSuffix() && !$this->hasPreReleaseSuffix()) {
  5240. return \false;
  5241. }
  5242. if ($version->hasPreReleaseSuffix() && !$this->hasPreReleaseSuffix()) {
  5243. return \true;
  5244. }
  5245. if (!$version->hasPreReleaseSuffix() && $this->hasPreReleaseSuffix()) {
  5246. return \false;
  5247. }
  5248. return $this->getPreReleaseSuffix()->isGreaterThan($version->getPreReleaseSuffix());
  5249. }
  5250. /**
  5251. * @return VersionNumber
  5252. */
  5253. public function getMajor()
  5254. {
  5255. return $this->major;
  5256. }
  5257. /**
  5258. * @return VersionNumber
  5259. */
  5260. public function getMinor()
  5261. {
  5262. return $this->minor;
  5263. }
  5264. /**
  5265. * @return VersionNumber
  5266. */
  5267. public function getPatch()
  5268. {
  5269. return $this->patch;
  5270. }
  5271. /**
  5272. * @param array $matches
  5273. */
  5274. private function parseVersion(array $matches)
  5275. {
  5276. $this->major = new \PHPUnit\PharIo\Version\VersionNumber($matches['Major']);
  5277. $this->minor = new \PHPUnit\PharIo\Version\VersionNumber($matches['Minor']);
  5278. $this->patch = isset($matches['Patch']) ? new \PHPUnit\PharIo\Version\VersionNumber($matches['Patch']) : new \PHPUnit\PharIo\Version\VersionNumber(null);
  5279. if (isset($matches['PreReleaseSuffix'])) {
  5280. $this->preReleaseSuffix = new \PHPUnit\PharIo\Version\PreReleaseSuffix($matches['PreReleaseSuffix']);
  5281. }
  5282. }
  5283. /**
  5284. * @param string $version
  5285. *
  5286. * @throws InvalidVersionException
  5287. */
  5288. private function ensureVersionStringIsValid($version)
  5289. {
  5290. $regex = '/^v?
  5291. (?<Major>(0|(?:[1-9][0-9]*)))
  5292. \\.
  5293. (?<Minor>(0|(?:[1-9][0-9]*)))
  5294. (\\.
  5295. (?<Patch>(0|(?:[1-9][0-9]*)))
  5296. )?
  5297. (?:
  5298. -
  5299. (?<PreReleaseSuffix>(?:(dev|beta|b|RC|alpha|a|patch|p)\\.?\\d*))
  5300. )?
  5301. $/x';
  5302. if (\preg_match($regex, $version, $matches) !== 1) {
  5303. throw new \PHPUnit\PharIo\Version\InvalidVersionException(\sprintf("Version string '%s' does not follow SemVer semantics", $version));
  5304. }
  5305. $this->parseVersion($matches);
  5306. }
  5307. }
  5308. <?php
  5309. namespace PHPUnit\PharIo\Version;
  5310. class InvalidPreReleaseSuffixException extends \Exception implements \PHPUnit\PharIo\Version\Exception
  5311. {
  5312. }
  5313. <?php
  5314. /*
  5315. * This file is part of PharIo\Version.
  5316. *
  5317. * (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>
  5318. *
  5319. * For the full copyright and license information, please view the LICENSE
  5320. * file that was distributed with this source code.
  5321. */
  5322. namespace PHPUnit\PharIo\Version;
  5323. final class UnsupportedVersionConstraintException extends \RuntimeException implements \PHPUnit\PharIo\Version\Exception
  5324. {
  5325. }
  5326. <?php
  5327. /*
  5328. * This file is part of PharIo\Version.
  5329. *
  5330. * (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>
  5331. *
  5332. * For the full copyright and license information, please view the LICENSE
  5333. * file that was distributed with this source code.
  5334. */
  5335. namespace PHPUnit\PharIo\Version;
  5336. interface Exception
  5337. {
  5338. }
  5339. <?php
  5340. namespace PHPUnit\PharIo\Version;
  5341. class InvalidVersionException extends \InvalidArgumentException implements \PHPUnit\PharIo\Version\Exception
  5342. {
  5343. }
  5344. <?php
  5345. namespace PHPUnit\PharIo\Version;
  5346. class PreReleaseSuffix
  5347. {
  5348. private $valueScoreMap = ['dev' => 0, 'a' => 1, 'alpha' => 1, 'b' => 2, 'beta' => 2, 'rc' => 3, 'p' => 4, 'patch' => 4];
  5349. /**
  5350. * @var string
  5351. */
  5352. private $value;
  5353. /**
  5354. * @var int
  5355. */
  5356. private $valueScore;
  5357. /**
  5358. * @var int
  5359. */
  5360. private $number = 0;
  5361. /**
  5362. * @param string $value
  5363. */
  5364. public function __construct($value)
  5365. {
  5366. $this->parseValue($value);
  5367. }
  5368. /**
  5369. * @return string
  5370. */
  5371. public function getValue()
  5372. {
  5373. return $this->value;
  5374. }
  5375. /**
  5376. * @return int|null
  5377. */
  5378. public function getNumber()
  5379. {
  5380. return $this->number;
  5381. }
  5382. /**
  5383. * @param PreReleaseSuffix $suffix
  5384. *
  5385. * @return bool
  5386. */
  5387. public function isGreaterThan(\PHPUnit\PharIo\Version\PreReleaseSuffix $suffix)
  5388. {
  5389. if ($this->valueScore > $suffix->valueScore) {
  5390. return \true;
  5391. }
  5392. if ($this->valueScore < $suffix->valueScore) {
  5393. return \false;
  5394. }
  5395. return $this->getNumber() > $suffix->getNumber();
  5396. }
  5397. /**
  5398. * @param $value
  5399. *
  5400. * @return int
  5401. */
  5402. private function mapValueToScore($value)
  5403. {
  5404. if (\array_key_exists($value, $this->valueScoreMap)) {
  5405. return $this->valueScoreMap[$value];
  5406. }
  5407. return 0;
  5408. }
  5409. private function parseValue($value)
  5410. {
  5411. $regex = '/-?(dev|beta|b|rc|alpha|a|patch|p)\\.?(\\d*).*$/i';
  5412. if (\preg_match($regex, $value, $matches) !== 1) {
  5413. throw new \PHPUnit\PharIo\Version\InvalidPreReleaseSuffixException(\sprintf('Invalid label %s', $value));
  5414. }
  5415. $this->value = $matches[1];
  5416. if (isset($matches[2])) {
  5417. $this->number = (int) $matches[2];
  5418. }
  5419. $this->valueScore = $this->mapValueToScore($this->value);
  5420. }
  5421. }
  5422. phar-io/version
  5423. Copyright (c) 2016-2017 Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de> and contributors
  5424. All rights reserved.
  5425. Redistribution and use in source and binary forms, with or without modification,
  5426. are permitted provided that the following conditions are met:
  5427. * Redistributions of source code must retain the above copyright notice,
  5428. this list of conditions and the following disclaimer.
  5429. * Redistributions in binary form must reproduce the above copyright notice,
  5430. this list of conditions and the following disclaimer in the documentation
  5431. and/or other materials provided with the distribution.
  5432. * Neither the name of Arne Blankerts nor the names of contributors
  5433. may be used to endorse or promote products derived from this software
  5434. without specific prior written permission.
  5435. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  5436. AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO,
  5437. THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  5438. PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS
  5439. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
  5440. OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  5441. SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  5442. INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  5443. CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  5444. ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  5445. POSSIBILITY OF SUCH DAMAGE.
  5446. <?php
  5447. namespace PHPUnit\PharIo\Version;
  5448. class VersionConstraintValue
  5449. {
  5450. /**
  5451. * @var VersionNumber
  5452. */
  5453. private $major;
  5454. /**
  5455. * @var VersionNumber
  5456. */
  5457. private $minor;
  5458. /**
  5459. * @var VersionNumber
  5460. */
  5461. private $patch;
  5462. /**
  5463. * @var string
  5464. */
  5465. private $label = '';
  5466. /**
  5467. * @var string
  5468. */
  5469. private $buildMetaData = '';
  5470. /**
  5471. * @var string
  5472. */
  5473. private $versionString = '';
  5474. /**
  5475. * @param string $versionString
  5476. */
  5477. public function __construct($versionString)
  5478. {
  5479. $this->versionString = $versionString;
  5480. $this->parseVersion($versionString);
  5481. }
  5482. /**
  5483. * @return string
  5484. */
  5485. public function getLabel()
  5486. {
  5487. return $this->label;
  5488. }
  5489. /**
  5490. * @return string
  5491. */
  5492. public function getBuildMetaData()
  5493. {
  5494. return $this->buildMetaData;
  5495. }
  5496. /**
  5497. * @return string
  5498. */
  5499. public function getVersionString()
  5500. {
  5501. return $this->versionString;
  5502. }
  5503. /**
  5504. * @return VersionNumber
  5505. */
  5506. public function getMajor()
  5507. {
  5508. return $this->major;
  5509. }
  5510. /**
  5511. * @return VersionNumber
  5512. */
  5513. public function getMinor()
  5514. {
  5515. return $this->minor;
  5516. }
  5517. /**
  5518. * @return VersionNumber
  5519. */
  5520. public function getPatch()
  5521. {
  5522. return $this->patch;
  5523. }
  5524. /**
  5525. * @param $versionString
  5526. */
  5527. private function parseVersion($versionString)
  5528. {
  5529. $this->extractBuildMetaData($versionString);
  5530. $this->extractLabel($versionString);
  5531. $versionSegments = \explode('.', $versionString);
  5532. $this->major = new \PHPUnit\PharIo\Version\VersionNumber($versionSegments[0]);
  5533. $minorValue = isset($versionSegments[1]) ? $versionSegments[1] : null;
  5534. $patchValue = isset($versionSegments[2]) ? $versionSegments[2] : null;
  5535. $this->minor = new \PHPUnit\PharIo\Version\VersionNumber($minorValue);
  5536. $this->patch = new \PHPUnit\PharIo\Version\VersionNumber($patchValue);
  5537. }
  5538. /**
  5539. * @param string $versionString
  5540. */
  5541. private function extractBuildMetaData(&$versionString)
  5542. {
  5543. if (\preg_match('/\\+(.*)/', $versionString, $matches) == 1) {
  5544. $this->buildMetaData = $matches[1];
  5545. $versionString = \str_replace($matches[0], '', $versionString);
  5546. }
  5547. }
  5548. /**
  5549. * @param string $versionString
  5550. */
  5551. private function extractLabel(&$versionString)
  5552. {
  5553. if (\preg_match('/\\-(.*)/', $versionString, $matches) == 1) {
  5554. $this->label = $matches[1];
  5555. $versionString = \str_replace($matches[0], '', $versionString);
  5556. }
  5557. }
  5558. }
  5559. <?php
  5560. declare (strict_types=1);
  5561. /*
  5562. * This file is part of sebastian/object-enumerator.
  5563. *
  5564. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  5565. *
  5566. * For the full copyright and license information, please view the LICENSE
  5567. * file that was distributed with this source code.
  5568. */
  5569. namespace PHPUnit\SebastianBergmann\ObjectEnumerator;
  5570. use PHPUnit\SebastianBergmann\ObjectReflector\ObjectReflector;
  5571. use PHPUnit\SebastianBergmann\RecursionContext\Context;
  5572. /**
  5573. * Traverses array structures and object graphs
  5574. * to enumerate all referenced objects.
  5575. */
  5576. class Enumerator
  5577. {
  5578. /**
  5579. * Returns an array of all objects referenced either
  5580. * directly or indirectly by a variable.
  5581. *
  5582. * @param array|object $variable
  5583. *
  5584. * @return object[]
  5585. */
  5586. public function enumerate($variable)
  5587. {
  5588. if (!\is_array($variable) && !\is_object($variable)) {
  5589. throw new \PHPUnit\SebastianBergmann\ObjectEnumerator\InvalidArgumentException();
  5590. }
  5591. if (isset(\func_get_args()[1])) {
  5592. if (!\func_get_args()[1] instanceof \PHPUnit\SebastianBergmann\RecursionContext\Context) {
  5593. throw new \PHPUnit\SebastianBergmann\ObjectEnumerator\InvalidArgumentException();
  5594. }
  5595. $processed = \func_get_args()[1];
  5596. } else {
  5597. $processed = new \PHPUnit\SebastianBergmann\RecursionContext\Context();
  5598. }
  5599. $objects = [];
  5600. if ($processed->contains($variable)) {
  5601. return $objects;
  5602. }
  5603. $array = $variable;
  5604. $processed->add($variable);
  5605. if (\is_array($variable)) {
  5606. foreach ($array as $element) {
  5607. if (!\is_array($element) && !\is_object($element)) {
  5608. continue;
  5609. }
  5610. $objects = \array_merge($objects, $this->enumerate($element, $processed));
  5611. }
  5612. } else {
  5613. $objects[] = $variable;
  5614. $reflector = new \PHPUnit\SebastianBergmann\ObjectReflector\ObjectReflector();
  5615. foreach ($reflector->getAttributes($variable) as $value) {
  5616. if (!\is_array($value) && !\is_object($value)) {
  5617. continue;
  5618. }
  5619. $objects = \array_merge($objects, $this->enumerate($value, $processed));
  5620. }
  5621. }
  5622. return $objects;
  5623. }
  5624. }
  5625. <?php
  5626. declare (strict_types=1);
  5627. /*
  5628. * This file is part of sebastian/object-enumerator.
  5629. *
  5630. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  5631. *
  5632. * For the full copyright and license information, please view the LICENSE
  5633. * file that was distributed with this source code.
  5634. */
  5635. namespace PHPUnit\SebastianBergmann\ObjectEnumerator;
  5636. interface Exception
  5637. {
  5638. }
  5639. <?php
  5640. declare (strict_types=1);
  5641. /*
  5642. * This file is part of sebastian/object-enumerator.
  5643. *
  5644. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  5645. *
  5646. * For the full copyright and license information, please view the LICENSE
  5647. * file that was distributed with this source code.
  5648. */
  5649. namespace PHPUnit\SebastianBergmann\ObjectEnumerator;
  5650. class InvalidArgumentException extends \InvalidArgumentException implements \PHPUnit\SebastianBergmann\ObjectEnumerator\Exception
  5651. {
  5652. }
  5653. <?xml version="1.0" encoding="UTF-8"?>
  5654. <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
  5655. <xs:annotation>
  5656. <xs:documentation source="https://phpunit.de/documentation.html">
  5657. This Schema file defines the rules by which the XML configuration file of PHPUnit 9.2 may be structured.
  5658. </xs:documentation>
  5659. <xs:appinfo source="https://phpunit.de/documentation.html"/>
  5660. </xs:annotation>
  5661. <xs:element name="phpunit" type="phpUnitType">
  5662. <xs:annotation>
  5663. <xs:documentation>Root Element</xs:documentation>
  5664. </xs:annotation>
  5665. </xs:element>
  5666. <xs:complexType name="filtersType">
  5667. <xs:sequence>
  5668. <xs:element name="whitelist" type="whiteListType" minOccurs="0"/>
  5669. </xs:sequence>
  5670. </xs:complexType>
  5671. <xs:complexType name="filterType">
  5672. <xs:sequence>
  5673. <xs:choice maxOccurs="unbounded" minOccurs="0">
  5674. <xs:group ref="pathGroup"/>
  5675. <xs:element name="exclude">
  5676. <xs:complexType>
  5677. <xs:group ref="pathGroup"/>
  5678. </xs:complexType>
  5679. </xs:element>
  5680. </xs:choice>
  5681. </xs:sequence>
  5682. </xs:complexType>
  5683. <xs:complexType name="whiteListType">
  5684. <xs:complexContent>
  5685. <xs:extension base="filterType">
  5686. <xs:attribute name="addUncoveredFilesFromWhitelist" default="true" type="xs:boolean"/>
  5687. <xs:attribute name="processUncoveredFilesFromWhitelist" default="false" type="xs:boolean"/>
  5688. </xs:extension>
  5689. </xs:complexContent>
  5690. </xs:complexType>
  5691. <xs:complexType name="groupsType">
  5692. <xs:choice>
  5693. <xs:sequence>
  5694. <xs:element name="include" type="groupType"/>
  5695. <xs:element name="exclude" type="groupType" minOccurs="0"/>
  5696. </xs:sequence>
  5697. <xs:sequence>
  5698. <xs:element name="exclude" type="groupType"/>
  5699. </xs:sequence>
  5700. </xs:choice>
  5701. </xs:complexType>
  5702. <xs:complexType name="groupType">
  5703. <xs:sequence>
  5704. <xs:element name="group" type="xs:string" maxOccurs="unbounded"/>
  5705. </xs:sequence>
  5706. </xs:complexType>
  5707. <xs:complexType name="extensionsType">
  5708. <xs:sequence>
  5709. <xs:element name="extension" type="objectType" maxOccurs="unbounded"/>
  5710. </xs:sequence>
  5711. </xs:complexType>
  5712. <xs:complexType name="listenersType">
  5713. <xs:sequence>
  5714. <xs:element name="listener" type="objectType" maxOccurs="unbounded"/>
  5715. </xs:sequence>
  5716. </xs:complexType>
  5717. <xs:complexType name="objectType">
  5718. <xs:sequence>
  5719. <xs:element name="arguments" minOccurs="0">
  5720. <xs:complexType>
  5721. <xs:group ref="argumentsGroup"/>
  5722. </xs:complexType>
  5723. </xs:element>
  5724. </xs:sequence>
  5725. <xs:attribute name="class" type="xs:string" use="required"/>
  5726. <xs:attribute name="file" type="xs:anyURI"/>
  5727. </xs:complexType>
  5728. <xs:complexType name="arrayType">
  5729. <xs:sequence>
  5730. <xs:element name="element" type="argumentType" minOccurs="0" maxOccurs="unbounded"/>
  5731. </xs:sequence>
  5732. </xs:complexType>
  5733. <xs:complexType name="argumentType">
  5734. <xs:group ref="argumentChoice"/>
  5735. <xs:attribute name="key" use="required"/>
  5736. </xs:complexType>
  5737. <xs:group name="argumentsGroup">
  5738. <xs:sequence>
  5739. <xs:choice minOccurs="0" maxOccurs="unbounded">
  5740. <xs:element name="array" type="arrayType" />
  5741. <xs:element name="integer" type="xs:integer" />
  5742. <xs:element name="string" type="xs:string" />
  5743. <xs:element name="double" type="xs:double" />
  5744. <xs:element name="null" />
  5745. <xs:element name="object" type="objectType" />
  5746. <xs:element name="file" type="xs:anyURI" />
  5747. <xs:element name="directory" type="xs:anyURI" />
  5748. <xs:element name="boolean" type="xs:boolean" />
  5749. </xs:choice>
  5750. </xs:sequence>
  5751. </xs:group>
  5752. <xs:group name="argumentChoice">
  5753. <xs:choice>
  5754. <xs:element name="array" type="arrayType" minOccurs="0" maxOccurs="unbounded"/>
  5755. <xs:element name="integer" type="xs:integer" minOccurs="0" maxOccurs="unbounded"/>
  5756. <xs:element name="string" type="xs:string" minOccurs="0" maxOccurs="unbounded"/>
  5757. <xs:element name="double" type="xs:double" minOccurs="0" maxOccurs="unbounded"/>
  5758. <xs:element name="null" minOccurs="0" maxOccurs="unbounded"/>
  5759. <xs:element name="object" type="objectType" minOccurs="0" maxOccurs="unbounded"/>
  5760. <xs:element name="file" type="xs:anyURI" minOccurs="0" maxOccurs="unbounded"/>
  5761. <xs:element name="directory" type="xs:anyURI" minOccurs="0" maxOccurs="unbounded"/>
  5762. <xs:element name="boolean" type="xs:boolean" minOccurs="0" maxOccurs="unbounded"/>
  5763. </xs:choice>
  5764. </xs:group>
  5765. <xs:simpleType name="columnsType">
  5766. <xs:union>
  5767. <xs:simpleType>
  5768. <xs:restriction base="xs:integer"/>
  5769. </xs:simpleType>
  5770. <xs:simpleType>
  5771. <xs:restriction base="xs:string">
  5772. <xs:enumeration value="max"/>
  5773. </xs:restriction>
  5774. </xs:simpleType>
  5775. </xs:union>
  5776. </xs:simpleType>
  5777. <xs:complexType name="loggersType">
  5778. <xs:sequence>
  5779. <xs:element name="log" type="loggerType" maxOccurs="unbounded"/>
  5780. </xs:sequence>
  5781. </xs:complexType>
  5782. <xs:complexType name="loggerType">
  5783. <xs:attribute name="type">
  5784. <xs:simpleType>
  5785. <xs:restriction base="xs:string">
  5786. <xs:enumeration value="coverage-html"/>
  5787. <xs:enumeration value="coverage-text"/>
  5788. <xs:enumeration value="coverage-clover"/>
  5789. <xs:enumeration value="coverage-crap4j"/>
  5790. <xs:enumeration value="coverage-xml"/>
  5791. <xs:enumeration value="coverage-php"/>
  5792. <xs:enumeration value="plain"/>
  5793. <xs:enumeration value="teamcity"/>
  5794. <xs:enumeration value="junit"/>
  5795. <xs:enumeration value="testdox-html"/>
  5796. <xs:enumeration value="testdox-text"/>
  5797. <xs:enumeration value="testdox-xml"/>
  5798. </xs:restriction>
  5799. </xs:simpleType>
  5800. </xs:attribute>
  5801. <xs:attribute name="target" type="xs:anyURI"/>
  5802. <xs:attribute name="lowUpperBound" type="xs:nonNegativeInteger" default="50"/>
  5803. <xs:attribute name="highLowerBound" type="xs:nonNegativeInteger" default="90"/>
  5804. <xs:attribute name="showUncoveredFiles" type="xs:boolean" default="false"/>
  5805. <xs:attribute name="showOnlySummary" type="xs:boolean" default="false"/>
  5806. <xs:attribute name="threshold" type="xs:nonNegativeInteger" default="30"/>
  5807. </xs:complexType>
  5808. <xs:group name="pathGroup">
  5809. <xs:sequence>
  5810. <xs:choice minOccurs="0" maxOccurs="unbounded">
  5811. <xs:element name="directory" type="directoryFilterType"/>
  5812. <xs:element name="file" type="fileFilterType"/>
  5813. </xs:choice>
  5814. </xs:sequence>
  5815. </xs:group>
  5816. <xs:complexType name="directoryFilterType">
  5817. <xs:simpleContent>
  5818. <xs:extension base="xs:anyURI">
  5819. <xs:attribute type="xs:string" name="prefix" default=""/>
  5820. <xs:attribute type="xs:string" name="suffix" default="Test.php"/>
  5821. <xs:attributeGroup ref="phpVersionGroup"/>
  5822. </xs:extension>
  5823. </xs:simpleContent>
  5824. </xs:complexType>
  5825. <xs:simpleType name="executionOrderType">
  5826. <xs:restriction base="xs:string">
  5827. <xs:enumeration value="default"/>
  5828. <xs:enumeration value="defects"/>
  5829. <xs:enumeration value="depends"/>
  5830. <xs:enumeration value="depends,defects"/>
  5831. <xs:enumeration value="depends,duration"/>
  5832. <xs:enumeration value="depends,random"/>
  5833. <xs:enumeration value="depends,reverse"/>
  5834. <xs:enumeration value="depends,size"/>
  5835. <xs:enumeration value="duration"/>
  5836. <xs:enumeration value="no-depends"/>
  5837. <xs:enumeration value="no-depends,defects"/>
  5838. <xs:enumeration value="no-depends,duration"/>
  5839. <xs:enumeration value="no-depends,random"/>
  5840. <xs:enumeration value="no-depends,reverse"/>
  5841. <xs:enumeration value="no-depends,size"/>
  5842. <xs:enumeration value="random"/>
  5843. <xs:enumeration value="reverse"/>
  5844. <xs:enumeration value="size"/>
  5845. </xs:restriction>
  5846. </xs:simpleType>
  5847. <xs:complexType name="fileFilterType">
  5848. <xs:simpleContent>
  5849. <xs:extension base="xs:anyURI">
  5850. <xs:attributeGroup ref="phpVersionGroup"/>
  5851. </xs:extension>
  5852. </xs:simpleContent>
  5853. </xs:complexType>
  5854. <xs:attributeGroup name="phpVersionGroup">
  5855. <xs:attribute name="phpVersion" type="xs:string" default="5.3.0"/>
  5856. <xs:attribute name="phpVersionOperator" type="xs:string" default="&gt;="/>
  5857. </xs:attributeGroup>
  5858. <xs:complexType name="phpType">
  5859. <xs:sequence>
  5860. <xs:choice maxOccurs="unbounded">
  5861. <xs:element name="includePath" type="xs:anyURI" minOccurs="0" maxOccurs="unbounded"/>
  5862. <xs:element name="ini" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/>
  5863. <xs:element name="const" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/>
  5864. <xs:element name="var" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/>
  5865. <xs:element name="env" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/>
  5866. <xs:element name="post" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/>
  5867. <xs:element name="get" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/>
  5868. <xs:element name="cookie" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/>
  5869. <xs:element name="server" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/>
  5870. <xs:element name="files" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/>
  5871. <xs:element name="request" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/>
  5872. </xs:choice>
  5873. </xs:sequence>
  5874. </xs:complexType>
  5875. <xs:complexType name="namedValueType">
  5876. <xs:attribute name="name" use="required" type="xs:string"/>
  5877. <xs:attribute name="value" use="required" type="xs:anySimpleType"/>
  5878. <xs:attribute name="verbatim" use="optional" type="xs:boolean"/>
  5879. <xs:attribute name="force" use="optional" type="xs:boolean"/>
  5880. </xs:complexType>
  5881. <xs:complexType name="phpUnitType">
  5882. <xs:annotation>
  5883. <xs:documentation>The main type specifying the document structure</xs:documentation>
  5884. </xs:annotation>
  5885. <xs:group ref="configGroup"/>
  5886. <xs:attributeGroup ref="configAttributeGroup"/>
  5887. </xs:complexType>
  5888. <xs:attributeGroup name="configAttributeGroup">
  5889. <xs:attribute name="backupGlobals" type="xs:boolean" default="false"/>
  5890. <xs:attribute name="backupStaticAttributes" type="xs:boolean" default="false"/>
  5891. <xs:attribute name="bootstrap" type="xs:anyURI"/>
  5892. <xs:attribute name="cacheResult" type="xs:boolean" default="true"/>
  5893. <xs:attribute name="cacheResultFile" type="xs:anyURI"/>
  5894. <xs:attribute name="cacheTokens" type="xs:boolean" default="false"/>
  5895. <xs:attribute name="colors" type="xs:boolean" default="false"/>
  5896. <xs:attribute name="columns" type="columnsType" default="80"/>
  5897. <xs:attribute name="convertDeprecationsToExceptions" type="xs:boolean" default="true"/>
  5898. <xs:attribute name="convertErrorsToExceptions" type="xs:boolean" default="true"/>
  5899. <xs:attribute name="convertNoticesToExceptions" type="xs:boolean" default="true"/>
  5900. <xs:attribute name="convertWarningsToExceptions" type="xs:boolean" default="true"/>
  5901. <xs:attribute name="disableCodeCoverageIgnore" type="xs:boolean" default="false"/>
  5902. <xs:attribute name="forceCoversAnnotation" type="xs:boolean" default="false"/>
  5903. <xs:attribute name="printerClass" type="xs:string" default="PHPUnit\TextUI\ResultPrinter"/>
  5904. <xs:attribute name="printerFile" type="xs:anyURI"/>
  5905. <xs:attribute name="processIsolation" type="xs:boolean" default="false"/>
  5906. <xs:attribute name="stopOnDefect" type="xs:boolean" default="false"/>
  5907. <xs:attribute name="stopOnError" type="xs:boolean" default="false"/>
  5908. <xs:attribute name="stopOnFailure" type="xs:boolean" default="false"/>
  5909. <xs:attribute name="stopOnWarning" type="xs:boolean" default="false"/>
  5910. <xs:attribute name="stopOnIncomplete" type="xs:boolean" default="false"/>
  5911. <xs:attribute name="stopOnRisky" type="xs:boolean" default="false"/>
  5912. <xs:attribute name="stopOnSkipped" type="xs:boolean" default="false"/>
  5913. <xs:attribute name="failOnIncomplete" type="xs:boolean" default="false"/>
  5914. <xs:attribute name="failOnRisky" type="xs:boolean" default="false"/>
  5915. <xs:attribute name="failOnSkipped" type="xs:boolean" default="false"/>
  5916. <xs:attribute name="failOnWarning" type="xs:boolean" default="false"/>
  5917. <xs:attribute name="beStrictAboutChangesToGlobalState" type="xs:boolean" default="false"/>
  5918. <xs:attribute name="beStrictAboutOutputDuringTests" type="xs:boolean" default="false"/>
  5919. <xs:attribute name="beStrictAboutResourceUsageDuringSmallTests" type="xs:boolean" default="false"/>
  5920. <xs:attribute name="beStrictAboutTestsThatDoNotTestAnything" type="xs:boolean" default="true"/>
  5921. <xs:attribute name="beStrictAboutTodoAnnotatedTests" type="xs:boolean" default="false"/>
  5922. <xs:attribute name="beStrictAboutCoversAnnotation" type="xs:boolean" default="false"/>
  5923. <xs:attribute name="defaultTimeLimit" type="xs:integer" default="0"/>
  5924. <xs:attribute name="enforceTimeLimit" type="xs:boolean" default="false"/>
  5925. <xs:attribute name="ignoreDeprecatedCodeUnitsFromCodeCoverage" type="xs:boolean" default="false"/>
  5926. <xs:attribute name="timeoutForSmallTests" type="xs:integer" default="1"/>
  5927. <xs:attribute name="timeoutForMediumTests" type="xs:integer" default="10"/>
  5928. <xs:attribute name="timeoutForLargeTests" type="xs:integer" default="60"/>
  5929. <xs:attribute name="testSuiteLoaderClass" type="xs:string" default="PHPUnit\Runner\StandardTestSuiteLoader"/>
  5930. <xs:attribute name="testSuiteLoaderFile" type="xs:anyURI"/>
  5931. <xs:attribute name="defaultTestSuite" type="xs:string" default=""/>
  5932. <xs:attribute name="verbose" type="xs:boolean" default="false"/>
  5933. <xs:attribute name="testdox" type="xs:boolean" default="false"/>
  5934. <xs:attribute name="stderr" type="xs:boolean" default="false"/>
  5935. <xs:attribute name="reverseDefectList" type="xs:boolean" default="false"/>
  5936. <xs:attribute name="registerMockObjectsFromTestArgumentsRecursively" type="xs:boolean" default="false"/>
  5937. <xs:attribute name="extensionsDirectory" type="xs:string"/>
  5938. <xs:attribute name="executionOrder" type="executionOrderType" default="default"/>
  5939. <xs:attribute name="resolveDependencies" type="xs:boolean" default="true"/>
  5940. <xs:attribute name="noInteraction" type="xs:boolean" default="false"/>
  5941. </xs:attributeGroup>
  5942. <xs:group name="configGroup">
  5943. <xs:all>
  5944. <xs:element ref="testSuiteFacet" minOccurs="0"/>
  5945. <xs:element name="groups" type="groupsType" minOccurs="0"/>
  5946. <xs:element name="testdoxGroups" type="groupsType" minOccurs="0"/>
  5947. <xs:element name="filter" type="filtersType" minOccurs="0"/>
  5948. <xs:element name="logging" type="loggersType" minOccurs="0"/>
  5949. <xs:element name="extensions" type="extensionsType" minOccurs="0"/>
  5950. <xs:element name="listeners" type="listenersType" minOccurs="0"/>
  5951. <xs:element name="php" type="phpType" minOccurs="0"/>
  5952. </xs:all>
  5953. </xs:group>
  5954. <xs:element name="testSuiteFacet" abstract="true"/>
  5955. <xs:element name="testsuite" type="testSuiteType" substitutionGroup="testSuiteFacet"/>
  5956. <xs:element name="testsuites" type="testSuitesType" substitutionGroup="testSuiteFacet"/>
  5957. <xs:complexType name="testSuitesType">
  5958. <xs:sequence>
  5959. <xs:element name="testsuite" type="testSuiteType" maxOccurs="unbounded"/>
  5960. </xs:sequence>
  5961. </xs:complexType>
  5962. <xs:complexType name="testSuiteType">
  5963. <xs:sequence>
  5964. <xs:group ref="pathGroup"/>
  5965. <xs:element name="exclude" type="xs:anyURI" minOccurs="0" maxOccurs="unbounded"/>
  5966. </xs:sequence>
  5967. <xs:attribute name="name" type="xs:string" use="required"/>
  5968. </xs:complexType>
  5969. </xs:schema>
  5970. <?php
  5971. declare (strict_types=1);
  5972. /*
  5973. * This file is part of phpunit/php-timer.
  5974. *
  5975. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  5976. *
  5977. * For the full copyright and license information, please view the LICENSE
  5978. * file that was distributed with this source code.
  5979. */
  5980. namespace PHPUnit\SebastianBergmann\Timer;
  5981. final class Timer
  5982. {
  5983. /**
  5984. * @psalm-var list<float>
  5985. */
  5986. private $startTimes = [];
  5987. public function start() : void
  5988. {
  5989. $this->startTimes[] = (float) \hrtime(\true);
  5990. }
  5991. /**
  5992. * @throws NoActiveTimerException
  5993. */
  5994. public function stop() : \PHPUnit\SebastianBergmann\Timer\Duration
  5995. {
  5996. if (empty($this->startTimes)) {
  5997. throw new \PHPUnit\SebastianBergmann\Timer\NoActiveTimerException('Timer::start() has to be called before Timer::stop()');
  5998. }
  5999. return \PHPUnit\SebastianBergmann\Timer\Duration::fromNanoseconds((float) \hrtime(\true) - \array_pop($this->startTimes));
  6000. }
  6001. }
  6002. <?php
  6003. declare (strict_types=1);
  6004. /*
  6005. * This file is part of phpunit/php-timer.
  6006. *
  6007. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  6008. *
  6009. * For the full copyright and license information, please view the LICENSE
  6010. * file that was distributed with this source code.
  6011. */
  6012. namespace PHPUnit\SebastianBergmann\Timer;
  6013. final class ResourceUsageFormatter
  6014. {
  6015. /**
  6016. * @psalm-var array<string,int>
  6017. */
  6018. private const SIZES = ['GB' => 1073741824, 'MB' => 1048576, 'KB' => 1024];
  6019. public function resourceUsage(\PHPUnit\SebastianBergmann\Timer\Duration $duration) : string
  6020. {
  6021. return \sprintf('Time: %s, Memory: %s', $duration->asString(), $this->bytesToString(\memory_get_peak_usage(\true)));
  6022. }
  6023. /**
  6024. * @throws TimeSinceStartOfRequestNotAvailableException
  6025. */
  6026. public function resourceUsageSinceStartOfRequest() : string
  6027. {
  6028. if (!isset($_SERVER['REQUEST_TIME_FLOAT'])) {
  6029. throw new \PHPUnit\SebastianBergmann\Timer\TimeSinceStartOfRequestNotAvailableException('Cannot determine time at which the request started because $_SERVER[\'REQUEST_TIME_FLOAT\'] is not available');
  6030. }
  6031. if (!\is_float($_SERVER['REQUEST_TIME_FLOAT'])) {
  6032. throw new \PHPUnit\SebastianBergmann\Timer\TimeSinceStartOfRequestNotAvailableException('Cannot determine time at which the request started because $_SERVER[\'REQUEST_TIME_FLOAT\'] is not of type float');
  6033. }
  6034. return $this->resourceUsage(\PHPUnit\SebastianBergmann\Timer\Duration::fromMicroseconds(1000000 * (\microtime(\true) - $_SERVER['REQUEST_TIME_FLOAT'])));
  6035. }
  6036. private function bytesToString(int $bytes) : string
  6037. {
  6038. foreach (self::SIZES as $unit => $value) {
  6039. if ($bytes >= $value) {
  6040. return \sprintf('%.2f %s', $bytes >= 1024 ? $bytes / $value : $bytes, $unit);
  6041. }
  6042. }
  6043. // @codeCoverageIgnoreStart
  6044. return $bytes . ' byte' . ($bytes !== 1 ? 's' : '');
  6045. // @codeCoverageIgnoreEnd
  6046. }
  6047. }
  6048. <?php
  6049. declare (strict_types=1);
  6050. /*
  6051. * This file is part of phpunit/php-timer.
  6052. *
  6053. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  6054. *
  6055. * For the full copyright and license information, please view the LICENSE
  6056. * file that was distributed with this source code.
  6057. */
  6058. namespace PHPUnit\SebastianBergmann\Timer;
  6059. /**
  6060. * @psalm-immutable
  6061. */
  6062. final class Duration
  6063. {
  6064. /**
  6065. * @var float
  6066. */
  6067. private $nanoseconds;
  6068. /**
  6069. * @var int
  6070. */
  6071. private $hours;
  6072. /**
  6073. * @var int
  6074. */
  6075. private $minutes;
  6076. /**
  6077. * @var int
  6078. */
  6079. private $seconds;
  6080. /**
  6081. * @var int
  6082. */
  6083. private $milliseconds;
  6084. public static function fromMicroseconds(float $microseconds) : self
  6085. {
  6086. return new self($microseconds * 1000);
  6087. }
  6088. public static function fromNanoseconds(float $nanoseconds) : self
  6089. {
  6090. return new self($nanoseconds);
  6091. }
  6092. private function __construct(float $nanoseconds)
  6093. {
  6094. $this->nanoseconds = $nanoseconds;
  6095. $timeInMilliseconds = $nanoseconds / 1000000;
  6096. $hours = \floor($timeInMilliseconds / 60 / 60 / 1000);
  6097. $hoursInMilliseconds = $hours * 60 * 60 * 1000;
  6098. $minutes = \floor($timeInMilliseconds / 60 / 1000) % 60;
  6099. $minutesInMilliseconds = $minutes * 60 * 1000;
  6100. $seconds = \floor(($timeInMilliseconds - $hoursInMilliseconds - $minutesInMilliseconds) / 1000);
  6101. $secondsInMilliseconds = $seconds * 1000;
  6102. $milliseconds = $timeInMilliseconds - $hoursInMilliseconds - $minutesInMilliseconds - $secondsInMilliseconds;
  6103. $this->hours = (int) $hours;
  6104. $this->minutes = $minutes;
  6105. $this->seconds = (int) $seconds;
  6106. $this->milliseconds = (int) $milliseconds;
  6107. }
  6108. public function asNanoseconds() : float
  6109. {
  6110. return $this->nanoseconds;
  6111. }
  6112. public function asMicroseconds() : float
  6113. {
  6114. return $this->nanoseconds / 1000;
  6115. }
  6116. public function asMilliseconds() : float
  6117. {
  6118. return $this->nanoseconds / 1000000;
  6119. }
  6120. public function asSeconds() : float
  6121. {
  6122. return $this->nanoseconds / 1000000000;
  6123. }
  6124. public function asString() : string
  6125. {
  6126. $result = '';
  6127. if ($this->hours > 0) {
  6128. $result = \sprintf('%02d', $this->hours) . ':';
  6129. }
  6130. $result .= \sprintf('%02d', $this->minutes) . ':';
  6131. $result .= \sprintf('%02d', $this->seconds);
  6132. if ($this->milliseconds > 0) {
  6133. $result .= '.' . \sprintf('%03d', $this->milliseconds);
  6134. }
  6135. return $result;
  6136. }
  6137. }
  6138. <?php
  6139. declare (strict_types=1);
  6140. /*
  6141. * This file is part of phpunit/php-timer.
  6142. *
  6143. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  6144. *
  6145. * For the full copyright and license information, please view the LICENSE
  6146. * file that was distributed with this source code.
  6147. */
  6148. namespace PHPUnit\SebastianBergmann\Timer;
  6149. final class NoActiveTimerException extends \LogicException implements \PHPUnit\SebastianBergmann\Timer\Exception
  6150. {
  6151. }
  6152. <?php
  6153. declare (strict_types=1);
  6154. /*
  6155. * This file is part of phpunit/php-timer.
  6156. *
  6157. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  6158. *
  6159. * For the full copyright and license information, please view the LICENSE
  6160. * file that was distributed with this source code.
  6161. */
  6162. namespace PHPUnit\SebastianBergmann\Timer;
  6163. final class TimeSinceStartOfRequestNotAvailableException extends \RuntimeException implements \PHPUnit\SebastianBergmann\Timer\Exception
  6164. {
  6165. }
  6166. <?php
  6167. declare (strict_types=1);
  6168. /*
  6169. * This file is part of phpunit/php-timer.
  6170. *
  6171. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  6172. *
  6173. * For the full copyright and license information, please view the LICENSE
  6174. * file that was distributed with this source code.
  6175. */
  6176. namespace PHPUnit\SebastianBergmann\Timer;
  6177. interface Exception
  6178. {
  6179. }
  6180. phpunit/php-timer
  6181. Copyright (c) 2010-2020, Sebastian Bergmann <sebastian@phpunit.de>.
  6182. All rights reserved.
  6183. Redistribution and use in source and binary forms, with or without
  6184. modification, are permitted provided that the following conditions
  6185. are met:
  6186. * Redistributions of source code must retain the above copyright
  6187. notice, this list of conditions and the following disclaimer.
  6188. * Redistributions in binary form must reproduce the above copyright
  6189. notice, this list of conditions and the following disclaimer in
  6190. the documentation and/or other materials provided with the
  6191. distribution.
  6192. * Neither the name of Sebastian Bergmann nor the names of his
  6193. contributors may be used to endorse or promote products derived
  6194. from this software without specific prior written permission.
  6195. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  6196. "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  6197. LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  6198. FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  6199. COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  6200. INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  6201. BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  6202. LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  6203. CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  6204. LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
  6205. ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  6206. POSSIBILITY OF SUCH DAMAGE.
  6207. <?php
  6208. declare (strict_types=1);
  6209. /*
  6210. * This file is part of sebastian/global-state.
  6211. *
  6212. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  6213. *
  6214. * For the full copyright and license information, please view the LICENSE
  6215. * file that was distributed with this source code.
  6216. */
  6217. namespace PHPUnit\SebastianBergmann\GlobalState;
  6218. /**
  6219. * A blacklist for global state elements that should not be snapshotted.
  6220. */
  6221. final class Blacklist
  6222. {
  6223. /**
  6224. * @var array
  6225. */
  6226. private $globalVariables = [];
  6227. /**
  6228. * @var string[]
  6229. */
  6230. private $classes = [];
  6231. /**
  6232. * @var string[]
  6233. */
  6234. private $classNamePrefixes = [];
  6235. /**
  6236. * @var string[]
  6237. */
  6238. private $parentClasses = [];
  6239. /**
  6240. * @var string[]
  6241. */
  6242. private $interfaces = [];
  6243. /**
  6244. * @var array
  6245. */
  6246. private $staticAttributes = [];
  6247. public function addGlobalVariable(string $variableName) : void
  6248. {
  6249. $this->globalVariables[$variableName] = \true;
  6250. }
  6251. public function addClass(string $className) : void
  6252. {
  6253. $this->classes[] = $className;
  6254. }
  6255. public function addSubclassesOf(string $className) : void
  6256. {
  6257. $this->parentClasses[] = $className;
  6258. }
  6259. public function addImplementorsOf(string $interfaceName) : void
  6260. {
  6261. $this->interfaces[] = $interfaceName;
  6262. }
  6263. public function addClassNamePrefix(string $classNamePrefix) : void
  6264. {
  6265. $this->classNamePrefixes[] = $classNamePrefix;
  6266. }
  6267. public function addStaticAttribute(string $className, string $attributeName) : void
  6268. {
  6269. if (!isset($this->staticAttributes[$className])) {
  6270. $this->staticAttributes[$className] = [];
  6271. }
  6272. $this->staticAttributes[$className][$attributeName] = \true;
  6273. }
  6274. public function isGlobalVariableBlacklisted(string $variableName) : bool
  6275. {
  6276. return isset($this->globalVariables[$variableName]);
  6277. }
  6278. public function isStaticAttributeBlacklisted(string $className, string $attributeName) : bool
  6279. {
  6280. if (\in_array($className, $this->classes)) {
  6281. return \true;
  6282. }
  6283. foreach ($this->classNamePrefixes as $prefix) {
  6284. if (\strpos($className, $prefix) === 0) {
  6285. return \true;
  6286. }
  6287. }
  6288. $class = new \ReflectionClass($className);
  6289. foreach ($this->parentClasses as $type) {
  6290. if ($class->isSubclassOf($type)) {
  6291. return \true;
  6292. }
  6293. }
  6294. foreach ($this->interfaces as $type) {
  6295. if ($class->implementsInterface($type)) {
  6296. return \true;
  6297. }
  6298. }
  6299. if (isset($this->staticAttributes[$className][$attributeName])) {
  6300. return \true;
  6301. }
  6302. return \false;
  6303. }
  6304. }
  6305. <?php
  6306. declare (strict_types=1);
  6307. /*
  6308. * This file is part of sebastian/global-state.
  6309. *
  6310. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  6311. *
  6312. * For the full copyright and license information, please view the LICENSE
  6313. * file that was distributed with this source code.
  6314. */
  6315. namespace PHPUnit\SebastianBergmann\GlobalState;
  6316. use PHPUnit\SebastianBergmann\ObjectReflector\ObjectReflector;
  6317. use PHPUnit\SebastianBergmann\RecursionContext\Context;
  6318. /**
  6319. * A snapshot of global state.
  6320. */
  6321. class Snapshot
  6322. {
  6323. /**
  6324. * @var Blacklist
  6325. */
  6326. private $blacklist;
  6327. /**
  6328. * @var array
  6329. */
  6330. private $globalVariables = [];
  6331. /**
  6332. * @var array
  6333. */
  6334. private $superGlobalArrays = [];
  6335. /**
  6336. * @var array
  6337. */
  6338. private $superGlobalVariables = [];
  6339. /**
  6340. * @var array
  6341. */
  6342. private $staticAttributes = [];
  6343. /**
  6344. * @var array
  6345. */
  6346. private $iniSettings = [];
  6347. /**
  6348. * @var array
  6349. */
  6350. private $includedFiles = [];
  6351. /**
  6352. * @var array
  6353. */
  6354. private $constants = [];
  6355. /**
  6356. * @var array
  6357. */
  6358. private $functions = [];
  6359. /**
  6360. * @var array
  6361. */
  6362. private $interfaces = [];
  6363. /**
  6364. * @var array
  6365. */
  6366. private $classes = [];
  6367. /**
  6368. * @var array
  6369. */
  6370. private $traits = [];
  6371. /**
  6372. * Creates a snapshot of the current global state.
  6373. */
  6374. public function __construct(\PHPUnit\SebastianBergmann\GlobalState\Blacklist $blacklist = null, bool $includeGlobalVariables = \true, bool $includeStaticAttributes = \true, bool $includeConstants = \true, bool $includeFunctions = \true, bool $includeClasses = \true, bool $includeInterfaces = \true, bool $includeTraits = \true, bool $includeIniSettings = \true, bool $includeIncludedFiles = \true)
  6375. {
  6376. $this->blacklist = $blacklist ?: new \PHPUnit\SebastianBergmann\GlobalState\Blacklist();
  6377. if ($includeConstants) {
  6378. $this->snapshotConstants();
  6379. }
  6380. if ($includeFunctions) {
  6381. $this->snapshotFunctions();
  6382. }
  6383. if ($includeClasses || $includeStaticAttributes) {
  6384. $this->snapshotClasses();
  6385. }
  6386. if ($includeInterfaces) {
  6387. $this->snapshotInterfaces();
  6388. }
  6389. if ($includeGlobalVariables) {
  6390. $this->setupSuperGlobalArrays();
  6391. $this->snapshotGlobals();
  6392. }
  6393. if ($includeStaticAttributes) {
  6394. $this->snapshotStaticAttributes();
  6395. }
  6396. if ($includeIniSettings) {
  6397. $this->iniSettings = \ini_get_all(null, \false);
  6398. }
  6399. if ($includeIncludedFiles) {
  6400. $this->includedFiles = \get_included_files();
  6401. }
  6402. $this->traits = \get_declared_traits();
  6403. }
  6404. public function blacklist() : \PHPUnit\SebastianBergmann\GlobalState\Blacklist
  6405. {
  6406. return $this->blacklist;
  6407. }
  6408. public function globalVariables() : array
  6409. {
  6410. return $this->globalVariables;
  6411. }
  6412. public function superGlobalVariables() : array
  6413. {
  6414. return $this->superGlobalVariables;
  6415. }
  6416. public function superGlobalArrays() : array
  6417. {
  6418. return $this->superGlobalArrays;
  6419. }
  6420. public function staticAttributes() : array
  6421. {
  6422. return $this->staticAttributes;
  6423. }
  6424. public function iniSettings() : array
  6425. {
  6426. return $this->iniSettings;
  6427. }
  6428. public function includedFiles() : array
  6429. {
  6430. return $this->includedFiles;
  6431. }
  6432. public function constants() : array
  6433. {
  6434. return $this->constants;
  6435. }
  6436. public function functions() : array
  6437. {
  6438. return $this->functions;
  6439. }
  6440. public function interfaces() : array
  6441. {
  6442. return $this->interfaces;
  6443. }
  6444. public function classes() : array
  6445. {
  6446. return $this->classes;
  6447. }
  6448. public function traits() : array
  6449. {
  6450. return $this->traits;
  6451. }
  6452. /**
  6453. * Creates a snapshot user-defined constants.
  6454. */
  6455. private function snapshotConstants() : void
  6456. {
  6457. $constants = \get_defined_constants(\true);
  6458. if (isset($constants['user'])) {
  6459. $this->constants = $constants['user'];
  6460. }
  6461. }
  6462. /**
  6463. * Creates a snapshot user-defined functions.
  6464. */
  6465. private function snapshotFunctions() : void
  6466. {
  6467. $functions = \get_defined_functions();
  6468. $this->functions = $functions['user'];
  6469. }
  6470. /**
  6471. * Creates a snapshot user-defined classes.
  6472. */
  6473. private function snapshotClasses() : void
  6474. {
  6475. foreach (\array_reverse(\get_declared_classes()) as $className) {
  6476. $class = new \ReflectionClass($className);
  6477. if (!$class->isUserDefined()) {
  6478. break;
  6479. }
  6480. $this->classes[] = $className;
  6481. }
  6482. $this->classes = \array_reverse($this->classes);
  6483. }
  6484. /**
  6485. * Creates a snapshot user-defined interfaces.
  6486. */
  6487. private function snapshotInterfaces() : void
  6488. {
  6489. foreach (\array_reverse(\get_declared_interfaces()) as $interfaceName) {
  6490. $class = new \ReflectionClass($interfaceName);
  6491. if (!$class->isUserDefined()) {
  6492. break;
  6493. }
  6494. $this->interfaces[] = $interfaceName;
  6495. }
  6496. $this->interfaces = \array_reverse($this->interfaces);
  6497. }
  6498. /**
  6499. * Creates a snapshot of all global and super-global variables.
  6500. */
  6501. private function snapshotGlobals() : void
  6502. {
  6503. $superGlobalArrays = $this->superGlobalArrays();
  6504. foreach ($superGlobalArrays as $superGlobalArray) {
  6505. $this->snapshotSuperGlobalArray($superGlobalArray);
  6506. }
  6507. foreach (\array_keys($GLOBALS) as $key) {
  6508. if ($key !== 'GLOBALS' && !\in_array($key, $superGlobalArrays) && $this->canBeSerialized($GLOBALS[$key]) && !$this->blacklist->isGlobalVariableBlacklisted($key)) {
  6509. /* @noinspection UnserializeExploitsInspection */
  6510. $this->globalVariables[$key] = \unserialize(\serialize($GLOBALS[$key]));
  6511. }
  6512. }
  6513. }
  6514. /**
  6515. * Creates a snapshot a super-global variable array.
  6516. */
  6517. private function snapshotSuperGlobalArray(string $superGlobalArray) : void
  6518. {
  6519. $this->superGlobalVariables[$superGlobalArray] = [];
  6520. if (isset($GLOBALS[$superGlobalArray]) && \is_array($GLOBALS[$superGlobalArray])) {
  6521. foreach ($GLOBALS[$superGlobalArray] as $key => $value) {
  6522. /* @noinspection UnserializeExploitsInspection */
  6523. $this->superGlobalVariables[$superGlobalArray][$key] = \unserialize(\serialize($value));
  6524. }
  6525. }
  6526. }
  6527. /**
  6528. * Creates a snapshot of all static attributes in user-defined classes.
  6529. */
  6530. private function snapshotStaticAttributes() : void
  6531. {
  6532. foreach ($this->classes as $className) {
  6533. $class = new \ReflectionClass($className);
  6534. $snapshot = [];
  6535. foreach ($class->getProperties() as $attribute) {
  6536. if ($attribute->isStatic()) {
  6537. $name = $attribute->getName();
  6538. if ($this->blacklist->isStaticAttributeBlacklisted($className, $name)) {
  6539. continue;
  6540. }
  6541. $attribute->setAccessible(\true);
  6542. $value = $attribute->getValue();
  6543. if ($this->canBeSerialized($value)) {
  6544. /* @noinspection UnserializeExploitsInspection */
  6545. $snapshot[$name] = \unserialize(\serialize($value));
  6546. }
  6547. }
  6548. }
  6549. if (!empty($snapshot)) {
  6550. $this->staticAttributes[$className] = $snapshot;
  6551. }
  6552. }
  6553. }
  6554. /**
  6555. * Returns a list of all super-global variable arrays.
  6556. */
  6557. private function setupSuperGlobalArrays() : void
  6558. {
  6559. $this->superGlobalArrays = ['_ENV', '_POST', '_GET', '_COOKIE', '_SERVER', '_FILES', '_REQUEST'];
  6560. }
  6561. private function canBeSerialized($variable) : bool
  6562. {
  6563. if (\is_scalar($variable) || $variable === null) {
  6564. return \true;
  6565. }
  6566. if (\is_resource($variable)) {
  6567. return \false;
  6568. }
  6569. foreach ($this->enumerateObjectsAndResources($variable) as $value) {
  6570. if (\is_resource($value)) {
  6571. return \false;
  6572. }
  6573. if (\is_object($value)) {
  6574. $class = new \ReflectionClass($value);
  6575. if ($class->isAnonymous()) {
  6576. return \false;
  6577. }
  6578. try {
  6579. @\serialize($value);
  6580. } catch (\Throwable $t) {
  6581. return \false;
  6582. }
  6583. }
  6584. }
  6585. return \true;
  6586. }
  6587. private function enumerateObjectsAndResources($variable) : array
  6588. {
  6589. if (isset(\func_get_args()[1])) {
  6590. $processed = \func_get_args()[1];
  6591. } else {
  6592. $processed = new \PHPUnit\SebastianBergmann\RecursionContext\Context();
  6593. }
  6594. $result = [];
  6595. if ($processed->contains($variable)) {
  6596. return $result;
  6597. }
  6598. $array = $variable;
  6599. $processed->add($variable);
  6600. if (\is_array($variable)) {
  6601. foreach ($array as $element) {
  6602. if (!\is_array($element) && !\is_object($element) && !\is_resource($element)) {
  6603. continue;
  6604. }
  6605. if (!\is_resource($element)) {
  6606. /** @noinspection SlowArrayOperationsInLoopInspection */
  6607. $result = \array_merge($result, $this->enumerateObjectsAndResources($element, $processed));
  6608. } else {
  6609. $result[] = $element;
  6610. }
  6611. }
  6612. } else {
  6613. $result[] = $variable;
  6614. foreach ((new \PHPUnit\SebastianBergmann\ObjectReflector\ObjectReflector())->getAttributes($variable) as $value) {
  6615. if (!\is_array($value) && !\is_object($value) && !\is_resource($value)) {
  6616. continue;
  6617. }
  6618. if (!\is_resource($value)) {
  6619. /** @noinspection SlowArrayOperationsInLoopInspection */
  6620. $result = \array_merge($result, $this->enumerateObjectsAndResources($value, $processed));
  6621. } else {
  6622. $result[] = $value;
  6623. }
  6624. }
  6625. }
  6626. return $result;
  6627. }
  6628. }
  6629. <?php
  6630. declare (strict_types=1);
  6631. /*
  6632. * This file is part of sebastian/global-state.
  6633. *
  6634. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  6635. *
  6636. * For the full copyright and license information, please view the LICENSE
  6637. * file that was distributed with this source code.
  6638. */
  6639. namespace PHPUnit\SebastianBergmann\GlobalState;
  6640. /**
  6641. * Exports parts of a Snapshot as PHP code.
  6642. */
  6643. final class CodeExporter
  6644. {
  6645. public function constants(\PHPUnit\SebastianBergmann\GlobalState\Snapshot $snapshot) : string
  6646. {
  6647. $result = '';
  6648. foreach ($snapshot->constants() as $name => $value) {
  6649. $result .= \sprintf('if (!defined(\'%s\')) define(\'%s\', %s);' . "\n", $name, $name, $this->exportVariable($value));
  6650. }
  6651. return $result;
  6652. }
  6653. public function globalVariables(\PHPUnit\SebastianBergmann\GlobalState\Snapshot $snapshot) : string
  6654. {
  6655. $result = '$GLOBALS = [];' . \PHP_EOL;
  6656. foreach ($snapshot->globalVariables() as $name => $value) {
  6657. $result .= \sprintf('$GLOBALS[%s] = %s;' . \PHP_EOL, $this->exportVariable($name), $this->exportVariable($value));
  6658. }
  6659. return $result;
  6660. }
  6661. public function iniSettings(\PHPUnit\SebastianBergmann\GlobalState\Snapshot $snapshot) : string
  6662. {
  6663. $result = '';
  6664. foreach ($snapshot->iniSettings() as $key => $value) {
  6665. $result .= \sprintf('@ini_set(%s, %s);' . "\n", $this->exportVariable($key), $this->exportVariable($value));
  6666. }
  6667. return $result;
  6668. }
  6669. private function exportVariable($variable) : string
  6670. {
  6671. if (\is_scalar($variable) || null === $variable || \is_array($variable) && $this->arrayOnlyContainsScalars($variable)) {
  6672. return \var_export($variable, \true);
  6673. }
  6674. return 'unserialize(' . \var_export(\serialize($variable), \true) . ')';
  6675. }
  6676. private function arrayOnlyContainsScalars(array $array) : bool
  6677. {
  6678. $result = \true;
  6679. foreach ($array as $element) {
  6680. if (\is_array($element)) {
  6681. $result = $this->arrayOnlyContainsScalars($element);
  6682. } elseif (!\is_scalar($element) && null !== $element) {
  6683. $result = \false;
  6684. }
  6685. if ($result === \false) {
  6686. break;
  6687. }
  6688. }
  6689. return $result;
  6690. }
  6691. }
  6692. <?php
  6693. declare (strict_types=1);
  6694. /*
  6695. * This file is part of sebastian/global-state.
  6696. *
  6697. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  6698. *
  6699. * For the full copyright and license information, please view the LICENSE
  6700. * file that was distributed with this source code.
  6701. */
  6702. namespace PHPUnit\SebastianBergmann\GlobalState;
  6703. /**
  6704. * Restorer of snapshots of global state.
  6705. */
  6706. class Restorer
  6707. {
  6708. /**
  6709. * Deletes function definitions that are not defined in a snapshot.
  6710. *
  6711. * @throws RuntimeException when the uopz_delete() function is not available
  6712. *
  6713. * @see https://github.com/krakjoe/uopz
  6714. */
  6715. public function restoreFunctions(\PHPUnit\SebastianBergmann\GlobalState\Snapshot $snapshot) : void
  6716. {
  6717. if (!\function_exists('PHPUnit\\uopz_delete')) {
  6718. throw new \PHPUnit\SebastianBergmann\GlobalState\RuntimeException('The uopz_delete() function is required for this operation');
  6719. }
  6720. $functions = \get_defined_functions();
  6721. foreach (\array_diff($functions['user'], $snapshot->functions()) as $function) {
  6722. uopz_delete($function);
  6723. }
  6724. }
  6725. /**
  6726. * Restores all global and super-global variables from a snapshot.
  6727. */
  6728. public function restoreGlobalVariables(\PHPUnit\SebastianBergmann\GlobalState\Snapshot $snapshot) : void
  6729. {
  6730. $superGlobalArrays = $snapshot->superGlobalArrays();
  6731. foreach ($superGlobalArrays as $superGlobalArray) {
  6732. $this->restoreSuperGlobalArray($snapshot, $superGlobalArray);
  6733. }
  6734. $globalVariables = $snapshot->globalVariables();
  6735. foreach (\array_keys($GLOBALS) as $key) {
  6736. if ($key !== 'GLOBALS' && !\in_array($key, $superGlobalArrays) && !$snapshot->blacklist()->isGlobalVariableBlacklisted($key)) {
  6737. if (\array_key_exists($key, $globalVariables)) {
  6738. $GLOBALS[$key] = $globalVariables[$key];
  6739. } else {
  6740. unset($GLOBALS[$key]);
  6741. }
  6742. }
  6743. }
  6744. }
  6745. /**
  6746. * Restores all static attributes in user-defined classes from this snapshot.
  6747. */
  6748. public function restoreStaticAttributes(\PHPUnit\SebastianBergmann\GlobalState\Snapshot $snapshot) : void
  6749. {
  6750. $current = new \PHPUnit\SebastianBergmann\GlobalState\Snapshot($snapshot->blacklist(), \false, \false, \false, \false, \true, \false, \false, \false, \false);
  6751. $newClasses = \array_diff($current->classes(), $snapshot->classes());
  6752. unset($current);
  6753. foreach ($snapshot->staticAttributes() as $className => $staticAttributes) {
  6754. foreach ($staticAttributes as $name => $value) {
  6755. $reflector = new \ReflectionProperty($className, $name);
  6756. $reflector->setAccessible(\true);
  6757. $reflector->setValue($value);
  6758. }
  6759. }
  6760. foreach ($newClasses as $className) {
  6761. $class = new \ReflectionClass($className);
  6762. $defaults = $class->getDefaultProperties();
  6763. foreach ($class->getProperties() as $attribute) {
  6764. if (!$attribute->isStatic()) {
  6765. continue;
  6766. }
  6767. $name = $attribute->getName();
  6768. if ($snapshot->blacklist()->isStaticAttributeBlacklisted($className, $name)) {
  6769. continue;
  6770. }
  6771. if (!isset($defaults[$name])) {
  6772. continue;
  6773. }
  6774. $attribute->setAccessible(\true);
  6775. $attribute->setValue($defaults[$name]);
  6776. }
  6777. }
  6778. }
  6779. /**
  6780. * Restores a super-global variable array from this snapshot.
  6781. */
  6782. private function restoreSuperGlobalArray(\PHPUnit\SebastianBergmann\GlobalState\Snapshot $snapshot, string $superGlobalArray) : void
  6783. {
  6784. $superGlobalVariables = $snapshot->superGlobalVariables();
  6785. if (isset($GLOBALS[$superGlobalArray]) && \is_array($GLOBALS[$superGlobalArray]) && isset($superGlobalVariables[$superGlobalArray])) {
  6786. $keys = \array_keys(\array_merge($GLOBALS[$superGlobalArray], $superGlobalVariables[$superGlobalArray]));
  6787. foreach ($keys as $key) {
  6788. if (isset($superGlobalVariables[$superGlobalArray][$key])) {
  6789. $GLOBALS[$superGlobalArray][$key] = $superGlobalVariables[$superGlobalArray][$key];
  6790. } else {
  6791. unset($GLOBALS[$superGlobalArray][$key]);
  6792. }
  6793. }
  6794. }
  6795. }
  6796. }
  6797. <?php
  6798. declare (strict_types=1);
  6799. /*
  6800. * This file is part of sebastian/global-state.
  6801. *
  6802. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  6803. *
  6804. * For the full copyright and license information, please view the LICENSE
  6805. * file that was distributed with this source code.
  6806. */
  6807. namespace PHPUnit\SebastianBergmann\GlobalState;
  6808. final class RuntimeException extends \RuntimeException implements \PHPUnit\SebastianBergmann\GlobalState\Exception
  6809. {
  6810. }
  6811. <?php
  6812. declare (strict_types=1);
  6813. /*
  6814. * This file is part of sebastian/global-state.
  6815. *
  6816. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  6817. *
  6818. * For the full copyright and license information, please view the LICENSE
  6819. * file that was distributed with this source code.
  6820. */
  6821. namespace PHPUnit\SebastianBergmann\GlobalState;
  6822. interface Exception
  6823. {
  6824. }
  6825. sebastian/global-state
  6826. Copyright (c) 2001-2020, Sebastian Bergmann <sebastian@phpunit.de>.
  6827. All rights reserved.
  6828. Redistribution and use in source and binary forms, with or without
  6829. modification, are permitted provided that the following conditions
  6830. are met:
  6831. * Redistributions of source code must retain the above copyright
  6832. notice, this list of conditions and the following disclaimer.
  6833. * Redistributions in binary form must reproduce the above copyright
  6834. notice, this list of conditions and the following disclaimer in
  6835. the documentation and/or other materials provided with the
  6836. distribution.
  6837. * Neither the name of Sebastian Bergmann nor the names of his
  6838. contributors may be used to endorse or promote products derived
  6839. from this software without specific prior written permission.
  6840. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  6841. "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  6842. LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  6843. FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  6844. COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  6845. INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  6846. BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  6847. LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  6848. CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  6849. LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
  6850. ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  6851. POSSIBILITY OF SUCH DAMAGE.
  6852. <?php
  6853. namespace PHPUnit\DeepCopy\Matcher;
  6854. /**
  6855. * @final
  6856. */
  6857. class PropertyNameMatcher implements \PHPUnit\DeepCopy\Matcher\Matcher
  6858. {
  6859. /**
  6860. * @var string
  6861. */
  6862. private $property;
  6863. /**
  6864. * @param string $property Property name
  6865. */
  6866. public function __construct($property)
  6867. {
  6868. $this->property = $property;
  6869. }
  6870. /**
  6871. * Matches a property by its name.
  6872. *
  6873. * {@inheritdoc}
  6874. */
  6875. public function matches($object, $property)
  6876. {
  6877. return $property == $this->property;
  6878. }
  6879. }
  6880. <?php
  6881. namespace PHPUnit\DeepCopy\Matcher;
  6882. /**
  6883. * @final
  6884. */
  6885. class PropertyMatcher implements \PHPUnit\DeepCopy\Matcher\Matcher
  6886. {
  6887. /**
  6888. * @var string
  6889. */
  6890. private $class;
  6891. /**
  6892. * @var string
  6893. */
  6894. private $property;
  6895. /**
  6896. * @param string $class Class name
  6897. * @param string $property Property name
  6898. */
  6899. public function __construct($class, $property)
  6900. {
  6901. $this->class = $class;
  6902. $this->property = $property;
  6903. }
  6904. /**
  6905. * Matches a specific property of a specific class.
  6906. *
  6907. * {@inheritdoc}
  6908. */
  6909. public function matches($object, $property)
  6910. {
  6911. return $object instanceof $this->class && $property == $this->property;
  6912. }
  6913. }
  6914. <?php
  6915. namespace PHPUnit\DeepCopy\Matcher;
  6916. interface Matcher
  6917. {
  6918. /**
  6919. * @param object $object
  6920. * @param string $property
  6921. *
  6922. * @return boolean
  6923. */
  6924. public function matches($object, $property);
  6925. }
  6926. <?php
  6927. namespace PHPUnit\DeepCopy\Matcher\Doctrine;
  6928. use PHPUnit\DeepCopy\Matcher\Matcher;
  6929. use PHPUnit\Doctrine\Common\Persistence\Proxy;
  6930. /**
  6931. * @final
  6932. */
  6933. class DoctrineProxyMatcher implements \PHPUnit\DeepCopy\Matcher\Matcher
  6934. {
  6935. /**
  6936. * Matches a Doctrine Proxy class.
  6937. *
  6938. * {@inheritdoc}
  6939. */
  6940. public function matches($object, $property)
  6941. {
  6942. return $object instanceof \PHPUnit\Doctrine\Common\Persistence\Proxy;
  6943. }
  6944. }
  6945. <?php
  6946. namespace PHPUnit\DeepCopy\Matcher;
  6947. use PHPUnit\DeepCopy\Reflection\ReflectionHelper;
  6948. use ReflectionException;
  6949. /**
  6950. * Matches a property by its type.
  6951. *
  6952. * It is recommended to use {@see DeepCopy\TypeFilter\TypeFilter} instead, as it applies on all occurrences
  6953. * of given type in copied context (eg. array elements), not just on object properties.
  6954. *
  6955. * @final
  6956. */
  6957. class PropertyTypeMatcher implements \PHPUnit\DeepCopy\Matcher\Matcher
  6958. {
  6959. /**
  6960. * @var string
  6961. */
  6962. private $propertyType;
  6963. /**
  6964. * @param string $propertyType Property type
  6965. */
  6966. public function __construct($propertyType)
  6967. {
  6968. $this->propertyType = $propertyType;
  6969. }
  6970. /**
  6971. * {@inheritdoc}
  6972. */
  6973. public function matches($object, $property)
  6974. {
  6975. try {
  6976. $reflectionProperty = \PHPUnit\DeepCopy\Reflection\ReflectionHelper::getProperty($object, $property);
  6977. } catch (\ReflectionException $exception) {
  6978. return \false;
  6979. }
  6980. $reflectionProperty->setAccessible(\true);
  6981. return $reflectionProperty->getValue($object) instanceof $this->propertyType;
  6982. }
  6983. }
  6984. <?php
  6985. namespace PHPUnit\DeepCopy\Exception;
  6986. use ReflectionException;
  6987. class PropertyException extends \ReflectionException
  6988. {
  6989. }
  6990. <?php
  6991. namespace PHPUnit\DeepCopy\Exception;
  6992. use UnexpectedValueException;
  6993. class CloneException extends \UnexpectedValueException
  6994. {
  6995. }
  6996. <?php
  6997. namespace PHPUnit\DeepCopy;
  6998. use function function_exists;
  6999. if (\false === \function_exists('PHPUnit\\DeepCopy\\deep_copy')) {
  7000. /**
  7001. * Deep copies the given value.
  7002. *
  7003. * @param mixed $value
  7004. * @param bool $useCloneMethod
  7005. *
  7006. * @return mixed
  7007. */
  7008. function deep_copy($value, $useCloneMethod = \false)
  7009. {
  7010. return (new \PHPUnit\DeepCopy\DeepCopy($useCloneMethod))->copy($value);
  7011. }
  7012. }
  7013. <?php
  7014. namespace PHPUnit\DeepCopy\Filter;
  7015. use PHPUnit\DeepCopy\Reflection\ReflectionHelper;
  7016. /**
  7017. * @final
  7018. */
  7019. class ReplaceFilter implements \PHPUnit\DeepCopy\Filter\Filter
  7020. {
  7021. /**
  7022. * @var callable
  7023. */
  7024. protected $callback;
  7025. /**
  7026. * @param callable $callable Will be called to get the new value for each property to replace
  7027. */
  7028. public function __construct(callable $callable)
  7029. {
  7030. $this->callback = $callable;
  7031. }
  7032. /**
  7033. * Replaces the object property by the result of the callback called with the object property.
  7034. *
  7035. * {@inheritdoc}
  7036. */
  7037. public function apply($object, $property, $objectCopier)
  7038. {
  7039. $reflectionProperty = \PHPUnit\DeepCopy\Reflection\ReflectionHelper::getProperty($object, $property);
  7040. $reflectionProperty->setAccessible(\true);
  7041. $value = \call_user_func($this->callback, $reflectionProperty->getValue($object));
  7042. $reflectionProperty->setValue($object, $value);
  7043. }
  7044. }
  7045. <?php
  7046. namespace PHPUnit\DeepCopy\Filter;
  7047. use PHPUnit\DeepCopy\Reflection\ReflectionHelper;
  7048. /**
  7049. * @final
  7050. */
  7051. class SetNullFilter implements \PHPUnit\DeepCopy\Filter\Filter
  7052. {
  7053. /**
  7054. * Sets the object property to null.
  7055. *
  7056. * {@inheritdoc}
  7057. */
  7058. public function apply($object, $property, $objectCopier)
  7059. {
  7060. $reflectionProperty = \PHPUnit\DeepCopy\Reflection\ReflectionHelper::getProperty($object, $property);
  7061. $reflectionProperty->setAccessible(\true);
  7062. $reflectionProperty->setValue($object, null);
  7063. }
  7064. }
  7065. <?php
  7066. namespace PHPUnit\DeepCopy\Filter;
  7067. class KeepFilter implements \PHPUnit\DeepCopy\Filter\Filter
  7068. {
  7069. /**
  7070. * Keeps the value of the object property.
  7071. *
  7072. * {@inheritdoc}
  7073. */
  7074. public function apply($object, $property, $objectCopier)
  7075. {
  7076. // Nothing to do
  7077. }
  7078. }
  7079. <?php
  7080. namespace PHPUnit\DeepCopy\Filter;
  7081. /**
  7082. * Filter to apply to a property while copying an object
  7083. */
  7084. interface Filter
  7085. {
  7086. /**
  7087. * Applies the filter to the object.
  7088. *
  7089. * @param object $object
  7090. * @param string $property
  7091. * @param callable $objectCopier
  7092. */
  7093. public function apply($object, $property, $objectCopier);
  7094. }
  7095. <?php
  7096. namespace PHPUnit\DeepCopy\Filter\Doctrine;
  7097. use PHPUnit\DeepCopy\Filter\Filter;
  7098. use PHPUnit\DeepCopy\Reflection\ReflectionHelper;
  7099. /**
  7100. * @final
  7101. */
  7102. class DoctrineCollectionFilter implements \PHPUnit\DeepCopy\Filter\Filter
  7103. {
  7104. /**
  7105. * Copies the object property doctrine collection.
  7106. *
  7107. * {@inheritdoc}
  7108. */
  7109. public function apply($object, $property, $objectCopier)
  7110. {
  7111. $reflectionProperty = \PHPUnit\DeepCopy\Reflection\ReflectionHelper::getProperty($object, $property);
  7112. $reflectionProperty->setAccessible(\true);
  7113. $oldCollection = $reflectionProperty->getValue($object);
  7114. $newCollection = $oldCollection->map(function ($item) use($objectCopier) {
  7115. return $objectCopier($item);
  7116. });
  7117. $reflectionProperty->setValue($object, $newCollection);
  7118. }
  7119. }
  7120. <?php
  7121. namespace PHPUnit\DeepCopy\Filter\Doctrine;
  7122. use PHPUnit\DeepCopy\Filter\Filter;
  7123. use PHPUnit\DeepCopy\Reflection\ReflectionHelper;
  7124. use PHPUnit\Doctrine\Common\Collections\ArrayCollection;
  7125. /**
  7126. * @final
  7127. */
  7128. class DoctrineEmptyCollectionFilter implements \PHPUnit\DeepCopy\Filter\Filter
  7129. {
  7130. /**
  7131. * Sets the object property to an empty doctrine collection.
  7132. *
  7133. * @param object $object
  7134. * @param string $property
  7135. * @param callable $objectCopier
  7136. */
  7137. public function apply($object, $property, $objectCopier)
  7138. {
  7139. $reflectionProperty = \PHPUnit\DeepCopy\Reflection\ReflectionHelper::getProperty($object, $property);
  7140. $reflectionProperty->setAccessible(\true);
  7141. $reflectionProperty->setValue($object, new \PHPUnit\Doctrine\Common\Collections\ArrayCollection());
  7142. }
  7143. }
  7144. <?php
  7145. namespace PHPUnit\DeepCopy\Filter\Doctrine;
  7146. use PHPUnit\DeepCopy\Filter\Filter;
  7147. /**
  7148. * @final
  7149. */
  7150. class DoctrineProxyFilter implements \PHPUnit\DeepCopy\Filter\Filter
  7151. {
  7152. /**
  7153. * Triggers the magic method __load() on a Doctrine Proxy class to load the
  7154. * actual entity from the database.
  7155. *
  7156. * {@inheritdoc}
  7157. */
  7158. public function apply($object, $property, $objectCopier)
  7159. {
  7160. $object->__load();
  7161. }
  7162. }
  7163. <?php
  7164. namespace PHPUnit\DeepCopy\TypeMatcher;
  7165. class TypeMatcher
  7166. {
  7167. /**
  7168. * @var string
  7169. */
  7170. private $type;
  7171. /**
  7172. * @param string $type
  7173. */
  7174. public function __construct($type)
  7175. {
  7176. $this->type = $type;
  7177. }
  7178. /**
  7179. * @param mixed $element
  7180. *
  7181. * @return boolean
  7182. */
  7183. public function matches($element)
  7184. {
  7185. return \is_object($element) ? \is_a($element, $this->type) : \gettype($element) === $this->type;
  7186. }
  7187. }
  7188. <?php
  7189. namespace PHPUnit\DeepCopy\TypeFilter;
  7190. /**
  7191. * @final
  7192. */
  7193. class ReplaceFilter implements \PHPUnit\DeepCopy\TypeFilter\TypeFilter
  7194. {
  7195. /**
  7196. * @var callable
  7197. */
  7198. protected $callback;
  7199. /**
  7200. * @param callable $callable Will be called to get the new value for each element to replace
  7201. */
  7202. public function __construct(callable $callable)
  7203. {
  7204. $this->callback = $callable;
  7205. }
  7206. /**
  7207. * {@inheritdoc}
  7208. */
  7209. public function apply($element)
  7210. {
  7211. return \call_user_func($this->callback, $element);
  7212. }
  7213. }
  7214. <?php
  7215. namespace PHPUnit\DeepCopy\TypeFilter;
  7216. interface TypeFilter
  7217. {
  7218. /**
  7219. * Applies the filter to the object.
  7220. *
  7221. * @param mixed $element
  7222. */
  7223. public function apply($element);
  7224. }
  7225. <?php
  7226. namespace PHPUnit\DeepCopy\TypeFilter\Spl;
  7227. use ArrayObject;
  7228. use PHPUnit\DeepCopy\DeepCopy;
  7229. use PHPUnit\DeepCopy\TypeFilter\TypeFilter;
  7230. /**
  7231. * In PHP 7.4 the storage of an ArrayObject isn't returned as
  7232. * ReflectionProperty. So we deep copy its array copy.
  7233. */
  7234. final class ArrayObjectFilter implements \PHPUnit\DeepCopy\TypeFilter\TypeFilter
  7235. {
  7236. /**
  7237. * @var DeepCopy
  7238. */
  7239. private $copier;
  7240. public function __construct(\PHPUnit\DeepCopy\DeepCopy $copier)
  7241. {
  7242. $this->copier = $copier;
  7243. }
  7244. /**
  7245. * {@inheritdoc}
  7246. */
  7247. public function apply($arrayObject)
  7248. {
  7249. return new \ArrayObject($this->copier->copy($arrayObject->getArrayCopy()), $arrayObject->getFlags(), $arrayObject->getIteratorClass());
  7250. }
  7251. }
  7252. <?php
  7253. namespace PHPUnit\DeepCopy\TypeFilter\Spl;
  7254. /**
  7255. * @deprecated Use {@see SplDoublyLinkedListFilter} instead.
  7256. */
  7257. class SplDoublyLinkedList extends \PHPUnit\DeepCopy\TypeFilter\Spl\SplDoublyLinkedListFilter
  7258. {
  7259. }
  7260. <?php
  7261. namespace PHPUnit\DeepCopy\TypeFilter\Spl;
  7262. use Closure;
  7263. use PHPUnit\DeepCopy\DeepCopy;
  7264. use PHPUnit\DeepCopy\TypeFilter\TypeFilter;
  7265. use SplDoublyLinkedList;
  7266. /**
  7267. * @final
  7268. */
  7269. class SplDoublyLinkedListFilter implements \PHPUnit\DeepCopy\TypeFilter\TypeFilter
  7270. {
  7271. private $copier;
  7272. public function __construct(\PHPUnit\DeepCopy\DeepCopy $copier)
  7273. {
  7274. $this->copier = $copier;
  7275. }
  7276. /**
  7277. * {@inheritdoc}
  7278. */
  7279. public function apply($element)
  7280. {
  7281. $newElement = clone $element;
  7282. $copy = $this->createCopyClosure();
  7283. return $copy($newElement);
  7284. }
  7285. private function createCopyClosure()
  7286. {
  7287. $copier = $this->copier;
  7288. $copy = function (\SplDoublyLinkedList $list) use($copier) {
  7289. // Replace each element in the list with a deep copy of itself
  7290. for ($i = 1; $i <= $list->count(); $i++) {
  7291. $copy = $copier->recursiveCopy($list->shift());
  7292. $list->push($copy);
  7293. }
  7294. return $list;
  7295. };
  7296. return \Closure::bind($copy, null, \PHPUnit\DeepCopy\DeepCopy::class);
  7297. }
  7298. }
  7299. <?php
  7300. namespace PHPUnit\DeepCopy\TypeFilter;
  7301. /**
  7302. * @final
  7303. */
  7304. class ShallowCopyFilter implements \PHPUnit\DeepCopy\TypeFilter\TypeFilter
  7305. {
  7306. /**
  7307. * {@inheritdoc}
  7308. */
  7309. public function apply($element)
  7310. {
  7311. return clone $element;
  7312. }
  7313. }
  7314. <?php
  7315. namespace PHPUnit\DeepCopy\TypeFilter\Date;
  7316. use DateInterval;
  7317. use PHPUnit\DeepCopy\TypeFilter\TypeFilter;
  7318. /**
  7319. * @final
  7320. *
  7321. * @deprecated Will be removed in 2.0. This filter will no longer be necessary in PHP 7.1+.
  7322. */
  7323. class DateIntervalFilter implements \PHPUnit\DeepCopy\TypeFilter\TypeFilter
  7324. {
  7325. /**
  7326. * {@inheritdoc}
  7327. *
  7328. * @param DateInterval $element
  7329. *
  7330. * @see http://news.php.net/php.bugs/205076
  7331. */
  7332. public function apply($element)
  7333. {
  7334. $copy = new \DateInterval('P0D');
  7335. foreach ($element as $propertyName => $propertyValue) {
  7336. $copy->{$propertyName} = $propertyValue;
  7337. }
  7338. return $copy;
  7339. }
  7340. }
  7341. <?php
  7342. namespace PHPUnit\DeepCopy\Reflection;
  7343. use PHPUnit\DeepCopy\Exception\PropertyException;
  7344. use ReflectionClass;
  7345. use ReflectionException;
  7346. use ReflectionObject;
  7347. use ReflectionProperty;
  7348. class ReflectionHelper
  7349. {
  7350. /**
  7351. * Retrieves all properties (including private ones), from object and all its ancestors.
  7352. *
  7353. * Standard \ReflectionClass->getProperties() does not return private properties from ancestor classes.
  7354. *
  7355. * @author muratyaman@gmail.com
  7356. * @see http://php.net/manual/en/reflectionclass.getproperties.php
  7357. *
  7358. * @param ReflectionClass $ref
  7359. *
  7360. * @return ReflectionProperty[]
  7361. */
  7362. public static function getProperties(\ReflectionClass $ref)
  7363. {
  7364. $props = $ref->getProperties();
  7365. $propsArr = array();
  7366. foreach ($props as $prop) {
  7367. $propertyName = $prop->getName();
  7368. $propsArr[$propertyName] = $prop;
  7369. }
  7370. if ($parentClass = $ref->getParentClass()) {
  7371. $parentPropsArr = self::getProperties($parentClass);
  7372. foreach ($propsArr as $key => $property) {
  7373. $parentPropsArr[$key] = $property;
  7374. }
  7375. return $parentPropsArr;
  7376. }
  7377. return $propsArr;
  7378. }
  7379. /**
  7380. * Retrieves property by name from object and all its ancestors.
  7381. *
  7382. * @param object|string $object
  7383. * @param string $name
  7384. *
  7385. * @throws PropertyException
  7386. * @throws ReflectionException
  7387. *
  7388. * @return ReflectionProperty
  7389. */
  7390. public static function getProperty($object, $name)
  7391. {
  7392. $reflection = \is_object($object) ? new \ReflectionObject($object) : new \ReflectionClass($object);
  7393. if ($reflection->hasProperty($name)) {
  7394. return $reflection->getProperty($name);
  7395. }
  7396. if ($parentClass = $reflection->getParentClass()) {
  7397. return self::getProperty($parentClass->getName(), $name);
  7398. }
  7399. throw new \PHPUnit\DeepCopy\Exception\PropertyException(\sprintf('The class "%s" doesn\'t have a property with the given name: "%s".', \is_object($object) ? \get_class($object) : $object, $name));
  7400. }
  7401. }
  7402. <?php
  7403. namespace PHPUnit\DeepCopy;
  7404. use ArrayObject;
  7405. use DateInterval;
  7406. use DateTimeInterface;
  7407. use DateTimeZone;
  7408. use PHPUnit\DeepCopy\Exception\CloneException;
  7409. use PHPUnit\DeepCopy\Filter\Filter;
  7410. use PHPUnit\DeepCopy\Matcher\Matcher;
  7411. use PHPUnit\DeepCopy\Reflection\ReflectionHelper;
  7412. use PHPUnit\DeepCopy\TypeFilter\Date\DateIntervalFilter;
  7413. use PHPUnit\DeepCopy\TypeFilter\Spl\ArrayObjectFilter;
  7414. use PHPUnit\DeepCopy\TypeFilter\Spl\SplDoublyLinkedListFilter;
  7415. use PHPUnit\DeepCopy\TypeFilter\TypeFilter;
  7416. use PHPUnit\DeepCopy\TypeMatcher\TypeMatcher;
  7417. use ReflectionObject;
  7418. use ReflectionProperty;
  7419. use SplDoublyLinkedList;
  7420. /**
  7421. * @final
  7422. */
  7423. class DeepCopy
  7424. {
  7425. /**
  7426. * @var object[] List of objects copied.
  7427. */
  7428. private $hashMap = [];
  7429. /**
  7430. * Filters to apply.
  7431. *
  7432. * @var array Array of ['filter' => Filter, 'matcher' => Matcher] pairs.
  7433. */
  7434. private $filters = [];
  7435. /**
  7436. * Type Filters to apply.
  7437. *
  7438. * @var array Array of ['filter' => Filter, 'matcher' => Matcher] pairs.
  7439. */
  7440. private $typeFilters = [];
  7441. /**
  7442. * @var bool
  7443. */
  7444. private $skipUncloneable = \false;
  7445. /**
  7446. * @var bool
  7447. */
  7448. private $useCloneMethod;
  7449. /**
  7450. * @param bool $useCloneMethod If set to true, when an object implements the __clone() function, it will be used
  7451. * instead of the regular deep cloning.
  7452. */
  7453. public function __construct($useCloneMethod = \false)
  7454. {
  7455. $this->useCloneMethod = $useCloneMethod;
  7456. $this->addTypeFilter(new \PHPUnit\DeepCopy\TypeFilter\Spl\ArrayObjectFilter($this), new \PHPUnit\DeepCopy\TypeMatcher\TypeMatcher(\ArrayObject::class));
  7457. $this->addTypeFilter(new \PHPUnit\DeepCopy\TypeFilter\Date\DateIntervalFilter(), new \PHPUnit\DeepCopy\TypeMatcher\TypeMatcher(\DateInterval::class));
  7458. $this->addTypeFilter(new \PHPUnit\DeepCopy\TypeFilter\Spl\SplDoublyLinkedListFilter($this), new \PHPUnit\DeepCopy\TypeMatcher\TypeMatcher(\SplDoublyLinkedList::class));
  7459. }
  7460. /**
  7461. * If enabled, will not throw an exception when coming across an uncloneable property.
  7462. *
  7463. * @param $skipUncloneable
  7464. *
  7465. * @return $this
  7466. */
  7467. public function skipUncloneable($skipUncloneable = \true)
  7468. {
  7469. $this->skipUncloneable = $skipUncloneable;
  7470. return $this;
  7471. }
  7472. /**
  7473. * Deep copies the given object.
  7474. *
  7475. * @param mixed $object
  7476. *
  7477. * @return mixed
  7478. */
  7479. public function copy($object)
  7480. {
  7481. $this->hashMap = [];
  7482. return $this->recursiveCopy($object);
  7483. }
  7484. public function addFilter(\PHPUnit\DeepCopy\Filter\Filter $filter, \PHPUnit\DeepCopy\Matcher\Matcher $matcher)
  7485. {
  7486. $this->filters[] = ['matcher' => $matcher, 'filter' => $filter];
  7487. }
  7488. public function prependFilter(\PHPUnit\DeepCopy\Filter\Filter $filter, \PHPUnit\DeepCopy\Matcher\Matcher $matcher)
  7489. {
  7490. \array_unshift($this->filters, ['matcher' => $matcher, 'filter' => $filter]);
  7491. }
  7492. public function addTypeFilter(\PHPUnit\DeepCopy\TypeFilter\TypeFilter $filter, \PHPUnit\DeepCopy\TypeMatcher\TypeMatcher $matcher)
  7493. {
  7494. $this->typeFilters[] = ['matcher' => $matcher, 'filter' => $filter];
  7495. }
  7496. private function recursiveCopy($var)
  7497. {
  7498. // Matches Type Filter
  7499. if ($filter = $this->getFirstMatchedTypeFilter($this->typeFilters, $var)) {
  7500. return $filter->apply($var);
  7501. }
  7502. // Resource
  7503. if (\is_resource($var)) {
  7504. return $var;
  7505. }
  7506. // Array
  7507. if (\is_array($var)) {
  7508. return $this->copyArray($var);
  7509. }
  7510. // Scalar
  7511. if (!\is_object($var)) {
  7512. return $var;
  7513. }
  7514. // Object
  7515. return $this->copyObject($var);
  7516. }
  7517. /**
  7518. * Copy an array
  7519. * @param array $array
  7520. * @return array
  7521. */
  7522. private function copyArray(array $array)
  7523. {
  7524. foreach ($array as $key => $value) {
  7525. $array[$key] = $this->recursiveCopy($value);
  7526. }
  7527. return $array;
  7528. }
  7529. /**
  7530. * Copies an object.
  7531. *
  7532. * @param object $object
  7533. *
  7534. * @throws CloneException
  7535. *
  7536. * @return object
  7537. */
  7538. private function copyObject($object)
  7539. {
  7540. $objectHash = \spl_object_hash($object);
  7541. if (isset($this->hashMap[$objectHash])) {
  7542. return $this->hashMap[$objectHash];
  7543. }
  7544. $reflectedObject = new \ReflectionObject($object);
  7545. $isCloneable = $reflectedObject->isCloneable();
  7546. if (\false === $isCloneable) {
  7547. if ($this->skipUncloneable) {
  7548. $this->hashMap[$objectHash] = $object;
  7549. return $object;
  7550. }
  7551. throw new \PHPUnit\DeepCopy\Exception\CloneException(\sprintf('The class "%s" is not cloneable.', $reflectedObject->getName()));
  7552. }
  7553. $newObject = clone $object;
  7554. $this->hashMap[$objectHash] = $newObject;
  7555. if ($this->useCloneMethod && $reflectedObject->hasMethod('__clone')) {
  7556. return $newObject;
  7557. }
  7558. if ($newObject instanceof \DateTimeInterface || $newObject instanceof \DateTimeZone) {
  7559. return $newObject;
  7560. }
  7561. foreach (\PHPUnit\DeepCopy\Reflection\ReflectionHelper::getProperties($reflectedObject) as $property) {
  7562. $this->copyObjectProperty($newObject, $property);
  7563. }
  7564. return $newObject;
  7565. }
  7566. private function copyObjectProperty($object, \ReflectionProperty $property)
  7567. {
  7568. // Ignore static properties
  7569. if ($property->isStatic()) {
  7570. return;
  7571. }
  7572. // Apply the filters
  7573. foreach ($this->filters as $item) {
  7574. /** @var Matcher $matcher */
  7575. $matcher = $item['matcher'];
  7576. /** @var Filter $filter */
  7577. $filter = $item['filter'];
  7578. if ($matcher->matches($object, $property->getName())) {
  7579. $filter->apply($object, $property->getName(), function ($object) {
  7580. return $this->recursiveCopy($object);
  7581. });
  7582. // If a filter matches, we stop processing this property
  7583. return;
  7584. }
  7585. }
  7586. $property->setAccessible(\true);
  7587. // Ignore uninitialized properties (for PHP >7.4)
  7588. if (\method_exists($property, 'isInitialized') && !$property->isInitialized($object)) {
  7589. return;
  7590. }
  7591. $propertyValue = $property->getValue($object);
  7592. // Copy the property
  7593. $property->setValue($object, $this->recursiveCopy($propertyValue));
  7594. }
  7595. /**
  7596. * Returns first filter that matches variable, `null` if no such filter found.
  7597. *
  7598. * @param array $filterRecords Associative array with 2 members: 'filter' with value of type {@see TypeFilter} and
  7599. * 'matcher' with value of type {@see TypeMatcher}
  7600. * @param mixed $var
  7601. *
  7602. * @return TypeFilter|null
  7603. */
  7604. private function getFirstMatchedTypeFilter(array $filterRecords, $var)
  7605. {
  7606. $matched = $this->first($filterRecords, function (array $record) use($var) {
  7607. /* @var TypeMatcher $matcher */
  7608. $matcher = $record['matcher'];
  7609. return $matcher->matches($var);
  7610. });
  7611. return isset($matched) ? $matched['filter'] : null;
  7612. }
  7613. /**
  7614. * Returns first element that matches predicate, `null` if no such element found.
  7615. *
  7616. * @param array $elements Array of ['filter' => Filter, 'matcher' => Matcher] pairs.
  7617. * @param callable $predicate Predicate arguments are: element.
  7618. *
  7619. * @return array|null Associative array with 2 members: 'filter' with value of type {@see TypeFilter} and 'matcher'
  7620. * with value of type {@see TypeMatcher} or `null`.
  7621. */
  7622. private function first(array $elements, callable $predicate)
  7623. {
  7624. foreach ($elements as $element) {
  7625. if (\call_user_func($predicate, $element)) {
  7626. return $element;
  7627. }
  7628. }
  7629. return null;
  7630. }
  7631. }
  7632. The MIT License (MIT)
  7633. Copyright (c) 2013 My C-Sense
  7634. Permission is hereby granted, free of charge, to any person obtaining a copy of
  7635. this software and associated documentation files (the "Software"), to deal in
  7636. the Software without restriction, including without limitation the rights to
  7637. use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
  7638. the Software, and to permit persons to whom the Software is furnished to do so,
  7639. subject to the following conditions:
  7640. The above copyright notice and this permission notice shall be included in all
  7641. copies or substantial portions of the Software.
  7642. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  7643. IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
  7644. FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
  7645. COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
  7646. IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  7647. CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  7648. <?php
  7649. declare (strict_types=1);
  7650. /*
  7651. * This file is part of sebastian/type.
  7652. *
  7653. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  7654. *
  7655. * For the full copyright and license information, please view the LICENSE
  7656. * file that was distributed with this source code.
  7657. */
  7658. namespace PHPUnit\SebastianBergmann\Type;
  7659. final class UnknownType extends \PHPUnit\SebastianBergmann\Type\Type
  7660. {
  7661. public function isAssignable(\PHPUnit\SebastianBergmann\Type\Type $other) : bool
  7662. {
  7663. return \true;
  7664. }
  7665. public function name() : string
  7666. {
  7667. return 'unknown type';
  7668. }
  7669. public function asString() : string
  7670. {
  7671. return '';
  7672. }
  7673. /**
  7674. * @deprecated
  7675. *
  7676. * @codeCoverageIgnore
  7677. */
  7678. public function getReturnTypeDeclaration() : string
  7679. {
  7680. return '';
  7681. }
  7682. public function allowsNull() : bool
  7683. {
  7684. return \true;
  7685. }
  7686. }
  7687. <?php
  7688. declare (strict_types=1);
  7689. /*
  7690. * This file is part of sebastian/type.
  7691. *
  7692. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  7693. *
  7694. * For the full copyright and license information, please view the LICENSE
  7695. * file that was distributed with this source code.
  7696. */
  7697. namespace PHPUnit\SebastianBergmann\Type;
  7698. final class GenericObjectType extends \PHPUnit\SebastianBergmann\Type\Type
  7699. {
  7700. /**
  7701. * @var bool
  7702. */
  7703. private $allowsNull;
  7704. public function __construct(bool $nullable)
  7705. {
  7706. $this->allowsNull = $nullable;
  7707. }
  7708. public function isAssignable(\PHPUnit\SebastianBergmann\Type\Type $other) : bool
  7709. {
  7710. if ($this->allowsNull && $other instanceof \PHPUnit\SebastianBergmann\Type\NullType) {
  7711. return \true;
  7712. }
  7713. if (!$other instanceof \PHPUnit\SebastianBergmann\Type\ObjectType) {
  7714. return \false;
  7715. }
  7716. return \true;
  7717. }
  7718. public function name() : string
  7719. {
  7720. return 'object';
  7721. }
  7722. public function allowsNull() : bool
  7723. {
  7724. return $this->allowsNull;
  7725. }
  7726. }
  7727. <?php
  7728. declare (strict_types=1);
  7729. /*
  7730. * This file is part of sebastian/type.
  7731. *
  7732. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  7733. *
  7734. * For the full copyright and license information, please view the LICENSE
  7735. * file that was distributed with this source code.
  7736. */
  7737. namespace PHPUnit\SebastianBergmann\Type;
  7738. final class UnionType extends \PHPUnit\SebastianBergmann\Type\Type
  7739. {
  7740. /**
  7741. * @psalm-var list<Type>
  7742. */
  7743. private $types;
  7744. /**
  7745. * @throws RuntimeException
  7746. */
  7747. public function __construct(\PHPUnit\SebastianBergmann\Type\Type ...$types)
  7748. {
  7749. $this->ensureMinimumOfTwoTypes(...$types);
  7750. $this->ensureOnlyValidTypes(...$types);
  7751. $this->types = $types;
  7752. }
  7753. public function isAssignable(\PHPUnit\SebastianBergmann\Type\Type $other) : bool
  7754. {
  7755. foreach ($this->types as $type) {
  7756. if ($type->isAssignable($other)) {
  7757. return \true;
  7758. }
  7759. }
  7760. return \false;
  7761. }
  7762. public function asString() : string
  7763. {
  7764. return $this->name();
  7765. }
  7766. /**
  7767. * @deprecated
  7768. *
  7769. * @codeCoverageIgnore
  7770. */
  7771. public function getReturnTypeDeclaration() : string
  7772. {
  7773. return ': ' . $this->name();
  7774. }
  7775. public function name() : string
  7776. {
  7777. $types = [];
  7778. foreach ($this->types as $type) {
  7779. $types[] = $type->name();
  7780. }
  7781. \sort($types);
  7782. return \implode('|', $types);
  7783. }
  7784. public function allowsNull() : bool
  7785. {
  7786. foreach ($this->types as $type) {
  7787. if ($type instanceof \PHPUnit\SebastianBergmann\Type\NullType) {
  7788. return \true;
  7789. }
  7790. }
  7791. return \false;
  7792. }
  7793. /**
  7794. * @throws RuntimeException
  7795. */
  7796. private function ensureMinimumOfTwoTypes(\PHPUnit\SebastianBergmann\Type\Type ...$types) : void
  7797. {
  7798. if (\count($types) < 2) {
  7799. throw new \PHPUnit\SebastianBergmann\Type\RuntimeException('A union type must be composed of at least two types');
  7800. }
  7801. }
  7802. /**
  7803. * @throws RuntimeException
  7804. */
  7805. private function ensureOnlyValidTypes(\PHPUnit\SebastianBergmann\Type\Type ...$types) : void
  7806. {
  7807. foreach ($types as $type) {
  7808. if ($type instanceof \PHPUnit\SebastianBergmann\Type\UnknownType) {
  7809. throw new \PHPUnit\SebastianBergmann\Type\RuntimeException('A union type must not be composed of an unknown type');
  7810. }
  7811. if ($type instanceof \PHPUnit\SebastianBergmann\Type\VoidType) {
  7812. throw new \PHPUnit\SebastianBergmann\Type\RuntimeException('A union type must not be composed of a void type');
  7813. }
  7814. }
  7815. }
  7816. }
  7817. <?php
  7818. declare (strict_types=1);
  7819. /*
  7820. * This file is part of sebastian/type.
  7821. *
  7822. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  7823. *
  7824. * For the full copyright and license information, please view the LICENSE
  7825. * file that was distributed with this source code.
  7826. */
  7827. namespace PHPUnit\SebastianBergmann\Type;
  7828. final class CallableType extends \PHPUnit\SebastianBergmann\Type\Type
  7829. {
  7830. /**
  7831. * @var bool
  7832. */
  7833. private $allowsNull;
  7834. public function __construct(bool $nullable)
  7835. {
  7836. $this->allowsNull = $nullable;
  7837. }
  7838. /**
  7839. * @throws RuntimeException
  7840. */
  7841. public function isAssignable(\PHPUnit\SebastianBergmann\Type\Type $other) : bool
  7842. {
  7843. if ($this->allowsNull && $other instanceof \PHPUnit\SebastianBergmann\Type\NullType) {
  7844. return \true;
  7845. }
  7846. if ($other instanceof self) {
  7847. return \true;
  7848. }
  7849. if ($other instanceof \PHPUnit\SebastianBergmann\Type\ObjectType) {
  7850. if ($this->isClosure($other)) {
  7851. return \true;
  7852. }
  7853. if ($this->hasInvokeMethod($other)) {
  7854. return \true;
  7855. }
  7856. }
  7857. if ($other instanceof \PHPUnit\SebastianBergmann\Type\SimpleType) {
  7858. if ($this->isFunction($other)) {
  7859. return \true;
  7860. }
  7861. if ($this->isClassCallback($other)) {
  7862. return \true;
  7863. }
  7864. if ($this->isObjectCallback($other)) {
  7865. return \true;
  7866. }
  7867. }
  7868. return \false;
  7869. }
  7870. public function name() : string
  7871. {
  7872. return 'callable';
  7873. }
  7874. public function allowsNull() : bool
  7875. {
  7876. return $this->allowsNull;
  7877. }
  7878. private function isClosure(\PHPUnit\SebastianBergmann\Type\ObjectType $type) : bool
  7879. {
  7880. return !$type->className()->isNamespaced() && $type->className()->simpleName() === \Closure::class;
  7881. }
  7882. /**
  7883. * @throws RuntimeException
  7884. */
  7885. private function hasInvokeMethod(\PHPUnit\SebastianBergmann\Type\ObjectType $type) : bool
  7886. {
  7887. $className = $type->className()->qualifiedName();
  7888. \assert(\class_exists($className));
  7889. try {
  7890. $class = new \ReflectionClass($className);
  7891. // @codeCoverageIgnoreStart
  7892. } catch (\ReflectionException $e) {
  7893. throw new \PHPUnit\SebastianBergmann\Type\RuntimeException($e->getMessage(), (int) $e->getCode(), $e);
  7894. // @codeCoverageIgnoreEnd
  7895. }
  7896. if ($class->hasMethod('__invoke')) {
  7897. return \true;
  7898. }
  7899. return \false;
  7900. }
  7901. private function isFunction(\PHPUnit\SebastianBergmann\Type\SimpleType $type) : bool
  7902. {
  7903. if (!\is_string($type->value())) {
  7904. return \false;
  7905. }
  7906. return \function_exists($type->value());
  7907. }
  7908. private function isObjectCallback(\PHPUnit\SebastianBergmann\Type\SimpleType $type) : bool
  7909. {
  7910. if (!\is_array($type->value())) {
  7911. return \false;
  7912. }
  7913. if (\count($type->value()) !== 2) {
  7914. return \false;
  7915. }
  7916. if (!\is_object($type->value()[0]) || !\is_string($type->value()[1])) {
  7917. return \false;
  7918. }
  7919. [$object, $methodName] = $type->value();
  7920. return (new \ReflectionObject($object))->hasMethod($methodName);
  7921. }
  7922. private function isClassCallback(\PHPUnit\SebastianBergmann\Type\SimpleType $type) : bool
  7923. {
  7924. if (!\is_string($type->value()) && !\is_array($type->value())) {
  7925. return \false;
  7926. }
  7927. if (\is_string($type->value())) {
  7928. if (\strpos($type->value(), '::') === \false) {
  7929. return \false;
  7930. }
  7931. [$className, $methodName] = \explode('::', $type->value());
  7932. }
  7933. if (\is_array($type->value())) {
  7934. if (\count($type->value()) !== 2) {
  7935. return \false;
  7936. }
  7937. if (!\is_string($type->value()[0]) || !\is_string($type->value()[1])) {
  7938. return \false;
  7939. }
  7940. [$className, $methodName] = $type->value();
  7941. }
  7942. \assert(isset($className) && \is_string($className) && \class_exists($className));
  7943. \assert(isset($methodName) && \is_string($methodName));
  7944. try {
  7945. $class = new \ReflectionClass($className);
  7946. if ($class->hasMethod($methodName)) {
  7947. $method = $class->getMethod($methodName);
  7948. return $method->isPublic() && $method->isStatic();
  7949. }
  7950. // @codeCoverageIgnoreStart
  7951. } catch (\ReflectionException $e) {
  7952. throw new \PHPUnit\SebastianBergmann\Type\RuntimeException($e->getMessage(), (int) $e->getCode(), $e);
  7953. // @codeCoverageIgnoreEnd
  7954. }
  7955. return \false;
  7956. }
  7957. }
  7958. <?php
  7959. declare (strict_types=1);
  7960. /*
  7961. * This file is part of sebastian/type.
  7962. *
  7963. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  7964. *
  7965. * For the full copyright and license information, please view the LICENSE
  7966. * file that was distributed with this source code.
  7967. */
  7968. namespace PHPUnit\SebastianBergmann\Type;
  7969. final class VoidType extends \PHPUnit\SebastianBergmann\Type\Type
  7970. {
  7971. public function isAssignable(\PHPUnit\SebastianBergmann\Type\Type $other) : bool
  7972. {
  7973. return $other instanceof self;
  7974. }
  7975. public function name() : string
  7976. {
  7977. return 'void';
  7978. }
  7979. public function allowsNull() : bool
  7980. {
  7981. return \false;
  7982. }
  7983. }
  7984. <?php
  7985. declare (strict_types=1);
  7986. /*
  7987. * This file is part of sebastian/type.
  7988. *
  7989. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  7990. *
  7991. * For the full copyright and license information, please view the LICENSE
  7992. * file that was distributed with this source code.
  7993. */
  7994. namespace PHPUnit\SebastianBergmann\Type;
  7995. final class NullType extends \PHPUnit\SebastianBergmann\Type\Type
  7996. {
  7997. public function isAssignable(\PHPUnit\SebastianBergmann\Type\Type $other) : bool
  7998. {
  7999. return !$other instanceof \PHPUnit\SebastianBergmann\Type\VoidType;
  8000. }
  8001. public function name() : string
  8002. {
  8003. return 'null';
  8004. }
  8005. public function asString() : string
  8006. {
  8007. return 'null';
  8008. }
  8009. /**
  8010. * @deprecated
  8011. *
  8012. * @codeCoverageIgnore
  8013. */
  8014. public function getReturnTypeDeclaration() : string
  8015. {
  8016. return '';
  8017. }
  8018. public function allowsNull() : bool
  8019. {
  8020. return \true;
  8021. }
  8022. }
  8023. <?php
  8024. declare (strict_types=1);
  8025. /*
  8026. * This file is part of sebastian/type.
  8027. *
  8028. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  8029. *
  8030. * For the full copyright and license information, please view the LICENSE
  8031. * file that was distributed with this source code.
  8032. */
  8033. namespace PHPUnit\SebastianBergmann\Type;
  8034. final class ObjectType extends \PHPUnit\SebastianBergmann\Type\Type
  8035. {
  8036. /**
  8037. * @var TypeName
  8038. */
  8039. private $className;
  8040. /**
  8041. * @var bool
  8042. */
  8043. private $allowsNull;
  8044. public function __construct(\PHPUnit\SebastianBergmann\Type\TypeName $className, bool $allowsNull)
  8045. {
  8046. $this->className = $className;
  8047. $this->allowsNull = $allowsNull;
  8048. }
  8049. public function isAssignable(\PHPUnit\SebastianBergmann\Type\Type $other) : bool
  8050. {
  8051. if ($this->allowsNull && $other instanceof \PHPUnit\SebastianBergmann\Type\NullType) {
  8052. return \true;
  8053. }
  8054. if ($other instanceof self) {
  8055. if (0 === \strcasecmp($this->className->qualifiedName(), $other->className->qualifiedName())) {
  8056. return \true;
  8057. }
  8058. if (\is_subclass_of($other->className->qualifiedName(), $this->className->qualifiedName(), \true)) {
  8059. return \true;
  8060. }
  8061. }
  8062. return \false;
  8063. }
  8064. public function name() : string
  8065. {
  8066. return $this->className->qualifiedName();
  8067. }
  8068. public function allowsNull() : bool
  8069. {
  8070. return $this->allowsNull;
  8071. }
  8072. public function className() : \PHPUnit\SebastianBergmann\Type\TypeName
  8073. {
  8074. return $this->className;
  8075. }
  8076. }
  8077. <?php
  8078. declare (strict_types=1);
  8079. /*
  8080. * This file is part of sebastian/type.
  8081. *
  8082. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  8083. *
  8084. * For the full copyright and license information, please view the LICENSE
  8085. * file that was distributed with this source code.
  8086. */
  8087. namespace PHPUnit\SebastianBergmann\Type;
  8088. final class SimpleType extends \PHPUnit\SebastianBergmann\Type\Type
  8089. {
  8090. /**
  8091. * @var string
  8092. */
  8093. private $name;
  8094. /**
  8095. * @var bool
  8096. */
  8097. private $allowsNull;
  8098. /**
  8099. * @var mixed
  8100. */
  8101. private $value;
  8102. public function __construct(string $name, bool $nullable, $value = null)
  8103. {
  8104. $this->name = $this->normalize($name);
  8105. $this->allowsNull = $nullable;
  8106. $this->value = $value;
  8107. }
  8108. public function isAssignable(\PHPUnit\SebastianBergmann\Type\Type $other) : bool
  8109. {
  8110. if ($this->allowsNull && $other instanceof \PHPUnit\SebastianBergmann\Type\NullType) {
  8111. return \true;
  8112. }
  8113. if ($other instanceof self) {
  8114. return $this->name === $other->name;
  8115. }
  8116. return \false;
  8117. }
  8118. public function name() : string
  8119. {
  8120. return $this->name;
  8121. }
  8122. public function allowsNull() : bool
  8123. {
  8124. return $this->allowsNull;
  8125. }
  8126. public function value()
  8127. {
  8128. return $this->value;
  8129. }
  8130. private function normalize(string $name) : string
  8131. {
  8132. $name = \strtolower($name);
  8133. switch ($name) {
  8134. case 'boolean':
  8135. return 'bool';
  8136. case 'real':
  8137. case 'double':
  8138. return 'float';
  8139. case 'integer':
  8140. return 'int';
  8141. case '[]':
  8142. return 'array';
  8143. default:
  8144. return $name;
  8145. }
  8146. }
  8147. }
  8148. <?php
  8149. declare (strict_types=1);
  8150. /*
  8151. * This file is part of sebastian/type.
  8152. *
  8153. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  8154. *
  8155. * For the full copyright and license information, please view the LICENSE
  8156. * file that was distributed with this source code.
  8157. */
  8158. namespace PHPUnit\SebastianBergmann\Type;
  8159. final class TypeName
  8160. {
  8161. /**
  8162. * @var ?string
  8163. */
  8164. private $namespaceName;
  8165. /**
  8166. * @var string
  8167. */
  8168. private $simpleName;
  8169. public static function fromQualifiedName(string $fullClassName) : self
  8170. {
  8171. if ($fullClassName[0] === '\\') {
  8172. $fullClassName = \substr($fullClassName, 1);
  8173. }
  8174. $classNameParts = \explode('\\', $fullClassName);
  8175. $simpleName = \array_pop($classNameParts);
  8176. $namespaceName = \implode('\\', $classNameParts);
  8177. return new self($namespaceName, $simpleName);
  8178. }
  8179. public static function fromReflection(\ReflectionClass $type) : self
  8180. {
  8181. return new self($type->getNamespaceName(), $type->getShortName());
  8182. }
  8183. public function __construct(?string $namespaceName, string $simpleName)
  8184. {
  8185. if ($namespaceName === '') {
  8186. $namespaceName = null;
  8187. }
  8188. $this->namespaceName = $namespaceName;
  8189. $this->simpleName = $simpleName;
  8190. }
  8191. public function namespaceName() : ?string
  8192. {
  8193. return $this->namespaceName;
  8194. }
  8195. public function simpleName() : string
  8196. {
  8197. return $this->simpleName;
  8198. }
  8199. public function qualifiedName() : string
  8200. {
  8201. return $this->namespaceName === null ? $this->simpleName : $this->namespaceName . '\\' . $this->simpleName;
  8202. }
  8203. /**
  8204. * @deprecated Use namespaceName() instead
  8205. *
  8206. * @codeCoverageIgnore
  8207. */
  8208. public function getNamespaceName() : ?string
  8209. {
  8210. return $this->namespaceName();
  8211. }
  8212. /**
  8213. * @deprecated Use simpleName() instead
  8214. *
  8215. * @codeCoverageIgnore
  8216. */
  8217. public function getSimpleName() : string
  8218. {
  8219. return $this->simpleName();
  8220. }
  8221. /**
  8222. * @deprecated Use qualifiedName() instead
  8223. *
  8224. * @codeCoverageIgnore
  8225. */
  8226. public function getQualifiedName() : string
  8227. {
  8228. return $this->qualifiedName();
  8229. }
  8230. public function isNamespaced() : bool
  8231. {
  8232. return $this->namespaceName !== null;
  8233. }
  8234. }
  8235. <?php
  8236. declare (strict_types=1);
  8237. /*
  8238. * This file is part of sebastian/type.
  8239. *
  8240. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  8241. *
  8242. * For the full copyright and license information, please view the LICENSE
  8243. * file that was distributed with this source code.
  8244. */
  8245. namespace PHPUnit\SebastianBergmann\Type;
  8246. final class ReflectionMapper
  8247. {
  8248. public function fromMethodReturnType(\ReflectionMethod $method) : \PHPUnit\SebastianBergmann\Type\Type
  8249. {
  8250. if (!$method->hasReturnType()) {
  8251. return new \PHPUnit\SebastianBergmann\Type\UnknownType();
  8252. }
  8253. $returnType = $method->getReturnType();
  8254. \assert($returnType instanceof \ReflectionNamedType || $returnType instanceof \ReflectionUnionType);
  8255. if ($returnType instanceof \ReflectionNamedType) {
  8256. if ($returnType->getName() === 'self') {
  8257. return \PHPUnit\SebastianBergmann\Type\ObjectType::fromName($method->getDeclaringClass()->getName(), $returnType->allowsNull());
  8258. }
  8259. if ($returnType->getName() === 'parent') {
  8260. $parentClass = $method->getDeclaringClass()->getParentClass();
  8261. // @codeCoverageIgnoreStart
  8262. if ($parentClass === \false) {
  8263. throw new \PHPUnit\SebastianBergmann\Type\RuntimeException(\sprintf('%s::%s() has a "parent" return type declaration but %s does not have a parent class', $method->getDeclaringClass()->getName(), $method->getName(), $method->getDeclaringClass()->getName()));
  8264. }
  8265. // @codeCoverageIgnoreEnd
  8266. return \PHPUnit\SebastianBergmann\Type\ObjectType::fromName($parentClass->getName(), $returnType->allowsNull());
  8267. }
  8268. return \PHPUnit\SebastianBergmann\Type\Type::fromName($returnType->getName(), $returnType->allowsNull());
  8269. }
  8270. $types = [];
  8271. foreach ($returnType->getTypes() as $type) {
  8272. if ($type->getName() === 'self') {
  8273. $types[] = \PHPUnit\SebastianBergmann\Type\ObjectType::fromName($method->getDeclaringClass()->getName(), \false);
  8274. } else {
  8275. $types[] = \PHPUnit\SebastianBergmann\Type\Type::fromName($type->getName(), \false);
  8276. }
  8277. }
  8278. return new \PHPUnit\SebastianBergmann\Type\UnionType(...$types);
  8279. }
  8280. }
  8281. <?php
  8282. declare (strict_types=1);
  8283. /*
  8284. * This file is part of sebastian/type.
  8285. *
  8286. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  8287. *
  8288. * For the full copyright and license information, please view the LICENSE
  8289. * file that was distributed with this source code.
  8290. */
  8291. namespace PHPUnit\SebastianBergmann\Type;
  8292. final class IterableType extends \PHPUnit\SebastianBergmann\Type\Type
  8293. {
  8294. /**
  8295. * @var bool
  8296. */
  8297. private $allowsNull;
  8298. public function __construct(bool $nullable)
  8299. {
  8300. $this->allowsNull = $nullable;
  8301. }
  8302. /**
  8303. * @throws RuntimeException
  8304. */
  8305. public function isAssignable(\PHPUnit\SebastianBergmann\Type\Type $other) : bool
  8306. {
  8307. if ($this->allowsNull && $other instanceof \PHPUnit\SebastianBergmann\Type\NullType) {
  8308. return \true;
  8309. }
  8310. if ($other instanceof self) {
  8311. return \true;
  8312. }
  8313. if ($other instanceof \PHPUnit\SebastianBergmann\Type\SimpleType) {
  8314. return \is_iterable($other->value());
  8315. }
  8316. if ($other instanceof \PHPUnit\SebastianBergmann\Type\ObjectType) {
  8317. $className = $other->className()->qualifiedName();
  8318. \assert(\class_exists($className));
  8319. try {
  8320. return (new \ReflectionClass($className))->isIterable();
  8321. // @codeCoverageIgnoreStart
  8322. } catch (\ReflectionException $e) {
  8323. throw new \PHPUnit\SebastianBergmann\Type\RuntimeException($e->getMessage(), (int) $e->getCode(), $e);
  8324. // @codeCoverageIgnoreEnd
  8325. }
  8326. }
  8327. return \false;
  8328. }
  8329. public function name() : string
  8330. {
  8331. return 'iterable';
  8332. }
  8333. public function allowsNull() : bool
  8334. {
  8335. return $this->allowsNull;
  8336. }
  8337. }
  8338. <?php
  8339. declare (strict_types=1);
  8340. /*
  8341. * This file is part of sebastian/type.
  8342. *
  8343. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  8344. *
  8345. * For the full copyright and license information, please view the LICENSE
  8346. * file that was distributed with this source code.
  8347. */
  8348. namespace PHPUnit\SebastianBergmann\Type;
  8349. abstract class Type
  8350. {
  8351. public static function fromValue($value, bool $allowsNull) : self
  8352. {
  8353. $typeName = \gettype($value);
  8354. if ($typeName === 'object') {
  8355. return new \PHPUnit\SebastianBergmann\Type\ObjectType(\PHPUnit\SebastianBergmann\Type\TypeName::fromQualifiedName(\get_class($value)), $allowsNull);
  8356. }
  8357. $type = self::fromName($typeName, $allowsNull);
  8358. if ($type instanceof \PHPUnit\SebastianBergmann\Type\SimpleType) {
  8359. $type = new \PHPUnit\SebastianBergmann\Type\SimpleType($typeName, $allowsNull, $value);
  8360. }
  8361. return $type;
  8362. }
  8363. public static function fromName(string $typeName, bool $allowsNull) : self
  8364. {
  8365. switch (\strtolower($typeName)) {
  8366. case 'callable':
  8367. return new \PHPUnit\SebastianBergmann\Type\CallableType($allowsNull);
  8368. case 'iterable':
  8369. return new \PHPUnit\SebastianBergmann\Type\IterableType($allowsNull);
  8370. case 'null':
  8371. return new \PHPUnit\SebastianBergmann\Type\NullType();
  8372. case 'object':
  8373. return new \PHPUnit\SebastianBergmann\Type\GenericObjectType($allowsNull);
  8374. case 'unknown type':
  8375. return new \PHPUnit\SebastianBergmann\Type\UnknownType();
  8376. case 'void':
  8377. return new \PHPUnit\SebastianBergmann\Type\VoidType();
  8378. case 'array':
  8379. case 'bool':
  8380. case 'boolean':
  8381. case 'double':
  8382. case 'float':
  8383. case 'int':
  8384. case 'integer':
  8385. case 'real':
  8386. case 'resource':
  8387. case 'resource (closed)':
  8388. case 'string':
  8389. return new \PHPUnit\SebastianBergmann\Type\SimpleType($typeName, $allowsNull);
  8390. default:
  8391. return new \PHPUnit\SebastianBergmann\Type\ObjectType(\PHPUnit\SebastianBergmann\Type\TypeName::fromQualifiedName($typeName), $allowsNull);
  8392. }
  8393. }
  8394. public function asString() : string
  8395. {
  8396. return ($this->allowsNull() ? '?' : '') . $this->name();
  8397. }
  8398. /**
  8399. * @deprecated
  8400. *
  8401. * @codeCoverageIgnore
  8402. */
  8403. public function getReturnTypeDeclaration() : string
  8404. {
  8405. return ': ' . $this->asString();
  8406. }
  8407. public abstract function isAssignable(\PHPUnit\SebastianBergmann\Type\Type $other) : bool;
  8408. public abstract function name() : string;
  8409. public abstract function allowsNull() : bool;
  8410. }
  8411. sebastian/type
  8412. Copyright (c) 2019-2020, Sebastian Bergmann <sebastian@phpunit.de>.
  8413. All rights reserved.
  8414. Redistribution and use in source and binary forms, with or without
  8415. modification, are permitted provided that the following conditions
  8416. are met:
  8417. * Redistributions of source code must retain the above copyright
  8418. notice, this list of conditions and the following disclaimer.
  8419. * Redistributions in binary form must reproduce the above copyright
  8420. notice, this list of conditions and the following disclaimer in
  8421. the documentation and/or other materials provided with the
  8422. distribution.
  8423. * Neither the name of Sebastian Bergmann nor the names of his
  8424. contributors may be used to endorse or promote products derived
  8425. from this software without specific prior written permission.
  8426. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  8427. "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  8428. LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  8429. FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  8430. COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  8431. INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  8432. BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  8433. LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  8434. CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  8435. LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
  8436. ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  8437. POSSIBILITY OF SUCH DAMAGE.
  8438. <?php
  8439. declare (strict_types=1);
  8440. /*
  8441. * This file is part of sebastian/type.
  8442. *
  8443. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  8444. *
  8445. * For the full copyright and license information, please view the LICENSE
  8446. * file that was distributed with this source code.
  8447. */
  8448. namespace PHPUnit\SebastianBergmann\Type;
  8449. final class RuntimeException extends \RuntimeException implements \PHPUnit\SebastianBergmann\Type\Exception
  8450. {
  8451. }
  8452. <?php
  8453. declare (strict_types=1);
  8454. /*
  8455. * This file is part of sebastian/type.
  8456. *
  8457. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  8458. *
  8459. * For the full copyright and license information, please view the LICENSE
  8460. * file that was distributed with this source code.
  8461. */
  8462. namespace PHPUnit\SebastianBergmann\Type;
  8463. interface Exception
  8464. {
  8465. }
  8466. <?php
  8467. /*
  8468. * This file is part of sebastian/version.
  8469. *
  8470. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  8471. *
  8472. * For the full copyright and license information, please view the LICENSE
  8473. * file that was distributed with this source code.
  8474. */
  8475. namespace PHPUnit\SebastianBergmann;
  8476. final class Version
  8477. {
  8478. /**
  8479. * @var string
  8480. */
  8481. private $path;
  8482. /**
  8483. * @var string
  8484. */
  8485. private $release;
  8486. /**
  8487. * @var string
  8488. */
  8489. private $version;
  8490. public function __construct(string $release, string $path)
  8491. {
  8492. $this->release = $release;
  8493. $this->path = $path;
  8494. }
  8495. public function getVersion() : string
  8496. {
  8497. if ($this->version === null) {
  8498. if (\substr_count($this->release, '.') + 1 === 3) {
  8499. $this->version = $this->release;
  8500. } else {
  8501. $this->version = $this->release . '-dev';
  8502. }
  8503. $git = $this->getGitInformation($this->path);
  8504. if ($git) {
  8505. if (\substr_count($this->release, '.') + 1 === 3) {
  8506. $this->version = $git;
  8507. } else {
  8508. $git = \explode('-', $git);
  8509. $this->version = $this->release . '-' . \end($git);
  8510. }
  8511. }
  8512. }
  8513. return $this->version;
  8514. }
  8515. /**
  8516. * @return bool|string
  8517. */
  8518. private function getGitInformation(string $path)
  8519. {
  8520. if (!\is_dir($path . \DIRECTORY_SEPARATOR . '.git')) {
  8521. return \false;
  8522. }
  8523. $process = \proc_open('git describe --tags', [1 => ['pipe', 'w'], 2 => ['pipe', 'w']], $pipes, $path);
  8524. if (!\is_resource($process)) {
  8525. return \false;
  8526. }
  8527. $result = \trim(\stream_get_contents($pipes[1]));
  8528. \fclose($pipes[1]);
  8529. \fclose($pipes[2]);
  8530. $returnCode = \proc_close($process);
  8531. if ($returnCode !== 0) {
  8532. return \false;
  8533. }
  8534. return $result;
  8535. }
  8536. }
  8537. Version
  8538. Copyright (c) 2013-2020, Sebastian Bergmann <sebastian@phpunit.de>.
  8539. All rights reserved.
  8540. Redistribution and use in source and binary forms, with or without
  8541. modification, are permitted provided that the following conditions
  8542. are met:
  8543. * Redistributions of source code must retain the above copyright
  8544. notice, this list of conditions and the following disclaimer.
  8545. * Redistributions in binary form must reproduce the above copyright
  8546. notice, this list of conditions and the following disclaimer in
  8547. the documentation and/or other materials provided with the
  8548. distribution.
  8549. * Neither the name of Sebastian Bergmann nor the names of his
  8550. contributors may be used to endorse or promote products derived
  8551. from this software without specific prior written permission.
  8552. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  8553. "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  8554. LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  8555. FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  8556. COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  8557. INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  8558. BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  8559. LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  8560. CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  8561. LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
  8562. ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  8563. POSSIBILITY OF SUCH DAMAGE.
  8564. <?php
  8565. declare (strict_types=1);
  8566. /**
  8567. * This file is part of phpDocumentor.
  8568. *
  8569. * For the full copyright and license information, please view the LICENSE
  8570. * file that was distributed with this source code.
  8571. *
  8572. * @link http://phpdoc.org
  8573. */
  8574. namespace PHPUnit\phpDocumentor\Reflection\DocBlock;
  8575. use InvalidArgumentException;
  8576. use PHPUnit\phpDocumentor\Reflection\DocBlock\Tags\Author;
  8577. use PHPUnit\phpDocumentor\Reflection\DocBlock\Tags\Covers;
  8578. use PHPUnit\phpDocumentor\Reflection\DocBlock\Tags\Deprecated;
  8579. use PHPUnit\phpDocumentor\Reflection\DocBlock\Tags\Factory\StaticMethod;
  8580. use PHPUnit\phpDocumentor\Reflection\DocBlock\Tags\Generic;
  8581. use PHPUnit\phpDocumentor\Reflection\DocBlock\Tags\InvalidTag;
  8582. use PHPUnit\phpDocumentor\Reflection\DocBlock\Tags\Link as LinkTag;
  8583. use PHPUnit\phpDocumentor\Reflection\DocBlock\Tags\Method;
  8584. use PHPUnit\phpDocumentor\Reflection\DocBlock\Tags\Param;
  8585. use PHPUnit\phpDocumentor\Reflection\DocBlock\Tags\Property;
  8586. use PHPUnit\phpDocumentor\Reflection\DocBlock\Tags\PropertyRead;
  8587. use PHPUnit\phpDocumentor\Reflection\DocBlock\Tags\PropertyWrite;
  8588. use PHPUnit\phpDocumentor\Reflection\DocBlock\Tags\Return_;
  8589. use PHPUnit\phpDocumentor\Reflection\DocBlock\Tags\See as SeeTag;
  8590. use PHPUnit\phpDocumentor\Reflection\DocBlock\Tags\Since;
  8591. use PHPUnit\phpDocumentor\Reflection\DocBlock\Tags\Source;
  8592. use PHPUnit\phpDocumentor\Reflection\DocBlock\Tags\Throws;
  8593. use PHPUnit\phpDocumentor\Reflection\DocBlock\Tags\Uses;
  8594. use PHPUnit\phpDocumentor\Reflection\DocBlock\Tags\Var_;
  8595. use PHPUnit\phpDocumentor\Reflection\DocBlock\Tags\Version;
  8596. use PHPUnit\phpDocumentor\Reflection\FqsenResolver;
  8597. use PHPUnit\phpDocumentor\Reflection\Types\Context as TypeContext;
  8598. use ReflectionMethod;
  8599. use ReflectionParameter;
  8600. use PHPUnit\Webmozart\Assert\Assert;
  8601. use function array_merge;
  8602. use function array_slice;
  8603. use function call_user_func_array;
  8604. use function count;
  8605. use function get_class;
  8606. use function preg_match;
  8607. use function strpos;
  8608. use function trim;
  8609. /**
  8610. * Creates a Tag object given the contents of a tag.
  8611. *
  8612. * This Factory is capable of determining the appropriate class for a tag and instantiate it using its `create`
  8613. * factory method. The `create` factory method of a Tag can have a variable number of arguments; this way you can
  8614. * pass the dependencies that you need to construct a tag object.
  8615. *
  8616. * > Important: each parameter in addition to the body variable for the `create` method must default to null, otherwise
  8617. * > it violates the constraint with the interface; it is recommended to use the {@see Assert::notNull()} method to
  8618. * > verify that a dependency is actually passed.
  8619. *
  8620. * This Factory also features a Service Locator component that is used to pass the right dependencies to the
  8621. * `create` method of a tag; each dependency should be registered as a service or as a parameter.
  8622. *
  8623. * When you want to use a Tag of your own with custom handling you need to call the `registerTagHandler` method, pass
  8624. * the name of the tag and a Fully Qualified Class Name pointing to a class that implements the Tag interface.
  8625. */
  8626. final class StandardTagFactory implements \PHPUnit\phpDocumentor\Reflection\DocBlock\TagFactory
  8627. {
  8628. /** PCRE regular expression matching a tag name. */
  8629. public const REGEX_TAGNAME = '[\\w\\-\\_\\\\:]+';
  8630. /**
  8631. * @var array<class-string<Tag>> An array with a tag as a key, and an
  8632. * FQCN to a class that handles it as an array value.
  8633. */
  8634. private $tagHandlerMappings = [
  8635. 'author' => \PHPUnit\phpDocumentor\Reflection\DocBlock\Tags\Author::class,
  8636. 'covers' => \PHPUnit\phpDocumentor\Reflection\DocBlock\Tags\Covers::class,
  8637. 'deprecated' => \PHPUnit\phpDocumentor\Reflection\DocBlock\Tags\Deprecated::class,
  8638. // 'example' => '\phpDocumentor\Reflection\DocBlock\Tags\Example',
  8639. 'link' => \PHPUnit\phpDocumentor\Reflection\DocBlock\Tags\Link::class,
  8640. 'method' => \PHPUnit\phpDocumentor\Reflection\DocBlock\Tags\Method::class,
  8641. 'param' => \PHPUnit\phpDocumentor\Reflection\DocBlock\Tags\Param::class,
  8642. 'property-read' => \PHPUnit\phpDocumentor\Reflection\DocBlock\Tags\PropertyRead::class,
  8643. 'property' => \PHPUnit\phpDocumentor\Reflection\DocBlock\Tags\Property::class,
  8644. 'property-write' => \PHPUnit\phpDocumentor\Reflection\DocBlock\Tags\PropertyWrite::class,
  8645. 'return' => \PHPUnit\phpDocumentor\Reflection\DocBlock\Tags\Return_::class,
  8646. 'see' => \PHPUnit\phpDocumentor\Reflection\DocBlock\Tags\See::class,
  8647. 'since' => \PHPUnit\phpDocumentor\Reflection\DocBlock\Tags\Since::class,
  8648. 'source' => \PHPUnit\phpDocumentor\Reflection\DocBlock\Tags\Source::class,
  8649. 'throw' => \PHPUnit\phpDocumentor\Reflection\DocBlock\Tags\Throws::class,
  8650. 'throws' => \PHPUnit\phpDocumentor\Reflection\DocBlock\Tags\Throws::class,
  8651. 'uses' => \PHPUnit\phpDocumentor\Reflection\DocBlock\Tags\Uses::class,
  8652. 'var' => \PHPUnit\phpDocumentor\Reflection\DocBlock\Tags\Var_::class,
  8653. 'version' => \PHPUnit\phpDocumentor\Reflection\DocBlock\Tags\Version::class,
  8654. ];
  8655. /**
  8656. * @var array<class-string<Tag>> An array with a anotation s a key, and an
  8657. * FQCN to a class that handles it as an array value.
  8658. */
  8659. private $annotationMappings = [];
  8660. /**
  8661. * @var ReflectionParameter[][] a lazy-loading cache containing parameters
  8662. * for each tagHandler that has been used.
  8663. */
  8664. private $tagHandlerParameterCache = [];
  8665. /** @var FqsenResolver */
  8666. private $fqsenResolver;
  8667. /**
  8668. * @var mixed[] an array representing a simple Service Locator where we can store parameters and
  8669. * services that can be inserted into the Factory Methods of Tag Handlers.
  8670. */
  8671. private $serviceLocator = [];
  8672. /**
  8673. * Initialize this tag factory with the means to resolve an FQSEN and optionally a list of tag handlers.
  8674. *
  8675. * If no tag handlers are provided than the default list in the {@see self::$tagHandlerMappings} property
  8676. * is used.
  8677. *
  8678. * @see self::registerTagHandler() to add a new tag handler to the existing default list.
  8679. *
  8680. * @param array<class-string<Tag>> $tagHandlers
  8681. */
  8682. public function __construct(\PHPUnit\phpDocumentor\Reflection\FqsenResolver $fqsenResolver, ?array $tagHandlers = null)
  8683. {
  8684. $this->fqsenResolver = $fqsenResolver;
  8685. if ($tagHandlers !== null) {
  8686. $this->tagHandlerMappings = $tagHandlers;
  8687. }
  8688. $this->addService($fqsenResolver, \PHPUnit\phpDocumentor\Reflection\FqsenResolver::class);
  8689. }
  8690. public function create(string $tagLine, ?\PHPUnit\phpDocumentor\Reflection\Types\Context $context = null) : \PHPUnit\phpDocumentor\Reflection\DocBlock\Tag
  8691. {
  8692. if (!$context) {
  8693. $context = new \PHPUnit\phpDocumentor\Reflection\Types\Context('');
  8694. }
  8695. [$tagName, $tagBody] = $this->extractTagParts($tagLine);
  8696. return $this->createTag(\trim($tagBody), $tagName, $context);
  8697. }
  8698. /**
  8699. * @param mixed $value
  8700. */
  8701. public function addParameter(string $name, $value) : void
  8702. {
  8703. $this->serviceLocator[$name] = $value;
  8704. }
  8705. public function addService(object $service, ?string $alias = null) : void
  8706. {
  8707. $this->serviceLocator[$alias ?: \get_class($service)] = $service;
  8708. }
  8709. public function registerTagHandler(string $tagName, string $handler) : void
  8710. {
  8711. \PHPUnit\Webmozart\Assert\Assert::stringNotEmpty($tagName);
  8712. \PHPUnit\Webmozart\Assert\Assert::classExists($handler);
  8713. \PHPUnit\Webmozart\Assert\Assert::implementsInterface($handler, \PHPUnit\phpDocumentor\Reflection\DocBlock\Tags\Factory\StaticMethod::class);
  8714. if (\strpos($tagName, '\\') && $tagName[0] !== '\\') {
  8715. throw new \InvalidArgumentException('A namespaced tag must have a leading backslash as it must be fully qualified');
  8716. }
  8717. $this->tagHandlerMappings[$tagName] = $handler;
  8718. }
  8719. /**
  8720. * Extracts all components for a tag.
  8721. *
  8722. * @return string[]
  8723. */
  8724. private function extractTagParts(string $tagLine) : array
  8725. {
  8726. $matches = [];
  8727. if (!\preg_match('/^@(' . self::REGEX_TAGNAME . ')((?:[\\s\\(\\{])\\s*([^\\s].*)|$)/us', $tagLine, $matches)) {
  8728. throw new \InvalidArgumentException('The tag "' . $tagLine . '" does not seem to be wellformed, please check it for errors');
  8729. }
  8730. if (\count($matches) < 3) {
  8731. $matches[] = '';
  8732. }
  8733. return \array_slice($matches, 1);
  8734. }
  8735. /**
  8736. * Creates a new tag object with the given name and body or returns null if the tag name was recognized but the
  8737. * body was invalid.
  8738. */
  8739. private function createTag(string $body, string $name, \PHPUnit\phpDocumentor\Reflection\Types\Context $context) : \PHPUnit\phpDocumentor\Reflection\DocBlock\Tag
  8740. {
  8741. $handlerClassName = $this->findHandlerClassName($name, $context);
  8742. $arguments = $this->getArgumentsForParametersFromWiring($this->fetchParametersForHandlerFactoryMethod($handlerClassName), $this->getServiceLocatorWithDynamicParameters($context, $name, $body));
  8743. try {
  8744. $callable = [$handlerClassName, 'create'];
  8745. \PHPUnit\Webmozart\Assert\Assert::isCallable($callable);
  8746. /** @phpstan-var callable(string): ?Tag $callable */
  8747. $tag = \call_user_func_array($callable, $arguments);
  8748. return $tag ?? \PHPUnit\phpDocumentor\Reflection\DocBlock\Tags\InvalidTag::create($body, $name);
  8749. } catch (\InvalidArgumentException $e) {
  8750. return \PHPUnit\phpDocumentor\Reflection\DocBlock\Tags\InvalidTag::create($body, $name)->withError($e);
  8751. }
  8752. }
  8753. /**
  8754. * Determines the Fully Qualified Class Name of the Factory or Tag (containing a Factory Method `create`).
  8755. *
  8756. * @return class-string<Tag>
  8757. */
  8758. private function findHandlerClassName(string $tagName, \PHPUnit\phpDocumentor\Reflection\Types\Context $context) : string
  8759. {
  8760. $handlerClassName = \PHPUnit\phpDocumentor\Reflection\DocBlock\Tags\Generic::class;
  8761. if (isset($this->tagHandlerMappings[$tagName])) {
  8762. $handlerClassName = $this->tagHandlerMappings[$tagName];
  8763. } elseif ($this->isAnnotation($tagName)) {
  8764. // TODO: Annotation support is planned for a later stage and as such is disabled for now
  8765. $tagName = (string) $this->fqsenResolver->resolve($tagName, $context);
  8766. if (isset($this->annotationMappings[$tagName])) {
  8767. $handlerClassName = $this->annotationMappings[$tagName];
  8768. }
  8769. }
  8770. return $handlerClassName;
  8771. }
  8772. /**
  8773. * Retrieves the arguments that need to be passed to the Factory Method with the given Parameters.
  8774. *
  8775. * @param ReflectionParameter[] $parameters
  8776. * @param mixed[] $locator
  8777. *
  8778. * @return mixed[] A series of values that can be passed to the Factory Method of the tag whose parameters
  8779. * is provided with this method.
  8780. */
  8781. private function getArgumentsForParametersFromWiring(array $parameters, array $locator) : array
  8782. {
  8783. $arguments = [];
  8784. foreach ($parameters as $parameter) {
  8785. $class = $parameter->getClass();
  8786. $typeHint = null;
  8787. if ($class !== null) {
  8788. $typeHint = $class->getName();
  8789. }
  8790. if (isset($locator[$typeHint])) {
  8791. $arguments[] = $locator[$typeHint];
  8792. continue;
  8793. }
  8794. $parameterName = $parameter->getName();
  8795. if (isset($locator[$parameterName])) {
  8796. $arguments[] = $locator[$parameterName];
  8797. continue;
  8798. }
  8799. $arguments[] = null;
  8800. }
  8801. return $arguments;
  8802. }
  8803. /**
  8804. * Retrieves a series of ReflectionParameter objects for the static 'create' method of the given
  8805. * tag handler class name.
  8806. *
  8807. * @return ReflectionParameter[]
  8808. */
  8809. private function fetchParametersForHandlerFactoryMethod(string $handlerClassName) : array
  8810. {
  8811. if (!isset($this->tagHandlerParameterCache[$handlerClassName])) {
  8812. $methodReflection = new \ReflectionMethod($handlerClassName, 'create');
  8813. $this->tagHandlerParameterCache[$handlerClassName] = $methodReflection->getParameters();
  8814. }
  8815. return $this->tagHandlerParameterCache[$handlerClassName];
  8816. }
  8817. /**
  8818. * Returns a copy of this class' Service Locator with added dynamic parameters,
  8819. * such as the tag's name, body and Context.
  8820. *
  8821. * @param TypeContext $context The Context (namespace and aliasses) that may be
  8822. * passed and is used to resolve FQSENs.
  8823. * @param string $tagName The name of the tag that may be
  8824. * passed onto the factory method of the Tag class.
  8825. * @param string $tagBody The body of the tag that may be
  8826. * passed onto the factory method of the Tag class.
  8827. *
  8828. * @return mixed[]
  8829. */
  8830. private function getServiceLocatorWithDynamicParameters(\PHPUnit\phpDocumentor\Reflection\Types\Context $context, string $tagName, string $tagBody) : array
  8831. {
  8832. return \array_merge($this->serviceLocator, ['name' => $tagName, 'body' => $tagBody, \PHPUnit\phpDocumentor\Reflection\Types\Context::class => $context]);
  8833. }
  8834. /**
  8835. * Returns whether the given tag belongs to an annotation.
  8836. *
  8837. * @todo this method should be populated once we implement Annotation notation support.
  8838. */
  8839. private function isAnnotation(string $tagContent) : bool
  8840. {
  8841. // 1. Contains a namespace separator
  8842. // 2. Contains parenthesis
  8843. // 3. Is present in a list of known annotations (make the algorithm smart by first checking is the last part
  8844. // of the annotation class name matches the found tag name
  8845. return \false;
  8846. }
  8847. }
  8848. <?php
  8849. declare (strict_types=1);
  8850. /**
  8851. * This file is part of phpDocumentor.
  8852. *
  8853. * For the full copyright and license information, please view the LICENSE
  8854. * file that was distributed with this source code.
  8855. *
  8856. * @link http://phpdoc.org
  8857. */
  8858. namespace PHPUnit\phpDocumentor\Reflection\DocBlock;
  8859. use PHPUnit\phpDocumentor\Reflection\DocBlock;
  8860. use PHPUnit\phpDocumentor\Reflection\DocBlock\Tags\Formatter;
  8861. use PHPUnit\phpDocumentor\Reflection\DocBlock\Tags\Formatter\PassthroughFormatter;
  8862. use function sprintf;
  8863. use function str_repeat;
  8864. use function str_replace;
  8865. use function strlen;
  8866. use function wordwrap;
  8867. /**
  8868. * Converts a DocBlock back from an object to a complete DocComment including Asterisks.
  8869. */
  8870. class Serializer
  8871. {
  8872. /** @var string The string to indent the comment with. */
  8873. protected $indentString = ' ';
  8874. /** @var int The number of times the indent string is repeated. */
  8875. protected $indent = 0;
  8876. /** @var bool Whether to indent the first line with the given indent amount and string. */
  8877. protected $isFirstLineIndented = \true;
  8878. /** @var int|null The max length of a line. */
  8879. protected $lineLength;
  8880. /** @var Formatter A custom tag formatter. */
  8881. protected $tagFormatter;
  8882. /**
  8883. * Create a Serializer instance.
  8884. *
  8885. * @param int $indent The number of times the indent string is repeated.
  8886. * @param string $indentString The string to indent the comment with.
  8887. * @param bool $indentFirstLine Whether to indent the first line.
  8888. * @param int|null $lineLength The max length of a line or NULL to disable line wrapping.
  8889. * @param Formatter $tagFormatter A custom tag formatter, defaults to PassthroughFormatter.
  8890. */
  8891. public function __construct(int $indent = 0, string $indentString = ' ', bool $indentFirstLine = \true, ?int $lineLength = null, ?\PHPUnit\phpDocumentor\Reflection\DocBlock\Tags\Formatter $tagFormatter = null)
  8892. {
  8893. $this->indent = $indent;
  8894. $this->indentString = $indentString;
  8895. $this->isFirstLineIndented = $indentFirstLine;
  8896. $this->lineLength = $lineLength;
  8897. $this->tagFormatter = $tagFormatter ?: new \PHPUnit\phpDocumentor\Reflection\DocBlock\Tags\Formatter\PassthroughFormatter();
  8898. }
  8899. /**
  8900. * Generate a DocBlock comment.
  8901. *
  8902. * @param DocBlock $docblock The DocBlock to serialize.
  8903. *
  8904. * @return string The serialized doc block.
  8905. */
  8906. public function getDocComment(\PHPUnit\phpDocumentor\Reflection\DocBlock $docblock) : string
  8907. {
  8908. $indent = \str_repeat($this->indentString, $this->indent);
  8909. $firstIndent = $this->isFirstLineIndented ? $indent : '';
  8910. // 3 === strlen(' * ')
  8911. $wrapLength = $this->lineLength ? $this->lineLength - \strlen($indent) - 3 : null;
  8912. $text = $this->removeTrailingSpaces($indent, $this->addAsterisksForEachLine($indent, $this->getSummaryAndDescriptionTextBlock($docblock, $wrapLength)));
  8913. $comment = $firstIndent . "/**\n";
  8914. if ($text) {
  8915. $comment .= $indent . ' * ' . $text . "\n";
  8916. $comment .= $indent . " *\n";
  8917. }
  8918. $comment = $this->addTagBlock($docblock, $wrapLength, $indent, $comment);
  8919. return $comment . $indent . ' */';
  8920. }
  8921. private function removeTrailingSpaces(string $indent, string $text) : string
  8922. {
  8923. return \str_replace(\sprintf("\n%s * \n", $indent), \sprintf("\n%s *\n", $indent), $text);
  8924. }
  8925. private function addAsterisksForEachLine(string $indent, string $text) : string
  8926. {
  8927. return \str_replace("\n", \sprintf("\n%s * ", $indent), $text);
  8928. }
  8929. private function getSummaryAndDescriptionTextBlock(\PHPUnit\phpDocumentor\Reflection\DocBlock $docblock, ?int $wrapLength) : string
  8930. {
  8931. $text = $docblock->getSummary() . ((string) $docblock->getDescription() ? "\n\n" . $docblock->getDescription() : '');
  8932. if ($wrapLength !== null) {
  8933. $text = \wordwrap($text, $wrapLength);
  8934. return $text;
  8935. }
  8936. return $text;
  8937. }
  8938. private function addTagBlock(\PHPUnit\phpDocumentor\Reflection\DocBlock $docblock, ?int $wrapLength, string $indent, string $comment) : string
  8939. {
  8940. foreach ($docblock->getTags() as $tag) {
  8941. $tagText = $this->tagFormatter->format($tag);
  8942. if ($wrapLength !== null) {
  8943. $tagText = \wordwrap($tagText, $wrapLength);
  8944. }
  8945. $tagText = \str_replace("\n", \sprintf("\n%s * ", $indent), $tagText);
  8946. $comment .= \sprintf("%s * %s\n", $indent, $tagText);
  8947. }
  8948. return $comment;
  8949. }
  8950. }
  8951. <?php
  8952. declare (strict_types=1);
  8953. /**
  8954. * This file is part of phpDocumentor.
  8955. *
  8956. * For the full copyright and license information, please view the LICENSE
  8957. * file that was distributed with this source code.
  8958. *
  8959. * @link http://phpdoc.org
  8960. */
  8961. namespace PHPUnit\phpDocumentor\Reflection\DocBlock;
  8962. use InvalidArgumentException;
  8963. use PHPUnit\phpDocumentor\Reflection\Types\Context as TypeContext;
  8964. interface TagFactory
  8965. {
  8966. /**
  8967. * Adds a parameter to the service locator that can be injected in a tag's factory method.
  8968. *
  8969. * When calling a tag's "create" method we always check the signature for dependencies to inject. One way is to
  8970. * typehint a parameter in the signature so that we can use that interface or class name to inject a dependency
  8971. * (see {@see addService()} for more information on that).
  8972. *
  8973. * Another way is to check the name of the argument against the names in the Service Locator. With this method
  8974. * you can add a variable that will be inserted when a tag's create method is not typehinted and has a matching
  8975. * name.
  8976. *
  8977. * Be aware that there are two reserved names:
  8978. *
  8979. * - name, representing the name of the tag.
  8980. * - body, representing the complete body of the tag.
  8981. *
  8982. * These parameters are injected at the last moment and will override any existing parameter with those names.
  8983. *
  8984. * @param mixed $value
  8985. */
  8986. public function addParameter(string $name, $value) : void;
  8987. /**
  8988. * Factory method responsible for instantiating the correct sub type.
  8989. *
  8990. * @param string $tagLine The text for this tag, including description.
  8991. *
  8992. * @return Tag A new tag object.
  8993. *
  8994. * @throws InvalidArgumentException If an invalid tag line was presented.
  8995. */
  8996. public function create(string $tagLine, ?\PHPUnit\phpDocumentor\Reflection\Types\Context $context = null) : \PHPUnit\phpDocumentor\Reflection\DocBlock\Tag;
  8997. /**
  8998. * Registers a service with the Service Locator using the FQCN of the class or the alias, if provided.
  8999. *
  9000. * When calling a tag's "create" method we always check the signature for dependencies to inject. If a parameter
  9001. * has a typehint then the ServiceLocator is queried to see if a Service is registered for that typehint.
  9002. *
  9003. * Because interfaces are regularly used as type-hints this method provides an alias parameter; if the FQCN of the
  9004. * interface is passed as alias then every time that interface is requested the provided service will be returned.
  9005. */
  9006. public function addService(object $service) : void;
  9007. /**
  9008. * Registers a handler for tags.
  9009. *
  9010. * If you want to use your own tags then you can use this method to instruct the TagFactory
  9011. * to register the name of a tag with the FQCN of a 'Tag Handler'. The Tag handler should implement
  9012. * the {@see Tag} interface (and thus the create method).
  9013. *
  9014. * @param string $tagName Name of tag to register a handler for. When registering a namespaced
  9015. * tag, the full name, along with a prefixing slash MUST be provided.
  9016. * @param class-string<Tag> $handler FQCN of handler.
  9017. *
  9018. * @throws InvalidArgumentException If the tag name is not a string.
  9019. * @throws InvalidArgumentException If the tag name is namespaced (contains backslashes) but
  9020. * does not start with a backslash.
  9021. * @throws InvalidArgumentException If the handler is not a string.
  9022. * @throws InvalidArgumentException If the handler is not an existing class.
  9023. * @throws InvalidArgumentException If the handler does not implement the {@see Tag} interface.
  9024. */
  9025. public function registerTagHandler(string $tagName, string $handler) : void;
  9026. }
  9027. <?php
  9028. declare (strict_types=1);
  9029. /**
  9030. * This file is part of phpDocumentor.
  9031. *
  9032. * For the full copyright and license information, please view the LICENSE
  9033. * file that was distributed with this source code.
  9034. *
  9035. * @link http://phpdoc.org
  9036. */
  9037. namespace PHPUnit\phpDocumentor\Reflection\DocBlock\Tags;
  9038. use PHPUnit\phpDocumentor\Reflection\DocBlock\Description;
  9039. use PHPUnit\phpDocumentor\Reflection\DocBlock\DescriptionFactory;
  9040. use PHPUnit\phpDocumentor\Reflection\DocBlock\Tags\Reference\Fqsen as FqsenRef;
  9041. use PHPUnit\phpDocumentor\Reflection\DocBlock\Tags\Reference\Reference;
  9042. use PHPUnit\phpDocumentor\Reflection\DocBlock\Tags\Reference\Url;
  9043. use PHPUnit\phpDocumentor\Reflection\FqsenResolver;
  9044. use PHPUnit\phpDocumentor\Reflection\Types\Context as TypeContext;
  9045. use PHPUnit\Webmozart\Assert\Assert;
  9046. use function preg_match;
  9047. use function preg_split;
  9048. /**
  9049. * Reflection class for an {@}see tag in a Docblock.
  9050. */
  9051. final class See extends \PHPUnit\phpDocumentor\Reflection\DocBlock\Tags\BaseTag implements \PHPUnit\phpDocumentor\Reflection\DocBlock\Tags\Factory\StaticMethod
  9052. {
  9053. /** @var string */
  9054. protected $name = 'see';
  9055. /** @var Reference */
  9056. protected $refers;
  9057. /**
  9058. * Initializes this tag.
  9059. */
  9060. public function __construct(\PHPUnit\phpDocumentor\Reflection\DocBlock\Tags\Reference\Reference $refers, ?\PHPUnit\phpDocumentor\Reflection\DocBlock\Description $description = null)
  9061. {
  9062. $this->refers = $refers;
  9063. $this->description = $description;
  9064. }
  9065. public static function create(string $body, ?\PHPUnit\phpDocumentor\Reflection\FqsenResolver $typeResolver = null, ?\PHPUnit\phpDocumentor\Reflection\DocBlock\DescriptionFactory $descriptionFactory = null, ?\PHPUnit\phpDocumentor\Reflection\Types\Context $context = null) : self
  9066. {
  9067. \PHPUnit\Webmozart\Assert\Assert::notNull($typeResolver);
  9068. \PHPUnit\Webmozart\Assert\Assert::notNull($descriptionFactory);
  9069. $parts = \preg_split('/\\s+/Su', $body, 2);
  9070. \PHPUnit\Webmozart\Assert\Assert::isArray($parts);
  9071. $description = isset($parts[1]) ? $descriptionFactory->create($parts[1], $context) : null;
  9072. // https://tools.ietf.org/html/rfc2396#section-3
  9073. if (\preg_match('/\\w:\\/\\/\\w/i', $parts[0])) {
  9074. return new static(new \PHPUnit\phpDocumentor\Reflection\DocBlock\Tags\Reference\Url($parts[0]), $description);
  9075. }
  9076. return new static(new \PHPUnit\phpDocumentor\Reflection\DocBlock\Tags\Reference\Fqsen($typeResolver->resolve($parts[0], $context)), $description);
  9077. }
  9078. /**
  9079. * Returns the ref of this tag.
  9080. */
  9081. public function getReference() : \PHPUnit\phpDocumentor\Reflection\DocBlock\Tags\Reference\Reference
  9082. {
  9083. return $this->refers;
  9084. }
  9085. /**
  9086. * Returns a string representation of this tag.
  9087. */
  9088. public function __toString() : string
  9089. {
  9090. return $this->refers . ($this->description ? ' ' . $this->description->render() : '');
  9091. }
  9092. }
  9093. <?php
  9094. declare (strict_types=1);
  9095. /**
  9096. * This file is part of phpDocumentor.
  9097. *
  9098. * For the full copyright and license information, please view the LICENSE
  9099. * file that was distributed with this source code.
  9100. *
  9101. * @link http://phpdoc.org
  9102. */
  9103. namespace PHPUnit\phpDocumentor\Reflection\DocBlock\Tags;
  9104. use InvalidArgumentException;
  9105. use PHPUnit\phpDocumentor\Reflection\DocBlock\Description;
  9106. use PHPUnit\phpDocumentor\Reflection\DocBlock\DescriptionFactory;
  9107. use PHPUnit\phpDocumentor\Reflection\DocBlock\StandardTagFactory;
  9108. use PHPUnit\phpDocumentor\Reflection\Types\Context as TypeContext;
  9109. use PHPUnit\Webmozart\Assert\Assert;
  9110. use function preg_match;
  9111. /**
  9112. * Parses a tag definition for a DocBlock.
  9113. */
  9114. final class Generic extends \PHPUnit\phpDocumentor\Reflection\DocBlock\Tags\BaseTag implements \PHPUnit\phpDocumentor\Reflection\DocBlock\Tags\Factory\StaticMethod
  9115. {
  9116. /**
  9117. * Parses a tag and populates the member variables.
  9118. *
  9119. * @param string $name Name of the tag.
  9120. * @param Description $description The contents of the given tag.
  9121. */
  9122. public function __construct(string $name, ?\PHPUnit\phpDocumentor\Reflection\DocBlock\Description $description = null)
  9123. {
  9124. $this->validateTagName($name);
  9125. $this->name = $name;
  9126. $this->description = $description;
  9127. }
  9128. /**
  9129. * Creates a new tag that represents any unknown tag type.
  9130. *
  9131. * @return static
  9132. */
  9133. public static function create(string $body, string $name = '', ?\PHPUnit\phpDocumentor\Reflection\DocBlock\DescriptionFactory $descriptionFactory = null, ?\PHPUnit\phpDocumentor\Reflection\Types\Context $context = null) : self
  9134. {
  9135. \PHPUnit\Webmozart\Assert\Assert::stringNotEmpty($name);
  9136. \PHPUnit\Webmozart\Assert\Assert::notNull($descriptionFactory);
  9137. $description = $body !== '' ? $descriptionFactory->create($body, $context) : null;
  9138. return new static($name, $description);
  9139. }
  9140. /**
  9141. * Returns the tag as a serialized string
  9142. */
  9143. public function __toString() : string
  9144. {
  9145. return $this->description ? $this->description->render() : '';
  9146. }
  9147. /**
  9148. * Validates if the tag name matches the expected format, otherwise throws an exception.
  9149. */
  9150. private function validateTagName(string $name) : void
  9151. {
  9152. if (!\preg_match('/^' . \PHPUnit\phpDocumentor\Reflection\DocBlock\StandardTagFactory::REGEX_TAGNAME . '$/u', $name)) {
  9153. throw new \InvalidArgumentException('The tag name "' . $name . '" is not wellformed. Tags may only consist of letters, underscores, ' . 'hyphens and backslashes.');
  9154. }
  9155. }
  9156. }
  9157. <?php
  9158. declare (strict_types=1);
  9159. namespace PHPUnit\phpDocumentor\Reflection\DocBlock\Tags;
  9160. use Closure;
  9161. use Exception;
  9162. use PHPUnit\phpDocumentor\Reflection\DocBlock\Tag;
  9163. use ReflectionClass;
  9164. use ReflectionFunction;
  9165. use Throwable;
  9166. use function array_map;
  9167. use function array_walk_recursive;
  9168. use function get_class;
  9169. use function get_resource_type;
  9170. use function is_object;
  9171. use function is_resource;
  9172. use function sprintf;
  9173. /**
  9174. * This class represents an exception during the tag creation
  9175. *
  9176. * Since the internals of the library are relaying on the correct syntax of a docblock
  9177. * we cannot simply throw exceptions at all time because the exceptions will break the creation of a
  9178. * docklock. Just silently ignore the exceptions is not an option because the user as an issue to fix.
  9179. *
  9180. * This tag holds that error information until a using application is able to display it. The object wil just behave
  9181. * like any normal tag. So the normal application flow will not break.
  9182. */
  9183. final class InvalidTag implements \PHPUnit\phpDocumentor\Reflection\DocBlock\Tag
  9184. {
  9185. /** @var string */
  9186. private $name;
  9187. /** @var string */
  9188. private $body;
  9189. /** @var Throwable|null */
  9190. private $throwable;
  9191. private function __construct(string $name, string $body)
  9192. {
  9193. $this->name = $name;
  9194. $this->body = $body;
  9195. }
  9196. public function getException() : ?\Throwable
  9197. {
  9198. return $this->throwable;
  9199. }
  9200. public function getName() : string
  9201. {
  9202. return $this->name;
  9203. }
  9204. public static function create(string $body, string $name = '') : self
  9205. {
  9206. return new self($name, $body);
  9207. }
  9208. public function withError(\Throwable $exception) : self
  9209. {
  9210. $this->flattenExceptionBacktrace($exception);
  9211. $tag = new self($this->name, $this->body);
  9212. $tag->throwable = $exception;
  9213. return $tag;
  9214. }
  9215. /**
  9216. * Removes all complex types from backtrace
  9217. *
  9218. * Not all objects are serializable. So we need to remove them from the
  9219. * stored exception to be sure that we do not break existing library usage.
  9220. */
  9221. private function flattenExceptionBacktrace(\Throwable $exception) : void
  9222. {
  9223. $traceProperty = (new \ReflectionClass(\Exception::class))->getProperty('trace');
  9224. $traceProperty->setAccessible(\true);
  9225. $flatten = static function (&$value) : void {
  9226. if ($value instanceof \Closure) {
  9227. $closureReflection = new \ReflectionFunction($value);
  9228. $value = \sprintf('(Closure at %s:%s)', $closureReflection->getFileName(), $closureReflection->getStartLine());
  9229. } elseif (\is_object($value)) {
  9230. $value = \sprintf('object(%s)', \get_class($value));
  9231. } elseif (\is_resource($value)) {
  9232. $value = \sprintf('resource(%s)', \get_resource_type($value));
  9233. }
  9234. };
  9235. do {
  9236. $trace = $exception->getTrace();
  9237. if (isset($trace[0]['args'])) {
  9238. $trace = \array_map(static function (array $call) use($flatten) : array {
  9239. \array_walk_recursive($call['args'], $flatten);
  9240. return $call;
  9241. }, $trace);
  9242. }
  9243. $traceProperty->setValue($exception, $trace);
  9244. $exception = $exception->getPrevious();
  9245. } while ($exception !== null);
  9246. $traceProperty->setAccessible(\false);
  9247. }
  9248. public function render(?\PHPUnit\phpDocumentor\Reflection\DocBlock\Tags\Formatter $formatter = null) : string
  9249. {
  9250. if ($formatter === null) {
  9251. $formatter = new \PHPUnit\phpDocumentor\Reflection\DocBlock\Tags\Formatter\PassthroughFormatter();
  9252. }
  9253. return $formatter->format($this);
  9254. }
  9255. public function __toString() : string
  9256. {
  9257. return $this->body;
  9258. }
  9259. }
  9260. <?php
  9261. declare (strict_types=1);
  9262. /**
  9263. * This file is part of phpDocumentor.
  9264. *
  9265. * For the full copyright and license information, please view the LICENSE
  9266. * file that was distributed with this source code.
  9267. *
  9268. * @link http://phpdoc.org
  9269. */
  9270. namespace PHPUnit\phpDocumentor\Reflection\DocBlock\Tags;
  9271. use PHPUnit\phpDocumentor\Reflection\DocBlock\Description;
  9272. use PHPUnit\phpDocumentor\Reflection\DocBlock\DescriptionFactory;
  9273. use PHPUnit\phpDocumentor\Reflection\Types\Context as TypeContext;
  9274. use PHPUnit\Webmozart\Assert\Assert;
  9275. use function preg_match;
  9276. /**
  9277. * Reflection class for a {@}source tag in a Docblock.
  9278. */
  9279. final class Source extends \PHPUnit\phpDocumentor\Reflection\DocBlock\Tags\BaseTag implements \PHPUnit\phpDocumentor\Reflection\DocBlock\Tags\Factory\StaticMethod
  9280. {
  9281. /** @var string */
  9282. protected $name = 'source';
  9283. /** @var int The starting line, relative to the structural element's location. */
  9284. private $startingLine;
  9285. /** @var int|null The number of lines, relative to the starting line. NULL means "to the end". */
  9286. private $lineCount;
  9287. /**
  9288. * @param int|string $startingLine should be a to int convertible value
  9289. * @param int|string|null $lineCount should be a to int convertible value
  9290. */
  9291. public function __construct($startingLine, $lineCount = null, ?\PHPUnit\phpDocumentor\Reflection\DocBlock\Description $description = null)
  9292. {
  9293. \PHPUnit\Webmozart\Assert\Assert::integerish($startingLine);
  9294. \PHPUnit\Webmozart\Assert\Assert::nullOrIntegerish($lineCount);
  9295. $this->startingLine = (int) $startingLine;
  9296. $this->lineCount = $lineCount !== null ? (int) $lineCount : null;
  9297. $this->description = $description;
  9298. }
  9299. public static function create(string $body, ?\PHPUnit\phpDocumentor\Reflection\DocBlock\DescriptionFactory $descriptionFactory = null, ?\PHPUnit\phpDocumentor\Reflection\Types\Context $context = null) : self
  9300. {
  9301. \PHPUnit\Webmozart\Assert\Assert::stringNotEmpty($body);
  9302. \PHPUnit\Webmozart\Assert\Assert::notNull($descriptionFactory);
  9303. $startingLine = 1;
  9304. $lineCount = null;
  9305. $description = null;
  9306. // Starting line / Number of lines / Description
  9307. if (\preg_match('/^([1-9]\\d*)\\s*(?:((?1))\\s+)?(.*)$/sux', $body, $matches)) {
  9308. $startingLine = (int) $matches[1];
  9309. if (isset($matches[2]) && $matches[2] !== '') {
  9310. $lineCount = (int) $matches[2];
  9311. }
  9312. $description = $matches[3];
  9313. }
  9314. return new static($startingLine, $lineCount, $descriptionFactory->create($description ?? '', $context));
  9315. }
  9316. /**
  9317. * Gets the starting line.
  9318. *
  9319. * @return int The starting line, relative to the structural element's
  9320. * location.
  9321. */
  9322. public function getStartingLine() : int
  9323. {
  9324. return $this->startingLine;
  9325. }
  9326. /**
  9327. * Returns the number of lines.
  9328. *
  9329. * @return int|null The number of lines, relative to the starting line. NULL
  9330. * means "to the end".
  9331. */
  9332. public function getLineCount() : ?int
  9333. {
  9334. return $this->lineCount;
  9335. }
  9336. public function __toString() : string
  9337. {
  9338. return $this->startingLine . ($this->lineCount !== null ? ' ' . $this->lineCount : '') . ($this->description ? ' ' . (string) $this->description : '');
  9339. }
  9340. }
  9341. <?php
  9342. declare (strict_types=1);
  9343. /**
  9344. * This file is part of phpDocumentor.
  9345. *
  9346. * For the full copyright and license information, please view the LICENSE
  9347. * file that was distributed with this source code.
  9348. *
  9349. * @link http://phpdoc.org
  9350. */
  9351. namespace PHPUnit\phpDocumentor\Reflection\DocBlock\Tags;
  9352. use InvalidArgumentException;
  9353. use PHPUnit\phpDocumentor\Reflection\DocBlock\Description;
  9354. use PHPUnit\phpDocumentor\Reflection\DocBlock\DescriptionFactory;
  9355. use PHPUnit\phpDocumentor\Reflection\Type;
  9356. use PHPUnit\phpDocumentor\Reflection\TypeResolver;
  9357. use PHPUnit\phpDocumentor\Reflection\Types\Context as TypeContext;
  9358. use PHPUnit\phpDocumentor\Reflection\Types\Mixed_;
  9359. use PHPUnit\phpDocumentor\Reflection\Types\Void_;
  9360. use PHPUnit\Webmozart\Assert\Assert;
  9361. use function array_keys;
  9362. use function explode;
  9363. use function implode;
  9364. use function is_string;
  9365. use function preg_match;
  9366. use function sort;
  9367. use function strpos;
  9368. use function substr;
  9369. use function trim;
  9370. use function var_export;
  9371. /**
  9372. * Reflection class for an {@}method in a Docblock.
  9373. */
  9374. final class Method extends \PHPUnit\phpDocumentor\Reflection\DocBlock\Tags\BaseTag implements \PHPUnit\phpDocumentor\Reflection\DocBlock\Tags\Factory\StaticMethod
  9375. {
  9376. /** @var string */
  9377. protected $name = 'method';
  9378. /** @var string */
  9379. private $methodName;
  9380. /**
  9381. * @phpstan-var array<int, array{name: string, type: Type}>
  9382. * @var array<int, array<string, Type|string>>
  9383. */
  9384. private $arguments;
  9385. /** @var bool */
  9386. private $isStatic;
  9387. /** @var Type */
  9388. private $returnType;
  9389. /**
  9390. * @param array<int, array<string, Type|string>> $arguments
  9391. *
  9392. * @phpstan-param array<int, array{name: string, type: Type}|string> $arguments
  9393. */
  9394. public function __construct(string $methodName, array $arguments = [], ?\PHPUnit\phpDocumentor\Reflection\Type $returnType = null, bool $static = \false, ?\PHPUnit\phpDocumentor\Reflection\DocBlock\Description $description = null)
  9395. {
  9396. \PHPUnit\Webmozart\Assert\Assert::stringNotEmpty($methodName);
  9397. if ($returnType === null) {
  9398. $returnType = new \PHPUnit\phpDocumentor\Reflection\Types\Void_();
  9399. }
  9400. $this->methodName = $methodName;
  9401. $this->arguments = $this->filterArguments($arguments);
  9402. $this->returnType = $returnType;
  9403. $this->isStatic = $static;
  9404. $this->description = $description;
  9405. }
  9406. public static function create(string $body, ?\PHPUnit\phpDocumentor\Reflection\TypeResolver $typeResolver = null, ?\PHPUnit\phpDocumentor\Reflection\DocBlock\DescriptionFactory $descriptionFactory = null, ?\PHPUnit\phpDocumentor\Reflection\Types\Context $context = null) : ?self
  9407. {
  9408. \PHPUnit\Webmozart\Assert\Assert::stringNotEmpty($body);
  9409. \PHPUnit\Webmozart\Assert\Assert::notNull($typeResolver);
  9410. \PHPUnit\Webmozart\Assert\Assert::notNull($descriptionFactory);
  9411. // 1. none or more whitespace
  9412. // 2. optionally the keyword "static" followed by whitespace
  9413. // 3. optionally a word with underscores followed by whitespace : as
  9414. // type for the return value
  9415. // 4. then optionally a word with underscores followed by () and
  9416. // whitespace : as method name as used by phpDocumentor
  9417. // 5. then a word with underscores, followed by ( and any character
  9418. // until a ) and whitespace : as method name with signature
  9419. // 6. any remaining text : as description
  9420. if (!\preg_match('/^
  9421. # Static keyword
  9422. # Declares a static method ONLY if type is also present
  9423. (?:
  9424. (static)
  9425. \\s+
  9426. )?
  9427. # Return type
  9428. (?:
  9429. (
  9430. (?:[\\w\\|_\\\\]*\\$this[\\w\\|_\\\\]*)
  9431. |
  9432. (?:
  9433. (?:[\\w\\|_\\\\]+)
  9434. # array notation
  9435. (?:\\[\\])*
  9436. )*+
  9437. )
  9438. \\s+
  9439. )?
  9440. # Method name
  9441. ([\\w_]+)
  9442. # Arguments
  9443. (?:
  9444. \\(([^\\)]*)\\)
  9445. )?
  9446. \\s*
  9447. # Description
  9448. (.*)
  9449. $/sux', $body, $matches)) {
  9450. return null;
  9451. }
  9452. [, $static, $returnType, $methodName, $argumentLines, $description] = $matches;
  9453. $static = $static === 'static';
  9454. if ($returnType === '') {
  9455. $returnType = 'void';
  9456. }
  9457. $returnType = $typeResolver->resolve($returnType, $context);
  9458. $description = $descriptionFactory->create($description, $context);
  9459. /** @phpstan-var array<int, array{name: string, type: Type}> $arguments */
  9460. $arguments = [];
  9461. if ($argumentLines !== '') {
  9462. $argumentsExploded = \explode(',', $argumentLines);
  9463. foreach ($argumentsExploded as $argument) {
  9464. $argument = \explode(' ', self::stripRestArg(\trim($argument)), 2);
  9465. if (\strpos($argument[0], '$') === 0) {
  9466. $argumentName = \substr($argument[0], 1);
  9467. $argumentType = new \PHPUnit\phpDocumentor\Reflection\Types\Mixed_();
  9468. } else {
  9469. $argumentType = $typeResolver->resolve($argument[0], $context);
  9470. $argumentName = '';
  9471. if (isset($argument[1])) {
  9472. $argument[1] = self::stripRestArg($argument[1]);
  9473. $argumentName = \substr($argument[1], 1);
  9474. }
  9475. }
  9476. $arguments[] = ['name' => $argumentName, 'type' => $argumentType];
  9477. }
  9478. }
  9479. return new static($methodName, $arguments, $returnType, $static, $description);
  9480. }
  9481. /**
  9482. * Retrieves the method name.
  9483. */
  9484. public function getMethodName() : string
  9485. {
  9486. return $this->methodName;
  9487. }
  9488. /**
  9489. * @return array<int, array<string, Type|string>>
  9490. *
  9491. * @phpstan-return array<int, array{name: string, type: Type}>
  9492. */
  9493. public function getArguments() : array
  9494. {
  9495. return $this->arguments;
  9496. }
  9497. /**
  9498. * Checks whether the method tag describes a static method or not.
  9499. *
  9500. * @return bool TRUE if the method declaration is for a static method, FALSE otherwise.
  9501. */
  9502. public function isStatic() : bool
  9503. {
  9504. return $this->isStatic;
  9505. }
  9506. public function getReturnType() : \PHPUnit\phpDocumentor\Reflection\Type
  9507. {
  9508. return $this->returnType;
  9509. }
  9510. public function __toString() : string
  9511. {
  9512. $arguments = [];
  9513. foreach ($this->arguments as $argument) {
  9514. $arguments[] = $argument['type'] . ' $' . $argument['name'];
  9515. }
  9516. return \trim(($this->isStatic() ? 'static ' : '') . (string) $this->returnType . ' ' . $this->methodName . '(' . \implode(', ', $arguments) . ')' . ($this->description ? ' ' . $this->description->render() : ''));
  9517. }
  9518. /**
  9519. * @param mixed[][]|string[] $arguments
  9520. *
  9521. * @return mixed[][]
  9522. *
  9523. * @phpstan-param array<int, array{name: string, type: Type}|string> $arguments
  9524. * @phpstan-return array<int, array{name: string, type: Type}>
  9525. */
  9526. private function filterArguments(array $arguments = []) : array
  9527. {
  9528. $result = [];
  9529. foreach ($arguments as $argument) {
  9530. if (\is_string($argument)) {
  9531. $argument = ['name' => $argument];
  9532. }
  9533. if (!isset($argument['type'])) {
  9534. $argument['type'] = new \PHPUnit\phpDocumentor\Reflection\Types\Mixed_();
  9535. }
  9536. $keys = \array_keys($argument);
  9537. \sort($keys);
  9538. if ($keys !== ['name', 'type']) {
  9539. throw new \InvalidArgumentException('Arguments can only have the "name" and "type" fields, found: ' . \var_export($keys, \true));
  9540. }
  9541. $result[] = $argument;
  9542. }
  9543. return $result;
  9544. }
  9545. private static function stripRestArg(string $argument) : string
  9546. {
  9547. if (\strpos($argument, '...') === 0) {
  9548. $argument = \trim(\substr($argument, 3));
  9549. }
  9550. return $argument;
  9551. }
  9552. }
  9553. <?php
  9554. declare (strict_types=1);
  9555. /**
  9556. * This file is part of phpDocumentor.
  9557. *
  9558. * For the full copyright and license information, please view the LICENSE
  9559. * file that was distributed with this source code.
  9560. *
  9561. * @link http://phpdoc.org
  9562. */
  9563. namespace PHPUnit\phpDocumentor\Reflection\DocBlock\Tags;
  9564. use PHPUnit\phpDocumentor\Reflection\DocBlock\Tag;
  9565. interface Formatter
  9566. {
  9567. /**
  9568. * Formats a tag into a string representation according to a specific format, such as Markdown.
  9569. */
  9570. public function format(\PHPUnit\phpDocumentor\Reflection\DocBlock\Tag $tag) : string;
  9571. }
  9572. <?php
  9573. declare (strict_types=1);
  9574. /**
  9575. * This file is part of phpDocumentor.
  9576. *
  9577. * For the full copyright and license information, please view the LICENSE
  9578. * file that was distributed with this source code.
  9579. *
  9580. * @link http://phpdoc.org
  9581. */
  9582. namespace PHPUnit\phpDocumentor\Reflection\DocBlock\Tags\Reference;
  9583. use PHPUnit\Webmozart\Assert\Assert;
  9584. /**
  9585. * Url reference used by {@see \phpDocumentor\Reflection\DocBlock\Tags\See}
  9586. */
  9587. final class Url implements \PHPUnit\phpDocumentor\Reflection\DocBlock\Tags\Reference\Reference
  9588. {
  9589. /** @var string */
  9590. private $uri;
  9591. public function __construct(string $uri)
  9592. {
  9593. \PHPUnit\Webmozart\Assert\Assert::stringNotEmpty($uri);
  9594. $this->uri = $uri;
  9595. }
  9596. public function __toString() : string
  9597. {
  9598. return $this->uri;
  9599. }
  9600. }
  9601. <?php
  9602. declare (strict_types=1);
  9603. /**
  9604. * This file is part of phpDocumentor.
  9605. *
  9606. * For the full copyright and license information, please view the LICENSE
  9607. * file that was distributed with this source code.
  9608. *
  9609. * @link http://phpdoc.org
  9610. */
  9611. namespace PHPUnit\phpDocumentor\Reflection\DocBlock\Tags\Reference;
  9612. use PHPUnit\phpDocumentor\Reflection\Fqsen as RealFqsen;
  9613. /**
  9614. * Fqsen reference used by {@see \phpDocumentor\Reflection\DocBlock\Tags\See}
  9615. */
  9616. final class Fqsen implements \PHPUnit\phpDocumentor\Reflection\DocBlock\Tags\Reference\Reference
  9617. {
  9618. /** @var RealFqsen */
  9619. private $fqsen;
  9620. public function __construct(\PHPUnit\phpDocumentor\Reflection\Fqsen $fqsen)
  9621. {
  9622. $this->fqsen = $fqsen;
  9623. }
  9624. /**
  9625. * @return string string representation of the referenced fqsen
  9626. */
  9627. public function __toString() : string
  9628. {
  9629. return (string) $this->fqsen;
  9630. }
  9631. }
  9632. <?php
  9633. declare (strict_types=1);
  9634. /**
  9635. * This file is part of phpDocumentor.
  9636. *
  9637. * For the full copyright and license information, please view the LICENSE
  9638. * file that was distributed with this source code.
  9639. *
  9640. * @link http://phpdoc.org
  9641. */
  9642. namespace PHPUnit\phpDocumentor\Reflection\DocBlock\Tags\Reference;
  9643. /**
  9644. * Interface for references in {@see \phpDocumentor\Reflection\DocBlock\Tags\See}
  9645. */
  9646. interface Reference
  9647. {
  9648. public function __toString() : string;
  9649. }
  9650. <?php
  9651. declare (strict_types=1);
  9652. /**
  9653. * This file is part of phpDocumentor.
  9654. *
  9655. * For the full copyright and license information, please view the LICENSE
  9656. * file that was distributed with this source code.
  9657. *
  9658. * @link http://phpdoc.org
  9659. */
  9660. namespace PHPUnit\phpDocumentor\Reflection\DocBlock\Tags;
  9661. use PHPUnit\phpDocumentor\Reflection\DocBlock;
  9662. use PHPUnit\phpDocumentor\Reflection\DocBlock\Description;
  9663. /**
  9664. * Parses a tag definition for a DocBlock.
  9665. */
  9666. abstract class BaseTag implements \PHPUnit\phpDocumentor\Reflection\DocBlock\Tag
  9667. {
  9668. /** @var string Name of the tag */
  9669. protected $name = '';
  9670. /** @var Description|null Description of the tag. */
  9671. protected $description;
  9672. /**
  9673. * Gets the name of this tag.
  9674. *
  9675. * @return string The name of this tag.
  9676. */
  9677. public function getName() : string
  9678. {
  9679. return $this->name;
  9680. }
  9681. public function getDescription() : ?\PHPUnit\phpDocumentor\Reflection\DocBlock\Description
  9682. {
  9683. return $this->description;
  9684. }
  9685. public function render(?\PHPUnit\phpDocumentor\Reflection\DocBlock\Tags\Formatter $formatter = null) : string
  9686. {
  9687. if ($formatter === null) {
  9688. $formatter = new \PHPUnit\phpDocumentor\Reflection\DocBlock\Tags\Formatter\PassthroughFormatter();
  9689. }
  9690. return $formatter->format($this);
  9691. }
  9692. }
  9693. <?php
  9694. declare (strict_types=1);
  9695. /**
  9696. * This file is part of phpDocumentor.
  9697. *
  9698. * For the full copyright and license information, please view the LICENSE
  9699. * file that was distributed with this source code.
  9700. *
  9701. * @link http://phpdoc.org
  9702. */
  9703. namespace PHPUnit\phpDocumentor\Reflection\DocBlock\Tags;
  9704. use InvalidArgumentException;
  9705. use function filter_var;
  9706. use function preg_match;
  9707. use function trim;
  9708. use const FILTER_VALIDATE_EMAIL;
  9709. /**
  9710. * Reflection class for an {@}author tag in a Docblock.
  9711. */
  9712. final class Author extends \PHPUnit\phpDocumentor\Reflection\DocBlock\Tags\BaseTag implements \PHPUnit\phpDocumentor\Reflection\DocBlock\Tags\Factory\StaticMethod
  9713. {
  9714. /** @var string register that this is the author tag. */
  9715. protected $name = 'author';
  9716. /** @var string The name of the author */
  9717. private $authorName;
  9718. /** @var string The email of the author */
  9719. private $authorEmail;
  9720. /**
  9721. * Initializes this tag with the author name and e-mail.
  9722. */
  9723. public function __construct(string $authorName, string $authorEmail)
  9724. {
  9725. if ($authorEmail && !\filter_var($authorEmail, \FILTER_VALIDATE_EMAIL)) {
  9726. throw new \InvalidArgumentException('The author tag does not have a valid e-mail address');
  9727. }
  9728. $this->authorName = $authorName;
  9729. $this->authorEmail = $authorEmail;
  9730. }
  9731. /**
  9732. * Gets the author's name.
  9733. *
  9734. * @return string The author's name.
  9735. */
  9736. public function getAuthorName() : string
  9737. {
  9738. return $this->authorName;
  9739. }
  9740. /**
  9741. * Returns the author's email.
  9742. *
  9743. * @return string The author's email.
  9744. */
  9745. public function getEmail() : string
  9746. {
  9747. return $this->authorEmail;
  9748. }
  9749. /**
  9750. * Returns this tag in string form.
  9751. */
  9752. public function __toString() : string
  9753. {
  9754. return $this->authorName . ($this->authorEmail !== '' ? ' <' . $this->authorEmail . '>' : '');
  9755. }
  9756. /**
  9757. * Attempts to create a new Author object based on †he tag body.
  9758. */
  9759. public static function create(string $body) : ?self
  9760. {
  9761. $splitTagContent = \preg_match('/^([^\\<]*)(?:\\<([^\\>]*)\\>)?$/u', $body, $matches);
  9762. if (!$splitTagContent) {
  9763. return null;
  9764. }
  9765. $authorName = \trim($matches[1]);
  9766. $email = isset($matches[2]) ? \trim($matches[2]) : '';
  9767. return new static($authorName, $email);
  9768. }
  9769. }
  9770. <?php
  9771. declare (strict_types=1);
  9772. /**
  9773. * This file is part of phpDocumentor.
  9774. *
  9775. * For the full copyright and license information, please view the LICENSE
  9776. * file that was distributed with this source code.
  9777. *
  9778. * @link http://phpdoc.org
  9779. */
  9780. namespace PHPUnit\phpDocumentor\Reflection\DocBlock\Tags;
  9781. use PHPUnit\phpDocumentor\Reflection\DocBlock\Description;
  9782. use PHPUnit\phpDocumentor\Reflection\DocBlock\DescriptionFactory;
  9783. use PHPUnit\phpDocumentor\Reflection\Types\Context as TypeContext;
  9784. use PHPUnit\Webmozart\Assert\Assert;
  9785. use function preg_match;
  9786. /**
  9787. * Reflection class for a {@}since tag in a Docblock.
  9788. */
  9789. final class Since extends \PHPUnit\phpDocumentor\Reflection\DocBlock\Tags\BaseTag implements \PHPUnit\phpDocumentor\Reflection\DocBlock\Tags\Factory\StaticMethod
  9790. {
  9791. /** @var string */
  9792. protected $name = 'since';
  9793. /**
  9794. * PCRE regular expression matching a version vector.
  9795. * Assumes the "x" modifier.
  9796. */
  9797. public const REGEX_VECTOR = '(?:
  9798. # Normal release vectors.
  9799. \\d\\S*
  9800. |
  9801. # VCS version vectors. Per PHPCS, they are expected to
  9802. # follow the form of the VCS name, followed by ":", followed
  9803. # by the version vector itself.
  9804. # By convention, popular VCSes like CVS, SVN and GIT use "$"
  9805. # around the actual version vector.
  9806. [^\\s\\:]+\\:\\s*\\$[^\\$]+\\$
  9807. )';
  9808. /** @var string|null The version vector. */
  9809. private $version;
  9810. public function __construct(?string $version = null, ?\PHPUnit\phpDocumentor\Reflection\DocBlock\Description $description = null)
  9811. {
  9812. \PHPUnit\Webmozart\Assert\Assert::nullOrStringNotEmpty($version);
  9813. $this->version = $version;
  9814. $this->description = $description;
  9815. }
  9816. public static function create(?string $body, ?\PHPUnit\phpDocumentor\Reflection\DocBlock\DescriptionFactory $descriptionFactory = null, ?\PHPUnit\phpDocumentor\Reflection\Types\Context $context = null) : ?self
  9817. {
  9818. if (empty($body)) {
  9819. return new static();
  9820. }
  9821. $matches = [];
  9822. if (!\preg_match('/^(' . self::REGEX_VECTOR . ')\\s*(.+)?$/sux', $body, $matches)) {
  9823. return null;
  9824. }
  9825. \PHPUnit\Webmozart\Assert\Assert::notNull($descriptionFactory);
  9826. return new static($matches[1], $descriptionFactory->create($matches[2] ?? '', $context));
  9827. }
  9828. /**
  9829. * Gets the version section of the tag.
  9830. */
  9831. public function getVersion() : ?string
  9832. {
  9833. return $this->version;
  9834. }
  9835. /**
  9836. * Returns a string representation for this tag.
  9837. */
  9838. public function __toString() : string
  9839. {
  9840. return (string) $this->version . ($this->description ? ' ' . (string) $this->description : '');
  9841. }
  9842. }
  9843. <?php
  9844. declare (strict_types=1);
  9845. /**
  9846. * This file is part of phpDocumentor.
  9847. *
  9848. * For the full copyright and license information, please view the LICENSE
  9849. * file that was distributed with this source code.
  9850. *
  9851. * @link http://phpdoc.org
  9852. */
  9853. namespace PHPUnit\phpDocumentor\Reflection\DocBlock\Tags\Formatter;
  9854. use PHPUnit\phpDocumentor\Reflection\DocBlock\Tag;
  9855. use PHPUnit\phpDocumentor\Reflection\DocBlock\Tags\Formatter;
  9856. use function trim;
  9857. class PassthroughFormatter implements \PHPUnit\phpDocumentor\Reflection\DocBlock\Tags\Formatter
  9858. {
  9859. /**
  9860. * Formats the given tag to return a simple plain text version.
  9861. */
  9862. public function format(\PHPUnit\phpDocumentor\Reflection\DocBlock\Tag $tag) : string
  9863. {
  9864. return \trim('@' . $tag->getName() . ' ' . $tag);
  9865. }
  9866. }
  9867. <?php
  9868. declare (strict_types=1);
  9869. /**
  9870. * This file is part of phpDocumentor.
  9871. *
  9872. * For the full copyright and license information, please view the LICENSE
  9873. * file that was distributed with this source code.
  9874. *
  9875. * @link http://phpdoc.org
  9876. */
  9877. namespace PHPUnit\phpDocumentor\Reflection\DocBlock\Tags\Formatter;
  9878. use PHPUnit\phpDocumentor\Reflection\DocBlock\Tag;
  9879. use PHPUnit\phpDocumentor\Reflection\DocBlock\Tags\Formatter;
  9880. use function max;
  9881. use function str_repeat;
  9882. use function strlen;
  9883. class AlignFormatter implements \PHPUnit\phpDocumentor\Reflection\DocBlock\Tags\Formatter
  9884. {
  9885. /** @var int The maximum tag name length. */
  9886. protected $maxLen = 0;
  9887. /**
  9888. * @param Tag[] $tags All tags that should later be aligned with the formatter.
  9889. */
  9890. public function __construct(array $tags)
  9891. {
  9892. foreach ($tags as $tag) {
  9893. $this->maxLen = \max($this->maxLen, \strlen($tag->getName()));
  9894. }
  9895. }
  9896. /**
  9897. * Formats the given tag to return a simple plain text version.
  9898. */
  9899. public function format(\PHPUnit\phpDocumentor\Reflection\DocBlock\Tag $tag) : string
  9900. {
  9901. return '@' . $tag->getName() . \str_repeat(' ', $this->maxLen - \strlen($tag->getName()) + 1) . $tag;
  9902. }
  9903. }
  9904. <?php
  9905. declare (strict_types=1);
  9906. /**
  9907. * This file is part of phpDocumentor.
  9908. *
  9909. * For the full copyright and license information, please view the LICENSE
  9910. * file that was distributed with this source code.
  9911. *
  9912. * @link http://phpdoc.org
  9913. */
  9914. namespace PHPUnit\phpDocumentor\Reflection\DocBlock\Tags;
  9915. use PHPUnit\phpDocumentor\Reflection\DocBlock\Description;
  9916. use PHPUnit\phpDocumentor\Reflection\DocBlock\DescriptionFactory;
  9917. use PHPUnit\phpDocumentor\Reflection\Type;
  9918. use PHPUnit\phpDocumentor\Reflection\TypeResolver;
  9919. use PHPUnit\phpDocumentor\Reflection\Types\Context as TypeContext;
  9920. use PHPUnit\Webmozart\Assert\Assert;
  9921. use function array_shift;
  9922. use function array_unshift;
  9923. use function implode;
  9924. use function preg_split;
  9925. use function strpos;
  9926. use function substr;
  9927. use const PREG_SPLIT_DELIM_CAPTURE;
  9928. /**
  9929. * Reflection class for a {@}property-read tag in a Docblock.
  9930. */
  9931. final class PropertyRead extends \PHPUnit\phpDocumentor\Reflection\DocBlock\Tags\TagWithType implements \PHPUnit\phpDocumentor\Reflection\DocBlock\Tags\Factory\StaticMethod
  9932. {
  9933. /** @var string|null */
  9934. protected $variableName;
  9935. public function __construct(?string $variableName, ?\PHPUnit\phpDocumentor\Reflection\Type $type = null, ?\PHPUnit\phpDocumentor\Reflection\DocBlock\Description $description = null)
  9936. {
  9937. \PHPUnit\Webmozart\Assert\Assert::string($variableName);
  9938. $this->name = 'property-read';
  9939. $this->variableName = $variableName;
  9940. $this->type = $type;
  9941. $this->description = $description;
  9942. }
  9943. public static function create(string $body, ?\PHPUnit\phpDocumentor\Reflection\TypeResolver $typeResolver = null, ?\PHPUnit\phpDocumentor\Reflection\DocBlock\DescriptionFactory $descriptionFactory = null, ?\PHPUnit\phpDocumentor\Reflection\Types\Context $context = null) : self
  9944. {
  9945. \PHPUnit\Webmozart\Assert\Assert::stringNotEmpty($body);
  9946. \PHPUnit\Webmozart\Assert\Assert::notNull($typeResolver);
  9947. \PHPUnit\Webmozart\Assert\Assert::notNull($descriptionFactory);
  9948. [$firstPart, $body] = self::extractTypeFromBody($body);
  9949. $type = null;
  9950. $parts = \preg_split('/(\\s+)/Su', $body, 2, \PREG_SPLIT_DELIM_CAPTURE);
  9951. \PHPUnit\Webmozart\Assert\Assert::isArray($parts);
  9952. $variableName = '';
  9953. // if the first item that is encountered is not a variable; it is a type
  9954. if ($firstPart && $firstPart[0] !== '$') {
  9955. $type = $typeResolver->resolve($firstPart, $context);
  9956. } else {
  9957. // first part is not a type; we should prepend it to the parts array for further processing
  9958. \array_unshift($parts, $firstPart);
  9959. }
  9960. // if the next item starts with a $ or ...$ it must be the variable name
  9961. if (isset($parts[0]) && \strpos($parts[0], '$') === 0) {
  9962. $variableName = \array_shift($parts);
  9963. \array_shift($parts);
  9964. \PHPUnit\Webmozart\Assert\Assert::notNull($variableName);
  9965. $variableName = \substr($variableName, 1);
  9966. }
  9967. $description = $descriptionFactory->create(\implode('', $parts), $context);
  9968. return new static($variableName, $type, $description);
  9969. }
  9970. /**
  9971. * Returns the variable's name.
  9972. */
  9973. public function getVariableName() : ?string
  9974. {
  9975. return $this->variableName;
  9976. }
  9977. /**
  9978. * Returns a string representation for this tag.
  9979. */
  9980. public function __toString() : string
  9981. {
  9982. return ($this->type ? $this->type . ' ' : '') . ($this->variableName ? '$' . $this->variableName : '') . ($this->description ? ' ' . $this->description : '');
  9983. }
  9984. }
  9985. <?php
  9986. declare (strict_types=1);
  9987. /**
  9988. * This file is part of phpDocumentor.
  9989. *
  9990. * For the full copyright and license information, please view the LICENSE
  9991. * file that was distributed with this source code.
  9992. *
  9993. * @link http://phpdoc.org
  9994. */
  9995. namespace PHPUnit\phpDocumentor\Reflection\DocBlock\Tags;
  9996. use PHPUnit\phpDocumentor\Reflection\Type;
  9997. use function in_array;
  9998. use function strlen;
  9999. use function substr;
  10000. use function trim;
  10001. abstract class TagWithType extends \PHPUnit\phpDocumentor\Reflection\DocBlock\Tags\BaseTag
  10002. {
  10003. /** @var ?Type */
  10004. protected $type;
  10005. /**
  10006. * Returns the type section of the variable.
  10007. */
  10008. public function getType() : ?\PHPUnit\phpDocumentor\Reflection\Type
  10009. {
  10010. return $this->type;
  10011. }
  10012. /**
  10013. * @return string[]
  10014. */
  10015. protected static function extractTypeFromBody(string $body) : array
  10016. {
  10017. $type = '';
  10018. $nestingLevel = 0;
  10019. for ($i = 0, $iMax = \strlen($body); $i < $iMax; $i++) {
  10020. $character = $body[$i];
  10021. if ($nestingLevel === 0 && \trim($character) === '') {
  10022. break;
  10023. }
  10024. $type .= $character;
  10025. if (\in_array($character, ['<', '(', '[', '{'])) {
  10026. $nestingLevel++;
  10027. continue;
  10028. }
  10029. if (\in_array($character, ['>', ')', ']', '}'])) {
  10030. $nestingLevel--;
  10031. continue;
  10032. }
  10033. }
  10034. $description = \trim(\substr($body, \strlen($type)));
  10035. return [$type, $description];
  10036. }
  10037. }
  10038. <?php
  10039. declare (strict_types=1);
  10040. /**
  10041. * This file is part of phpDocumentor.
  10042. *
  10043. * For the full copyright and license information, please view the LICENSE
  10044. * file that was distributed with this source code.
  10045. *
  10046. * @link http://phpdoc.org
  10047. */
  10048. namespace PHPUnit\phpDocumentor\Reflection\DocBlock\Tags\Factory;
  10049. /**
  10050. * @deprecated This contract is totally covered by Tag contract. Every class using StaticMethod also use Tag
  10051. */
  10052. interface StaticMethod
  10053. {
  10054. /**
  10055. * @return mixed
  10056. */
  10057. public static function create(string $body);
  10058. }
  10059. <?php
  10060. declare (strict_types=1);
  10061. /**
  10062. * This file is part of phpDocumentor.
  10063. *
  10064. * For the full copyright and license information, please view the LICENSE
  10065. * file that was distributed with this source code.
  10066. *
  10067. * @link http://phpdoc.org
  10068. */
  10069. namespace PHPUnit\phpDocumentor\Reflection\DocBlock\Tags;
  10070. use PHPUnit\phpDocumentor\Reflection\DocBlock\Description;
  10071. use PHPUnit\phpDocumentor\Reflection\DocBlock\DescriptionFactory;
  10072. use PHPUnit\phpDocumentor\Reflection\Type;
  10073. use PHPUnit\phpDocumentor\Reflection\TypeResolver;
  10074. use PHPUnit\phpDocumentor\Reflection\Types\Context as TypeContext;
  10075. use PHPUnit\Webmozart\Assert\Assert;
  10076. use function array_shift;
  10077. use function array_unshift;
  10078. use function implode;
  10079. use function preg_split;
  10080. use function strpos;
  10081. use function substr;
  10082. use const PREG_SPLIT_DELIM_CAPTURE;
  10083. /**
  10084. * Reflection class for a {@}property-write tag in a Docblock.
  10085. */
  10086. final class PropertyWrite extends \PHPUnit\phpDocumentor\Reflection\DocBlock\Tags\TagWithType implements \PHPUnit\phpDocumentor\Reflection\DocBlock\Tags\Factory\StaticMethod
  10087. {
  10088. /** @var string */
  10089. protected $variableName;
  10090. public function __construct(?string $variableName, ?\PHPUnit\phpDocumentor\Reflection\Type $type = null, ?\PHPUnit\phpDocumentor\Reflection\DocBlock\Description $description = null)
  10091. {
  10092. \PHPUnit\Webmozart\Assert\Assert::string($variableName);
  10093. $this->name = 'property-write';
  10094. $this->variableName = $variableName;
  10095. $this->type = $type;
  10096. $this->description = $description;
  10097. }
  10098. public static function create(string $body, ?\PHPUnit\phpDocumentor\Reflection\TypeResolver $typeResolver = null, ?\PHPUnit\phpDocumentor\Reflection\DocBlock\DescriptionFactory $descriptionFactory = null, ?\PHPUnit\phpDocumentor\Reflection\Types\Context $context = null) : self
  10099. {
  10100. \PHPUnit\Webmozart\Assert\Assert::stringNotEmpty($body);
  10101. \PHPUnit\Webmozart\Assert\Assert::notNull($typeResolver);
  10102. \PHPUnit\Webmozart\Assert\Assert::notNull($descriptionFactory);
  10103. [$firstPart, $body] = self::extractTypeFromBody($body);
  10104. $type = null;
  10105. $parts = \preg_split('/(\\s+)/Su', $body, 2, \PREG_SPLIT_DELIM_CAPTURE);
  10106. \PHPUnit\Webmozart\Assert\Assert::isArray($parts);
  10107. $variableName = '';
  10108. // if the first item that is encountered is not a variable; it is a type
  10109. if ($firstPart && $firstPart[0] !== '$') {
  10110. $type = $typeResolver->resolve($firstPart, $context);
  10111. } else {
  10112. // first part is not a type; we should prepend it to the parts array for further processing
  10113. \array_unshift($parts, $firstPart);
  10114. }
  10115. // if the next item starts with a $ or ...$ it must be the variable name
  10116. if (isset($parts[0]) && \strpos($parts[0], '$') === 0) {
  10117. $variableName = \array_shift($parts);
  10118. \array_shift($parts);
  10119. \PHPUnit\Webmozart\Assert\Assert::notNull($variableName);
  10120. $variableName = \substr($variableName, 1);
  10121. }
  10122. $description = $descriptionFactory->create(\implode('', $parts), $context);
  10123. return new static($variableName, $type, $description);
  10124. }
  10125. /**
  10126. * Returns the variable's name.
  10127. */
  10128. public function getVariableName() : ?string
  10129. {
  10130. return $this->variableName;
  10131. }
  10132. /**
  10133. * Returns a string representation for this tag.
  10134. */
  10135. public function __toString() : string
  10136. {
  10137. return ($this->type ? $this->type . ' ' : '') . ($this->variableName ? '$' . $this->variableName : '') . ($this->description ? ' ' . $this->description : '');
  10138. }
  10139. }
  10140. <?php
  10141. declare (strict_types=1);
  10142. /**
  10143. * This file is part of phpDocumentor.
  10144. *
  10145. * For the full copyright and license information, please view the LICENSE
  10146. * file that was distributed with this source code.
  10147. *
  10148. * @link http://phpdoc.org
  10149. */
  10150. namespace PHPUnit\phpDocumentor\Reflection\DocBlock\Tags;
  10151. use PHPUnit\phpDocumentor\Reflection\DocBlock\Description;
  10152. use PHPUnit\phpDocumentor\Reflection\DocBlock\DescriptionFactory;
  10153. use PHPUnit\phpDocumentor\Reflection\Types\Context as TypeContext;
  10154. use PHPUnit\Webmozart\Assert\Assert;
  10155. use function preg_match;
  10156. /**
  10157. * Reflection class for a {@}version tag in a Docblock.
  10158. */
  10159. final class Version extends \PHPUnit\phpDocumentor\Reflection\DocBlock\Tags\BaseTag implements \PHPUnit\phpDocumentor\Reflection\DocBlock\Tags\Factory\StaticMethod
  10160. {
  10161. /** @var string */
  10162. protected $name = 'version';
  10163. /**
  10164. * PCRE regular expression matching a version vector.
  10165. * Assumes the "x" modifier.
  10166. */
  10167. public const REGEX_VECTOR = '(?:
  10168. # Normal release vectors.
  10169. \\d\\S*
  10170. |
  10171. # VCS version vectors. Per PHPCS, they are expected to
  10172. # follow the form of the VCS name, followed by ":", followed
  10173. # by the version vector itself.
  10174. # By convention, popular VCSes like CVS, SVN and GIT use "$"
  10175. # around the actual version vector.
  10176. [^\\s\\:]+\\:\\s*\\$[^\\$]+\\$
  10177. )';
  10178. /** @var string|null The version vector. */
  10179. private $version;
  10180. public function __construct(?string $version = null, ?\PHPUnit\phpDocumentor\Reflection\DocBlock\Description $description = null)
  10181. {
  10182. \PHPUnit\Webmozart\Assert\Assert::nullOrStringNotEmpty($version);
  10183. $this->version = $version;
  10184. $this->description = $description;
  10185. }
  10186. public static function create(?string $body, ?\PHPUnit\phpDocumentor\Reflection\DocBlock\DescriptionFactory $descriptionFactory = null, ?\PHPUnit\phpDocumentor\Reflection\Types\Context $context = null) : ?self
  10187. {
  10188. if (empty($body)) {
  10189. return new static();
  10190. }
  10191. $matches = [];
  10192. if (!\preg_match('/^(' . self::REGEX_VECTOR . ')\\s*(.+)?$/sux', $body, $matches)) {
  10193. return null;
  10194. }
  10195. $description = null;
  10196. if ($descriptionFactory !== null) {
  10197. $description = $descriptionFactory->create($matches[2] ?? '', $context);
  10198. }
  10199. return new static($matches[1], $description);
  10200. }
  10201. /**
  10202. * Gets the version section of the tag.
  10203. */
  10204. public function getVersion() : ?string
  10205. {
  10206. return $this->version;
  10207. }
  10208. /**
  10209. * Returns a string representation for this tag.
  10210. */
  10211. public function __toString() : string
  10212. {
  10213. return (string) $this->version . ($this->description instanceof \PHPUnit\phpDocumentor\Reflection\DocBlock\Description ? ' ' . $this->description->render() : '');
  10214. }
  10215. }
  10216. <?php
  10217. declare (strict_types=1);
  10218. /**
  10219. * This file is part of phpDocumentor.
  10220. *
  10221. * For the full copyright and license information, please view the LICENSE
  10222. * file that was distributed with this source code.
  10223. *
  10224. * @link http://phpdoc.org
  10225. */
  10226. namespace PHPUnit\phpDocumentor\Reflection\DocBlock\Tags;
  10227. use PHPUnit\phpDocumentor\Reflection\DocBlock\Description;
  10228. use PHPUnit\phpDocumentor\Reflection\DocBlock\DescriptionFactory;
  10229. use PHPUnit\phpDocumentor\Reflection\Types\Context as TypeContext;
  10230. use PHPUnit\Webmozart\Assert\Assert;
  10231. use function preg_match;
  10232. /**
  10233. * Reflection class for a {@}deprecated tag in a Docblock.
  10234. */
  10235. final class Deprecated extends \PHPUnit\phpDocumentor\Reflection\DocBlock\Tags\BaseTag implements \PHPUnit\phpDocumentor\Reflection\DocBlock\Tags\Factory\StaticMethod
  10236. {
  10237. /** @var string */
  10238. protected $name = 'deprecated';
  10239. /**
  10240. * PCRE regular expression matching a version vector.
  10241. * Assumes the "x" modifier.
  10242. */
  10243. public const REGEX_VECTOR = '(?:
  10244. # Normal release vectors.
  10245. \\d\\S*
  10246. |
  10247. # VCS version vectors. Per PHPCS, they are expected to
  10248. # follow the form of the VCS name, followed by ":", followed
  10249. # by the version vector itself.
  10250. # By convention, popular VCSes like CVS, SVN and GIT use "$"
  10251. # around the actual version vector.
  10252. [^\\s\\:]+\\:\\s*\\$[^\\$]+\\$
  10253. )';
  10254. /** @var string|null The version vector. */
  10255. private $version;
  10256. public function __construct(?string $version = null, ?\PHPUnit\phpDocumentor\Reflection\DocBlock\Description $description = null)
  10257. {
  10258. \PHPUnit\Webmozart\Assert\Assert::nullOrStringNotEmpty($version);
  10259. $this->version = $version;
  10260. $this->description = $description;
  10261. }
  10262. /**
  10263. * @return static
  10264. */
  10265. public static function create(?string $body, ?\PHPUnit\phpDocumentor\Reflection\DocBlock\DescriptionFactory $descriptionFactory = null, ?\PHPUnit\phpDocumentor\Reflection\Types\Context $context = null) : self
  10266. {
  10267. if (empty($body)) {
  10268. return new static();
  10269. }
  10270. $matches = [];
  10271. if (!\preg_match('/^(' . self::REGEX_VECTOR . ')\\s*(.+)?$/sux', $body, $matches)) {
  10272. return new static(null, $descriptionFactory !== null ? $descriptionFactory->create($body, $context) : null);
  10273. }
  10274. \PHPUnit\Webmozart\Assert\Assert::notNull($descriptionFactory);
  10275. return new static($matches[1], $descriptionFactory->create($matches[2] ?? '', $context));
  10276. }
  10277. /**
  10278. * Gets the version section of the tag.
  10279. */
  10280. public function getVersion() : ?string
  10281. {
  10282. return $this->version;
  10283. }
  10284. /**
  10285. * Returns a string representation for this tag.
  10286. */
  10287. public function __toString() : string
  10288. {
  10289. return ($this->version ?? '') . ($this->description ? ' ' . $this->description->render() : '');
  10290. }
  10291. }
  10292. <?php
  10293. declare (strict_types=1);
  10294. /**
  10295. * This file is part of phpDocumentor.
  10296. *
  10297. * For the full copyright and license information, please view the LICENSE
  10298. * file that was distributed with this source code.
  10299. *
  10300. * @link http://phpdoc.org
  10301. */
  10302. namespace PHPUnit\phpDocumentor\Reflection\DocBlock\Tags;
  10303. use PHPUnit\phpDocumentor\Reflection\DocBlock\Description;
  10304. use PHPUnit\phpDocumentor\Reflection\DocBlock\DescriptionFactory;
  10305. use PHPUnit\phpDocumentor\Reflection\Types\Context as TypeContext;
  10306. use PHPUnit\Webmozart\Assert\Assert;
  10307. use function preg_split;
  10308. /**
  10309. * Reflection class for a @link tag in a Docblock.
  10310. */
  10311. final class Link extends \PHPUnit\phpDocumentor\Reflection\DocBlock\Tags\BaseTag implements \PHPUnit\phpDocumentor\Reflection\DocBlock\Tags\Factory\StaticMethod
  10312. {
  10313. /** @var string */
  10314. protected $name = 'link';
  10315. /** @var string */
  10316. private $link;
  10317. /**
  10318. * Initializes a link to a URL.
  10319. */
  10320. public function __construct(string $link, ?\PHPUnit\phpDocumentor\Reflection\DocBlock\Description $description = null)
  10321. {
  10322. $this->link = $link;
  10323. $this->description = $description;
  10324. }
  10325. public static function create(string $body, ?\PHPUnit\phpDocumentor\Reflection\DocBlock\DescriptionFactory $descriptionFactory = null, ?\PHPUnit\phpDocumentor\Reflection\Types\Context $context = null) : self
  10326. {
  10327. \PHPUnit\Webmozart\Assert\Assert::notNull($descriptionFactory);
  10328. $parts = \preg_split('/\\s+/Su', $body, 2);
  10329. \PHPUnit\Webmozart\Assert\Assert::isArray($parts);
  10330. $description = isset($parts[1]) ? $descriptionFactory->create($parts[1], $context) : null;
  10331. return new static($parts[0], $description);
  10332. }
  10333. /**
  10334. * Gets the link
  10335. */
  10336. public function getLink() : string
  10337. {
  10338. return $this->link;
  10339. }
  10340. /**
  10341. * Returns a string representation for this tag.
  10342. */
  10343. public function __toString() : string
  10344. {
  10345. return $this->link . ($this->description ? ' ' . $this->description->render() : '');
  10346. }
  10347. }
  10348. <?php
  10349. declare (strict_types=1);
  10350. /**
  10351. * This file is part of phpDocumentor.
  10352. *
  10353. * For the full copyright and license information, please view the LICENSE
  10354. * file that was distributed with this source code.
  10355. *
  10356. * @link http://phpdoc.org
  10357. */
  10358. namespace PHPUnit\phpDocumentor\Reflection\DocBlock\Tags;
  10359. use PHPUnit\phpDocumentor\Reflection\DocBlock\Description;
  10360. use PHPUnit\phpDocumentor\Reflection\DocBlock\DescriptionFactory;
  10361. use PHPUnit\phpDocumentor\Reflection\Type;
  10362. use PHPUnit\phpDocumentor\Reflection\TypeResolver;
  10363. use PHPUnit\phpDocumentor\Reflection\Types\Context as TypeContext;
  10364. use PHPUnit\Webmozart\Assert\Assert;
  10365. use function array_shift;
  10366. use function array_unshift;
  10367. use function implode;
  10368. use function preg_split;
  10369. use function strpos;
  10370. use function substr;
  10371. use const PREG_SPLIT_DELIM_CAPTURE;
  10372. /**
  10373. * Reflection class for a {@}var tag in a Docblock.
  10374. */
  10375. final class Var_ extends \PHPUnit\phpDocumentor\Reflection\DocBlock\Tags\TagWithType implements \PHPUnit\phpDocumentor\Reflection\DocBlock\Tags\Factory\StaticMethod
  10376. {
  10377. /** @var string|null */
  10378. protected $variableName = '';
  10379. public function __construct(?string $variableName, ?\PHPUnit\phpDocumentor\Reflection\Type $type = null, ?\PHPUnit\phpDocumentor\Reflection\DocBlock\Description $description = null)
  10380. {
  10381. \PHPUnit\Webmozart\Assert\Assert::string($variableName);
  10382. $this->name = 'var';
  10383. $this->variableName = $variableName;
  10384. $this->type = $type;
  10385. $this->description = $description;
  10386. }
  10387. public static function create(string $body, ?\PHPUnit\phpDocumentor\Reflection\TypeResolver $typeResolver = null, ?\PHPUnit\phpDocumentor\Reflection\DocBlock\DescriptionFactory $descriptionFactory = null, ?\PHPUnit\phpDocumentor\Reflection\Types\Context $context = null) : self
  10388. {
  10389. \PHPUnit\Webmozart\Assert\Assert::stringNotEmpty($body);
  10390. \PHPUnit\Webmozart\Assert\Assert::notNull($typeResolver);
  10391. \PHPUnit\Webmozart\Assert\Assert::notNull($descriptionFactory);
  10392. [$firstPart, $body] = self::extractTypeFromBody($body);
  10393. $parts = \preg_split('/(\\s+)/Su', $body, 2, \PREG_SPLIT_DELIM_CAPTURE);
  10394. \PHPUnit\Webmozart\Assert\Assert::isArray($parts);
  10395. $type = null;
  10396. $variableName = '';
  10397. // if the first item that is encountered is not a variable; it is a type
  10398. if ($firstPart && $firstPart[0] !== '$') {
  10399. $type = $typeResolver->resolve($firstPart, $context);
  10400. } else {
  10401. // first part is not a type; we should prepend it to the parts array for further processing
  10402. \array_unshift($parts, $firstPart);
  10403. }
  10404. // if the next item starts with a $ or ...$ it must be the variable name
  10405. if (isset($parts[0]) && \strpos($parts[0], '$') === 0) {
  10406. $variableName = \array_shift($parts);
  10407. \array_shift($parts);
  10408. \PHPUnit\Webmozart\Assert\Assert::notNull($variableName);
  10409. $variableName = \substr($variableName, 1);
  10410. }
  10411. $description = $descriptionFactory->create(\implode('', $parts), $context);
  10412. return new static($variableName, $type, $description);
  10413. }
  10414. /**
  10415. * Returns the variable's name.
  10416. */
  10417. public function getVariableName() : ?string
  10418. {
  10419. return $this->variableName;
  10420. }
  10421. /**
  10422. * Returns a string representation for this tag.
  10423. */
  10424. public function __toString() : string
  10425. {
  10426. return ($this->type ? $this->type . ' ' : '') . (empty($this->variableName) ? '' : '$' . $this->variableName) . ($this->description ? ' ' . $this->description : '');
  10427. }
  10428. }
  10429. <?php
  10430. declare (strict_types=1);
  10431. /**
  10432. * This file is part of phpDocumentor.
  10433. *
  10434. * For the full copyright and license information, please view the LICENSE
  10435. * file that was distributed with this source code.
  10436. *
  10437. * @link http://phpdoc.org
  10438. */
  10439. namespace PHPUnit\phpDocumentor\Reflection\DocBlock\Tags;
  10440. use PHPUnit\phpDocumentor\Reflection\DocBlock\Description;
  10441. use PHPUnit\phpDocumentor\Reflection\DocBlock\DescriptionFactory;
  10442. use PHPUnit\phpDocumentor\Reflection\Type;
  10443. use PHPUnit\phpDocumentor\Reflection\TypeResolver;
  10444. use PHPUnit\phpDocumentor\Reflection\Types\Context as TypeContext;
  10445. use PHPUnit\Webmozart\Assert\Assert;
  10446. /**
  10447. * Reflection class for a {@}return tag in a Docblock.
  10448. */
  10449. final class Return_ extends \PHPUnit\phpDocumentor\Reflection\DocBlock\Tags\TagWithType implements \PHPUnit\phpDocumentor\Reflection\DocBlock\Tags\Factory\StaticMethod
  10450. {
  10451. public function __construct(\PHPUnit\phpDocumentor\Reflection\Type $type, ?\PHPUnit\phpDocumentor\Reflection\DocBlock\Description $description = null)
  10452. {
  10453. $this->name = 'return';
  10454. $this->type = $type;
  10455. $this->description = $description;
  10456. }
  10457. public static function create(string $body, ?\PHPUnit\phpDocumentor\Reflection\TypeResolver $typeResolver = null, ?\PHPUnit\phpDocumentor\Reflection\DocBlock\DescriptionFactory $descriptionFactory = null, ?\PHPUnit\phpDocumentor\Reflection\Types\Context $context = null) : self
  10458. {
  10459. \PHPUnit\Webmozart\Assert\Assert::notNull($typeResolver);
  10460. \PHPUnit\Webmozart\Assert\Assert::notNull($descriptionFactory);
  10461. [$type, $description] = self::extractTypeFromBody($body);
  10462. $type = $typeResolver->resolve($type, $context);
  10463. $description = $descriptionFactory->create($description, $context);
  10464. return new static($type, $description);
  10465. }
  10466. public function __toString() : string
  10467. {
  10468. return ($this->type ?: 'mixed') . ' ' . (string) $this->description;
  10469. }
  10470. }
  10471. <?php
  10472. declare (strict_types=1);
  10473. /**
  10474. * This file is part of phpDocumentor.
  10475. *
  10476. * For the full copyright and license information, please view the LICENSE
  10477. * file that was distributed with this source code.
  10478. *
  10479. * @link http://phpdoc.org
  10480. */
  10481. namespace PHPUnit\phpDocumentor\Reflection\DocBlock\Tags;
  10482. use PHPUnit\phpDocumentor\Reflection\DocBlock\Description;
  10483. use PHPUnit\phpDocumentor\Reflection\DocBlock\DescriptionFactory;
  10484. use PHPUnit\phpDocumentor\Reflection\Fqsen;
  10485. use PHPUnit\phpDocumentor\Reflection\FqsenResolver;
  10486. use PHPUnit\phpDocumentor\Reflection\Types\Context as TypeContext;
  10487. use PHPUnit\Webmozart\Assert\Assert;
  10488. use function preg_split;
  10489. /**
  10490. * Reflection class for a @covers tag in a Docblock.
  10491. */
  10492. final class Covers extends \PHPUnit\phpDocumentor\Reflection\DocBlock\Tags\BaseTag implements \PHPUnit\phpDocumentor\Reflection\DocBlock\Tags\Factory\StaticMethod
  10493. {
  10494. /** @var string */
  10495. protected $name = 'covers';
  10496. /** @var Fqsen */
  10497. private $refers;
  10498. /**
  10499. * Initializes this tag.
  10500. */
  10501. public function __construct(\PHPUnit\phpDocumentor\Reflection\Fqsen $refers, ?\PHPUnit\phpDocumentor\Reflection\DocBlock\Description $description = null)
  10502. {
  10503. $this->refers = $refers;
  10504. $this->description = $description;
  10505. }
  10506. public static function create(string $body, ?\PHPUnit\phpDocumentor\Reflection\DocBlock\DescriptionFactory $descriptionFactory = null, ?\PHPUnit\phpDocumentor\Reflection\FqsenResolver $resolver = null, ?\PHPUnit\phpDocumentor\Reflection\Types\Context $context = null) : self
  10507. {
  10508. \PHPUnit\Webmozart\Assert\Assert::notEmpty($body);
  10509. \PHPUnit\Webmozart\Assert\Assert::notNull($descriptionFactory);
  10510. \PHPUnit\Webmozart\Assert\Assert::notNull($resolver);
  10511. $parts = \preg_split('/\\s+/Su', $body, 2);
  10512. \PHPUnit\Webmozart\Assert\Assert::isArray($parts);
  10513. return new static($resolver->resolve($parts[0], $context), $descriptionFactory->create($parts[1] ?? '', $context));
  10514. }
  10515. /**
  10516. * Returns the structural element this tag refers to.
  10517. */
  10518. public function getReference() : \PHPUnit\phpDocumentor\Reflection\Fqsen
  10519. {
  10520. return $this->refers;
  10521. }
  10522. /**
  10523. * Returns a string representation of this tag.
  10524. */
  10525. public function __toString() : string
  10526. {
  10527. return $this->refers . ($this->description ? ' ' . $this->description->render() : '');
  10528. }
  10529. }
  10530. <?php
  10531. declare (strict_types=1);
  10532. /**
  10533. * This file is part of phpDocumentor.
  10534. *
  10535. * For the full copyright and license information, please view the LICENSE
  10536. * file that was distributed with this source code.
  10537. *
  10538. * @link http://phpdoc.org
  10539. */
  10540. namespace PHPUnit\phpDocumentor\Reflection\DocBlock\Tags;
  10541. use PHPUnit\phpDocumentor\Reflection\DocBlock\Tag;
  10542. use PHPUnit\Webmozart\Assert\Assert;
  10543. use function array_key_exists;
  10544. use function preg_match;
  10545. use function rawurlencode;
  10546. use function str_replace;
  10547. use function strpos;
  10548. use function trim;
  10549. /**
  10550. * Reflection class for a {@}example tag in a Docblock.
  10551. */
  10552. final class Example implements \PHPUnit\phpDocumentor\Reflection\DocBlock\Tag, \PHPUnit\phpDocumentor\Reflection\DocBlock\Tags\Factory\StaticMethod
  10553. {
  10554. /** @var string Path to a file to use as an example. May also be an absolute URI. */
  10555. private $filePath;
  10556. /**
  10557. * @var bool Whether the file path component represents an URI. This determines how the file portion
  10558. * appears at {@link getContent()}.
  10559. */
  10560. private $isURI;
  10561. /** @var int */
  10562. private $startingLine;
  10563. /** @var int */
  10564. private $lineCount;
  10565. /** @var string|null */
  10566. private $content;
  10567. public function __construct(string $filePath, bool $isURI, int $startingLine, int $lineCount, ?string $content)
  10568. {
  10569. \PHPUnit\Webmozart\Assert\Assert::notEmpty($filePath);
  10570. \PHPUnit\Webmozart\Assert\Assert::greaterThanEq($startingLine, 0);
  10571. \PHPUnit\Webmozart\Assert\Assert::greaterThanEq($lineCount, 0);
  10572. $this->filePath = $filePath;
  10573. $this->startingLine = $startingLine;
  10574. $this->lineCount = $lineCount;
  10575. if ($content !== null) {
  10576. $this->content = \trim($content);
  10577. }
  10578. $this->isURI = $isURI;
  10579. }
  10580. public function getContent() : string
  10581. {
  10582. if ($this->content === null) {
  10583. $filePath = '"' . $this->filePath . '"';
  10584. if ($this->isURI) {
  10585. $filePath = $this->isUriRelative($this->filePath) ? \str_replace('%2F', '/', \rawurlencode($this->filePath)) : $this->filePath;
  10586. }
  10587. return \trim($filePath);
  10588. }
  10589. return $this->content;
  10590. }
  10591. public function getDescription() : ?string
  10592. {
  10593. return $this->content;
  10594. }
  10595. public static function create(string $body) : ?\PHPUnit\phpDocumentor\Reflection\DocBlock\Tag
  10596. {
  10597. // File component: File path in quotes or File URI / Source information
  10598. if (!\preg_match('/^(?:\\"([^\\"]+)\\"|(\\S+))(?:\\s+(.*))?$/sux', $body, $matches)) {
  10599. return null;
  10600. }
  10601. $filePath = null;
  10602. $fileUri = null;
  10603. if ($matches[1] !== '') {
  10604. $filePath = $matches[1];
  10605. } else {
  10606. $fileUri = $matches[2];
  10607. }
  10608. $startingLine = 1;
  10609. $lineCount = 0;
  10610. $description = null;
  10611. if (\array_key_exists(3, $matches)) {
  10612. $description = $matches[3];
  10613. // Starting line / Number of lines / Description
  10614. if (\preg_match('/^([1-9]\\d*)(?:\\s+((?1))\\s*)?(.*)$/sux', $matches[3], $contentMatches)) {
  10615. $startingLine = (int) $contentMatches[1];
  10616. if (isset($contentMatches[2]) && $contentMatches[2] !== '') {
  10617. $lineCount = (int) $contentMatches[2];
  10618. }
  10619. if (\array_key_exists(3, $contentMatches)) {
  10620. $description = $contentMatches[3];
  10621. }
  10622. }
  10623. }
  10624. return new static($filePath ?? $fileUri ?? '', $fileUri !== null, $startingLine, $lineCount, $description);
  10625. }
  10626. /**
  10627. * Returns the file path.
  10628. *
  10629. * @return string Path to a file to use as an example.
  10630. * May also be an absolute URI.
  10631. */
  10632. public function getFilePath() : string
  10633. {
  10634. return $this->filePath;
  10635. }
  10636. /**
  10637. * Returns a string representation for this tag.
  10638. */
  10639. public function __toString() : string
  10640. {
  10641. return $this->filePath . ($this->content ? ' ' . $this->content : '');
  10642. }
  10643. /**
  10644. * Returns true if the provided URI is relative or contains a complete scheme (and thus is absolute).
  10645. */
  10646. private function isUriRelative(string $uri) : bool
  10647. {
  10648. return \strpos($uri, ':') === \false;
  10649. }
  10650. public function getStartingLine() : int
  10651. {
  10652. return $this->startingLine;
  10653. }
  10654. public function getLineCount() : int
  10655. {
  10656. return $this->lineCount;
  10657. }
  10658. public function getName() : string
  10659. {
  10660. return 'example';
  10661. }
  10662. public function render(?\PHPUnit\phpDocumentor\Reflection\DocBlock\Tags\Formatter $formatter = null) : string
  10663. {
  10664. if ($formatter === null) {
  10665. $formatter = new \PHPUnit\phpDocumentor\Reflection\DocBlock\Tags\Formatter\PassthroughFormatter();
  10666. }
  10667. return $formatter->format($this);
  10668. }
  10669. }
  10670. <?php
  10671. declare (strict_types=1);
  10672. /**
  10673. * This file is part of phpDocumentor.
  10674. *
  10675. * For the full copyright and license information, please view the LICENSE
  10676. * file that was distributed with this source code.
  10677. *
  10678. * @link http://phpdoc.org
  10679. */
  10680. namespace PHPUnit\phpDocumentor\Reflection\DocBlock\Tags;
  10681. use PHPUnit\phpDocumentor\Reflection\DocBlock\Description;
  10682. use PHPUnit\phpDocumentor\Reflection\DocBlock\DescriptionFactory;
  10683. use PHPUnit\phpDocumentor\Reflection\Type;
  10684. use PHPUnit\phpDocumentor\Reflection\TypeResolver;
  10685. use PHPUnit\phpDocumentor\Reflection\Types\Context as TypeContext;
  10686. use PHPUnit\Webmozart\Assert\Assert;
  10687. use function array_shift;
  10688. use function array_unshift;
  10689. use function implode;
  10690. use function preg_split;
  10691. use function strpos;
  10692. use function substr;
  10693. use const PREG_SPLIT_DELIM_CAPTURE;
  10694. /**
  10695. * Reflection class for the {@}param tag in a Docblock.
  10696. */
  10697. final class Param extends \PHPUnit\phpDocumentor\Reflection\DocBlock\Tags\TagWithType implements \PHPUnit\phpDocumentor\Reflection\DocBlock\Tags\Factory\StaticMethod
  10698. {
  10699. /** @var string|null */
  10700. private $variableName;
  10701. /** @var bool determines whether this is a variadic argument */
  10702. private $isVariadic;
  10703. public function __construct(?string $variableName, ?\PHPUnit\phpDocumentor\Reflection\Type $type = null, bool $isVariadic = \false, ?\PHPUnit\phpDocumentor\Reflection\DocBlock\Description $description = null)
  10704. {
  10705. $this->name = 'param';
  10706. $this->variableName = $variableName;
  10707. $this->type = $type;
  10708. $this->isVariadic = $isVariadic;
  10709. $this->description = $description;
  10710. }
  10711. public static function create(string $body, ?\PHPUnit\phpDocumentor\Reflection\TypeResolver $typeResolver = null, ?\PHPUnit\phpDocumentor\Reflection\DocBlock\DescriptionFactory $descriptionFactory = null, ?\PHPUnit\phpDocumentor\Reflection\Types\Context $context = null) : self
  10712. {
  10713. \PHPUnit\Webmozart\Assert\Assert::stringNotEmpty($body);
  10714. \PHPUnit\Webmozart\Assert\Assert::notNull($typeResolver);
  10715. \PHPUnit\Webmozart\Assert\Assert::notNull($descriptionFactory);
  10716. [$firstPart, $body] = self::extractTypeFromBody($body);
  10717. $type = null;
  10718. $parts = \preg_split('/(\\s+)/Su', $body, 2, \PREG_SPLIT_DELIM_CAPTURE);
  10719. \PHPUnit\Webmozart\Assert\Assert::isArray($parts);
  10720. $variableName = '';
  10721. $isVariadic = \false;
  10722. // if the first item that is encountered is not a variable; it is a type
  10723. if ($firstPart && $firstPart[0] !== '$') {
  10724. $type = $typeResolver->resolve($firstPart, $context);
  10725. } else {
  10726. // first part is not a type; we should prepend it to the parts array for further processing
  10727. \array_unshift($parts, $firstPart);
  10728. }
  10729. // if the next item starts with a $ or ...$ it must be the variable name
  10730. if (isset($parts[0]) && (\strpos($parts[0], '$') === 0 || \strpos($parts[0], '...$') === 0)) {
  10731. $variableName = \array_shift($parts);
  10732. \array_shift($parts);
  10733. \PHPUnit\Webmozart\Assert\Assert::notNull($variableName);
  10734. if (\strpos($variableName, '...') === 0) {
  10735. $isVariadic = \true;
  10736. $variableName = \substr($variableName, 3);
  10737. }
  10738. if (\strpos($variableName, '$') === 0) {
  10739. $variableName = \substr($variableName, 1);
  10740. }
  10741. }
  10742. $description = $descriptionFactory->create(\implode('', $parts), $context);
  10743. return new static($variableName, $type, $isVariadic, $description);
  10744. }
  10745. /**
  10746. * Returns the variable's name.
  10747. */
  10748. public function getVariableName() : ?string
  10749. {
  10750. return $this->variableName;
  10751. }
  10752. /**
  10753. * Returns whether this tag is variadic.
  10754. */
  10755. public function isVariadic() : bool
  10756. {
  10757. return $this->isVariadic;
  10758. }
  10759. /**
  10760. * Returns a string representation for this tag.
  10761. */
  10762. public function __toString() : string
  10763. {
  10764. return ($this->type ? $this->type . ' ' : '') . ($this->isVariadic() ? '...' : '') . ($this->variableName !== null ? '$' . $this->variableName : '') . ($this->description ? ' ' . $this->description : '');
  10765. }
  10766. }
  10767. <?php
  10768. declare (strict_types=1);
  10769. /**
  10770. * This file is part of phpDocumentor.
  10771. *
  10772. * For the full copyright and license information, please view the LICENSE
  10773. * file that was distributed with this source code.
  10774. *
  10775. * @link http://phpdoc.org
  10776. */
  10777. namespace PHPUnit\phpDocumentor\Reflection\DocBlock\Tags;
  10778. use PHPUnit\phpDocumentor\Reflection\DocBlock\Description;
  10779. use PHPUnit\phpDocumentor\Reflection\DocBlock\DescriptionFactory;
  10780. use PHPUnit\phpDocumentor\Reflection\Fqsen;
  10781. use PHPUnit\phpDocumentor\Reflection\FqsenResolver;
  10782. use PHPUnit\phpDocumentor\Reflection\Types\Context as TypeContext;
  10783. use PHPUnit\Webmozart\Assert\Assert;
  10784. use function preg_split;
  10785. /**
  10786. * Reflection class for a {@}uses tag in a Docblock.
  10787. */
  10788. final class Uses extends \PHPUnit\phpDocumentor\Reflection\DocBlock\Tags\BaseTag implements \PHPUnit\phpDocumentor\Reflection\DocBlock\Tags\Factory\StaticMethod
  10789. {
  10790. /** @var string */
  10791. protected $name = 'uses';
  10792. /** @var Fqsen */
  10793. protected $refers;
  10794. /**
  10795. * Initializes this tag.
  10796. */
  10797. public function __construct(\PHPUnit\phpDocumentor\Reflection\Fqsen $refers, ?\PHPUnit\phpDocumentor\Reflection\DocBlock\Description $description = null)
  10798. {
  10799. $this->refers = $refers;
  10800. $this->description = $description;
  10801. }
  10802. public static function create(string $body, ?\PHPUnit\phpDocumentor\Reflection\FqsenResolver $resolver = null, ?\PHPUnit\phpDocumentor\Reflection\DocBlock\DescriptionFactory $descriptionFactory = null, ?\PHPUnit\phpDocumentor\Reflection\Types\Context $context = null) : self
  10803. {
  10804. \PHPUnit\Webmozart\Assert\Assert::notNull($resolver);
  10805. \PHPUnit\Webmozart\Assert\Assert::notNull($descriptionFactory);
  10806. $parts = \preg_split('/\\s+/Su', $body, 2);
  10807. \PHPUnit\Webmozart\Assert\Assert::isArray($parts);
  10808. \PHPUnit\Webmozart\Assert\Assert::allString($parts);
  10809. return new static($resolver->resolve($parts[0], $context), $descriptionFactory->create($parts[1] ?? '', $context));
  10810. }
  10811. /**
  10812. * Returns the structural element this tag refers to.
  10813. */
  10814. public function getReference() : \PHPUnit\phpDocumentor\Reflection\Fqsen
  10815. {
  10816. return $this->refers;
  10817. }
  10818. /**
  10819. * Returns a string representation of this tag.
  10820. */
  10821. public function __toString() : string
  10822. {
  10823. return $this->refers . ' ' . (string) $this->description;
  10824. }
  10825. }
  10826. <?php
  10827. declare (strict_types=1);
  10828. /**
  10829. * This file is part of phpDocumentor.
  10830. *
  10831. * For the full copyright and license information, please view the LICENSE
  10832. * file that was distributed with this source code.
  10833. *
  10834. * @link http://phpdoc.org
  10835. */
  10836. namespace PHPUnit\phpDocumentor\Reflection\DocBlock\Tags;
  10837. use PHPUnit\phpDocumentor\Reflection\DocBlock\Description;
  10838. use PHPUnit\phpDocumentor\Reflection\DocBlock\DescriptionFactory;
  10839. use PHPUnit\phpDocumentor\Reflection\Type;
  10840. use PHPUnit\phpDocumentor\Reflection\TypeResolver;
  10841. use PHPUnit\phpDocumentor\Reflection\Types\Context as TypeContext;
  10842. use PHPUnit\Webmozart\Assert\Assert;
  10843. /**
  10844. * Reflection class for a {@}throws tag in a Docblock.
  10845. */
  10846. final class Throws extends \PHPUnit\phpDocumentor\Reflection\DocBlock\Tags\TagWithType implements \PHPUnit\phpDocumentor\Reflection\DocBlock\Tags\Factory\StaticMethod
  10847. {
  10848. public function __construct(\PHPUnit\phpDocumentor\Reflection\Type $type, ?\PHPUnit\phpDocumentor\Reflection\DocBlock\Description $description = null)
  10849. {
  10850. $this->name = 'throws';
  10851. $this->type = $type;
  10852. $this->description = $description;
  10853. }
  10854. public static function create(string $body, ?\PHPUnit\phpDocumentor\Reflection\TypeResolver $typeResolver = null, ?\PHPUnit\phpDocumentor\Reflection\DocBlock\DescriptionFactory $descriptionFactory = null, ?\PHPUnit\phpDocumentor\Reflection\Types\Context $context = null) : self
  10855. {
  10856. \PHPUnit\Webmozart\Assert\Assert::notNull($typeResolver);
  10857. \PHPUnit\Webmozart\Assert\Assert::notNull($descriptionFactory);
  10858. [$type, $description] = self::extractTypeFromBody($body);
  10859. $type = $typeResolver->resolve($type, $context);
  10860. $description = $descriptionFactory->create($description, $context);
  10861. return new static($type, $description);
  10862. }
  10863. public function __toString() : string
  10864. {
  10865. return (string) $this->type . ' ' . (string) $this->description;
  10866. }
  10867. }
  10868. <?php
  10869. declare (strict_types=1);
  10870. /**
  10871. * This file is part of phpDocumentor.
  10872. *
  10873. * For the full copyright and license information, please view the LICENSE
  10874. * file that was distributed with this source code.
  10875. *
  10876. * @link http://phpdoc.org
  10877. */
  10878. namespace PHPUnit\phpDocumentor\Reflection\DocBlock\Tags;
  10879. use PHPUnit\phpDocumentor\Reflection\DocBlock\Description;
  10880. use PHPUnit\phpDocumentor\Reflection\DocBlock\DescriptionFactory;
  10881. use PHPUnit\phpDocumentor\Reflection\Type;
  10882. use PHPUnit\phpDocumentor\Reflection\TypeResolver;
  10883. use PHPUnit\phpDocumentor\Reflection\Types\Context as TypeContext;
  10884. use PHPUnit\Webmozart\Assert\Assert;
  10885. use function array_shift;
  10886. use function array_unshift;
  10887. use function implode;
  10888. use function preg_split;
  10889. use function strpos;
  10890. use function substr;
  10891. use const PREG_SPLIT_DELIM_CAPTURE;
  10892. /**
  10893. * Reflection class for a {@}property tag in a Docblock.
  10894. */
  10895. final class Property extends \PHPUnit\phpDocumentor\Reflection\DocBlock\Tags\TagWithType implements \PHPUnit\phpDocumentor\Reflection\DocBlock\Tags\Factory\StaticMethod
  10896. {
  10897. /** @var string|null */
  10898. protected $variableName;
  10899. public function __construct(?string $variableName, ?\PHPUnit\phpDocumentor\Reflection\Type $type = null, ?\PHPUnit\phpDocumentor\Reflection\DocBlock\Description $description = null)
  10900. {
  10901. \PHPUnit\Webmozart\Assert\Assert::string($variableName);
  10902. $this->name = 'property';
  10903. $this->variableName = $variableName;
  10904. $this->type = $type;
  10905. $this->description = $description;
  10906. }
  10907. public static function create(string $body, ?\PHPUnit\phpDocumentor\Reflection\TypeResolver $typeResolver = null, ?\PHPUnit\phpDocumentor\Reflection\DocBlock\DescriptionFactory $descriptionFactory = null, ?\PHPUnit\phpDocumentor\Reflection\Types\Context $context = null) : self
  10908. {
  10909. \PHPUnit\Webmozart\Assert\Assert::stringNotEmpty($body);
  10910. \PHPUnit\Webmozart\Assert\Assert::notNull($typeResolver);
  10911. \PHPUnit\Webmozart\Assert\Assert::notNull($descriptionFactory);
  10912. [$firstPart, $body] = self::extractTypeFromBody($body);
  10913. $type = null;
  10914. $parts = \preg_split('/(\\s+)/Su', $body, 2, \PREG_SPLIT_DELIM_CAPTURE);
  10915. \PHPUnit\Webmozart\Assert\Assert::isArray($parts);
  10916. $variableName = '';
  10917. // if the first item that is encountered is not a variable; it is a type
  10918. if ($firstPart && $firstPart[0] !== '$') {
  10919. $type = $typeResolver->resolve($firstPart, $context);
  10920. } else {
  10921. // first part is not a type; we should prepend it to the parts array for further processing
  10922. \array_unshift($parts, $firstPart);
  10923. }
  10924. // if the next item starts with a $ or ...$ it must be the variable name
  10925. if (isset($parts[0]) && \strpos($parts[0], '$') === 0) {
  10926. $variableName = \array_shift($parts);
  10927. \array_shift($parts);
  10928. \PHPUnit\Webmozart\Assert\Assert::notNull($variableName);
  10929. $variableName = \substr($variableName, 1);
  10930. }
  10931. $description = $descriptionFactory->create(\implode('', $parts), $context);
  10932. return new static($variableName, $type, $description);
  10933. }
  10934. /**
  10935. * Returns the variable's name.
  10936. */
  10937. public function getVariableName() : ?string
  10938. {
  10939. return $this->variableName;
  10940. }
  10941. /**
  10942. * Returns a string representation for this tag.
  10943. */
  10944. public function __toString() : string
  10945. {
  10946. return ($this->type ? $this->type . ' ' : '') . ($this->variableName ? '$' . $this->variableName : '') . ($this->description ? ' ' . $this->description : '');
  10947. }
  10948. }
  10949. <?php
  10950. declare (strict_types=1);
  10951. /**
  10952. * This file is part of phpDocumentor.
  10953. *
  10954. * For the full copyright and license information, please view the LICENSE
  10955. * file that was distributed with this source code.
  10956. *
  10957. * @link http://phpdoc.org
  10958. */
  10959. namespace PHPUnit\phpDocumentor\Reflection\DocBlock;
  10960. use PHPUnit\phpDocumentor\Reflection\DocBlock\Tags\Formatter;
  10961. interface Tag
  10962. {
  10963. public function getName() : string;
  10964. /**
  10965. * @return Tag|mixed Class that implements Tag
  10966. *
  10967. * @phpstan-return ?Tag
  10968. */
  10969. public static function create(string $body);
  10970. public function render(?\PHPUnit\phpDocumentor\Reflection\DocBlock\Tags\Formatter $formatter = null) : string;
  10971. public function __toString() : string;
  10972. }
  10973. <?php
  10974. declare (strict_types=1);
  10975. /**
  10976. * This file is part of phpDocumentor.
  10977. *
  10978. * For the full copyright and license information, please view the LICENSE
  10979. * file that was distributed with this source code.
  10980. *
  10981. * @link http://phpdoc.org
  10982. */
  10983. namespace PHPUnit\phpDocumentor\Reflection\DocBlock;
  10984. use PHPUnit\phpDocumentor\Reflection\DocBlock\Tags\Example;
  10985. use function array_slice;
  10986. use function file;
  10987. use function getcwd;
  10988. use function implode;
  10989. use function is_readable;
  10990. use function rtrim;
  10991. use function sprintf;
  10992. use function trim;
  10993. use const DIRECTORY_SEPARATOR;
  10994. /**
  10995. * Class used to find an example file's location based on a given ExampleDescriptor.
  10996. */
  10997. class ExampleFinder
  10998. {
  10999. /** @var string */
  11000. private $sourceDirectory = '';
  11001. /** @var string[] */
  11002. private $exampleDirectories = [];
  11003. /**
  11004. * Attempts to find the example contents for the given descriptor.
  11005. */
  11006. public function find(\PHPUnit\phpDocumentor\Reflection\DocBlock\Tags\Example $example) : string
  11007. {
  11008. $filename = $example->getFilePath();
  11009. $file = $this->getExampleFileContents($filename);
  11010. if (!$file) {
  11011. return \sprintf('** File not found : %s **', $filename);
  11012. }
  11013. return \implode('', \array_slice($file, $example->getStartingLine() - 1, $example->getLineCount()));
  11014. }
  11015. /**
  11016. * Registers the project's root directory where an 'examples' folder can be expected.
  11017. */
  11018. public function setSourceDirectory(string $directory = '') : void
  11019. {
  11020. $this->sourceDirectory = $directory;
  11021. }
  11022. /**
  11023. * Returns the project's root directory where an 'examples' folder can be expected.
  11024. */
  11025. public function getSourceDirectory() : string
  11026. {
  11027. return $this->sourceDirectory;
  11028. }
  11029. /**
  11030. * Registers a series of directories that may contain examples.
  11031. *
  11032. * @param string[] $directories
  11033. */
  11034. public function setExampleDirectories(array $directories) : void
  11035. {
  11036. $this->exampleDirectories = $directories;
  11037. }
  11038. /**
  11039. * Returns a series of directories that may contain examples.
  11040. *
  11041. * @return string[]
  11042. */
  11043. public function getExampleDirectories() : array
  11044. {
  11045. return $this->exampleDirectories;
  11046. }
  11047. /**
  11048. * Attempts to find the requested example file and returns its contents or null if no file was found.
  11049. *
  11050. * This method will try several methods in search of the given example file, the first one it encounters is
  11051. * returned:
  11052. *
  11053. * 1. Iterates through all examples folders for the given filename
  11054. * 2. Checks the source folder for the given filename
  11055. * 3. Checks the 'examples' folder in the current working directory for examples
  11056. * 4. Checks the path relative to the current working directory for the given filename
  11057. *
  11058. * @return string[] all lines of the example file
  11059. */
  11060. private function getExampleFileContents(string $filename) : ?array
  11061. {
  11062. $normalizedPath = null;
  11063. foreach ($this->exampleDirectories as $directory) {
  11064. $exampleFileFromConfig = $this->constructExamplePath($directory, $filename);
  11065. if (\is_readable($exampleFileFromConfig)) {
  11066. $normalizedPath = $exampleFileFromConfig;
  11067. break;
  11068. }
  11069. }
  11070. if (!$normalizedPath) {
  11071. if (\is_readable($this->getExamplePathFromSource($filename))) {
  11072. $normalizedPath = $this->getExamplePathFromSource($filename);
  11073. } elseif (\is_readable($this->getExamplePathFromExampleDirectory($filename))) {
  11074. $normalizedPath = $this->getExamplePathFromExampleDirectory($filename);
  11075. } elseif (\is_readable($filename)) {
  11076. $normalizedPath = $filename;
  11077. }
  11078. }
  11079. $lines = $normalizedPath && \is_readable($normalizedPath) ? \file($normalizedPath) : \false;
  11080. return $lines !== \false ? $lines : null;
  11081. }
  11082. /**
  11083. * Get example filepath based on the example directory inside your project.
  11084. */
  11085. private function getExamplePathFromExampleDirectory(string $file) : string
  11086. {
  11087. return \getcwd() . \DIRECTORY_SEPARATOR . 'examples' . \DIRECTORY_SEPARATOR . $file;
  11088. }
  11089. /**
  11090. * Returns a path to the example file in the given directory..
  11091. */
  11092. private function constructExamplePath(string $directory, string $file) : string
  11093. {
  11094. return \rtrim($directory, '\\/') . \DIRECTORY_SEPARATOR . $file;
  11095. }
  11096. /**
  11097. * Get example filepath based on sourcecode.
  11098. */
  11099. private function getExamplePathFromSource(string $file) : string
  11100. {
  11101. return \sprintf('%s%s%s', \trim($this->getSourceDirectory(), '\\/'), \DIRECTORY_SEPARATOR, \trim($file, '"'));
  11102. }
  11103. }
  11104. <?php
  11105. declare (strict_types=1);
  11106. /**
  11107. * This file is part of phpDocumentor.
  11108. *
  11109. * For the full copyright and license information, please view the LICENSE
  11110. * file that was distributed with this source code.
  11111. *
  11112. * @link http://phpdoc.org
  11113. */
  11114. namespace PHPUnit\phpDocumentor\Reflection\DocBlock;
  11115. use PHPUnit\phpDocumentor\Reflection\Types\Context as TypeContext;
  11116. use PHPUnit\Webmozart\Assert\Assert;
  11117. use function count;
  11118. use function explode;
  11119. use function implode;
  11120. use function ltrim;
  11121. use function min;
  11122. use function preg_split;
  11123. use function str_replace;
  11124. use function strlen;
  11125. use function strpos;
  11126. use function substr;
  11127. use function trim;
  11128. use const PREG_SPLIT_DELIM_CAPTURE;
  11129. /**
  11130. * Creates a new Description object given a body of text.
  11131. *
  11132. * Descriptions in phpDocumentor are somewhat complex entities as they can contain one or more tags inside their
  11133. * body that can be replaced with a readable output. The replacing is done by passing a Formatter object to the
  11134. * Description object's `render` method.
  11135. *
  11136. * In addition to the above does a Description support two types of escape sequences:
  11137. *
  11138. * 1. `{@}` to escape the `@` character to prevent it from being interpreted as part of a tag, i.e. `{{@}link}`
  11139. * 2. `{}` to escape the `}` character, this can be used if you want to use the `}` character in the description
  11140. * of an inline tag.
  11141. *
  11142. * If a body consists of multiple lines then this factory will also remove any superfluous whitespace at the beginning
  11143. * of each line while maintaining any indentation that is used. This will prevent formatting parsers from tripping
  11144. * over unexpected spaces as can be observed with tag descriptions.
  11145. */
  11146. class DescriptionFactory
  11147. {
  11148. /** @var TagFactory */
  11149. private $tagFactory;
  11150. /**
  11151. * Initializes this factory with the means to construct (inline) tags.
  11152. */
  11153. public function __construct(\PHPUnit\phpDocumentor\Reflection\DocBlock\TagFactory $tagFactory)
  11154. {
  11155. $this->tagFactory = $tagFactory;
  11156. }
  11157. /**
  11158. * Returns the parsed text of this description.
  11159. */
  11160. public function create(string $contents, ?\PHPUnit\phpDocumentor\Reflection\Types\Context $context = null) : \PHPUnit\phpDocumentor\Reflection\DocBlock\Description
  11161. {
  11162. $tokens = $this->lex($contents);
  11163. $count = \count($tokens);
  11164. $tagCount = 0;
  11165. $tags = [];
  11166. for ($i = 1; $i < $count; $i += 2) {
  11167. $tags[] = $this->tagFactory->create($tokens[$i], $context);
  11168. $tokens[$i] = '%' . ++$tagCount . '$s';
  11169. }
  11170. //In order to allow "literal" inline tags, the otherwise invalid
  11171. //sequence "{@}" is changed to "@", and "{}" is changed to "}".
  11172. //"%" is escaped to "%%" because of vsprintf.
  11173. //See unit tests for examples.
  11174. for ($i = 0; $i < $count; $i += 2) {
  11175. $tokens[$i] = \str_replace(['{@}', '{}', '%'], ['@', '}', '%%'], $tokens[$i]);
  11176. }
  11177. return new \PHPUnit\phpDocumentor\Reflection\DocBlock\Description(\implode('', $tokens), $tags);
  11178. }
  11179. /**
  11180. * Strips the contents from superfluous whitespace and splits the description into a series of tokens.
  11181. *
  11182. * @return string[] A series of tokens of which the description text is composed.
  11183. */
  11184. private function lex(string $contents) : array
  11185. {
  11186. $contents = $this->removeSuperfluousStartingWhitespace($contents);
  11187. // performance optimalization; if there is no inline tag, don't bother splitting it up.
  11188. if (\strpos($contents, '{@') === \false) {
  11189. return [$contents];
  11190. }
  11191. $parts = \preg_split('/\\{
  11192. # "{@}" is not a valid inline tag. This ensures that we do not treat it as one, but treat it literally.
  11193. (?!@\\})
  11194. # We want to capture the whole tag line, but without the inline tag delimiters.
  11195. (\\@
  11196. # Match everything up to the next delimiter.
  11197. [^{}]*
  11198. # Nested inline tag content should not be captured, or it will appear in the result separately.
  11199. (?:
  11200. # Match nested inline tags.
  11201. (?:
  11202. # Because we did not catch the tag delimiters earlier, we must be explicit with them here.
  11203. # Notice that this also matches "{}", as a way to later introduce it as an escape sequence.
  11204. \\{(?1)?\\}
  11205. |
  11206. # Make sure we match hanging "{".
  11207. \\{
  11208. )
  11209. # Match content after the nested inline tag.
  11210. [^{}]*
  11211. )* # If there are more inline tags, match them as well. We use "*" since there may not be any
  11212. # nested inline tags.
  11213. )
  11214. \\}/Sux', $contents, 0, \PREG_SPLIT_DELIM_CAPTURE);
  11215. \PHPUnit\Webmozart\Assert\Assert::isArray($parts);
  11216. return $parts;
  11217. }
  11218. /**
  11219. * Removes the superfluous from a multi-line description.
  11220. *
  11221. * When a description has more than one line then it can happen that the second and subsequent lines have an
  11222. * additional indentation. This is commonly in use with tags like this:
  11223. *
  11224. * {@}since 1.1.0 This is an example
  11225. * description where we have an
  11226. * indentation in the second and
  11227. * subsequent lines.
  11228. *
  11229. * If we do not normalize the indentation then we have superfluous whitespace on the second and subsequent
  11230. * lines and this may cause rendering issues when, for example, using a Markdown converter.
  11231. */
  11232. private function removeSuperfluousStartingWhitespace(string $contents) : string
  11233. {
  11234. $lines = \explode("\n", $contents);
  11235. // if there is only one line then we don't have lines with superfluous whitespace and
  11236. // can use the contents as-is
  11237. if (\count($lines) <= 1) {
  11238. return $contents;
  11239. }
  11240. // determine how many whitespace characters need to be stripped
  11241. $startingSpaceCount = 9999999;
  11242. for ($i = 1, $iMax = \count($lines); $i < $iMax; ++$i) {
  11243. // lines with a no length do not count as they are not indented at all
  11244. if (\trim($lines[$i]) === '') {
  11245. continue;
  11246. }
  11247. // determine the number of prefixing spaces by checking the difference in line length before and after
  11248. // an ltrim
  11249. $startingSpaceCount = \min($startingSpaceCount, \strlen($lines[$i]) - \strlen(\ltrim($lines[$i])));
  11250. }
  11251. // strip the number of spaces from each line
  11252. if ($startingSpaceCount > 0) {
  11253. for ($i = 1, $iMax = \count($lines); $i < $iMax; ++$i) {
  11254. $lines[$i] = \substr($lines[$i], $startingSpaceCount);
  11255. }
  11256. }
  11257. return \implode("\n", $lines);
  11258. }
  11259. }
  11260. <?php
  11261. declare (strict_types=1);
  11262. /**
  11263. * This file is part of phpDocumentor.
  11264. *
  11265. * For the full copyright and license information, please view the LICENSE
  11266. * file that was distributed with this source code.
  11267. *
  11268. * @link http://phpdoc.org
  11269. */
  11270. namespace PHPUnit\phpDocumentor\Reflection\DocBlock;
  11271. use PHPUnit\phpDocumentor\Reflection\DocBlock\Tags\Formatter;
  11272. use PHPUnit\phpDocumentor\Reflection\DocBlock\Tags\Formatter\PassthroughFormatter;
  11273. use function vsprintf;
  11274. /**
  11275. * Object representing to description for a DocBlock.
  11276. *
  11277. * A Description object can consist of plain text but can also include tags. A Description Formatter can then combine
  11278. * a body template with sprintf-style placeholders together with formatted tags in order to reconstitute a complete
  11279. * description text using the format that you would prefer.
  11280. *
  11281. * Because parsing a Description text can be a verbose process this is handled by the {@see DescriptionFactory}. It is
  11282. * thus recommended to use that to create a Description object, like this:
  11283. *
  11284. * $description = $descriptionFactory->create('This is a {@see Description}', $context);
  11285. *
  11286. * The description factory will interpret the given body and create a body template and list of tags from them, and pass
  11287. * that onto the constructor if this class.
  11288. *
  11289. * > The $context variable is a class of type {@see \phpDocumentor\Reflection\Types\Context} and contains the namespace
  11290. * > and the namespace aliases that apply to this DocBlock. These are used by the Factory to resolve and expand partial
  11291. * > type names and FQSENs.
  11292. *
  11293. * If you do not want to use the DescriptionFactory you can pass a body template and tag listing like this:
  11294. *
  11295. * $description = new Description(
  11296. * 'This is a %1$s',
  11297. * [ new See(new Fqsen('\phpDocumentor\Reflection\DocBlock\Description')) ]
  11298. * );
  11299. *
  11300. * It is generally recommended to use the Factory as that will also apply escaping rules, while the Description object
  11301. * is mainly responsible for rendering.
  11302. *
  11303. * @see DescriptionFactory to create a new Description.
  11304. * @see Description\Formatter for the formatting of the body and tags.
  11305. */
  11306. class Description
  11307. {
  11308. /** @var string */
  11309. private $bodyTemplate;
  11310. /** @var Tag[] */
  11311. private $tags;
  11312. /**
  11313. * Initializes a Description with its body (template) and a listing of the tags used in the body template.
  11314. *
  11315. * @param Tag[] $tags
  11316. */
  11317. public function __construct(string $bodyTemplate, array $tags = [])
  11318. {
  11319. $this->bodyTemplate = $bodyTemplate;
  11320. $this->tags = $tags;
  11321. }
  11322. /**
  11323. * Returns the body template.
  11324. */
  11325. public function getBodyTemplate() : string
  11326. {
  11327. return $this->bodyTemplate;
  11328. }
  11329. /**
  11330. * Returns the tags for this DocBlock.
  11331. *
  11332. * @return Tag[]
  11333. */
  11334. public function getTags() : array
  11335. {
  11336. return $this->tags;
  11337. }
  11338. /**
  11339. * Renders this description as a string where the provided formatter will format the tags in the expected string
  11340. * format.
  11341. */
  11342. public function render(?\PHPUnit\phpDocumentor\Reflection\DocBlock\Tags\Formatter $formatter = null) : string
  11343. {
  11344. if ($formatter === null) {
  11345. $formatter = new \PHPUnit\phpDocumentor\Reflection\DocBlock\Tags\Formatter\PassthroughFormatter();
  11346. }
  11347. $tags = [];
  11348. foreach ($this->tags as $tag) {
  11349. $tags[] = '{' . $formatter->format($tag) . '}';
  11350. }
  11351. return \vsprintf($this->bodyTemplate, $tags);
  11352. }
  11353. /**
  11354. * Returns a plain string representation of this description.
  11355. */
  11356. public function __toString() : string
  11357. {
  11358. return $this->render();
  11359. }
  11360. }
  11361. <?php
  11362. declare (strict_types=1);
  11363. /**
  11364. * This file is part of phpDocumentor.
  11365. *
  11366. * For the full copyright and license information, please view the LICENSE
  11367. * file that was distributed with this source code.
  11368. *
  11369. * @link http://phpdoc.org
  11370. */
  11371. namespace PHPUnit\phpDocumentor\Reflection;
  11372. use InvalidArgumentException;
  11373. use LogicException;
  11374. use PHPUnit\phpDocumentor\Reflection\DocBlock\DescriptionFactory;
  11375. use PHPUnit\phpDocumentor\Reflection\DocBlock\StandardTagFactory;
  11376. use PHPUnit\phpDocumentor\Reflection\DocBlock\Tag;
  11377. use PHPUnit\phpDocumentor\Reflection\DocBlock\TagFactory;
  11378. use PHPUnit\Webmozart\Assert\Assert;
  11379. use function array_shift;
  11380. use function count;
  11381. use function explode;
  11382. use function is_object;
  11383. use function method_exists;
  11384. use function preg_match;
  11385. use function preg_replace;
  11386. use function str_replace;
  11387. use function strpos;
  11388. use function substr;
  11389. use function trim;
  11390. final class DocBlockFactory implements \PHPUnit\phpDocumentor\Reflection\DocBlockFactoryInterface
  11391. {
  11392. /** @var DocBlock\DescriptionFactory */
  11393. private $descriptionFactory;
  11394. /** @var DocBlock\TagFactory */
  11395. private $tagFactory;
  11396. /**
  11397. * Initializes this factory with the required subcontractors.
  11398. */
  11399. public function __construct(\PHPUnit\phpDocumentor\Reflection\DocBlock\DescriptionFactory $descriptionFactory, \PHPUnit\phpDocumentor\Reflection\DocBlock\TagFactory $tagFactory)
  11400. {
  11401. $this->descriptionFactory = $descriptionFactory;
  11402. $this->tagFactory = $tagFactory;
  11403. }
  11404. /**
  11405. * Factory method for easy instantiation.
  11406. *
  11407. * @param array<string, class-string<Tag>> $additionalTags
  11408. */
  11409. public static function createInstance(array $additionalTags = []) : self
  11410. {
  11411. $fqsenResolver = new \PHPUnit\phpDocumentor\Reflection\FqsenResolver();
  11412. $tagFactory = new \PHPUnit\phpDocumentor\Reflection\DocBlock\StandardTagFactory($fqsenResolver);
  11413. $descriptionFactory = new \PHPUnit\phpDocumentor\Reflection\DocBlock\DescriptionFactory($tagFactory);
  11414. $tagFactory->addService($descriptionFactory);
  11415. $tagFactory->addService(new \PHPUnit\phpDocumentor\Reflection\TypeResolver($fqsenResolver));
  11416. $docBlockFactory = new self($descriptionFactory, $tagFactory);
  11417. foreach ($additionalTags as $tagName => $tagHandler) {
  11418. $docBlockFactory->registerTagHandler($tagName, $tagHandler);
  11419. }
  11420. return $docBlockFactory;
  11421. }
  11422. /**
  11423. * @param object|string $docblock A string containing the DocBlock to parse or an object supporting the
  11424. * getDocComment method (such as a ReflectionClass object).
  11425. */
  11426. public function create($docblock, ?\PHPUnit\phpDocumentor\Reflection\Types\Context $context = null, ?\PHPUnit\phpDocumentor\Reflection\Location $location = null) : \PHPUnit\phpDocumentor\Reflection\DocBlock
  11427. {
  11428. if (\is_object($docblock)) {
  11429. if (!\method_exists($docblock, 'getDocComment')) {
  11430. $exceptionMessage = 'Invalid object passed; the given object must support the getDocComment method';
  11431. throw new \InvalidArgumentException($exceptionMessage);
  11432. }
  11433. $docblock = $docblock->getDocComment();
  11434. \PHPUnit\Webmozart\Assert\Assert::string($docblock);
  11435. }
  11436. \PHPUnit\Webmozart\Assert\Assert::stringNotEmpty($docblock);
  11437. if ($context === null) {
  11438. $context = new \PHPUnit\phpDocumentor\Reflection\Types\Context('');
  11439. }
  11440. $parts = $this->splitDocBlock($this->stripDocComment($docblock));
  11441. [$templateMarker, $summary, $description, $tags] = $parts;
  11442. return new \PHPUnit\phpDocumentor\Reflection\DocBlock($summary, $description ? $this->descriptionFactory->create($description, $context) : null, $this->parseTagBlock($tags, $context), $context, $location, $templateMarker === '#@+', $templateMarker === '#@-');
  11443. }
  11444. /**
  11445. * @param class-string<Tag> $handler
  11446. */
  11447. public function registerTagHandler(string $tagName, string $handler) : void
  11448. {
  11449. $this->tagFactory->registerTagHandler($tagName, $handler);
  11450. }
  11451. /**
  11452. * Strips the asterisks from the DocBlock comment.
  11453. *
  11454. * @param string $comment String containing the comment text.
  11455. */
  11456. private function stripDocComment(string $comment) : string
  11457. {
  11458. $comment = \preg_replace('#[ \\t]*(?:\\/\\*\\*|\\*\\/|\\*)?[ \\t]?(.*)?#u', '$1', $comment);
  11459. \PHPUnit\Webmozart\Assert\Assert::string($comment);
  11460. $comment = \trim($comment);
  11461. // reg ex above is not able to remove */ from a single line docblock
  11462. if (\substr($comment, -2) === '*/') {
  11463. $comment = \trim(\substr($comment, 0, -2));
  11464. }
  11465. return \str_replace(["\r\n", "\r"], "\n", $comment);
  11466. }
  11467. // phpcs:disable
  11468. /**
  11469. * Splits the DocBlock into a template marker, summary, description and block of tags.
  11470. *
  11471. * @param string $comment Comment to split into the sub-parts.
  11472. *
  11473. * @return string[] containing the template marker (if any), summary, description and a string containing the tags.
  11474. *
  11475. * @author Mike van Riel <me@mikevanriel.com> for extending the regex with template marker support.
  11476. *
  11477. * @author Richard van Velzen (@_richardJ) Special thanks to Richard for the regex responsible for the split.
  11478. */
  11479. private function splitDocBlock(string $comment) : array
  11480. {
  11481. // phpcs:enable
  11482. // Performance improvement cheat: if the first character is an @ then only tags are in this DocBlock. This
  11483. // method does not split tags so we return this verbatim as the fourth result (tags). This saves us the
  11484. // performance impact of running a regular expression
  11485. if (\strpos($comment, '@') === 0) {
  11486. return ['', '', '', $comment];
  11487. }
  11488. // clears all extra horizontal whitespace from the line endings to prevent parsing issues
  11489. $comment = \preg_replace('/\\h*$/Sum', '', $comment);
  11490. \PHPUnit\Webmozart\Assert\Assert::string($comment);
  11491. /*
  11492. * Splits the docblock into a template marker, summary, description and tags section.
  11493. *
  11494. * - The template marker is empty, #@+ or #@- if the DocBlock starts with either of those (a newline may
  11495. * occur after it and will be stripped).
  11496. * - The short description is started from the first character until a dot is encountered followed by a
  11497. * newline OR two consecutive newlines (horizontal whitespace is taken into account to consider spacing
  11498. * errors). This is optional.
  11499. * - The long description, any character until a new line is encountered followed by an @ and word
  11500. * characters (a tag). This is optional.
  11501. * - Tags; the remaining characters
  11502. *
  11503. * Big thanks to RichardJ for contributing this Regular Expression
  11504. */
  11505. \preg_match('/
  11506. \\A
  11507. # 1. Extract the template marker
  11508. (?:(\\#\\@\\+|\\#\\@\\-)\\n?)?
  11509. # 2. Extract the summary
  11510. (?:
  11511. (?! @\\pL ) # The summary may not start with an @
  11512. (
  11513. [^\\n.]+
  11514. (?:
  11515. (?! \\. \\n | \\n{2} ) # End summary upon a dot followed by newline or two newlines
  11516. [\\n.]* (?! [ \\t]* @\\pL ) # End summary when an @ is found as first character on a new line
  11517. [^\\n.]+ # Include anything else
  11518. )*
  11519. \\.?
  11520. )?
  11521. )
  11522. # 3. Extract the description
  11523. (?:
  11524. \\s* # Some form of whitespace _must_ precede a description because a summary must be there
  11525. (?! @\\pL ) # The description may not start with an @
  11526. (
  11527. [^\\n]+
  11528. (?: \\n+
  11529. (?! [ \\t]* @\\pL ) # End description when an @ is found as first character on a new line
  11530. [^\\n]+ # Include anything else
  11531. )*
  11532. )
  11533. )?
  11534. # 4. Extract the tags (anything that follows)
  11535. (\\s+ [\\s\\S]*)? # everything that follows
  11536. /ux', $comment, $matches);
  11537. \array_shift($matches);
  11538. while (\count($matches) < 4) {
  11539. $matches[] = '';
  11540. }
  11541. return $matches;
  11542. }
  11543. /**
  11544. * Creates the tag objects.
  11545. *
  11546. * @param string $tags Tag block to parse.
  11547. * @param Types\Context $context Context of the parsed Tag
  11548. *
  11549. * @return DocBlock\Tag[]
  11550. */
  11551. private function parseTagBlock(string $tags, \PHPUnit\phpDocumentor\Reflection\Types\Context $context) : array
  11552. {
  11553. $tags = $this->filterTagBlock($tags);
  11554. if ($tags === null) {
  11555. return [];
  11556. }
  11557. $result = [];
  11558. $lines = $this->splitTagBlockIntoTagLines($tags);
  11559. foreach ($lines as $key => $tagLine) {
  11560. $result[$key] = $this->tagFactory->create(\trim($tagLine), $context);
  11561. }
  11562. return $result;
  11563. }
  11564. /**
  11565. * @return string[]
  11566. */
  11567. private function splitTagBlockIntoTagLines(string $tags) : array
  11568. {
  11569. $result = [];
  11570. foreach (\explode("\n", $tags) as $tagLine) {
  11571. if ($tagLine !== '' && \strpos($tagLine, '@') === 0) {
  11572. $result[] = $tagLine;
  11573. } else {
  11574. $result[\count($result) - 1] .= "\n" . $tagLine;
  11575. }
  11576. }
  11577. return $result;
  11578. }
  11579. private function filterTagBlock(string $tags) : ?string
  11580. {
  11581. $tags = \trim($tags);
  11582. if (!$tags) {
  11583. return null;
  11584. }
  11585. if ($tags[0] !== '@') {
  11586. // @codeCoverageIgnoreStart
  11587. // Can't simulate this; this only happens if there is an error with the parsing of the DocBlock that
  11588. // we didn't foresee.
  11589. throw new \LogicException('A tag block started with text instead of an at-sign(@): ' . $tags);
  11590. // @codeCoverageIgnoreEnd
  11591. }
  11592. return $tags;
  11593. }
  11594. }
  11595. <?php
  11596. declare (strict_types=1);
  11597. /**
  11598. * This file is part of phpDocumentor.
  11599. *
  11600. * For the full copyright and license information, please view the LICENSE
  11601. * file that was distributed with this source code.
  11602. *
  11603. * @link http://phpdoc.org
  11604. */
  11605. namespace PHPUnit\phpDocumentor\Reflection;
  11606. use PHPUnit\phpDocumentor\Reflection\DocBlock\Tag;
  11607. use PHPUnit\Webmozart\Assert\Assert;
  11608. final class DocBlock
  11609. {
  11610. /** @var string The opening line for this docblock. */
  11611. private $summary;
  11612. /** @var DocBlock\Description The actual description for this docblock. */
  11613. private $description;
  11614. /** @var Tag[] An array containing all the tags in this docblock; except inline. */
  11615. private $tags = [];
  11616. /** @var Types\Context|null Information about the context of this DocBlock. */
  11617. private $context;
  11618. /** @var Location|null Information about the location of this DocBlock. */
  11619. private $location;
  11620. /** @var bool Is this DocBlock (the start of) a template? */
  11621. private $isTemplateStart;
  11622. /** @var bool Does this DocBlock signify the end of a DocBlock template? */
  11623. private $isTemplateEnd;
  11624. /**
  11625. * @param DocBlock\Tag[] $tags
  11626. * @param Types\Context $context The context in which the DocBlock occurs.
  11627. * @param Location $location The location within the file that this DocBlock occurs in.
  11628. */
  11629. public function __construct(string $summary = '', ?\PHPUnit\phpDocumentor\Reflection\DocBlock\Description $description = null, array $tags = [], ?\PHPUnit\phpDocumentor\Reflection\Types\Context $context = null, ?\PHPUnit\phpDocumentor\Reflection\Location $location = null, bool $isTemplateStart = \false, bool $isTemplateEnd = \false)
  11630. {
  11631. \PHPUnit\Webmozart\Assert\Assert::allIsInstanceOf($tags, \PHPUnit\phpDocumentor\Reflection\DocBlock\Tag::class);
  11632. $this->summary = $summary;
  11633. $this->description = $description ?: new \PHPUnit\phpDocumentor\Reflection\DocBlock\Description('');
  11634. foreach ($tags as $tag) {
  11635. $this->addTag($tag);
  11636. }
  11637. $this->context = $context;
  11638. $this->location = $location;
  11639. $this->isTemplateEnd = $isTemplateEnd;
  11640. $this->isTemplateStart = $isTemplateStart;
  11641. }
  11642. public function getSummary() : string
  11643. {
  11644. return $this->summary;
  11645. }
  11646. public function getDescription() : \PHPUnit\phpDocumentor\Reflection\DocBlock\Description
  11647. {
  11648. return $this->description;
  11649. }
  11650. /**
  11651. * Returns the current context.
  11652. */
  11653. public function getContext() : ?\PHPUnit\phpDocumentor\Reflection\Types\Context
  11654. {
  11655. return $this->context;
  11656. }
  11657. /**
  11658. * Returns the current location.
  11659. */
  11660. public function getLocation() : ?\PHPUnit\phpDocumentor\Reflection\Location
  11661. {
  11662. return $this->location;
  11663. }
  11664. /**
  11665. * Returns whether this DocBlock is the start of a Template section.
  11666. *
  11667. * A Docblock may serve as template for a series of subsequent DocBlocks. This is indicated by a special marker
  11668. * (`#@+`) that is appended directly after the opening `/**` of a DocBlock.
  11669. *
  11670. * An example of such an opening is:
  11671. *
  11672. * ```
  11673. * /**#@+
  11674. * * My DocBlock
  11675. * * /
  11676. * ```
  11677. *
  11678. * The description and tags (not the summary!) are copied onto all subsequent DocBlocks and also applied to all
  11679. * elements that follow until another DocBlock is found that contains the closing marker (`#@-`).
  11680. *
  11681. * @see self::isTemplateEnd() for the check whether a closing marker was provided.
  11682. */
  11683. public function isTemplateStart() : bool
  11684. {
  11685. return $this->isTemplateStart;
  11686. }
  11687. /**
  11688. * Returns whether this DocBlock is the end of a Template section.
  11689. *
  11690. * @see self::isTemplateStart() for a more complete description of the Docblock Template functionality.
  11691. */
  11692. public function isTemplateEnd() : bool
  11693. {
  11694. return $this->isTemplateEnd;
  11695. }
  11696. /**
  11697. * Returns the tags for this DocBlock.
  11698. *
  11699. * @return Tag[]
  11700. */
  11701. public function getTags() : array
  11702. {
  11703. return $this->tags;
  11704. }
  11705. /**
  11706. * Returns an array of tags matching the given name. If no tags are found
  11707. * an empty array is returned.
  11708. *
  11709. * @param string $name String to search by.
  11710. *
  11711. * @return Tag[]
  11712. */
  11713. public function getTagsByName(string $name) : array
  11714. {
  11715. $result = [];
  11716. foreach ($this->getTags() as $tag) {
  11717. if ($tag->getName() !== $name) {
  11718. continue;
  11719. }
  11720. $result[] = $tag;
  11721. }
  11722. return $result;
  11723. }
  11724. /**
  11725. * Checks if a tag of a certain type is present in this DocBlock.
  11726. *
  11727. * @param string $name Tag name to check for.
  11728. */
  11729. public function hasTag(string $name) : bool
  11730. {
  11731. foreach ($this->getTags() as $tag) {
  11732. if ($tag->getName() === $name) {
  11733. return \true;
  11734. }
  11735. }
  11736. return \false;
  11737. }
  11738. /**
  11739. * Remove a tag from this DocBlock.
  11740. *
  11741. * @param Tag $tagToRemove The tag to remove.
  11742. */
  11743. public function removeTag(\PHPUnit\phpDocumentor\Reflection\DocBlock\Tag $tagToRemove) : void
  11744. {
  11745. foreach ($this->tags as $key => $tag) {
  11746. if ($tag === $tagToRemove) {
  11747. unset($this->tags[$key]);
  11748. break;
  11749. }
  11750. }
  11751. }
  11752. /**
  11753. * Adds a tag to this DocBlock.
  11754. *
  11755. * @param Tag $tag The tag to add.
  11756. */
  11757. private function addTag(\PHPUnit\phpDocumentor\Reflection\DocBlock\Tag $tag) : void
  11758. {
  11759. $this->tags[] = $tag;
  11760. }
  11761. }
  11762. The MIT License (MIT)
  11763. Copyright (c) 2010 Mike van Riel
  11764. Permission is hereby granted, free of charge, to any person obtaining a copy
  11765. of this software and associated documentation files (the "Software"), to deal
  11766. in the Software without restriction, including without limitation the rights
  11767. to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  11768. copies of the Software, and to permit persons to whom the Software is
  11769. furnished to do so, subject to the following conditions:
  11770. The above copyright notice and this permission notice shall be included in
  11771. all copies or substantial portions of the Software.
  11772. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  11773. IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  11774. FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  11775. AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  11776. LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  11777. OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  11778. THE SOFTWARE.
  11779. <?php
  11780. declare (strict_types=1);
  11781. namespace PHPUnit\phpDocumentor\Reflection;
  11782. use PHPUnit\phpDocumentor\Reflection\DocBlock\Tag;
  11783. // phpcs:ignore SlevomatCodingStandard.Classes.SuperfluousInterfaceNaming.SuperfluousSuffix
  11784. interface DocBlockFactoryInterface
  11785. {
  11786. /**
  11787. * Factory method for easy instantiation.
  11788. *
  11789. * @param array<string, class-string<Tag>> $additionalTags
  11790. */
  11791. public static function createInstance(array $additionalTags = []) : \PHPUnit\phpDocumentor\Reflection\DocBlockFactory;
  11792. /**
  11793. * @param string|object $docblock
  11794. */
  11795. public function create($docblock, ?\PHPUnit\phpDocumentor\Reflection\Types\Context $context = null, ?\PHPUnit\phpDocumentor\Reflection\Location $location = null) : \PHPUnit\phpDocumentor\Reflection\DocBlock;
  11796. }
  11797. <?php
  11798. declare (strict_types=1);
  11799. /**
  11800. * This file is part of phpDocumentor.
  11801. *
  11802. * For the full copyright and license information, please view the LICENSE
  11803. * file that was distributed with this source code.
  11804. *
  11805. * @link http://phpdoc.org
  11806. */
  11807. namespace PHPUnit\phpDocumentor\Reflection\Types;
  11808. use PHPUnit\phpDocumentor\Reflection\Type;
  11809. /**
  11810. * Value Object representing the 'resource' Type.
  11811. *
  11812. * @psalm-immutable
  11813. */
  11814. final class Resource_ implements \PHPUnit\phpDocumentor\Reflection\Type
  11815. {
  11816. /**
  11817. * Returns a rendered output of the Type as it would be used in a DocBlock.
  11818. */
  11819. public function __toString() : string
  11820. {
  11821. return 'resource';
  11822. }
  11823. }
  11824. <?php
  11825. declare (strict_types=1);
  11826. /**
  11827. * This file is part of phpDocumentor.
  11828. *
  11829. * For the full copyright and license information, please view the LICENSE
  11830. * file that was distributed with this source code.
  11831. *
  11832. * @link http://phpdoc.org
  11833. */
  11834. namespace PHPUnit\phpDocumentor\Reflection\Types;
  11835. use PHPUnit\phpDocumentor\Reflection\Type;
  11836. /**
  11837. * Value Object representing a Compound Type.
  11838. *
  11839. * A Compound Type is not so much a special keyword or object reference but is a series of Types that are separated
  11840. * using an OR operator (`|`). This combination of types signifies that whatever is associated with this compound type
  11841. * may contain a value with any of the given types.
  11842. *
  11843. * @psalm-immutable
  11844. */
  11845. final class Compound extends \PHPUnit\phpDocumentor\Reflection\Types\AggregatedType
  11846. {
  11847. /**
  11848. * Initializes a compound type (i.e. `string|int`) and tests if the provided types all implement the Type interface.
  11849. *
  11850. * @param Type[] $types
  11851. *
  11852. * @phpstan-param list<Type> $types
  11853. */
  11854. public function __construct(array $types)
  11855. {
  11856. parent::__construct($types, '|');
  11857. }
  11858. }
  11859. <?php
  11860. declare (strict_types=1);
  11861. /**
  11862. * This file is part of phpDocumentor.
  11863. *
  11864. * For the full copyright and license information, please view the LICENSE
  11865. * file that was distributed with this source code.
  11866. *
  11867. * @link http://phpdoc.org
  11868. */
  11869. namespace PHPUnit\phpDocumentor\Reflection\Types;
  11870. use PHPUnit\phpDocumentor\Reflection\Type;
  11871. /**
  11872. * Value object representing Integer type
  11873. *
  11874. * @psalm-immutable
  11875. */
  11876. final class Integer implements \PHPUnit\phpDocumentor\Reflection\Type
  11877. {
  11878. /**
  11879. * Returns a rendered output of the Type as it would be used in a DocBlock.
  11880. */
  11881. public function __toString() : string
  11882. {
  11883. return 'int';
  11884. }
  11885. }
  11886. <?php
  11887. declare (strict_types=1);
  11888. /**
  11889. * This file is part of phpDocumentor.
  11890. *
  11891. * For the full copyright and license information, please view the LICENSE
  11892. * file that was distributed with this source code.
  11893. *
  11894. * @link http://phpdoc.org
  11895. */
  11896. namespace PHPUnit\phpDocumentor\Reflection\Types;
  11897. use PHPUnit\phpDocumentor\Reflection\Type;
  11898. /**
  11899. * Value Object representing a null value or type.
  11900. *
  11901. * @psalm-immutable
  11902. */
  11903. final class Null_ implements \PHPUnit\phpDocumentor\Reflection\Type
  11904. {
  11905. /**
  11906. * Returns a rendered output of the Type as it would be used in a DocBlock.
  11907. */
  11908. public function __toString() : string
  11909. {
  11910. return 'null';
  11911. }
  11912. }
  11913. <?php
  11914. declare (strict_types=1);
  11915. /**
  11916. * This file is part of phpDocumentor.
  11917. *
  11918. * For the full copyright and license information, please view the LICENSE
  11919. * file that was distributed with this source code.
  11920. *
  11921. * @link http://phpdoc.org
  11922. */
  11923. namespace PHPUnit\phpDocumentor\Reflection\Types;
  11924. use PHPUnit\phpDocumentor\Reflection\Type;
  11925. /**
  11926. * Value Object representing the 'parent' type.
  11927. *
  11928. * Parent, as a Type, represents the parent class of class in which the associated element was defined.
  11929. *
  11930. * @psalm-immutable
  11931. */
  11932. final class Parent_ implements \PHPUnit\phpDocumentor\Reflection\Type
  11933. {
  11934. /**
  11935. * Returns a rendered output of the Type as it would be used in a DocBlock.
  11936. */
  11937. public function __toString() : string
  11938. {
  11939. return 'parent';
  11940. }
  11941. }
  11942. <?php
  11943. declare (strict_types=1);
  11944. /**
  11945. * This file is part of phpDocumentor.
  11946. *
  11947. * For the full copyright and license information, please view the LICENSE
  11948. * file that was distributed with this source code.
  11949. *
  11950. * @link http://phpdoc.org
  11951. */
  11952. namespace PHPUnit\phpDocumentor\Reflection\Types;
  11953. use PHPUnit\phpDocumentor\Reflection\Type;
  11954. /**
  11955. * Value Object representing the pseudo-type 'void'.
  11956. *
  11957. * Void is generally only used when working with return types as it signifies that the method intentionally does not
  11958. * return any value.
  11959. *
  11960. * @psalm-immutable
  11961. */
  11962. final class Void_ implements \PHPUnit\phpDocumentor\Reflection\Type
  11963. {
  11964. /**
  11965. * Returns a rendered output of the Type as it would be used in a DocBlock.
  11966. */
  11967. public function __toString() : string
  11968. {
  11969. return 'void';
  11970. }
  11971. }
  11972. <?php
  11973. declare (strict_types=1);
  11974. /**
  11975. * This file is part of phpDocumentor.
  11976. *
  11977. * For the full copyright and license information, please view the LICENSE
  11978. * file that was distributed with this source code.
  11979. *
  11980. * @link http://phpdoc.org
  11981. */
  11982. namespace PHPUnit\phpDocumentor\Reflection\Types;
  11983. use PHPUnit\phpDocumentor\Reflection\Type;
  11984. /**
  11985. * Value Object representing a Boolean type.
  11986. *
  11987. * @psalm-immutable
  11988. */
  11989. class Boolean implements \PHPUnit\phpDocumentor\Reflection\Type
  11990. {
  11991. /**
  11992. * Returns a rendered output of the Type as it would be used in a DocBlock.
  11993. */
  11994. public function __toString() : string
  11995. {
  11996. return 'bool';
  11997. }
  11998. }
  11999. <?php
  12000. declare (strict_types=1);
  12001. /**
  12002. * This file is part of phpDocumentor.
  12003. *
  12004. * For the full copyright and license information, please view the LICENSE
  12005. * file that was distributed with this source code.
  12006. *
  12007. * @link http://phpdoc.org
  12008. */
  12009. namespace PHPUnit\phpDocumentor\Reflection\Types;
  12010. use ArrayIterator;
  12011. use InvalidArgumentException;
  12012. use ReflectionClass;
  12013. use ReflectionClassConstant;
  12014. use ReflectionMethod;
  12015. use ReflectionParameter;
  12016. use ReflectionProperty;
  12017. use Reflector;
  12018. use RuntimeException;
  12019. use UnexpectedValueException;
  12020. use function file_exists;
  12021. use function file_get_contents;
  12022. use function get_class;
  12023. use function in_array;
  12024. use function is_string;
  12025. use function token_get_all;
  12026. use function trim;
  12027. use const T_AS;
  12028. use const T_CLASS;
  12029. use const T_CURLY_OPEN;
  12030. use const T_DOLLAR_OPEN_CURLY_BRACES;
  12031. use const T_NAMESPACE;
  12032. use const T_NS_SEPARATOR;
  12033. use const T_STRING;
  12034. use const T_USE;
  12035. /**
  12036. * Convenience class to create a Context for DocBlocks when not using the Reflection Component of phpDocumentor.
  12037. *
  12038. * For a DocBlock to be able to resolve types that use partial namespace names or rely on namespace imports we need to
  12039. * provide a bit of context so that the DocBlock can read that and based on it decide how to resolve the types to
  12040. * Fully Qualified names.
  12041. *
  12042. * @see Context for more information.
  12043. */
  12044. final class ContextFactory
  12045. {
  12046. /** The literal used at the end of a use statement. */
  12047. private const T_LITERAL_END_OF_USE = ';';
  12048. /** The literal used between sets of use statements */
  12049. private const T_LITERAL_USE_SEPARATOR = ',';
  12050. /**
  12051. * Build a Context given a Class Reflection.
  12052. *
  12053. * @see Context for more information on Contexts.
  12054. */
  12055. public function createFromReflector(\Reflector $reflector) : \PHPUnit\phpDocumentor\Reflection\Types\Context
  12056. {
  12057. if ($reflector instanceof \ReflectionClass) {
  12058. //phpcs:ignore SlevomatCodingStandard.Commenting.InlineDocCommentDeclaration.MissingVariable
  12059. /** @var ReflectionClass<object> $reflector */
  12060. return $this->createFromReflectionClass($reflector);
  12061. }
  12062. if ($reflector instanceof \ReflectionParameter) {
  12063. return $this->createFromReflectionParameter($reflector);
  12064. }
  12065. if ($reflector instanceof \ReflectionMethod) {
  12066. return $this->createFromReflectionMethod($reflector);
  12067. }
  12068. if ($reflector instanceof \ReflectionProperty) {
  12069. return $this->createFromReflectionProperty($reflector);
  12070. }
  12071. if ($reflector instanceof \ReflectionClassConstant) {
  12072. return $this->createFromReflectionClassConstant($reflector);
  12073. }
  12074. throw new \UnexpectedValueException('Unhandled \\Reflector instance given: ' . \get_class($reflector));
  12075. }
  12076. private function createFromReflectionParameter(\ReflectionParameter $parameter) : \PHPUnit\phpDocumentor\Reflection\Types\Context
  12077. {
  12078. $class = $parameter->getDeclaringClass();
  12079. if (!$class) {
  12080. throw new \InvalidArgumentException('Unable to get class of ' . $parameter->getName());
  12081. }
  12082. //phpcs:ignore SlevomatCodingStandard.Commenting.InlineDocCommentDeclaration.MissingVariable
  12083. /** @var ReflectionClass<object> $class */
  12084. return $this->createFromReflectionClass($class);
  12085. }
  12086. private function createFromReflectionMethod(\ReflectionMethod $method) : \PHPUnit\phpDocumentor\Reflection\Types\Context
  12087. {
  12088. //phpcs:ignore SlevomatCodingStandard.Commenting.InlineDocCommentDeclaration.MissingVariable
  12089. /** @var ReflectionClass<object> $class */
  12090. $class = $method->getDeclaringClass();
  12091. return $this->createFromReflectionClass($class);
  12092. }
  12093. private function createFromReflectionProperty(\ReflectionProperty $property) : \PHPUnit\phpDocumentor\Reflection\Types\Context
  12094. {
  12095. //phpcs:ignore SlevomatCodingStandard.Commenting.InlineDocCommentDeclaration.MissingVariable
  12096. /** @var ReflectionClass<object> $class */
  12097. $class = $property->getDeclaringClass();
  12098. return $this->createFromReflectionClass($class);
  12099. }
  12100. private function createFromReflectionClassConstant(\ReflectionClassConstant $constant) : \PHPUnit\phpDocumentor\Reflection\Types\Context
  12101. {
  12102. //phpcs:ignore SlevomatCodingStandard.Commenting.InlineDocCommentDeclaration.MissingVariable
  12103. /** @var ReflectionClass<object> $class */
  12104. $class = $constant->getDeclaringClass();
  12105. return $this->createFromReflectionClass($class);
  12106. }
  12107. /**
  12108. * @param ReflectionClass<object> $class
  12109. */
  12110. private function createFromReflectionClass(\ReflectionClass $class) : \PHPUnit\phpDocumentor\Reflection\Types\Context
  12111. {
  12112. $fileName = $class->getFileName();
  12113. $namespace = $class->getNamespaceName();
  12114. if (\is_string($fileName) && \file_exists($fileName)) {
  12115. $contents = \file_get_contents($fileName);
  12116. if ($contents === \false) {
  12117. throw new \RuntimeException('Unable to read file "' . $fileName . '"');
  12118. }
  12119. return $this->createForNamespace($namespace, $contents);
  12120. }
  12121. return new \PHPUnit\phpDocumentor\Reflection\Types\Context($namespace, []);
  12122. }
  12123. /**
  12124. * Build a Context for a namespace in the provided file contents.
  12125. *
  12126. * @see Context for more information on Contexts.
  12127. *
  12128. * @param string $namespace It does not matter if a `\` precedes the namespace name,
  12129. * this method first normalizes.
  12130. * @param string $fileContents The file's contents to retrieve the aliases from with the given namespace.
  12131. */
  12132. public function createForNamespace(string $namespace, string $fileContents) : \PHPUnit\phpDocumentor\Reflection\Types\Context
  12133. {
  12134. $namespace = \trim($namespace, '\\');
  12135. $useStatements = [];
  12136. $currentNamespace = '';
  12137. $tokens = new \ArrayIterator(\token_get_all($fileContents));
  12138. while ($tokens->valid()) {
  12139. $currentToken = $tokens->current();
  12140. switch ($currentToken[0]) {
  12141. case \T_NAMESPACE:
  12142. $currentNamespace = $this->parseNamespace($tokens);
  12143. break;
  12144. case \T_CLASS:
  12145. // Fast-forward the iterator through the class so that any
  12146. // T_USE tokens found within are skipped - these are not
  12147. // valid namespace use statements so should be ignored.
  12148. $braceLevel = 0;
  12149. $firstBraceFound = \false;
  12150. while ($tokens->valid() && ($braceLevel > 0 || !$firstBraceFound)) {
  12151. $currentToken = $tokens->current();
  12152. if ($currentToken === '{' || \in_array($currentToken[0], [\T_CURLY_OPEN, \T_DOLLAR_OPEN_CURLY_BRACES], \true)) {
  12153. if (!$firstBraceFound) {
  12154. $firstBraceFound = \true;
  12155. }
  12156. ++$braceLevel;
  12157. }
  12158. if ($currentToken === '}') {
  12159. --$braceLevel;
  12160. }
  12161. $tokens->next();
  12162. }
  12163. break;
  12164. case \T_USE:
  12165. if ($currentNamespace === $namespace) {
  12166. $useStatements += $this->parseUseStatement($tokens);
  12167. }
  12168. break;
  12169. }
  12170. $tokens->next();
  12171. }
  12172. return new \PHPUnit\phpDocumentor\Reflection\Types\Context($namespace, $useStatements);
  12173. }
  12174. /**
  12175. * Deduce the name from tokens when we are at the T_NAMESPACE token.
  12176. *
  12177. * @param ArrayIterator<int, string|array{0:int,1:string,2:int}> $tokens
  12178. */
  12179. private function parseNamespace(\ArrayIterator $tokens) : string
  12180. {
  12181. // skip to the first string or namespace separator
  12182. $this->skipToNextStringOrNamespaceSeparator($tokens);
  12183. $name = '';
  12184. while ($tokens->valid() && \in_array($tokens->current()[0], [\T_STRING, \T_NS_SEPARATOR], \true)) {
  12185. $name .= $tokens->current()[1];
  12186. $tokens->next();
  12187. }
  12188. return $name;
  12189. }
  12190. /**
  12191. * Deduce the names of all imports when we are at the T_USE token.
  12192. *
  12193. * @param ArrayIterator<int, string|array{0:int,1:string,2:int}> $tokens
  12194. *
  12195. * @return string[]
  12196. *
  12197. * @psalm-return array<string, string>
  12198. */
  12199. private function parseUseStatement(\ArrayIterator $tokens) : array
  12200. {
  12201. $uses = [];
  12202. while ($tokens->valid()) {
  12203. $this->skipToNextStringOrNamespaceSeparator($tokens);
  12204. $uses += $this->extractUseStatements($tokens);
  12205. $currentToken = $tokens->current();
  12206. if ($currentToken[0] === self::T_LITERAL_END_OF_USE) {
  12207. return $uses;
  12208. }
  12209. }
  12210. return $uses;
  12211. }
  12212. /**
  12213. * Fast-forwards the iterator as longs as we don't encounter a T_STRING or T_NS_SEPARATOR token.
  12214. *
  12215. * @param ArrayIterator<int, string|array{0:int,1:string,2:int}> $tokens
  12216. */
  12217. private function skipToNextStringOrNamespaceSeparator(\ArrayIterator $tokens) : void
  12218. {
  12219. while ($tokens->valid()) {
  12220. $currentToken = $tokens->current();
  12221. if (\in_array($currentToken[0], [\T_STRING, \T_NS_SEPARATOR], \true)) {
  12222. break;
  12223. }
  12224. $tokens->next();
  12225. }
  12226. }
  12227. /**
  12228. * Deduce the namespace name and alias of an import when we are at the T_USE token or have not reached the end of
  12229. * a USE statement yet. This will return a key/value array of the alias => namespace.
  12230. *
  12231. * @param ArrayIterator<int, string|array{0:int,1:string,2:int}> $tokens
  12232. *
  12233. * @return string[]
  12234. *
  12235. * @psalm-suppress TypeDoesNotContainType
  12236. *
  12237. * @psalm-return array<string, string>
  12238. */
  12239. private function extractUseStatements(\ArrayIterator $tokens) : array
  12240. {
  12241. $extractedUseStatements = [];
  12242. $groupedNs = '';
  12243. $currentNs = '';
  12244. $currentAlias = '';
  12245. $state = 'start';
  12246. while ($tokens->valid()) {
  12247. $currentToken = $tokens->current();
  12248. $tokenId = \is_string($currentToken) ? $currentToken : $currentToken[0];
  12249. $tokenValue = \is_string($currentToken) ? null : $currentToken[1];
  12250. switch ($state) {
  12251. case 'start':
  12252. switch ($tokenId) {
  12253. case \T_STRING:
  12254. case \T_NS_SEPARATOR:
  12255. $currentNs .= (string) $tokenValue;
  12256. $currentAlias = $tokenValue;
  12257. break;
  12258. case \T_CURLY_OPEN:
  12259. case '{':
  12260. $state = 'grouped';
  12261. $groupedNs = $currentNs;
  12262. break;
  12263. case \T_AS:
  12264. $state = 'start-alias';
  12265. break;
  12266. case self::T_LITERAL_USE_SEPARATOR:
  12267. case self::T_LITERAL_END_OF_USE:
  12268. $state = 'end';
  12269. break;
  12270. default:
  12271. break;
  12272. }
  12273. break;
  12274. case 'start-alias':
  12275. switch ($tokenId) {
  12276. case \T_STRING:
  12277. $currentAlias = $tokenValue;
  12278. break;
  12279. case self::T_LITERAL_USE_SEPARATOR:
  12280. case self::T_LITERAL_END_OF_USE:
  12281. $state = 'end';
  12282. break;
  12283. default:
  12284. break;
  12285. }
  12286. break;
  12287. case 'grouped':
  12288. switch ($tokenId) {
  12289. case \T_STRING:
  12290. case \T_NS_SEPARATOR:
  12291. $currentNs .= (string) $tokenValue;
  12292. $currentAlias = $tokenValue;
  12293. break;
  12294. case \T_AS:
  12295. $state = 'grouped-alias';
  12296. break;
  12297. case self::T_LITERAL_USE_SEPARATOR:
  12298. $state = 'grouped';
  12299. $extractedUseStatements[(string) $currentAlias] = $currentNs;
  12300. $currentNs = $groupedNs;
  12301. $currentAlias = '';
  12302. break;
  12303. case self::T_LITERAL_END_OF_USE:
  12304. $state = 'end';
  12305. break;
  12306. default:
  12307. break;
  12308. }
  12309. break;
  12310. case 'grouped-alias':
  12311. switch ($tokenId) {
  12312. case \T_STRING:
  12313. $currentAlias = $tokenValue;
  12314. break;
  12315. case self::T_LITERAL_USE_SEPARATOR:
  12316. $state = 'grouped';
  12317. $extractedUseStatements[(string) $currentAlias] = $currentNs;
  12318. $currentNs = $groupedNs;
  12319. $currentAlias = '';
  12320. break;
  12321. case self::T_LITERAL_END_OF_USE:
  12322. $state = 'end';
  12323. break;
  12324. default:
  12325. break;
  12326. }
  12327. }
  12328. if ($state === 'end') {
  12329. break;
  12330. }
  12331. $tokens->next();
  12332. }
  12333. if ($groupedNs !== $currentNs) {
  12334. $extractedUseStatements[(string) $currentAlias] = $currentNs;
  12335. }
  12336. return $extractedUseStatements;
  12337. }
  12338. }
  12339. <?php
  12340. declare (strict_types=1);
  12341. /**
  12342. * This file is part of phpDocumentor.
  12343. *
  12344. * For the full copyright and license information, please view the LICENSE
  12345. * file that was distributed with this source code.
  12346. *
  12347. * @link http://phpdoc.org
  12348. */
  12349. namespace PHPUnit\phpDocumentor\Reflection\Types;
  12350. use PHPUnit\phpDocumentor\Reflection\Type;
  12351. /**
  12352. * Represents a list of values. This is an abstract class for Array_ and Collection.
  12353. *
  12354. * @psalm-immutable
  12355. */
  12356. abstract class AbstractList implements \PHPUnit\phpDocumentor\Reflection\Type
  12357. {
  12358. /** @var Type */
  12359. protected $valueType;
  12360. /** @var Type|null */
  12361. protected $keyType;
  12362. /** @var Type */
  12363. protected $defaultKeyType;
  12364. /**
  12365. * Initializes this representation of an array with the given Type.
  12366. */
  12367. public function __construct(?\PHPUnit\phpDocumentor\Reflection\Type $valueType = null, ?\PHPUnit\phpDocumentor\Reflection\Type $keyType = null)
  12368. {
  12369. if ($valueType === null) {
  12370. $valueType = new \PHPUnit\phpDocumentor\Reflection\Types\Mixed_();
  12371. }
  12372. $this->valueType = $valueType;
  12373. $this->defaultKeyType = new \PHPUnit\phpDocumentor\Reflection\Types\Compound([new \PHPUnit\phpDocumentor\Reflection\Types\String_(), new \PHPUnit\phpDocumentor\Reflection\Types\Integer()]);
  12374. $this->keyType = $keyType;
  12375. }
  12376. /**
  12377. * Returns the type for the keys of this array.
  12378. */
  12379. public function getKeyType() : \PHPUnit\phpDocumentor\Reflection\Type
  12380. {
  12381. return $this->keyType ?? $this->defaultKeyType;
  12382. }
  12383. /**
  12384. * Returns the value for the keys of this array.
  12385. */
  12386. public function getValueType() : \PHPUnit\phpDocumentor\Reflection\Type
  12387. {
  12388. return $this->valueType;
  12389. }
  12390. /**
  12391. * Returns a rendered output of the Type as it would be used in a DocBlock.
  12392. */
  12393. public function __toString() : string
  12394. {
  12395. if ($this->keyType) {
  12396. return 'array<' . $this->keyType . ',' . $this->valueType . '>';
  12397. }
  12398. if ($this->valueType instanceof \PHPUnit\phpDocumentor\Reflection\Types\Mixed_) {
  12399. return 'array';
  12400. }
  12401. if ($this->valueType instanceof \PHPUnit\phpDocumentor\Reflection\Types\Compound) {
  12402. return '(' . $this->valueType . ')[]';
  12403. }
  12404. return $this->valueType . '[]';
  12405. }
  12406. }
  12407. <?php
  12408. /**
  12409. * This file is part of phpDocumentor.
  12410. *
  12411. * For the full copyright and license information, please view the LICENSE
  12412. * file that was distributed with this source code.
  12413. *
  12414. * @link http://phpdoc.org
  12415. */
  12416. declare (strict_types=1);
  12417. namespace PHPUnit\phpDocumentor\Reflection\Types;
  12418. /**
  12419. * Value Object representing a False pseudo type.
  12420. *
  12421. * @psalm-immutable
  12422. */
  12423. class False_ extends \PHPUnit\phpDocumentor\Reflection\Types\Boolean
  12424. {
  12425. /**
  12426. * Returns a rendered output of the Type as it would be used in a DocBlock.
  12427. */
  12428. public function __toString() : string
  12429. {
  12430. return 'false';
  12431. }
  12432. }
  12433. <?php
  12434. declare (strict_types=1);
  12435. /**
  12436. * This file is part of phpDocumentor.
  12437. *
  12438. * For the full copyright and license information, please view the LICENSE
  12439. * file that was distributed with this source code.
  12440. *
  12441. * @link http://phpdoc.org
  12442. */
  12443. namespace PHPUnit\phpDocumentor\Reflection\Types;
  12444. use PHPUnit\phpDocumentor\Reflection\Type;
  12445. /**
  12446. * Value Object representing the type 'string'.
  12447. *
  12448. * @psalm-immutable
  12449. */
  12450. final class String_ implements \PHPUnit\phpDocumentor\Reflection\Type
  12451. {
  12452. /**
  12453. * Returns a rendered output of the Type as it would be used in a DocBlock.
  12454. */
  12455. public function __toString() : string
  12456. {
  12457. return 'string';
  12458. }
  12459. }
  12460. <?php
  12461. /**
  12462. * This file is part of phpDocumentor.
  12463. *
  12464. * For the full copyright and license information, please view the LICENSE
  12465. * file that was distributed with this source code.
  12466. *
  12467. * @link http://phpdoc.org
  12468. */
  12469. declare (strict_types=1);
  12470. namespace PHPUnit\phpDocumentor\Reflection\Types;
  12471. /**
  12472. * Value Object representing a True pseudo type.
  12473. *
  12474. * @psalm-immutable
  12475. */
  12476. class True_ extends \PHPUnit\phpDocumentor\Reflection\Types\Boolean
  12477. {
  12478. /**
  12479. * Returns a rendered output of the Type as it would be used in a DocBlock.
  12480. */
  12481. public function __toString() : string
  12482. {
  12483. return 'true';
  12484. }
  12485. }
  12486. <?php
  12487. declare (strict_types=1);
  12488. /**
  12489. * This file is part of phpDocumentor.
  12490. *
  12491. * For the full copyright and license information, please view the LICENSE
  12492. * file that was distributed with this source code.
  12493. *
  12494. * @link http://phpdoc.org
  12495. */
  12496. namespace PHPUnit\phpDocumentor\Reflection\Types;
  12497. use PHPUnit\phpDocumentor\Reflection\Fqsen;
  12498. use PHPUnit\phpDocumentor\Reflection\Type;
  12499. /**
  12500. * Value Object representing the type 'string'.
  12501. *
  12502. * @psalm-immutable
  12503. */
  12504. final class ClassString implements \PHPUnit\phpDocumentor\Reflection\Type
  12505. {
  12506. /** @var Fqsen|null */
  12507. private $fqsen;
  12508. /**
  12509. * Initializes this representation of a class string with the given Fqsen.
  12510. */
  12511. public function __construct(?\PHPUnit\phpDocumentor\Reflection\Fqsen $fqsen = null)
  12512. {
  12513. $this->fqsen = $fqsen;
  12514. }
  12515. /**
  12516. * Returns the FQSEN associated with this object.
  12517. */
  12518. public function getFqsen() : ?\PHPUnit\phpDocumentor\Reflection\Fqsen
  12519. {
  12520. return $this->fqsen;
  12521. }
  12522. /**
  12523. * Returns a rendered output of the Type as it would be used in a DocBlock.
  12524. */
  12525. public function __toString() : string
  12526. {
  12527. if ($this->fqsen === null) {
  12528. return 'class-string';
  12529. }
  12530. return 'class-string<' . (string) $this->fqsen . '>';
  12531. }
  12532. }
  12533. <?php
  12534. declare (strict_types=1);
  12535. /**
  12536. * This file is part of phpDocumentor.
  12537. *
  12538. * For the full copyright and license information, please view the LICENSE
  12539. * file that was distributed with this source code.
  12540. *
  12541. * @link http://phpdoc.org
  12542. */
  12543. namespace PHPUnit\phpDocumentor\Reflection\Types;
  12544. use PHPUnit\phpDocumentor\Reflection\Type;
  12545. /**
  12546. * Value Object representing the 'self' type.
  12547. *
  12548. * Self, as a Type, represents the class in which the associated element was defined.
  12549. *
  12550. * @psalm-immutable
  12551. */
  12552. final class Self_ implements \PHPUnit\phpDocumentor\Reflection\Type
  12553. {
  12554. /**
  12555. * Returns a rendered output of the Type as it would be used in a DocBlock.
  12556. */
  12557. public function __toString() : string
  12558. {
  12559. return 'self';
  12560. }
  12561. }
  12562. <?php
  12563. declare (strict_types=1);
  12564. /**
  12565. * This file is part of phpDocumentor.
  12566. *
  12567. * For the full copyright and license information, please view the LICENSE
  12568. * file that was distributed with this source code.
  12569. *
  12570. * @link http://phpdoc.org
  12571. */
  12572. namespace PHPUnit\phpDocumentor\Reflection\Types;
  12573. use PHPUnit\phpDocumentor\Reflection\Type;
  12574. /**
  12575. * Value Object representing a Float.
  12576. *
  12577. * @psalm-immutable
  12578. */
  12579. final class Float_ implements \PHPUnit\phpDocumentor\Reflection\Type
  12580. {
  12581. /**
  12582. * Returns a rendered output of the Type as it would be used in a DocBlock.
  12583. */
  12584. public function __toString() : string
  12585. {
  12586. return 'float';
  12587. }
  12588. }
  12589. <?php
  12590. declare (strict_types=1);
  12591. /**
  12592. * This file is part of phpDocumentor.
  12593. *
  12594. * For the full copyright and license information, please view the LICENSE
  12595. * file that was distributed with this source code.
  12596. *
  12597. * @link http://phpdoc.org
  12598. */
  12599. namespace PHPUnit\phpDocumentor\Reflection\Types;
  12600. use PHPUnit\phpDocumentor\Reflection\Type;
  12601. /**
  12602. * Value Object representing the 'static' type.
  12603. *
  12604. * Self, as a Type, represents the class in which the associated element was called. This differs from self as self does
  12605. * not take inheritance into account but static means that the return type is always that of the class of the called
  12606. * element.
  12607. *
  12608. * See the documentation on late static binding in the PHP Documentation for more information on the difference between
  12609. * static and self.
  12610. *
  12611. * @psalm-immutable
  12612. */
  12613. final class Static_ implements \PHPUnit\phpDocumentor\Reflection\Type
  12614. {
  12615. /**
  12616. * Returns a rendered output of the Type as it would be used in a DocBlock.
  12617. */
  12618. public function __toString() : string
  12619. {
  12620. return 'static';
  12621. }
  12622. }
  12623. <?php
  12624. declare (strict_types=1);
  12625. /**
  12626. * This file is part of phpDocumentor.
  12627. *
  12628. * For the full copyright and license information, please view the LICENSE
  12629. * file that was distributed with this source code.
  12630. *
  12631. * @link http://phpdoc.org
  12632. */
  12633. namespace PHPUnit\phpDocumentor\Reflection\Types;
  12634. use function strlen;
  12635. use function substr;
  12636. use function trim;
  12637. /**
  12638. * Provides information about the Context in which the DocBlock occurs that receives this context.
  12639. *
  12640. * A DocBlock does not know of its own accord in which namespace it occurs and which namespace aliases are applicable
  12641. * for the block of code in which it is in. This information is however necessary to resolve Class names in tags since
  12642. * you can provide a short form or make use of namespace aliases.
  12643. *
  12644. * The phpDocumentor Reflection component knows how to create this class but if you use the DocBlock parser from your
  12645. * own application it is possible to generate a Context class using the ContextFactory; this will analyze the file in
  12646. * which an associated class resides for its namespace and imports.
  12647. *
  12648. * @see ContextFactory::createFromClassReflector()
  12649. * @see ContextFactory::createForNamespace()
  12650. *
  12651. * @psalm-immutable
  12652. */
  12653. final class Context
  12654. {
  12655. /** @var string The current namespace. */
  12656. private $namespace;
  12657. /**
  12658. * @var string[] List of namespace aliases => Fully Qualified Namespace.
  12659. * @psalm-var array<string, string>
  12660. */
  12661. private $namespaceAliases;
  12662. /**
  12663. * Initializes the new context and normalizes all passed namespaces to be in Qualified Namespace Name (QNN)
  12664. * format (without a preceding `\`).
  12665. *
  12666. * @param string $namespace The namespace where this DocBlock resides in.
  12667. * @param string[] $namespaceAliases List of namespace aliases => Fully Qualified Namespace.
  12668. *
  12669. * @psalm-param array<string, string> $namespaceAliases
  12670. */
  12671. public function __construct(string $namespace, array $namespaceAliases = [])
  12672. {
  12673. $this->namespace = $namespace !== 'global' && $namespace !== 'default' ? \trim($namespace, '\\') : '';
  12674. foreach ($namespaceAliases as $alias => $fqnn) {
  12675. if ($fqnn[0] === '\\') {
  12676. $fqnn = \substr($fqnn, 1);
  12677. }
  12678. if ($fqnn[\strlen($fqnn) - 1] === '\\') {
  12679. $fqnn = \substr($fqnn, 0, -1);
  12680. }
  12681. $namespaceAliases[$alias] = $fqnn;
  12682. }
  12683. $this->namespaceAliases = $namespaceAliases;
  12684. }
  12685. /**
  12686. * Returns the Qualified Namespace Name (thus without `\` in front) where the associated element is in.
  12687. */
  12688. public function getNamespace() : string
  12689. {
  12690. return $this->namespace;
  12691. }
  12692. /**
  12693. * Returns a list of Qualified Namespace Names (thus without `\` in front) that are imported, the keys represent
  12694. * the alias for the imported Namespace.
  12695. *
  12696. * @return string[]
  12697. *
  12698. * @psalm-return array<string, string>
  12699. */
  12700. public function getNamespaceAliases() : array
  12701. {
  12702. return $this->namespaceAliases;
  12703. }
  12704. }
  12705. <?php
  12706. declare (strict_types=1);
  12707. /**
  12708. * This file is part of phpDocumentor.
  12709. *
  12710. * For the full copyright and license information, please view the LICENSE
  12711. * file that was distributed with this source code.
  12712. *
  12713. * @link http://phpdoc.org
  12714. */
  12715. namespace PHPUnit\phpDocumentor\Reflection\Types;
  12716. /**
  12717. * Represents an array type as described in the PSR-5, the PHPDoc Standard.
  12718. *
  12719. * An array can be represented in two forms:
  12720. *
  12721. * 1. Untyped (`array`), where the key and value type is unknown and hence classified as 'Mixed_'.
  12722. * 2. Types (`string[]`), where the value type is provided by preceding an opening and closing square bracket with a
  12723. * type name.
  12724. *
  12725. * @psalm-immutable
  12726. */
  12727. final class Array_ extends \PHPUnit\phpDocumentor\Reflection\Types\AbstractList
  12728. {
  12729. }
  12730. <?php
  12731. declare (strict_types=1);
  12732. /**
  12733. * This file is part of phpDocumentor.
  12734. *
  12735. * For the full copyright and license information, please view the LICENSE
  12736. * file that was distributed with this source code.
  12737. *
  12738. * @link http://phpdoc.org
  12739. */
  12740. namespace PHPUnit\phpDocumentor\Reflection\Types;
  12741. use InvalidArgumentException;
  12742. use PHPUnit\phpDocumentor\Reflection\Fqsen;
  12743. use PHPUnit\phpDocumentor\Reflection\Type;
  12744. use function strpos;
  12745. /**
  12746. * Value Object representing an object.
  12747. *
  12748. * An object can be either typed or untyped. When an object is typed it means that it has an identifier, the FQSEN,
  12749. * pointing to an element in PHP. Object types that are untyped do not refer to a specific class but represent objects
  12750. * in general.
  12751. *
  12752. * @psalm-immutable
  12753. */
  12754. final class Object_ implements \PHPUnit\phpDocumentor\Reflection\Type
  12755. {
  12756. /** @var Fqsen|null */
  12757. private $fqsen;
  12758. /**
  12759. * Initializes this object with an optional FQSEN, if not provided this object is considered 'untyped'.
  12760. *
  12761. * @throws InvalidArgumentException When provided $fqsen is not a valid type.
  12762. */
  12763. public function __construct(?\PHPUnit\phpDocumentor\Reflection\Fqsen $fqsen = null)
  12764. {
  12765. if (\strpos((string) $fqsen, '::') !== \false || \strpos((string) $fqsen, '()') !== \false) {
  12766. throw new \InvalidArgumentException('Object types can only refer to a class, interface or trait but a method, function, constant or ' . 'property was received: ' . (string) $fqsen);
  12767. }
  12768. $this->fqsen = $fqsen;
  12769. }
  12770. /**
  12771. * Returns the FQSEN associated with this object.
  12772. */
  12773. public function getFqsen() : ?\PHPUnit\phpDocumentor\Reflection\Fqsen
  12774. {
  12775. return $this->fqsen;
  12776. }
  12777. public function __toString() : string
  12778. {
  12779. if ($this->fqsen) {
  12780. return (string) $this->fqsen;
  12781. }
  12782. return 'object';
  12783. }
  12784. }
  12785. <?php
  12786. declare (strict_types=1);
  12787. /**
  12788. * This file is part of phpDocumentor.
  12789. *
  12790. * For the full copyright and license information, please view the LICENSE
  12791. * file that was distributed with this source code.
  12792. *
  12793. * @link http://phpdoc.org
  12794. */
  12795. namespace PHPUnit\phpDocumentor\Reflection\Types;
  12796. use PHPUnit\phpDocumentor\Reflection\Type;
  12797. /**
  12798. * Value Object representing a Callable type.
  12799. *
  12800. * @psalm-immutable
  12801. */
  12802. final class Callable_ implements \PHPUnit\phpDocumentor\Reflection\Type
  12803. {
  12804. /**
  12805. * Returns a rendered output of the Type as it would be used in a DocBlock.
  12806. */
  12807. public function __toString() : string
  12808. {
  12809. return 'callable';
  12810. }
  12811. }
  12812. <?php
  12813. declare (strict_types=1);
  12814. /**
  12815. * This file is part of phpDocumentor.
  12816. *
  12817. * For the full copyright and license information, please view the LICENSE
  12818. * file that was distributed with this source code.
  12819. *
  12820. * @link http://phpdoc.org
  12821. */
  12822. namespace PHPUnit\phpDocumentor\Reflection\Types;
  12823. use PHPUnit\phpDocumentor\Reflection\Fqsen;
  12824. use PHPUnit\phpDocumentor\Reflection\Type;
  12825. /**
  12826. * Represents a collection type as described in the PSR-5, the PHPDoc Standard.
  12827. *
  12828. * A collection can be represented in two forms:
  12829. *
  12830. * 1. `ACollectionObject<aValueType>`
  12831. * 2. `ACollectionObject<aValueType,aKeyType>`
  12832. *
  12833. * - ACollectionObject can be 'array' or an object that can act as an array
  12834. * - aValueType and aKeyType can be any type expression
  12835. *
  12836. * @psalm-immutable
  12837. */
  12838. final class Collection extends \PHPUnit\phpDocumentor\Reflection\Types\AbstractList
  12839. {
  12840. /** @var Fqsen|null */
  12841. private $fqsen;
  12842. /**
  12843. * Initializes this representation of an array with the given Type or Fqsen.
  12844. */
  12845. public function __construct(?\PHPUnit\phpDocumentor\Reflection\Fqsen $fqsen, \PHPUnit\phpDocumentor\Reflection\Type $valueType, ?\PHPUnit\phpDocumentor\Reflection\Type $keyType = null)
  12846. {
  12847. parent::__construct($valueType, $keyType);
  12848. $this->fqsen = $fqsen;
  12849. }
  12850. /**
  12851. * Returns the FQSEN associated with this object.
  12852. */
  12853. public function getFqsen() : ?\PHPUnit\phpDocumentor\Reflection\Fqsen
  12854. {
  12855. return $this->fqsen;
  12856. }
  12857. /**
  12858. * Returns a rendered output of the Type as it would be used in a DocBlock.
  12859. */
  12860. public function __toString() : string
  12861. {
  12862. $objectType = (string) ($this->fqsen ?? 'object');
  12863. if ($this->keyType === null) {
  12864. return $objectType . '<' . $this->valueType . '>';
  12865. }
  12866. return $objectType . '<' . $this->keyType . ',' . $this->valueType . '>';
  12867. }
  12868. }
  12869. <?php
  12870. declare (strict_types=1);
  12871. /**
  12872. * This file is part of phpDocumentor.
  12873. *
  12874. * For the full copyright and license information, please view the LICENSE
  12875. * file that was distributed with this source code.
  12876. *
  12877. * @link http://phpdoc.org
  12878. */
  12879. namespace PHPUnit\phpDocumentor\Reflection\Types;
  12880. use PHPUnit\phpDocumentor\Reflection\Type;
  12881. /**
  12882. * Value Object representing the 'scalar' pseudo-type, which is either a string, integer, float or boolean.
  12883. *
  12884. * @psalm-immutable
  12885. */
  12886. final class Scalar implements \PHPUnit\phpDocumentor\Reflection\Type
  12887. {
  12888. /**
  12889. * Returns a rendered output of the Type as it would be used in a DocBlock.
  12890. */
  12891. public function __toString() : string
  12892. {
  12893. return 'scalar';
  12894. }
  12895. }
  12896. <?php
  12897. declare (strict_types=1);
  12898. /**
  12899. * This file is part of phpDocumentor.
  12900. *
  12901. * For the full copyright and license information, please view the LICENSE
  12902. * file that was distributed with this source code.
  12903. *
  12904. * @link http://phpdoc.org
  12905. */
  12906. namespace PHPUnit\phpDocumentor\Reflection\Types;
  12907. use PHPUnit\phpDocumentor\Reflection\Type;
  12908. /**
  12909. * Represents an expression type as described in the PSR-5, the PHPDoc Standard.
  12910. *
  12911. * @psalm-immutable
  12912. */
  12913. final class Expression implements \PHPUnit\phpDocumentor\Reflection\Type
  12914. {
  12915. /** @var Type */
  12916. protected $valueType;
  12917. /**
  12918. * Initializes this representation of an array with the given Type.
  12919. */
  12920. public function __construct(\PHPUnit\phpDocumentor\Reflection\Type $valueType)
  12921. {
  12922. $this->valueType = $valueType;
  12923. }
  12924. /**
  12925. * Returns the value for the keys of this array.
  12926. */
  12927. public function getValueType() : \PHPUnit\phpDocumentor\Reflection\Type
  12928. {
  12929. return $this->valueType;
  12930. }
  12931. /**
  12932. * Returns a rendered output of the Type as it would be used in a DocBlock.
  12933. */
  12934. public function __toString() : string
  12935. {
  12936. return '(' . $this->valueType . ')';
  12937. }
  12938. }
  12939. <?php
  12940. declare (strict_types=1);
  12941. /**
  12942. * This file is part of phpDocumentor.
  12943. *
  12944. * For the full copyright and license information, please view the LICENSE
  12945. * file that was distributed with this source code.
  12946. *
  12947. * @link http://phpdoc.org
  12948. */
  12949. namespace PHPUnit\phpDocumentor\Reflection\Types;
  12950. use PHPUnit\phpDocumentor\Reflection\Type;
  12951. /**
  12952. * Value Object representing an unknown, or mixed, type.
  12953. *
  12954. * @psalm-immutable
  12955. */
  12956. final class Mixed_ implements \PHPUnit\phpDocumentor\Reflection\Type
  12957. {
  12958. /**
  12959. * Returns a rendered output of the Type as it would be used in a DocBlock.
  12960. */
  12961. public function __toString() : string
  12962. {
  12963. return 'mixed';
  12964. }
  12965. }
  12966. <?php
  12967. /**
  12968. * This file is part of phpDocumentor.
  12969. *
  12970. * For the full copyright and license information, please view the LICENSE
  12971. * file that was distributed with this source code.
  12972. *
  12973. * @link http://phpdoc.org
  12974. */
  12975. declare (strict_types=1);
  12976. namespace PHPUnit\phpDocumentor\Reflection\Types;
  12977. use ArrayIterator;
  12978. use IteratorAggregate;
  12979. use PHPUnit\phpDocumentor\Reflection\Type;
  12980. use function array_key_exists;
  12981. use function implode;
  12982. /**
  12983. * Base class for aggregated types like Compound and Intersection
  12984. *
  12985. * A Aggregated Type is not so much a special keyword or object reference but is a series of Types that are separated
  12986. * using separator.
  12987. *
  12988. * @psalm-immutable
  12989. * @template-implements IteratorAggregate<int, Type>
  12990. */
  12991. abstract class AggregatedType implements \PHPUnit\phpDocumentor\Reflection\Type, \IteratorAggregate
  12992. {
  12993. /**
  12994. * @psalm-allow-private-mutation
  12995. * @var array<int, Type>
  12996. */
  12997. private $types = [];
  12998. /** @var string */
  12999. private $token;
  13000. /**
  13001. * @param Type[] $types
  13002. *
  13003. * @phpstan-param list<Type> $types
  13004. */
  13005. public function __construct(array $types, string $token)
  13006. {
  13007. foreach ($types as $type) {
  13008. $this->add($type);
  13009. }
  13010. $this->token = $token;
  13011. }
  13012. /**
  13013. * Returns the type at the given index.
  13014. */
  13015. public function get(int $index) : ?\PHPUnit\phpDocumentor\Reflection\Type
  13016. {
  13017. if (!$this->has($index)) {
  13018. return null;
  13019. }
  13020. return $this->types[$index];
  13021. }
  13022. /**
  13023. * Tests if this compound type has a type with the given index.
  13024. */
  13025. public function has(int $index) : bool
  13026. {
  13027. return \array_key_exists($index, $this->types);
  13028. }
  13029. /**
  13030. * Tests if this compound type contains the given type.
  13031. */
  13032. public function contains(\PHPUnit\phpDocumentor\Reflection\Type $type) : bool
  13033. {
  13034. foreach ($this->types as $typePart) {
  13035. // if the type is duplicate; do not add it
  13036. if ((string) $typePart === (string) $type) {
  13037. return \true;
  13038. }
  13039. }
  13040. return \false;
  13041. }
  13042. /**
  13043. * Returns a rendered output of the Type as it would be used in a DocBlock.
  13044. */
  13045. public function __toString() : string
  13046. {
  13047. return \implode($this->token, $this->types);
  13048. }
  13049. /**
  13050. * @return ArrayIterator<int, Type>
  13051. */
  13052. public function getIterator() : \ArrayIterator
  13053. {
  13054. return new \ArrayIterator($this->types);
  13055. }
  13056. /**
  13057. * @psalm-suppress ImpureMethodCall
  13058. */
  13059. private function add(\PHPUnit\phpDocumentor\Reflection\Type $type) : void
  13060. {
  13061. if ($type instanceof self) {
  13062. foreach ($type->getIterator() as $subType) {
  13063. $this->add($subType);
  13064. }
  13065. return;
  13066. }
  13067. // if the type is duplicate; do not add it
  13068. if ($this->contains($type)) {
  13069. return;
  13070. }
  13071. $this->types[] = $type;
  13072. }
  13073. }
  13074. <?php
  13075. declare (strict_types=1);
  13076. /**
  13077. * This file is part of phpDocumentor.
  13078. *
  13079. * For the full copyright and license information, please view the LICENSE
  13080. * file that was distributed with this source code.
  13081. *
  13082. * @link http://phpdoc.org
  13083. */
  13084. namespace PHPUnit\phpDocumentor\Reflection\Types;
  13085. /**
  13086. * Value Object representing iterable type
  13087. *
  13088. * @psalm-immutable
  13089. */
  13090. final class Iterable_ extends \PHPUnit\phpDocumentor\Reflection\Types\AbstractList
  13091. {
  13092. /**
  13093. * Returns a rendered output of the Type as it would be used in a DocBlock.
  13094. */
  13095. public function __toString() : string
  13096. {
  13097. if ($this->keyType) {
  13098. return 'iterable<' . $this->keyType . ',' . $this->valueType . '>';
  13099. }
  13100. if ($this->valueType instanceof \PHPUnit\phpDocumentor\Reflection\Types\Mixed_) {
  13101. return 'iterable';
  13102. }
  13103. return 'iterable<' . $this->valueType . '>';
  13104. }
  13105. }
  13106. <?php
  13107. /**
  13108. * This file is part of phpDocumentor.
  13109. *
  13110. * For the full copyright and license information, please view the LICENSE
  13111. * file that was distributed with this source code.
  13112. *
  13113. * @link http://phpdoc.org
  13114. */
  13115. declare (strict_types=1);
  13116. namespace PHPUnit\phpDocumentor\Reflection\Types;
  13117. use PHPUnit\phpDocumentor\Reflection\Type;
  13118. /**
  13119. * Value Object representing a Compound Type.
  13120. *
  13121. * A Intersection Type is not so much a special keyword or object reference but is a series of Types that are separated
  13122. * using an AND operator (`&`). This combination of types signifies that whatever is associated with this Intersection
  13123. * type may contain a value with any of the given types.
  13124. *
  13125. * @psalm-immutable
  13126. */
  13127. final class Intersection extends \PHPUnit\phpDocumentor\Reflection\Types\AggregatedType
  13128. {
  13129. /**
  13130. * Initializes a intersection type (i.e. `\A&\B`) and tests if the provided types all implement the Type interface.
  13131. *
  13132. * @param Type[] $types
  13133. *
  13134. * @phpstan-param list<Type> $types
  13135. */
  13136. public function __construct(array $types)
  13137. {
  13138. parent::__construct($types, '&');
  13139. }
  13140. }
  13141. <?php
  13142. declare (strict_types=1);
  13143. /**
  13144. * This file is part of phpDocumentor.
  13145. *
  13146. * For the full copyright and license information, please view the LICENSE
  13147. * file that was distributed with this source code.
  13148. *
  13149. * @link http://phpdoc.org
  13150. */
  13151. namespace PHPUnit\phpDocumentor\Reflection\Types;
  13152. use PHPUnit\phpDocumentor\Reflection\Type;
  13153. /**
  13154. * Value Object representing the '$this' pseudo-type.
  13155. *
  13156. * $this, as a Type, represents the instance of the class associated with the element as it was called. $this is
  13157. * commonly used when documenting fluent interfaces since it represents that the same object is returned.
  13158. *
  13159. * @psalm-immutable
  13160. */
  13161. final class This implements \PHPUnit\phpDocumentor\Reflection\Type
  13162. {
  13163. /**
  13164. * Returns a rendered output of the Type as it would be used in a DocBlock.
  13165. */
  13166. public function __toString() : string
  13167. {
  13168. return '$this';
  13169. }
  13170. }
  13171. <?php
  13172. declare (strict_types=1);
  13173. /**
  13174. * This file is part of phpDocumentor.
  13175. *
  13176. * For the full copyright and license information, please view the LICENSE
  13177. * file that was distributed with this source code.
  13178. *
  13179. * @link http://phpdoc.org
  13180. */
  13181. namespace PHPUnit\phpDocumentor\Reflection\Types;
  13182. use PHPUnit\phpDocumentor\Reflection\Type;
  13183. /**
  13184. * Value Object representing a nullable type. The real type is wrapped.
  13185. *
  13186. * @psalm-immutable
  13187. */
  13188. final class Nullable implements \PHPUnit\phpDocumentor\Reflection\Type
  13189. {
  13190. /** @var Type The actual type that is wrapped */
  13191. private $realType;
  13192. /**
  13193. * Initialises this nullable type using the real type embedded
  13194. */
  13195. public function __construct(\PHPUnit\phpDocumentor\Reflection\Type $realType)
  13196. {
  13197. $this->realType = $realType;
  13198. }
  13199. /**
  13200. * Provide access to the actual type directly, if needed.
  13201. */
  13202. public function getActualType() : \PHPUnit\phpDocumentor\Reflection\Type
  13203. {
  13204. return $this->realType;
  13205. }
  13206. /**
  13207. * Returns a rendered output of the Type as it would be used in a DocBlock.
  13208. */
  13209. public function __toString() : string
  13210. {
  13211. return '?' . $this->realType->__toString();
  13212. }
  13213. }
  13214. <?php
  13215. declare (strict_types=1);
  13216. /**
  13217. * This file is part of phpDocumentor.
  13218. *
  13219. * For the full copyright and license information, please view the LICENSE
  13220. * file that was distributed with this source code.
  13221. *
  13222. * @link http://phpdoc.org
  13223. */
  13224. namespace PHPUnit\phpDocumentor\Reflection;
  13225. use InvalidArgumentException;
  13226. use PHPUnit\phpDocumentor\Reflection\Types\Context;
  13227. use function explode;
  13228. use function implode;
  13229. use function strpos;
  13230. /**
  13231. * Resolver for Fqsen using Context information
  13232. *
  13233. * @psalm-immutable
  13234. */
  13235. class FqsenResolver
  13236. {
  13237. /** @var string Definition of the NAMESPACE operator in PHP */
  13238. private const OPERATOR_NAMESPACE = '\\';
  13239. public function resolve(string $fqsen, ?\PHPUnit\phpDocumentor\Reflection\Types\Context $context = null) : \PHPUnit\phpDocumentor\Reflection\Fqsen
  13240. {
  13241. if ($context === null) {
  13242. $context = new \PHPUnit\phpDocumentor\Reflection\Types\Context('');
  13243. }
  13244. if ($this->isFqsen($fqsen)) {
  13245. return new \PHPUnit\phpDocumentor\Reflection\Fqsen($fqsen);
  13246. }
  13247. return $this->resolvePartialStructuralElementName($fqsen, $context);
  13248. }
  13249. /**
  13250. * Tests whether the given type is a Fully Qualified Structural Element Name.
  13251. */
  13252. private function isFqsen(string $type) : bool
  13253. {
  13254. return \strpos($type, self::OPERATOR_NAMESPACE) === 0;
  13255. }
  13256. /**
  13257. * Resolves a partial Structural Element Name (i.e. `Reflection\DocBlock`) to its FQSEN representation
  13258. * (i.e. `\phpDocumentor\Reflection\DocBlock`) based on the Namespace and aliases mentioned in the Context.
  13259. *
  13260. * @throws InvalidArgumentException When type is not a valid FQSEN.
  13261. */
  13262. private function resolvePartialStructuralElementName(string $type, \PHPUnit\phpDocumentor\Reflection\Types\Context $context) : \PHPUnit\phpDocumentor\Reflection\Fqsen
  13263. {
  13264. $typeParts = \explode(self::OPERATOR_NAMESPACE, $type, 2);
  13265. $namespaceAliases = $context->getNamespaceAliases();
  13266. // if the first segment is not an alias; prepend namespace name and return
  13267. if (!isset($namespaceAliases[$typeParts[0]])) {
  13268. $namespace = $context->getNamespace();
  13269. if ($namespace !== '') {
  13270. $namespace .= self::OPERATOR_NAMESPACE;
  13271. }
  13272. return new \PHPUnit\phpDocumentor\Reflection\Fqsen(self::OPERATOR_NAMESPACE . $namespace . $type);
  13273. }
  13274. $typeParts[0] = $namespaceAliases[$typeParts[0]];
  13275. return new \PHPUnit\phpDocumentor\Reflection\Fqsen(self::OPERATOR_NAMESPACE . \implode(self::OPERATOR_NAMESPACE, $typeParts));
  13276. }
  13277. }
  13278. <?php
  13279. declare (strict_types=1);
  13280. /**
  13281. * This file is part of phpDocumentor.
  13282. *
  13283. * For the full copyright and license information, please view the LICENSE
  13284. * file that was distributed with this source code.
  13285. *
  13286. * @link http://phpdoc.org
  13287. */
  13288. namespace PHPUnit\phpDocumentor\Reflection;
  13289. /**
  13290. * @psalm-immutable
  13291. */
  13292. interface Type
  13293. {
  13294. /**
  13295. * Returns a rendered output of the Type as it would be used in a DocBlock.
  13296. */
  13297. public function __toString() : string;
  13298. }
  13299. The MIT License (MIT)
  13300. Copyright (c) 2010 Mike van Riel
  13301. Permission is hereby granted, free of charge, to any person obtaining a copy
  13302. of this software and associated documentation files (the "Software"), to deal
  13303. in the Software without restriction, including without limitation the rights
  13304. to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  13305. copies of the Software, and to permit persons to whom the Software is
  13306. furnished to do so, subject to the following conditions:
  13307. The above copyright notice and this permission notice shall be included in
  13308. all copies or substantial portions of the Software.
  13309. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  13310. IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  13311. FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  13312. AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  13313. LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  13314. OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  13315. THE SOFTWARE.
  13316. <?php
  13317. declare (strict_types=1);
  13318. /**
  13319. * This file is part of phpDocumentor.
  13320. *
  13321. * For the full copyright and license information, please view the LICENSE
  13322. * file that was distributed with this source code.
  13323. *
  13324. * @link http://phpdoc.org
  13325. */
  13326. namespace PHPUnit\phpDocumentor\Reflection;
  13327. use ArrayIterator;
  13328. use InvalidArgumentException;
  13329. use PHPUnit\phpDocumentor\Reflection\Types\Array_;
  13330. use PHPUnit\phpDocumentor\Reflection\Types\ClassString;
  13331. use PHPUnit\phpDocumentor\Reflection\Types\Collection;
  13332. use PHPUnit\phpDocumentor\Reflection\Types\Compound;
  13333. use PHPUnit\phpDocumentor\Reflection\Types\Context;
  13334. use PHPUnit\phpDocumentor\Reflection\Types\Expression;
  13335. use PHPUnit\phpDocumentor\Reflection\Types\Integer;
  13336. use PHPUnit\phpDocumentor\Reflection\Types\Intersection;
  13337. use PHPUnit\phpDocumentor\Reflection\Types\Iterable_;
  13338. use PHPUnit\phpDocumentor\Reflection\Types\Nullable;
  13339. use PHPUnit\phpDocumentor\Reflection\Types\Object_;
  13340. use PHPUnit\phpDocumentor\Reflection\Types\String_;
  13341. use RuntimeException;
  13342. use function array_key_exists;
  13343. use function array_pop;
  13344. use function array_values;
  13345. use function class_exists;
  13346. use function class_implements;
  13347. use function count;
  13348. use function end;
  13349. use function in_array;
  13350. use function key;
  13351. use function preg_split;
  13352. use function strpos;
  13353. use function strtolower;
  13354. use function trim;
  13355. use const PREG_SPLIT_DELIM_CAPTURE;
  13356. use const PREG_SPLIT_NO_EMPTY;
  13357. final class TypeResolver
  13358. {
  13359. /** @var string Definition of the ARRAY operator for types */
  13360. private const OPERATOR_ARRAY = '[]';
  13361. /** @var string Definition of the NAMESPACE operator in PHP */
  13362. private const OPERATOR_NAMESPACE = '\\';
  13363. /** @var int the iterator parser is inside a compound context */
  13364. private const PARSER_IN_COMPOUND = 0;
  13365. /** @var int the iterator parser is inside a nullable expression context */
  13366. private const PARSER_IN_NULLABLE = 1;
  13367. /** @var int the iterator parser is inside an array expression context */
  13368. private const PARSER_IN_ARRAY_EXPRESSION = 2;
  13369. /** @var int the iterator parser is inside a collection expression context */
  13370. private const PARSER_IN_COLLECTION_EXPRESSION = 3;
  13371. /**
  13372. * @var array<string, string> List of recognized keywords and unto which Value Object they map
  13373. * @psalm-var array<string, class-string<Type>>
  13374. */
  13375. private $keywords = ['string' => \PHPUnit\phpDocumentor\Reflection\Types\String_::class, 'class-string' => \PHPUnit\phpDocumentor\Reflection\Types\ClassString::class, 'int' => \PHPUnit\phpDocumentor\Reflection\Types\Integer::class, 'integer' => \PHPUnit\phpDocumentor\Reflection\Types\Integer::class, 'bool' => \PHPUnit\phpDocumentor\Reflection\Types\Boolean::class, 'boolean' => \PHPUnit\phpDocumentor\Reflection\Types\Boolean::class, 'real' => \PHPUnit\phpDocumentor\Reflection\Types\Float_::class, 'float' => \PHPUnit\phpDocumentor\Reflection\Types\Float_::class, 'double' => \PHPUnit\phpDocumentor\Reflection\Types\Float_::class, 'object' => \PHPUnit\phpDocumentor\Reflection\Types\Object_::class, 'mixed' => \PHPUnit\phpDocumentor\Reflection\Types\Mixed_::class, 'array' => \PHPUnit\phpDocumentor\Reflection\Types\Array_::class, 'resource' => \PHPUnit\phpDocumentor\Reflection\Types\Resource_::class, 'void' => \PHPUnit\phpDocumentor\Reflection\Types\Void_::class, 'null' => \PHPUnit\phpDocumentor\Reflection\Types\Null_::class, 'scalar' => \PHPUnit\phpDocumentor\Reflection\Types\Scalar::class, 'callback' => \PHPUnit\phpDocumentor\Reflection\Types\Callable_::class, 'callable' => \PHPUnit\phpDocumentor\Reflection\Types\Callable_::class, 'false' => \PHPUnit\phpDocumentor\Reflection\Types\False_::class, 'true' => \PHPUnit\phpDocumentor\Reflection\Types\True_::class, 'self' => \PHPUnit\phpDocumentor\Reflection\Types\Self_::class, '$this' => \PHPUnit\phpDocumentor\Reflection\Types\This::class, 'static' => \PHPUnit\phpDocumentor\Reflection\Types\Static_::class, 'parent' => \PHPUnit\phpDocumentor\Reflection\Types\Parent_::class, 'iterable' => \PHPUnit\phpDocumentor\Reflection\Types\Iterable_::class];
  13376. /**
  13377. * @var FqsenResolver
  13378. * @psalm-readonly
  13379. */
  13380. private $fqsenResolver;
  13381. /**
  13382. * Initializes this TypeResolver with the means to create and resolve Fqsen objects.
  13383. */
  13384. public function __construct(?\PHPUnit\phpDocumentor\Reflection\FqsenResolver $fqsenResolver = null)
  13385. {
  13386. $this->fqsenResolver = $fqsenResolver ?: new \PHPUnit\phpDocumentor\Reflection\FqsenResolver();
  13387. }
  13388. /**
  13389. * Analyzes the given type and returns the FQCN variant.
  13390. *
  13391. * When a type is provided this method checks whether it is not a keyword or
  13392. * Fully Qualified Class Name. If so it will use the given namespace and
  13393. * aliases to expand the type to a FQCN representation.
  13394. *
  13395. * This method only works as expected if the namespace and aliases are set;
  13396. * no dynamic reflection is being performed here.
  13397. *
  13398. * @uses Context::getNamespaceAliases() to check whether the first part of the relative type name should not be
  13399. * replaced with another namespace.
  13400. * @uses Context::getNamespace() to determine with what to prefix the type name.
  13401. *
  13402. * @param string $type The relative or absolute type.
  13403. */
  13404. public function resolve(string $type, ?\PHPUnit\phpDocumentor\Reflection\Types\Context $context = null) : \PHPUnit\phpDocumentor\Reflection\Type
  13405. {
  13406. $type = \trim($type);
  13407. if (!$type) {
  13408. throw new \InvalidArgumentException('Attempted to resolve "' . $type . '" but it appears to be empty');
  13409. }
  13410. if ($context === null) {
  13411. $context = new \PHPUnit\phpDocumentor\Reflection\Types\Context('');
  13412. }
  13413. // split the type string into tokens `|`, `?`, `<`, `>`, `,`, `(`, `)`, `[]`, '<', '>' and type names
  13414. $tokens = \preg_split('/(\\||\\?|<|>|&|, ?|\\(|\\)|\\[\\]+)/', $type, -1, \PREG_SPLIT_NO_EMPTY | \PREG_SPLIT_DELIM_CAPTURE);
  13415. if ($tokens === \false) {
  13416. throw new \InvalidArgumentException('Unable to split the type string "' . $type . '" into tokens');
  13417. }
  13418. /** @var ArrayIterator<int, string|null> $tokenIterator */
  13419. $tokenIterator = new \ArrayIterator($tokens);
  13420. return $this->parseTypes($tokenIterator, $context, self::PARSER_IN_COMPOUND);
  13421. }
  13422. /**
  13423. * Analyse each tokens and creates types
  13424. *
  13425. * @param ArrayIterator<int, string|null> $tokens the iterator on tokens
  13426. * @param int $parserContext on of self::PARSER_* constants, indicating
  13427. * the context where we are in the parsing
  13428. */
  13429. private function parseTypes(\ArrayIterator $tokens, \PHPUnit\phpDocumentor\Reflection\Types\Context $context, int $parserContext) : \PHPUnit\phpDocumentor\Reflection\Type
  13430. {
  13431. $types = [];
  13432. $token = '';
  13433. $compoundToken = '|';
  13434. while ($tokens->valid()) {
  13435. $token = $tokens->current();
  13436. if ($token === null) {
  13437. throw new \RuntimeException('Unexpected nullable character');
  13438. }
  13439. if ($token === '|' || $token === '&') {
  13440. if (\count($types) === 0) {
  13441. throw new \RuntimeException('A type is missing before a type separator');
  13442. }
  13443. if (!\in_array($parserContext, [self::PARSER_IN_COMPOUND, self::PARSER_IN_ARRAY_EXPRESSION, self::PARSER_IN_COLLECTION_EXPRESSION], \true)) {
  13444. throw new \RuntimeException('Unexpected type separator');
  13445. }
  13446. $compoundToken = $token;
  13447. $tokens->next();
  13448. } elseif ($token === '?') {
  13449. if (!\in_array($parserContext, [self::PARSER_IN_COMPOUND, self::PARSER_IN_ARRAY_EXPRESSION, self::PARSER_IN_COLLECTION_EXPRESSION], \true)) {
  13450. throw new \RuntimeException('Unexpected nullable character');
  13451. }
  13452. $tokens->next();
  13453. $type = $this->parseTypes($tokens, $context, self::PARSER_IN_NULLABLE);
  13454. $types[] = new \PHPUnit\phpDocumentor\Reflection\Types\Nullable($type);
  13455. } elseif ($token === '(') {
  13456. $tokens->next();
  13457. $type = $this->parseTypes($tokens, $context, self::PARSER_IN_ARRAY_EXPRESSION);
  13458. $token = $tokens->current();
  13459. if ($token === null) {
  13460. // Someone did not properly close their array expression ..
  13461. break;
  13462. }
  13463. $tokens->next();
  13464. $resolvedType = new \PHPUnit\phpDocumentor\Reflection\Types\Expression($type);
  13465. $types[] = $resolvedType;
  13466. } elseif ($parserContext === self::PARSER_IN_ARRAY_EXPRESSION && $token[0] === ')') {
  13467. break;
  13468. } elseif ($token === '<') {
  13469. if (\count($types) === 0) {
  13470. throw new \RuntimeException('Unexpected collection operator "<", class name is missing');
  13471. }
  13472. $classType = \array_pop($types);
  13473. if ($classType !== null) {
  13474. if ((string) $classType === 'class-string') {
  13475. $types[] = $this->resolveClassString($tokens, $context);
  13476. } else {
  13477. $types[] = $this->resolveCollection($tokens, $classType, $context);
  13478. }
  13479. }
  13480. $tokens->next();
  13481. } elseif ($parserContext === self::PARSER_IN_COLLECTION_EXPRESSION && ($token === '>' || \trim($token) === ',')) {
  13482. break;
  13483. } elseif ($token === self::OPERATOR_ARRAY) {
  13484. \end($types);
  13485. $last = \key($types);
  13486. $lastItem = $types[$last];
  13487. if ($lastItem instanceof \PHPUnit\phpDocumentor\Reflection\Types\Expression) {
  13488. $lastItem = $lastItem->getValueType();
  13489. }
  13490. $types[$last] = new \PHPUnit\phpDocumentor\Reflection\Types\Array_($lastItem);
  13491. $tokens->next();
  13492. } else {
  13493. $type = $this->resolveSingleType($token, $context);
  13494. $tokens->next();
  13495. if ($parserContext === self::PARSER_IN_NULLABLE) {
  13496. return $type;
  13497. }
  13498. $types[] = $type;
  13499. }
  13500. }
  13501. if ($token === '|' || $token === '&') {
  13502. throw new \RuntimeException('A type is missing after a type separator');
  13503. }
  13504. if (\count($types) === 0) {
  13505. if ($parserContext === self::PARSER_IN_NULLABLE) {
  13506. throw new \RuntimeException('A type is missing after a nullable character');
  13507. }
  13508. if ($parserContext === self::PARSER_IN_ARRAY_EXPRESSION) {
  13509. throw new \RuntimeException('A type is missing in an array expression');
  13510. }
  13511. if ($parserContext === self::PARSER_IN_COLLECTION_EXPRESSION) {
  13512. throw new \RuntimeException('A type is missing in a collection expression');
  13513. }
  13514. } elseif (\count($types) === 1) {
  13515. return $types[0];
  13516. }
  13517. if ($compoundToken === '|') {
  13518. return new \PHPUnit\phpDocumentor\Reflection\Types\Compound(\array_values($types));
  13519. }
  13520. return new \PHPUnit\phpDocumentor\Reflection\Types\Intersection(\array_values($types));
  13521. }
  13522. /**
  13523. * resolve the given type into a type object
  13524. *
  13525. * @param string $type the type string, representing a single type
  13526. *
  13527. * @return Type|Array_|Object_
  13528. *
  13529. * @psalm-pure
  13530. */
  13531. private function resolveSingleType(string $type, \PHPUnit\phpDocumentor\Reflection\Types\Context $context) : object
  13532. {
  13533. switch (\true) {
  13534. case $this->isKeyword($type):
  13535. return $this->resolveKeyword($type);
  13536. case $this->isFqsen($type):
  13537. return $this->resolveTypedObject($type);
  13538. case $this->isPartialStructuralElementName($type):
  13539. return $this->resolveTypedObject($type, $context);
  13540. // @codeCoverageIgnoreStart
  13541. default:
  13542. // I haven't got the foggiest how the logic would come here but added this as a defense.
  13543. throw new \RuntimeException('Unable to resolve type "' . $type . '", there is no known method to resolve it');
  13544. }
  13545. // @codeCoverageIgnoreEnd
  13546. }
  13547. /**
  13548. * Adds a keyword to the list of Keywords and associates it with a specific Value Object.
  13549. *
  13550. * @psalm-param class-string<Type> $typeClassName
  13551. */
  13552. public function addKeyword(string $keyword, string $typeClassName) : void
  13553. {
  13554. if (!\class_exists($typeClassName)) {
  13555. throw new \InvalidArgumentException('The Value Object that needs to be created with a keyword "' . $keyword . '" must be an existing class' . ' but we could not find the class ' . $typeClassName);
  13556. }
  13557. if (!\in_array(\PHPUnit\phpDocumentor\Reflection\Type::class, \class_implements($typeClassName), \true)) {
  13558. throw new \InvalidArgumentException('The class "' . $typeClassName . '" must implement the interface "phpDocumentor\\Reflection\\Type"');
  13559. }
  13560. $this->keywords[$keyword] = $typeClassName;
  13561. }
  13562. /**
  13563. * Detects whether the given type represents a PHPDoc keyword.
  13564. *
  13565. * @param string $type A relative or absolute type as defined in the phpDocumentor documentation.
  13566. *
  13567. * @psalm-pure
  13568. */
  13569. private function isKeyword(string $type) : bool
  13570. {
  13571. return \array_key_exists(\strtolower($type), $this->keywords);
  13572. }
  13573. /**
  13574. * Detects whether the given type represents a relative structural element name.
  13575. *
  13576. * @param string $type A relative or absolute type as defined in the phpDocumentor documentation.
  13577. *
  13578. * @psalm-pure
  13579. */
  13580. private function isPartialStructuralElementName(string $type) : bool
  13581. {
  13582. return $type[0] !== self::OPERATOR_NAMESPACE && !$this->isKeyword($type);
  13583. }
  13584. /**
  13585. * Tests whether the given type is a Fully Qualified Structural Element Name.
  13586. *
  13587. * @psalm-pure
  13588. */
  13589. private function isFqsen(string $type) : bool
  13590. {
  13591. return \strpos($type, self::OPERATOR_NAMESPACE) === 0;
  13592. }
  13593. /**
  13594. * Resolves the given keyword (such as `string`) into a Type object representing that keyword.
  13595. *
  13596. * @psalm-pure
  13597. */
  13598. private function resolveKeyword(string $type) : \PHPUnit\phpDocumentor\Reflection\Type
  13599. {
  13600. $className = $this->keywords[\strtolower($type)];
  13601. return new $className();
  13602. }
  13603. /**
  13604. * Resolves the given FQSEN string into an FQSEN object.
  13605. *
  13606. * @psalm-pure
  13607. */
  13608. private function resolveTypedObject(string $type, ?\PHPUnit\phpDocumentor\Reflection\Types\Context $context = null) : \PHPUnit\phpDocumentor\Reflection\Types\Object_
  13609. {
  13610. return new \PHPUnit\phpDocumentor\Reflection\Types\Object_($this->fqsenResolver->resolve($type, $context));
  13611. }
  13612. /**
  13613. * Resolves class string
  13614. *
  13615. * @param ArrayIterator<int, (string|null)> $tokens
  13616. */
  13617. private function resolveClassString(\ArrayIterator $tokens, \PHPUnit\phpDocumentor\Reflection\Types\Context $context) : \PHPUnit\phpDocumentor\Reflection\Type
  13618. {
  13619. $tokens->next();
  13620. $classType = $this->parseTypes($tokens, $context, self::PARSER_IN_COLLECTION_EXPRESSION);
  13621. if (!$classType instanceof \PHPUnit\phpDocumentor\Reflection\Types\Object_ || $classType->getFqsen() === null) {
  13622. throw new \RuntimeException($classType . ' is not a class string');
  13623. }
  13624. $token = $tokens->current();
  13625. if ($token !== '>') {
  13626. if (empty($token)) {
  13627. throw new \RuntimeException('class-string: ">" is missing');
  13628. }
  13629. throw new \RuntimeException('Unexpected character "' . $token . '", ">" is missing');
  13630. }
  13631. return new \PHPUnit\phpDocumentor\Reflection\Types\ClassString($classType->getFqsen());
  13632. }
  13633. /**
  13634. * Resolves the collection values and keys
  13635. *
  13636. * @param ArrayIterator<int, (string|null)> $tokens
  13637. *
  13638. * @return Array_|Iterable_|Collection
  13639. */
  13640. private function resolveCollection(\ArrayIterator $tokens, \PHPUnit\phpDocumentor\Reflection\Type $classType, \PHPUnit\phpDocumentor\Reflection\Types\Context $context) : \PHPUnit\phpDocumentor\Reflection\Type
  13641. {
  13642. $isArray = (string) $classType === 'array';
  13643. $isIterable = (string) $classType === 'iterable';
  13644. // allow only "array", "iterable" or class name before "<"
  13645. if (!$isArray && !$isIterable && (!$classType instanceof \PHPUnit\phpDocumentor\Reflection\Types\Object_ || $classType->getFqsen() === null)) {
  13646. throw new \RuntimeException($classType . ' is not a collection');
  13647. }
  13648. $tokens->next();
  13649. $valueType = $this->parseTypes($tokens, $context, self::PARSER_IN_COLLECTION_EXPRESSION);
  13650. $keyType = null;
  13651. $token = $tokens->current();
  13652. if ($token !== null && \trim($token) === ',') {
  13653. // if we have a comma, then we just parsed the key type, not the value type
  13654. $keyType = $valueType;
  13655. if ($isArray) {
  13656. // check the key type for an "array" collection. We allow only
  13657. // strings or integers.
  13658. if (!$keyType instanceof \PHPUnit\phpDocumentor\Reflection\Types\String_ && !$keyType instanceof \PHPUnit\phpDocumentor\Reflection\Types\Integer && !$keyType instanceof \PHPUnit\phpDocumentor\Reflection\Types\Compound) {
  13659. throw new \RuntimeException('An array can have only integers or strings as keys');
  13660. }
  13661. if ($keyType instanceof \PHPUnit\phpDocumentor\Reflection\Types\Compound) {
  13662. foreach ($keyType->getIterator() as $item) {
  13663. if (!$item instanceof \PHPUnit\phpDocumentor\Reflection\Types\String_ && !$item instanceof \PHPUnit\phpDocumentor\Reflection\Types\Integer) {
  13664. throw new \RuntimeException('An array can have only integers or strings as keys');
  13665. }
  13666. }
  13667. }
  13668. }
  13669. $tokens->next();
  13670. // now let's parse the value type
  13671. $valueType = $this->parseTypes($tokens, $context, self::PARSER_IN_COLLECTION_EXPRESSION);
  13672. }
  13673. $token = $tokens->current();
  13674. if ($token !== '>') {
  13675. if (empty($token)) {
  13676. throw new \RuntimeException('Collection: ">" is missing');
  13677. }
  13678. throw new \RuntimeException('Unexpected character "' . $token . '", ">" is missing');
  13679. }
  13680. if ($isArray) {
  13681. return new \PHPUnit\phpDocumentor\Reflection\Types\Array_($valueType, $keyType);
  13682. }
  13683. if ($isIterable) {
  13684. return new \PHPUnit\phpDocumentor\Reflection\Types\Iterable_($valueType, $keyType);
  13685. }
  13686. if ($classType instanceof \PHPUnit\phpDocumentor\Reflection\Types\Object_) {
  13687. return $this->makeCollectionFromObject($classType, $valueType, $keyType);
  13688. }
  13689. throw new \RuntimeException('Invalid $classType provided');
  13690. }
  13691. /**
  13692. * @psalm-pure
  13693. */
  13694. private function makeCollectionFromObject(\PHPUnit\phpDocumentor\Reflection\Types\Object_ $object, \PHPUnit\phpDocumentor\Reflection\Type $valueType, ?\PHPUnit\phpDocumentor\Reflection\Type $keyType = null) : \PHPUnit\phpDocumentor\Reflection\Types\Collection
  13695. {
  13696. return new \PHPUnit\phpDocumentor\Reflection\Types\Collection($object->getFqsen(), $valueType, $keyType);
  13697. }
  13698. }
  13699. <?php
  13700. declare (strict_types=1);
  13701. /*
  13702. * This file is part of sebastian/environment.
  13703. *
  13704. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  13705. *
  13706. * For the full copyright and license information, please view the LICENSE
  13707. * file that was distributed with this source code.
  13708. */
  13709. namespace PHPUnit\SebastianBergmann\Environment;
  13710. final class Console
  13711. {
  13712. /**
  13713. * @var int
  13714. */
  13715. public const STDIN = 0;
  13716. /**
  13717. * @var int
  13718. */
  13719. public const STDOUT = 1;
  13720. /**
  13721. * @var int
  13722. */
  13723. public const STDERR = 2;
  13724. /**
  13725. * Returns true if STDOUT supports colorization.
  13726. *
  13727. * This code has been copied and adapted from
  13728. * Symfony\Component\Console\Output\StreamOutput.
  13729. */
  13730. public function hasColorSupport() : bool
  13731. {
  13732. if ('Hyper' === \getenv('TERM_PROGRAM')) {
  13733. return \true;
  13734. }
  13735. if ($this->isWindows()) {
  13736. // @codeCoverageIgnoreStart
  13737. return \defined('STDOUT') && \function_exists('sapi_windows_vt100_support') && @\sapi_windows_vt100_support(\STDOUT) || \false !== \getenv('ANSICON') || 'ON' === \getenv('ConEmuANSI') || 'xterm' === \getenv('TERM');
  13738. // @codeCoverageIgnoreEnd
  13739. }
  13740. if (!\defined('STDOUT')) {
  13741. // @codeCoverageIgnoreStart
  13742. return \false;
  13743. // @codeCoverageIgnoreEnd
  13744. }
  13745. return $this->isInteractive(\STDOUT);
  13746. }
  13747. /**
  13748. * Returns the number of columns of the terminal.
  13749. *
  13750. * @codeCoverageIgnore
  13751. */
  13752. public function getNumberOfColumns() : int
  13753. {
  13754. if (!$this->isInteractive(\defined('STDIN') ? \STDIN : self::STDIN)) {
  13755. return 80;
  13756. }
  13757. if ($this->isWindows()) {
  13758. return $this->getNumberOfColumnsWindows();
  13759. }
  13760. return $this->getNumberOfColumnsInteractive();
  13761. }
  13762. /**
  13763. * Returns if the file descriptor is an interactive terminal or not.
  13764. *
  13765. * Normally, we want to use a resource as a parameter, yet sadly it's not always awailable,
  13766. * eg when running code in interactive console (`php -a`), STDIN/STDOUT/STDERR constants are not defined.
  13767. *
  13768. * @param int|resource $fileDescriptor
  13769. */
  13770. public function isInteractive($fileDescriptor = self::STDOUT) : bool
  13771. {
  13772. if (\is_resource($fileDescriptor)) {
  13773. // These functions require a descriptor that is a real resource, not a numeric ID of it
  13774. if (\function_exists('stream_isatty') && @\stream_isatty($fileDescriptor)) {
  13775. return \true;
  13776. }
  13777. // Check if formatted mode is S_IFCHR
  13778. if (\function_exists('fstat') && @\stream_isatty($fileDescriptor)) {
  13779. $stat = @\fstat(\STDOUT);
  13780. return $stat ? 020000 === ($stat['mode'] & 0170000) : \false;
  13781. }
  13782. return \false;
  13783. }
  13784. return \function_exists('posix_isatty') && @\posix_isatty($fileDescriptor);
  13785. }
  13786. private function isWindows() : bool
  13787. {
  13788. return \DIRECTORY_SEPARATOR === '\\';
  13789. }
  13790. /**
  13791. * @codeCoverageIgnore
  13792. */
  13793. private function getNumberOfColumnsInteractive() : int
  13794. {
  13795. if (\function_exists('shell_exec') && \preg_match('#\\d+ (\\d+)#', \shell_exec('stty size') ?: '', $match) === 1) {
  13796. if ((int) $match[1] > 0) {
  13797. return (int) $match[1];
  13798. }
  13799. }
  13800. if (\function_exists('shell_exec') && \preg_match('#columns = (\\d+);#', \shell_exec('stty') ?: '', $match) === 1) {
  13801. if ((int) $match[1] > 0) {
  13802. return (int) $match[1];
  13803. }
  13804. }
  13805. return 80;
  13806. }
  13807. /**
  13808. * @codeCoverageIgnore
  13809. */
  13810. private function getNumberOfColumnsWindows() : int
  13811. {
  13812. $ansicon = \getenv('ANSICON');
  13813. $columns = 80;
  13814. if (\is_string($ansicon) && \preg_match('/^(\\d+)x\\d+ \\(\\d+x(\\d+)\\)$/', \trim($ansicon), $matches)) {
  13815. $columns = (int) $matches[1];
  13816. } elseif (\function_exists('proc_open')) {
  13817. $process = \proc_open('mode CON', [1 => ['pipe', 'w'], 2 => ['pipe', 'w']], $pipes, null, null, ['suppress_errors' => \true]);
  13818. if (\is_resource($process)) {
  13819. $info = \stream_get_contents($pipes[1]);
  13820. \fclose($pipes[1]);
  13821. \fclose($pipes[2]);
  13822. \proc_close($process);
  13823. if (\preg_match('/--------+\\r?\\n.+?(\\d+)\\r?\\n.+?(\\d+)\\r?\\n/', $info, $matches)) {
  13824. $columns = (int) $matches[2];
  13825. }
  13826. }
  13827. }
  13828. return $columns - 1;
  13829. }
  13830. }
  13831. <?php
  13832. declare (strict_types=1);
  13833. /*
  13834. * This file is part of sebastian/environment.
  13835. *
  13836. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  13837. *
  13838. * For the full copyright and license information, please view the LICENSE
  13839. * file that was distributed with this source code.
  13840. */
  13841. namespace PHPUnit\SebastianBergmann\Environment;
  13842. final class OperatingSystem
  13843. {
  13844. /**
  13845. * Returns PHP_OS_FAMILY (if defined (which it is on PHP >= 7.2)).
  13846. * Returns a string (compatible with PHP_OS_FAMILY) derived from PHP_OS otherwise.
  13847. */
  13848. public function getFamily() : string
  13849. {
  13850. if (\defined('PHP_OS_FAMILY')) {
  13851. return \PHP_OS_FAMILY;
  13852. }
  13853. if (\DIRECTORY_SEPARATOR === '\\') {
  13854. return 'Windows';
  13855. }
  13856. switch (\PHP_OS) {
  13857. case 'Darwin':
  13858. return 'Darwin';
  13859. case 'DragonFly':
  13860. case 'FreeBSD':
  13861. case 'NetBSD':
  13862. case 'OpenBSD':
  13863. return 'BSD';
  13864. case 'Linux':
  13865. return 'Linux';
  13866. case 'SunOS':
  13867. return 'Solaris';
  13868. default:
  13869. return 'Unknown';
  13870. }
  13871. }
  13872. }
  13873. <?php
  13874. declare (strict_types=1);
  13875. /*
  13876. * This file is part of sebastian/environment.
  13877. *
  13878. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  13879. *
  13880. * For the full copyright and license information, please view the LICENSE
  13881. * file that was distributed with this source code.
  13882. */
  13883. namespace PHPUnit\SebastianBergmann\Environment;
  13884. /**
  13885. * Utility class for HHVM/PHP environment handling.
  13886. */
  13887. final class Runtime
  13888. {
  13889. /**
  13890. * @var string
  13891. */
  13892. private static $binary;
  13893. /**
  13894. * Returns true when Xdebug or PCOV is available or
  13895. * the runtime used is PHPDBG.
  13896. */
  13897. public function canCollectCodeCoverage() : bool
  13898. {
  13899. return $this->hasXdebug() || $this->hasPCOV() || $this->hasPHPDBGCodeCoverage();
  13900. }
  13901. /**
  13902. * Returns true when Zend OPcache is loaded, enabled,
  13903. * and is configured to discard comments.
  13904. */
  13905. public function discardsComments() : bool
  13906. {
  13907. if (!$this->isOpcacheActive()) {
  13908. return \false;
  13909. }
  13910. if (\ini_get('opcache.save_comments') !== '0') {
  13911. return \false;
  13912. }
  13913. return \true;
  13914. }
  13915. /**
  13916. * Returns true when Zend OPcache is loaded, enabled,
  13917. * and is configured to perform just-in-time compilation.
  13918. */
  13919. public function performsJustInTimeCompilation() : bool
  13920. {
  13921. if (\PHP_MAJOR_VERSION < 8) {
  13922. return \false;
  13923. }
  13924. if (!$this->isOpcacheActive()) {
  13925. return \false;
  13926. }
  13927. if (\strpos(\ini_get('opcache.jit'), '0') === 0) {
  13928. return \false;
  13929. }
  13930. return \true;
  13931. }
  13932. /**
  13933. * Returns the path to the binary of the current runtime.
  13934. * Appends ' --php' to the path when the runtime is HHVM.
  13935. */
  13936. public function getBinary() : string
  13937. {
  13938. // HHVM
  13939. if (self::$binary === null && $this->isHHVM()) {
  13940. // @codeCoverageIgnoreStart
  13941. if ((self::$binary = \getenv('PHP_BINARY')) === \false) {
  13942. self::$binary = \PHP_BINARY;
  13943. }
  13944. self::$binary = \escapeshellarg(self::$binary) . ' --php' . ' -d hhvm.php7.all=1';
  13945. // @codeCoverageIgnoreEnd
  13946. }
  13947. if (self::$binary === null && \PHP_BINARY !== '') {
  13948. self::$binary = \escapeshellarg(\PHP_BINARY);
  13949. }
  13950. if (self::$binary === null) {
  13951. // @codeCoverageIgnoreStart
  13952. $possibleBinaryLocations = [\PHP_BINDIR . '/php', \PHP_BINDIR . '/php-cli.exe', \PHP_BINDIR . '/php.exe'];
  13953. foreach ($possibleBinaryLocations as $binary) {
  13954. if (\is_readable($binary)) {
  13955. self::$binary = \escapeshellarg($binary);
  13956. break;
  13957. }
  13958. }
  13959. // @codeCoverageIgnoreEnd
  13960. }
  13961. if (self::$binary === null) {
  13962. // @codeCoverageIgnoreStart
  13963. self::$binary = 'php';
  13964. // @codeCoverageIgnoreEnd
  13965. }
  13966. return self::$binary;
  13967. }
  13968. public function getNameWithVersion() : string
  13969. {
  13970. return $this->getName() . ' ' . $this->getVersion();
  13971. }
  13972. public function getNameWithVersionAndCodeCoverageDriver() : string
  13973. {
  13974. if (!$this->canCollectCodeCoverage() || $this->hasPHPDBGCodeCoverage()) {
  13975. return $this->getNameWithVersion();
  13976. }
  13977. if ($this->hasPCOV()) {
  13978. return \sprintf('%s with PCOV %s', $this->getNameWithVersion(), \phpversion('pcov'));
  13979. }
  13980. if ($this->hasXdebug()) {
  13981. return \sprintf('%s with Xdebug %s', $this->getNameWithVersion(), \phpversion('xdebug'));
  13982. }
  13983. }
  13984. public function getName() : string
  13985. {
  13986. if ($this->isHHVM()) {
  13987. // @codeCoverageIgnoreStart
  13988. return 'HHVM';
  13989. // @codeCoverageIgnoreEnd
  13990. }
  13991. if ($this->isPHPDBG()) {
  13992. // @codeCoverageIgnoreStart
  13993. return 'PHPDBG';
  13994. // @codeCoverageIgnoreEnd
  13995. }
  13996. return 'PHP';
  13997. }
  13998. public function getVendorUrl() : string
  13999. {
  14000. if ($this->isHHVM()) {
  14001. // @codeCoverageIgnoreStart
  14002. return 'http://hhvm.com/';
  14003. // @codeCoverageIgnoreEnd
  14004. }
  14005. return 'https://secure.php.net/';
  14006. }
  14007. public function getVersion() : string
  14008. {
  14009. if ($this->isHHVM()) {
  14010. // @codeCoverageIgnoreStart
  14011. return HHVM_VERSION;
  14012. // @codeCoverageIgnoreEnd
  14013. }
  14014. return \PHP_VERSION;
  14015. }
  14016. /**
  14017. * Returns true when the runtime used is PHP and Xdebug is loaded.
  14018. */
  14019. public function hasXdebug() : bool
  14020. {
  14021. return ($this->isPHP() || $this->isHHVM()) && \extension_loaded('xdebug');
  14022. }
  14023. /**
  14024. * Returns true when the runtime used is HHVM.
  14025. */
  14026. public function isHHVM() : bool
  14027. {
  14028. return \defined('HHVM_VERSION');
  14029. }
  14030. /**
  14031. * Returns true when the runtime used is PHP without the PHPDBG SAPI.
  14032. */
  14033. public function isPHP() : bool
  14034. {
  14035. return !$this->isHHVM() && !$this->isPHPDBG();
  14036. }
  14037. /**
  14038. * Returns true when the runtime used is PHP with the PHPDBG SAPI.
  14039. */
  14040. public function isPHPDBG() : bool
  14041. {
  14042. return \PHP_SAPI === 'phpdbg' && !$this->isHHVM();
  14043. }
  14044. /**
  14045. * Returns true when the runtime used is PHP with the PHPDBG SAPI
  14046. * and the phpdbg_*_oplog() functions are available (PHP >= 7.0).
  14047. */
  14048. public function hasPHPDBGCodeCoverage() : bool
  14049. {
  14050. return $this->isPHPDBG();
  14051. }
  14052. /**
  14053. * Returns true when the runtime used is PHP with PCOV loaded and enabled
  14054. */
  14055. public function hasPCOV() : bool
  14056. {
  14057. return $this->isPHP() && \extension_loaded('pcov') && \ini_get('pcov.enabled');
  14058. }
  14059. /**
  14060. * Parses the loaded php.ini file (if any) as well as all
  14061. * additional php.ini files from the additional ini dir for
  14062. * a list of all configuration settings loaded from files
  14063. * at startup. Then checks for each php.ini setting passed
  14064. * via the `$values` parameter whether this setting has
  14065. * been changed at runtime. Returns an array of strings
  14066. * where each string has the format `key=value` denoting
  14067. * the name of a changed php.ini setting with its new value.
  14068. *
  14069. * @return string[]
  14070. */
  14071. public function getCurrentSettings(array $values) : array
  14072. {
  14073. $diff = [];
  14074. $files = [];
  14075. if ($file = \php_ini_loaded_file()) {
  14076. $files[] = $file;
  14077. }
  14078. if ($scanned = \php_ini_scanned_files()) {
  14079. $files = \array_merge($files, \array_map('trim', \explode(",\n", $scanned)));
  14080. }
  14081. foreach ($files as $ini) {
  14082. $config = \parse_ini_file($ini, \true);
  14083. foreach ($values as $value) {
  14084. $set = \ini_get($value);
  14085. if (isset($config[$value]) && $set != $config[$value]) {
  14086. $diff[] = \sprintf('%s=%s', $value, $set);
  14087. }
  14088. }
  14089. }
  14090. return $diff;
  14091. }
  14092. private function isOpcacheActive() : bool
  14093. {
  14094. if (!\extension_loaded('Zend OPcache')) {
  14095. return \false;
  14096. }
  14097. if ((\PHP_SAPI === 'cli' || \PHP_SAPI === 'phpdbg') && \ini_get('opcache.enable_cli') === '1') {
  14098. return \true;
  14099. }
  14100. if (\PHP_SAPI !== 'cli' && \PHP_SAPI !== 'phpdbg' && \ini_get('opcache.enable') === '1') {
  14101. return \true;
  14102. }
  14103. return \false;
  14104. }
  14105. }
  14106. sebastian/environment
  14107. Copyright (c) 2014-2020, Sebastian Bergmann <sebastian@phpunit.de>.
  14108. All rights reserved.
  14109. Redistribution and use in source and binary forms, with or without
  14110. modification, are permitted provided that the following conditions
  14111. are met:
  14112. * Redistributions of source code must retain the above copyright
  14113. notice, this list of conditions and the following disclaimer.
  14114. * Redistributions in binary form must reproduce the above copyright
  14115. notice, this list of conditions and the following disclaimer in
  14116. the documentation and/or other materials provided with the
  14117. distribution.
  14118. * Neither the name of Sebastian Bergmann nor the names of his
  14119. contributors may be used to endorse or promote products derived
  14120. from this software without specific prior written permission.
  14121. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  14122. "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  14123. LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  14124. FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  14125. COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  14126. INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  14127. BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  14128. LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  14129. CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  14130. LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
  14131. ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  14132. POSSIBILITY OF SUCH DAMAGE.
  14133. <?php
  14134. declare (strict_types=1);
  14135. /*
  14136. * This file is part of sebastian/comparator.
  14137. *
  14138. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  14139. *
  14140. * For the full copyright and license information, please view the LICENSE
  14141. * file that was distributed with this source code.
  14142. */
  14143. namespace PHPUnit\SebastianBergmann\Comparator;
  14144. use PHPUnit\SebastianBergmann\Diff\Differ;
  14145. use PHPUnit\SebastianBergmann\Diff\Output\UnifiedDiffOutputBuilder;
  14146. /**
  14147. * Thrown when an assertion for string equality failed.
  14148. */
  14149. class ComparisonFailure extends \RuntimeException
  14150. {
  14151. /**
  14152. * Expected value of the retrieval which does not match $actual.
  14153. *
  14154. * @var mixed
  14155. */
  14156. protected $expected;
  14157. /**
  14158. * Actually retrieved value which does not match $expected.
  14159. *
  14160. * @var mixed
  14161. */
  14162. protected $actual;
  14163. /**
  14164. * The string representation of the expected value
  14165. *
  14166. * @var string
  14167. */
  14168. protected $expectedAsString;
  14169. /**
  14170. * The string representation of the actual value
  14171. *
  14172. * @var string
  14173. */
  14174. protected $actualAsString;
  14175. /**
  14176. * @var bool
  14177. */
  14178. protected $identical;
  14179. /**
  14180. * Optional message which is placed in front of the first line
  14181. * returned by toString().
  14182. *
  14183. * @var string
  14184. */
  14185. protected $message;
  14186. /**
  14187. * Initialises with the expected value and the actual value.
  14188. *
  14189. * @param mixed $expected expected value retrieved
  14190. * @param mixed $actual actual value retrieved
  14191. * @param string $expectedAsString
  14192. * @param string $actualAsString
  14193. * @param bool $identical
  14194. * @param string $message a string which is prefixed on all returned lines
  14195. * in the difference output
  14196. */
  14197. public function __construct($expected, $actual, $expectedAsString, $actualAsString, $identical = \false, $message = '')
  14198. {
  14199. $this->expected = $expected;
  14200. $this->actual = $actual;
  14201. $this->expectedAsString = $expectedAsString;
  14202. $this->actualAsString = $actualAsString;
  14203. $this->message = $message;
  14204. }
  14205. public function getActual()
  14206. {
  14207. return $this->actual;
  14208. }
  14209. public function getExpected()
  14210. {
  14211. return $this->expected;
  14212. }
  14213. /**
  14214. * @return string
  14215. */
  14216. public function getActualAsString()
  14217. {
  14218. return $this->actualAsString;
  14219. }
  14220. /**
  14221. * @return string
  14222. */
  14223. public function getExpectedAsString()
  14224. {
  14225. return $this->expectedAsString;
  14226. }
  14227. /**
  14228. * @return string
  14229. */
  14230. public function getDiff()
  14231. {
  14232. if (!$this->actualAsString && !$this->expectedAsString) {
  14233. return '';
  14234. }
  14235. $differ = new \PHPUnit\SebastianBergmann\Diff\Differ(new \PHPUnit\SebastianBergmann\Diff\Output\UnifiedDiffOutputBuilder("\n--- Expected\n+++ Actual\n"));
  14236. return $differ->diff($this->expectedAsString, $this->actualAsString);
  14237. }
  14238. /**
  14239. * @return string
  14240. */
  14241. public function toString()
  14242. {
  14243. return $this->message . $this->getDiff();
  14244. }
  14245. }
  14246. <?php
  14247. declare (strict_types=1);
  14248. /*
  14249. * This file is part of sebastian/comparator.
  14250. *
  14251. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  14252. *
  14253. * For the full copyright and license information, please view the LICENSE
  14254. * file that was distributed with this source code.
  14255. */
  14256. namespace PHPUnit\SebastianBergmann\Comparator;
  14257. /**
  14258. * Compares resources for equality.
  14259. */
  14260. class ResourceComparator extends \PHPUnit\SebastianBergmann\Comparator\Comparator
  14261. {
  14262. /**
  14263. * Returns whether the comparator can compare two values.
  14264. *
  14265. * @param mixed $expected The first value to compare
  14266. * @param mixed $actual The second value to compare
  14267. *
  14268. * @return bool
  14269. */
  14270. public function accepts($expected, $actual)
  14271. {
  14272. return \is_resource($expected) && \is_resource($actual);
  14273. }
  14274. /**
  14275. * Asserts that two values are equal.
  14276. *
  14277. * @param mixed $expected First value to compare
  14278. * @param mixed $actual Second value to compare
  14279. * @param float $delta Allowed numerical distance between two values to consider them equal
  14280. * @param bool $canonicalize Arrays are sorted before comparison when set to true
  14281. * @param bool $ignoreCase Case is ignored when set to true
  14282. *
  14283. * @throws ComparisonFailure
  14284. */
  14285. public function assertEquals($expected, $actual, $delta = 0.0, $canonicalize = \false, $ignoreCase = \false)
  14286. {
  14287. if ($actual != $expected) {
  14288. throw new \PHPUnit\SebastianBergmann\Comparator\ComparisonFailure($expected, $actual, $this->exporter->export($expected), $this->exporter->export($actual));
  14289. }
  14290. }
  14291. }
  14292. <?php
  14293. declare (strict_types=1);
  14294. /*
  14295. * This file is part of sebastian/comparator.
  14296. *
  14297. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  14298. *
  14299. * For the full copyright and license information, please view the LICENSE
  14300. * file that was distributed with this source code.
  14301. */
  14302. namespace PHPUnit\SebastianBergmann\Comparator;
  14303. /**
  14304. * Compares doubles for equality.
  14305. */
  14306. class DoubleComparator extends \PHPUnit\SebastianBergmann\Comparator\NumericComparator
  14307. {
  14308. /**
  14309. * Smallest value available in PHP.
  14310. *
  14311. * @var float
  14312. */
  14313. public const EPSILON = 1.0E-10;
  14314. /**
  14315. * Returns whether the comparator can compare two values.
  14316. *
  14317. * @param mixed $expected The first value to compare
  14318. * @param mixed $actual The second value to compare
  14319. *
  14320. * @return bool
  14321. */
  14322. public function accepts($expected, $actual)
  14323. {
  14324. return (\is_float($expected) || \is_float($actual)) && \is_numeric($expected) && \is_numeric($actual);
  14325. }
  14326. /**
  14327. * Asserts that two values are equal.
  14328. *
  14329. * @param mixed $expected First value to compare
  14330. * @param mixed $actual Second value to compare
  14331. * @param float $delta Allowed numerical distance between two values to consider them equal
  14332. * @param bool $canonicalize Arrays are sorted before comparison when set to true
  14333. * @param bool $ignoreCase Case is ignored when set to true
  14334. *
  14335. * @throws ComparisonFailure
  14336. */
  14337. public function assertEquals($expected, $actual, $delta = 0.0, $canonicalize = \false, $ignoreCase = \false)
  14338. {
  14339. if ($delta == 0) {
  14340. $delta = self::EPSILON;
  14341. }
  14342. parent::assertEquals($expected, $actual, $delta, $canonicalize, $ignoreCase);
  14343. }
  14344. }
  14345. <?php
  14346. declare (strict_types=1);
  14347. /*
  14348. * This file is part of sebastian/comparator.
  14349. *
  14350. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  14351. *
  14352. * For the full copyright and license information, please view the LICENSE
  14353. * file that was distributed with this source code.
  14354. */
  14355. namespace PHPUnit\SebastianBergmann\Comparator;
  14356. /**
  14357. * Compares numerical values for equality.
  14358. */
  14359. class NumericComparator extends \PHPUnit\SebastianBergmann\Comparator\ScalarComparator
  14360. {
  14361. /**
  14362. * Returns whether the comparator can compare two values.
  14363. *
  14364. * @param mixed $expected The first value to compare
  14365. * @param mixed $actual The second value to compare
  14366. *
  14367. * @return bool
  14368. */
  14369. public function accepts($expected, $actual)
  14370. {
  14371. // all numerical values, but not if one of them is a double
  14372. // or both of them are strings
  14373. return \is_numeric($expected) && \is_numeric($actual) && !(\is_float($expected) || \is_float($actual)) && !(\is_string($expected) && \is_string($actual));
  14374. }
  14375. /**
  14376. * Asserts that two values are equal.
  14377. *
  14378. * @param mixed $expected First value to compare
  14379. * @param mixed $actual Second value to compare
  14380. * @param float $delta Allowed numerical distance between two values to consider them equal
  14381. * @param bool $canonicalize Arrays are sorted before comparison when set to true
  14382. * @param bool $ignoreCase Case is ignored when set to true
  14383. *
  14384. * @throws ComparisonFailure
  14385. */
  14386. public function assertEquals($expected, $actual, $delta = 0.0, $canonicalize = \false, $ignoreCase = \false)
  14387. {
  14388. if ($this->isInfinite($actual) && $this->isInfinite($expected)) {
  14389. return;
  14390. }
  14391. if (($this->isInfinite($actual) xor $this->isInfinite($expected)) || ($this->isNan($actual) || $this->isNan($expected)) || \abs($actual - $expected) > $delta) {
  14392. throw new \PHPUnit\SebastianBergmann\Comparator\ComparisonFailure($expected, $actual, '', '', \false, \sprintf('Failed asserting that %s matches expected %s.', $this->exporter->export($actual), $this->exporter->export($expected)));
  14393. }
  14394. }
  14395. private function isInfinite($value) : bool
  14396. {
  14397. return \is_float($value) && \is_infinite($value);
  14398. }
  14399. private function isNan($value) : bool
  14400. {
  14401. return \is_float($value) && \is_nan($value);
  14402. }
  14403. }
  14404. <?php
  14405. declare (strict_types=1);
  14406. /*
  14407. * This file is part of sebastian/comparator.
  14408. *
  14409. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  14410. *
  14411. * For the full copyright and license information, please view the LICENSE
  14412. * file that was distributed with this source code.
  14413. */
  14414. namespace PHPUnit\SebastianBergmann\Comparator;
  14415. /**
  14416. * Factory for comparators which compare values for equality.
  14417. */
  14418. class Factory
  14419. {
  14420. /**
  14421. * @var Factory
  14422. */
  14423. private static $instance;
  14424. /**
  14425. * @var Comparator[]
  14426. */
  14427. private $customComparators = [];
  14428. /**
  14429. * @var Comparator[]
  14430. */
  14431. private $defaultComparators = [];
  14432. /**
  14433. * @return Factory
  14434. */
  14435. public static function getInstance()
  14436. {
  14437. if (self::$instance === null) {
  14438. self::$instance = new self();
  14439. // @codeCoverageIgnore
  14440. }
  14441. return self::$instance;
  14442. }
  14443. /**
  14444. * Constructs a new factory.
  14445. */
  14446. public function __construct()
  14447. {
  14448. $this->registerDefaultComparators();
  14449. }
  14450. /**
  14451. * Returns the correct comparator for comparing two values.
  14452. *
  14453. * @param mixed $expected The first value to compare
  14454. * @param mixed $actual The second value to compare
  14455. *
  14456. * @return Comparator
  14457. */
  14458. public function getComparatorFor($expected, $actual)
  14459. {
  14460. foreach ($this->customComparators as $comparator) {
  14461. if ($comparator->accepts($expected, $actual)) {
  14462. return $comparator;
  14463. }
  14464. }
  14465. foreach ($this->defaultComparators as $comparator) {
  14466. if ($comparator->accepts($expected, $actual)) {
  14467. return $comparator;
  14468. }
  14469. }
  14470. throw new \PHPUnit\SebastianBergmann\Comparator\RuntimeException('No suitable Comparator implementation found');
  14471. }
  14472. /**
  14473. * Registers a new comparator.
  14474. *
  14475. * This comparator will be returned by getComparatorFor() if its accept() method
  14476. * returns TRUE for the compared values. It has higher priority than the
  14477. * existing comparators, meaning that its accept() method will be invoked
  14478. * before those of the other comparators.
  14479. *
  14480. * @param Comparator $comparator The comparator to be registered
  14481. */
  14482. public function register(\PHPUnit\SebastianBergmann\Comparator\Comparator $comparator)
  14483. {
  14484. \array_unshift($this->customComparators, $comparator);
  14485. $comparator->setFactory($this);
  14486. }
  14487. /**
  14488. * Unregisters a comparator.
  14489. *
  14490. * This comparator will no longer be considered by getComparatorFor().
  14491. *
  14492. * @param Comparator $comparator The comparator to be unregistered
  14493. */
  14494. public function unregister(\PHPUnit\SebastianBergmann\Comparator\Comparator $comparator)
  14495. {
  14496. foreach ($this->customComparators as $key => $_comparator) {
  14497. if ($comparator === $_comparator) {
  14498. unset($this->customComparators[$key]);
  14499. }
  14500. }
  14501. }
  14502. /**
  14503. * Unregisters all non-default comparators.
  14504. */
  14505. public function reset()
  14506. {
  14507. $this->customComparators = [];
  14508. }
  14509. private function registerDefaultComparators() : void
  14510. {
  14511. $this->registerDefaultComparator(new \PHPUnit\SebastianBergmann\Comparator\MockObjectComparator());
  14512. $this->registerDefaultComparator(new \PHPUnit\SebastianBergmann\Comparator\DateTimeComparator());
  14513. $this->registerDefaultComparator(new \PHPUnit\SebastianBergmann\Comparator\DOMNodeComparator());
  14514. $this->registerDefaultComparator(new \PHPUnit\SebastianBergmann\Comparator\SplObjectStorageComparator());
  14515. $this->registerDefaultComparator(new \PHPUnit\SebastianBergmann\Comparator\ExceptionComparator());
  14516. $this->registerDefaultComparator(new \PHPUnit\SebastianBergmann\Comparator\ObjectComparator());
  14517. $this->registerDefaultComparator(new \PHPUnit\SebastianBergmann\Comparator\ResourceComparator());
  14518. $this->registerDefaultComparator(new \PHPUnit\SebastianBergmann\Comparator\ArrayComparator());
  14519. $this->registerDefaultComparator(new \PHPUnit\SebastianBergmann\Comparator\DoubleComparator());
  14520. $this->registerDefaultComparator(new \PHPUnit\SebastianBergmann\Comparator\NumericComparator());
  14521. $this->registerDefaultComparator(new \PHPUnit\SebastianBergmann\Comparator\ScalarComparator());
  14522. $this->registerDefaultComparator(new \PHPUnit\SebastianBergmann\Comparator\TypeComparator());
  14523. }
  14524. private function registerDefaultComparator(\PHPUnit\SebastianBergmann\Comparator\Comparator $comparator) : void
  14525. {
  14526. $this->defaultComparators[] = $comparator;
  14527. $comparator->setFactory($this);
  14528. }
  14529. }
  14530. <?php
  14531. declare (strict_types=1);
  14532. /*
  14533. * This file is part of sebastian/comparator.
  14534. *
  14535. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  14536. *
  14537. * For the full copyright and license information, please view the LICENSE
  14538. * file that was distributed with this source code.
  14539. */
  14540. namespace PHPUnit\SebastianBergmann\Comparator;
  14541. use DOMDocument;
  14542. use DOMNode;
  14543. /**
  14544. * Compares DOMNode instances for equality.
  14545. */
  14546. class DOMNodeComparator extends \PHPUnit\SebastianBergmann\Comparator\ObjectComparator
  14547. {
  14548. /**
  14549. * Returns whether the comparator can compare two values.
  14550. *
  14551. * @param mixed $expected The first value to compare
  14552. * @param mixed $actual The second value to compare
  14553. *
  14554. * @return bool
  14555. */
  14556. public function accepts($expected, $actual)
  14557. {
  14558. return $expected instanceof \DOMNode && $actual instanceof \DOMNode;
  14559. }
  14560. /**
  14561. * Asserts that two values are equal.
  14562. *
  14563. * @param mixed $expected First value to compare
  14564. * @param mixed $actual Second value to compare
  14565. * @param float $delta Allowed numerical distance between two values to consider them equal
  14566. * @param bool $canonicalize Arrays are sorted before comparison when set to true
  14567. * @param bool $ignoreCase Case is ignored when set to true
  14568. * @param array $processed List of already processed elements (used to prevent infinite recursion)
  14569. *
  14570. * @throws ComparisonFailure
  14571. */
  14572. public function assertEquals($expected, $actual, $delta = 0.0, $canonicalize = \false, $ignoreCase = \false, array &$processed = [])
  14573. {
  14574. $expectedAsString = $this->nodeToText($expected, \true, $ignoreCase);
  14575. $actualAsString = $this->nodeToText($actual, \true, $ignoreCase);
  14576. if ($expectedAsString !== $actualAsString) {
  14577. $type = $expected instanceof \DOMDocument ? 'documents' : 'nodes';
  14578. throw new \PHPUnit\SebastianBergmann\Comparator\ComparisonFailure($expected, $actual, $expectedAsString, $actualAsString, \false, \sprintf("Failed asserting that two DOM %s are equal.\n", $type));
  14579. }
  14580. }
  14581. /**
  14582. * Returns the normalized, whitespace-cleaned, and indented textual
  14583. * representation of a DOMNode.
  14584. */
  14585. private function nodeToText(\DOMNode $node, bool $canonicalize, bool $ignoreCase) : string
  14586. {
  14587. if ($canonicalize) {
  14588. $document = new \DOMDocument();
  14589. @$document->loadXML($node->C14N());
  14590. $node = $document;
  14591. }
  14592. $document = $node instanceof \DOMDocument ? $node : $node->ownerDocument;
  14593. $document->formatOutput = \true;
  14594. $document->normalizeDocument();
  14595. $text = $node instanceof \DOMDocument ? $node->saveXML() : $document->saveXML($node);
  14596. return $ignoreCase ? \strtolower($text) : $text;
  14597. }
  14598. }
  14599. <?php
  14600. declare (strict_types=1);
  14601. /*
  14602. * This file is part of sebastian/comparator.
  14603. *
  14604. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  14605. *
  14606. * For the full copyright and license information, please view the LICENSE
  14607. * file that was distributed with this source code.
  14608. */
  14609. namespace PHPUnit\SebastianBergmann\Comparator;
  14610. /**
  14611. * Compares objects for equality.
  14612. */
  14613. class ObjectComparator extends \PHPUnit\SebastianBergmann\Comparator\ArrayComparator
  14614. {
  14615. /**
  14616. * Returns whether the comparator can compare two values.
  14617. *
  14618. * @param mixed $expected The first value to compare
  14619. * @param mixed $actual The second value to compare
  14620. *
  14621. * @return bool
  14622. */
  14623. public function accepts($expected, $actual)
  14624. {
  14625. return \is_object($expected) && \is_object($actual);
  14626. }
  14627. /**
  14628. * Asserts that two values are equal.
  14629. *
  14630. * @param mixed $expected First value to compare
  14631. * @param mixed $actual Second value to compare
  14632. * @param float $delta Allowed numerical distance between two values to consider them equal
  14633. * @param bool $canonicalize Arrays are sorted before comparison when set to true
  14634. * @param bool $ignoreCase Case is ignored when set to true
  14635. * @param array $processed List of already processed elements (used to prevent infinite recursion)
  14636. *
  14637. * @throws ComparisonFailure
  14638. */
  14639. public function assertEquals($expected, $actual, $delta = 0.0, $canonicalize = \false, $ignoreCase = \false, array &$processed = [])
  14640. {
  14641. if (\get_class($actual) !== \get_class($expected)) {
  14642. throw new \PHPUnit\SebastianBergmann\Comparator\ComparisonFailure($expected, $actual, $this->exporter->export($expected), $this->exporter->export($actual), \false, \sprintf('%s is not instance of expected class "%s".', $this->exporter->export($actual), \get_class($expected)));
  14643. }
  14644. // don't compare twice to allow for cyclic dependencies
  14645. if (\in_array([$actual, $expected], $processed, \true) || \in_array([$expected, $actual], $processed, \true)) {
  14646. return;
  14647. }
  14648. $processed[] = [$actual, $expected];
  14649. // don't compare objects if they are identical
  14650. // this helps to avoid the error "maximum function nesting level reached"
  14651. // CAUTION: this conditional clause is not tested
  14652. if ($actual !== $expected) {
  14653. try {
  14654. parent::assertEquals($this->toArray($expected), $this->toArray($actual), $delta, $canonicalize, $ignoreCase, $processed);
  14655. } catch (\PHPUnit\SebastianBergmann\Comparator\ComparisonFailure $e) {
  14656. throw new \PHPUnit\SebastianBergmann\Comparator\ComparisonFailure(
  14657. $expected,
  14658. $actual,
  14659. // replace "Array" with "MyClass object"
  14660. \substr_replace($e->getExpectedAsString(), \get_class($expected) . ' Object', 0, 5),
  14661. \substr_replace($e->getActualAsString(), \get_class($actual) . ' Object', 0, 5),
  14662. \false,
  14663. 'Failed asserting that two objects are equal.'
  14664. );
  14665. }
  14666. }
  14667. }
  14668. /**
  14669. * Converts an object to an array containing all of its private, protected
  14670. * and public properties.
  14671. *
  14672. * @param object $object
  14673. *
  14674. * @return array
  14675. */
  14676. protected function toArray($object)
  14677. {
  14678. return $this->exporter->toArray($object);
  14679. }
  14680. }
  14681. <?php
  14682. declare (strict_types=1);
  14683. /*
  14684. * This file is part of sebastian/comparator.
  14685. *
  14686. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  14687. *
  14688. * For the full copyright and license information, please view the LICENSE
  14689. * file that was distributed with this source code.
  14690. */
  14691. namespace PHPUnit\SebastianBergmann\Comparator;
  14692. /**
  14693. * Compares scalar or NULL values for equality.
  14694. */
  14695. class ScalarComparator extends \PHPUnit\SebastianBergmann\Comparator\Comparator
  14696. {
  14697. /**
  14698. * Returns whether the comparator can compare two values.
  14699. *
  14700. * @param mixed $expected The first value to compare
  14701. * @param mixed $actual The second value to compare
  14702. *
  14703. * @return bool
  14704. *
  14705. * @since Method available since Release 3.6.0
  14706. */
  14707. public function accepts($expected, $actual)
  14708. {
  14709. return (\is_scalar($expected) xor null === $expected) && (\is_scalar($actual) xor null === $actual) || \is_string($expected) && \is_object($actual) && \method_exists($actual, '__toString') || \is_object($expected) && \method_exists($expected, '__toString') && \is_string($actual);
  14710. }
  14711. /**
  14712. * Asserts that two values are equal.
  14713. *
  14714. * @param mixed $expected First value to compare
  14715. * @param mixed $actual Second value to compare
  14716. * @param float $delta Allowed numerical distance between two values to consider them equal
  14717. * @param bool $canonicalize Arrays are sorted before comparison when set to true
  14718. * @param bool $ignoreCase Case is ignored when set to true
  14719. *
  14720. * @throws ComparisonFailure
  14721. */
  14722. public function assertEquals($expected, $actual, $delta = 0.0, $canonicalize = \false, $ignoreCase = \false)
  14723. {
  14724. $expectedToCompare = $expected;
  14725. $actualToCompare = $actual;
  14726. // always compare as strings to avoid strange behaviour
  14727. // otherwise 0 == 'Foobar'
  14728. if (\is_string($expected) || \is_string($actual)) {
  14729. $expectedToCompare = (string) $expectedToCompare;
  14730. $actualToCompare = (string) $actualToCompare;
  14731. if ($ignoreCase) {
  14732. $expectedToCompare = \strtolower($expectedToCompare);
  14733. $actualToCompare = \strtolower($actualToCompare);
  14734. }
  14735. }
  14736. if ($expectedToCompare !== $actualToCompare && \is_string($expected) && \is_string($actual)) {
  14737. throw new \PHPUnit\SebastianBergmann\Comparator\ComparisonFailure($expected, $actual, $this->exporter->export($expected), $this->exporter->export($actual), \false, 'Failed asserting that two strings are equal.');
  14738. }
  14739. if ($expectedToCompare != $actualToCompare) {
  14740. throw new \PHPUnit\SebastianBergmann\Comparator\ComparisonFailure(
  14741. $expected,
  14742. $actual,
  14743. // no diff is required
  14744. '',
  14745. '',
  14746. \false,
  14747. \sprintf('Failed asserting that %s matches expected %s.', $this->exporter->export($actual), $this->exporter->export($expected))
  14748. );
  14749. }
  14750. }
  14751. }
  14752. <?php
  14753. declare (strict_types=1);
  14754. /*
  14755. * This file is part of sebastian/comparator.
  14756. *
  14757. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  14758. *
  14759. * For the full copyright and license information, please view the LICENSE
  14760. * file that was distributed with this source code.
  14761. */
  14762. namespace PHPUnit\SebastianBergmann\Comparator;
  14763. /**
  14764. * Compares DateTimeInterface instances for equality.
  14765. */
  14766. class DateTimeComparator extends \PHPUnit\SebastianBergmann\Comparator\ObjectComparator
  14767. {
  14768. /**
  14769. * Returns whether the comparator can compare two values.
  14770. *
  14771. * @param mixed $expected The first value to compare
  14772. * @param mixed $actual The second value to compare
  14773. *
  14774. * @return bool
  14775. */
  14776. public function accepts($expected, $actual)
  14777. {
  14778. return ($expected instanceof \DateTime || $expected instanceof \DateTimeInterface) && ($actual instanceof \DateTime || $actual instanceof \DateTimeInterface);
  14779. }
  14780. /**
  14781. * Asserts that two values are equal.
  14782. *
  14783. * @param mixed $expected First value to compare
  14784. * @param mixed $actual Second value to compare
  14785. * @param float $delta Allowed numerical distance between two values to consider them equal
  14786. * @param bool $canonicalize Arrays are sorted before comparison when set to true
  14787. * @param bool $ignoreCase Case is ignored when set to true
  14788. * @param array $processed List of already processed elements (used to prevent infinite recursion)
  14789. *
  14790. * @throws \Exception
  14791. * @throws ComparisonFailure
  14792. */
  14793. public function assertEquals($expected, $actual, $delta = 0.0, $canonicalize = \false, $ignoreCase = \false, array &$processed = [])
  14794. {
  14795. /** @var \DateTimeInterface $expected */
  14796. /** @var \DateTimeInterface $actual */
  14797. $absDelta = \abs($delta);
  14798. $delta = new \DateInterval(\sprintf('PT%dS', $absDelta));
  14799. $delta->f = $absDelta - \floor($absDelta);
  14800. $actualClone = (clone $actual)->setTimezone(new \DateTimeZone('UTC'));
  14801. $expectedLower = (clone $expected)->setTimezone(new \DateTimeZone('UTC'))->sub($delta);
  14802. $expectedUpper = (clone $expected)->setTimezone(new \DateTimeZone('UTC'))->add($delta);
  14803. if ($actualClone < $expectedLower || $actualClone > $expectedUpper) {
  14804. throw new \PHPUnit\SebastianBergmann\Comparator\ComparisonFailure($expected, $actual, $this->dateTimeToString($expected), $this->dateTimeToString($actual), \false, 'Failed asserting that two DateTime objects are equal.');
  14805. }
  14806. }
  14807. /**
  14808. * Returns an ISO 8601 formatted string representation of a datetime or
  14809. * 'Invalid DateTimeInterface object' if the provided DateTimeInterface was not properly
  14810. * initialized.
  14811. */
  14812. private function dateTimeToString(\DateTimeInterface $datetime) : string
  14813. {
  14814. $string = $datetime->format('Y-m-d\\TH:i:s.uO');
  14815. return $string ?: 'Invalid DateTimeInterface object';
  14816. }
  14817. }
  14818. <?php
  14819. declare (strict_types=1);
  14820. /*
  14821. * This file is part of sebastian/comparator.
  14822. *
  14823. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  14824. *
  14825. * For the full copyright and license information, please view the LICENSE
  14826. * file that was distributed with this source code.
  14827. */
  14828. namespace PHPUnit\SebastianBergmann\Comparator;
  14829. /**
  14830. * Compares values for type equality.
  14831. */
  14832. class TypeComparator extends \PHPUnit\SebastianBergmann\Comparator\Comparator
  14833. {
  14834. /**
  14835. * Returns whether the comparator can compare two values.
  14836. *
  14837. * @param mixed $expected The first value to compare
  14838. * @param mixed $actual The second value to compare
  14839. *
  14840. * @return bool
  14841. */
  14842. public function accepts($expected, $actual)
  14843. {
  14844. return \true;
  14845. }
  14846. /**
  14847. * Asserts that two values are equal.
  14848. *
  14849. * @param mixed $expected First value to compare
  14850. * @param mixed $actual Second value to compare
  14851. * @param float $delta Allowed numerical distance between two values to consider them equal
  14852. * @param bool $canonicalize Arrays are sorted before comparison when set to true
  14853. * @param bool $ignoreCase Case is ignored when set to true
  14854. *
  14855. * @throws ComparisonFailure
  14856. */
  14857. public function assertEquals($expected, $actual, $delta = 0.0, $canonicalize = \false, $ignoreCase = \false)
  14858. {
  14859. if (\gettype($expected) != \gettype($actual)) {
  14860. throw new \PHPUnit\SebastianBergmann\Comparator\ComparisonFailure(
  14861. $expected,
  14862. $actual,
  14863. // we don't need a diff
  14864. '',
  14865. '',
  14866. \false,
  14867. \sprintf('%s does not match expected type "%s".', $this->exporter->shortenedExport($actual), \gettype($expected))
  14868. );
  14869. }
  14870. }
  14871. }
  14872. <?php
  14873. declare (strict_types=1);
  14874. /*
  14875. * This file is part of sebastian/comparator.
  14876. *
  14877. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  14878. *
  14879. * For the full copyright and license information, please view the LICENSE
  14880. * file that was distributed with this source code.
  14881. */
  14882. namespace PHPUnit\SebastianBergmann\Comparator;
  14883. /**
  14884. * Compares Exception instances for equality.
  14885. */
  14886. class ExceptionComparator extends \PHPUnit\SebastianBergmann\Comparator\ObjectComparator
  14887. {
  14888. /**
  14889. * Returns whether the comparator can compare two values.
  14890. *
  14891. * @param mixed $expected The first value to compare
  14892. * @param mixed $actual The second value to compare
  14893. *
  14894. * @return bool
  14895. */
  14896. public function accepts($expected, $actual)
  14897. {
  14898. return $expected instanceof \Exception && $actual instanceof \Exception;
  14899. }
  14900. /**
  14901. * Converts an object to an array containing all of its private, protected
  14902. * and public properties.
  14903. *
  14904. * @param object $object
  14905. *
  14906. * @return array
  14907. */
  14908. protected function toArray($object)
  14909. {
  14910. $array = parent::toArray($object);
  14911. unset($array['file'], $array['line'], $array['trace'], $array['string'], $array['xdebug_message']);
  14912. return $array;
  14913. }
  14914. }
  14915. <?php
  14916. declare (strict_types=1);
  14917. /*
  14918. * This file is part of sebastian/comparator.
  14919. *
  14920. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  14921. *
  14922. * For the full copyright and license information, please view the LICENSE
  14923. * file that was distributed with this source code.
  14924. */
  14925. namespace PHPUnit\SebastianBergmann\Comparator;
  14926. final class RuntimeException extends \RuntimeException implements \PHPUnit\SebastianBergmann\Comparator\Exception
  14927. {
  14928. }
  14929. <?php
  14930. declare (strict_types=1);
  14931. /*
  14932. * This file is part of sebastian/comparator.
  14933. *
  14934. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  14935. *
  14936. * For the full copyright and license information, please view the LICENSE
  14937. * file that was distributed with this source code.
  14938. */
  14939. namespace PHPUnit\SebastianBergmann\Comparator;
  14940. interface Exception
  14941. {
  14942. }
  14943. <?php
  14944. declare (strict_types=1);
  14945. /*
  14946. * This file is part of sebastian/comparator.
  14947. *
  14948. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  14949. *
  14950. * For the full copyright and license information, please view the LICENSE
  14951. * file that was distributed with this source code.
  14952. */
  14953. namespace PHPUnit\SebastianBergmann\Comparator;
  14954. /**
  14955. * Compares \SplObjectStorage instances for equality.
  14956. */
  14957. class SplObjectStorageComparator extends \PHPUnit\SebastianBergmann\Comparator\Comparator
  14958. {
  14959. /**
  14960. * Returns whether the comparator can compare two values.
  14961. *
  14962. * @param mixed $expected The first value to compare
  14963. * @param mixed $actual The second value to compare
  14964. *
  14965. * @return bool
  14966. */
  14967. public function accepts($expected, $actual)
  14968. {
  14969. return $expected instanceof \SplObjectStorage && $actual instanceof \SplObjectStorage;
  14970. }
  14971. /**
  14972. * Asserts that two values are equal.
  14973. *
  14974. * @param mixed $expected First value to compare
  14975. * @param mixed $actual Second value to compare
  14976. * @param float $delta Allowed numerical distance between two values to consider them equal
  14977. * @param bool $canonicalize Arrays are sorted before comparison when set to true
  14978. * @param bool $ignoreCase Case is ignored when set to true
  14979. *
  14980. * @throws ComparisonFailure
  14981. */
  14982. public function assertEquals($expected, $actual, $delta = 0.0, $canonicalize = \false, $ignoreCase = \false)
  14983. {
  14984. foreach ($actual as $object) {
  14985. if (!$expected->contains($object)) {
  14986. throw new \PHPUnit\SebastianBergmann\Comparator\ComparisonFailure($expected, $actual, $this->exporter->export($expected), $this->exporter->export($actual), \false, 'Failed asserting that two objects are equal.');
  14987. }
  14988. }
  14989. foreach ($expected as $object) {
  14990. if (!$actual->contains($object)) {
  14991. throw new \PHPUnit\SebastianBergmann\Comparator\ComparisonFailure($expected, $actual, $this->exporter->export($expected), $this->exporter->export($actual), \false, 'Failed asserting that two objects are equal.');
  14992. }
  14993. }
  14994. }
  14995. }
  14996. <?php
  14997. declare (strict_types=1);
  14998. /*
  14999. * This file is part of sebastian/comparator.
  15000. *
  15001. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  15002. *
  15003. * For the full copyright and license information, please view the LICENSE
  15004. * file that was distributed with this source code.
  15005. */
  15006. namespace PHPUnit\SebastianBergmann\Comparator;
  15007. use PHPUnit\SebastianBergmann\Exporter\Exporter;
  15008. /**
  15009. * Abstract base class for comparators which compare values for equality.
  15010. */
  15011. abstract class Comparator
  15012. {
  15013. /**
  15014. * @var Factory
  15015. */
  15016. protected $factory;
  15017. /**
  15018. * @var Exporter
  15019. */
  15020. protected $exporter;
  15021. public function __construct()
  15022. {
  15023. $this->exporter = new \PHPUnit\SebastianBergmann\Exporter\Exporter();
  15024. }
  15025. public function setFactory(\PHPUnit\SebastianBergmann\Comparator\Factory $factory)
  15026. {
  15027. $this->factory = $factory;
  15028. }
  15029. /**
  15030. * Returns whether the comparator can compare two values.
  15031. *
  15032. * @param mixed $expected The first value to compare
  15033. * @param mixed $actual The second value to compare
  15034. *
  15035. * @return bool
  15036. */
  15037. public abstract function accepts($expected, $actual);
  15038. /**
  15039. * Asserts that two values are equal.
  15040. *
  15041. * @param mixed $expected First value to compare
  15042. * @param mixed $actual Second value to compare
  15043. * @param float $delta Allowed numerical distance between two values to consider them equal
  15044. * @param bool $canonicalize Arrays are sorted before comparison when set to true
  15045. * @param bool $ignoreCase Case is ignored when set to true
  15046. *
  15047. * @throws ComparisonFailure
  15048. */
  15049. public abstract function assertEquals($expected, $actual, $delta = 0.0, $canonicalize = \false, $ignoreCase = \false);
  15050. }
  15051. <?php
  15052. declare (strict_types=1);
  15053. /*
  15054. * This file is part of sebastian/comparator.
  15055. *
  15056. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  15057. *
  15058. * For the full copyright and license information, please view the LICENSE
  15059. * file that was distributed with this source code.
  15060. */
  15061. namespace PHPUnit\SebastianBergmann\Comparator;
  15062. /**
  15063. * Compares arrays for equality.
  15064. *
  15065. * Arrays are equal if they contain the same key-value pairs.
  15066. * The order of the keys does not matter.
  15067. * The types of key-value pairs do not matter.
  15068. */
  15069. class ArrayComparator extends \PHPUnit\SebastianBergmann\Comparator\Comparator
  15070. {
  15071. /**
  15072. * Returns whether the comparator can compare two values.
  15073. *
  15074. * @param mixed $expected The first value to compare
  15075. * @param mixed $actual The second value to compare
  15076. *
  15077. * @return bool
  15078. */
  15079. public function accepts($expected, $actual)
  15080. {
  15081. return \is_array($expected) && \is_array($actual);
  15082. }
  15083. /**
  15084. * Asserts that two arrays are equal.
  15085. *
  15086. * @param mixed $expected First value to compare
  15087. * @param mixed $actual Second value to compare
  15088. * @param float $delta Allowed numerical distance between two values to consider them equal
  15089. * @param bool $canonicalize Arrays are sorted before comparison when set to true
  15090. * @param bool $ignoreCase Case is ignored when set to true
  15091. * @param array $processed List of already processed elements (used to prevent infinite recursion)
  15092. *
  15093. * @throws ComparisonFailure
  15094. */
  15095. public function assertEquals($expected, $actual, $delta = 0.0, $canonicalize = \false, $ignoreCase = \false, array &$processed = [])
  15096. {
  15097. if ($canonicalize) {
  15098. \sort($expected);
  15099. \sort($actual);
  15100. }
  15101. $remaining = $actual;
  15102. $actualAsString = "Array (\n";
  15103. $expectedAsString = "Array (\n";
  15104. $equal = \true;
  15105. foreach ($expected as $key => $value) {
  15106. unset($remaining[$key]);
  15107. if (!\array_key_exists($key, $actual)) {
  15108. $expectedAsString .= \sprintf(" %s => %s\n", $this->exporter->export($key), $this->exporter->shortenedExport($value));
  15109. $equal = \false;
  15110. continue;
  15111. }
  15112. try {
  15113. $comparator = $this->factory->getComparatorFor($value, $actual[$key]);
  15114. $comparator->assertEquals($value, $actual[$key], $delta, $canonicalize, $ignoreCase, $processed);
  15115. $expectedAsString .= \sprintf(" %s => %s\n", $this->exporter->export($key), $this->exporter->shortenedExport($value));
  15116. $actualAsString .= \sprintf(" %s => %s\n", $this->exporter->export($key), $this->exporter->shortenedExport($actual[$key]));
  15117. } catch (\PHPUnit\SebastianBergmann\Comparator\ComparisonFailure $e) {
  15118. $expectedAsString .= \sprintf(" %s => %s\n", $this->exporter->export($key), $e->getExpectedAsString() ? $this->indent($e->getExpectedAsString()) : $this->exporter->shortenedExport($e->getExpected()));
  15119. $actualAsString .= \sprintf(" %s => %s\n", $this->exporter->export($key), $e->getActualAsString() ? $this->indent($e->getActualAsString()) : $this->exporter->shortenedExport($e->getActual()));
  15120. $equal = \false;
  15121. }
  15122. }
  15123. foreach ($remaining as $key => $value) {
  15124. $actualAsString .= \sprintf(" %s => %s\n", $this->exporter->export($key), $this->exporter->shortenedExport($value));
  15125. $equal = \false;
  15126. }
  15127. $expectedAsString .= ')';
  15128. $actualAsString .= ')';
  15129. if (!$equal) {
  15130. throw new \PHPUnit\SebastianBergmann\Comparator\ComparisonFailure($expected, $actual, $expectedAsString, $actualAsString, \false, 'Failed asserting that two arrays are equal.');
  15131. }
  15132. }
  15133. protected function indent($lines)
  15134. {
  15135. return \trim(\str_replace("\n", "\n ", $lines));
  15136. }
  15137. }
  15138. Comparator
  15139. Copyright (c) 2002-2020, Sebastian Bergmann <sebastian@phpunit.de>.
  15140. All rights reserved.
  15141. Redistribution and use in source and binary forms, with or without
  15142. modification, are permitted provided that the following conditions
  15143. are met:
  15144. * Redistributions of source code must retain the above copyright
  15145. notice, this list of conditions and the following disclaimer.
  15146. * Redistributions in binary form must reproduce the above copyright
  15147. notice, this list of conditions and the following disclaimer in
  15148. the documentation and/or other materials provided with the
  15149. distribution.
  15150. * Neither the name of Sebastian Bergmann nor the names of his
  15151. contributors may be used to endorse or promote products derived
  15152. from this software without specific prior written permission.
  15153. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  15154. "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  15155. LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  15156. FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  15157. COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  15158. INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  15159. BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  15160. LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  15161. CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  15162. LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
  15163. ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  15164. POSSIBILITY OF SUCH DAMAGE.
  15165. <?php
  15166. declare (strict_types=1);
  15167. /*
  15168. * This file is part of sebastian/comparator.
  15169. *
  15170. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  15171. *
  15172. * For the full copyright and license information, please view the LICENSE
  15173. * file that was distributed with this source code.
  15174. */
  15175. namespace PHPUnit\SebastianBergmann\Comparator;
  15176. use PHPUnit\Framework\MockObject\MockObject;
  15177. /**
  15178. * Compares PHPUnit\Framework\MockObject\MockObject instances for equality.
  15179. */
  15180. class MockObjectComparator extends \PHPUnit\SebastianBergmann\Comparator\ObjectComparator
  15181. {
  15182. /**
  15183. * Returns whether the comparator can compare two values.
  15184. *
  15185. * @param mixed $expected The first value to compare
  15186. * @param mixed $actual The second value to compare
  15187. *
  15188. * @return bool
  15189. */
  15190. public function accepts($expected, $actual)
  15191. {
  15192. return $expected instanceof \PHPUnit\Framework\MockObject\MockObject && $actual instanceof \PHPUnit\Framework\MockObject\MockObject;
  15193. }
  15194. /**
  15195. * Converts an object to an array containing all of its private, protected
  15196. * and public properties.
  15197. *
  15198. * @param object $object
  15199. *
  15200. * @return array
  15201. */
  15202. protected function toArray($object)
  15203. {
  15204. $array = parent::toArray($object);
  15205. unset($array['__phpunit_invocationMocker']);
  15206. return $array;
  15207. }
  15208. }
  15209. <?php
  15210. /*
  15211. * This file is part of PharIo\Manifest.
  15212. *
  15213. * (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>
  15214. *
  15215. * For the full copyright and license information, please view the LICENSE
  15216. * file that was distributed with this source code.
  15217. */
  15218. namespace PHPUnit\PharIo\Manifest;
  15219. use PHPUnit\PharIo\Version\Version;
  15220. use PHPUnit\PharIo\Version\Exception as VersionException;
  15221. use PHPUnit\PharIo\Version\VersionConstraintParser;
  15222. class ManifestDocumentMapper
  15223. {
  15224. /**
  15225. * @param ManifestDocument $document
  15226. *
  15227. * @returns Manifest
  15228. *
  15229. * @throws ManifestDocumentMapperException
  15230. */
  15231. public function map(\PHPUnit\PharIo\Manifest\ManifestDocument $document)
  15232. {
  15233. try {
  15234. $contains = $document->getContainsElement();
  15235. $type = $this->mapType($contains);
  15236. $copyright = $this->mapCopyright($document->getCopyrightElement());
  15237. $requirements = $this->mapRequirements($document->getRequiresElement());
  15238. $bundledComponents = $this->mapBundledComponents($document);
  15239. return new \PHPUnit\PharIo\Manifest\Manifest(new \PHPUnit\PharIo\Manifest\ApplicationName($contains->getName()), new \PHPUnit\PharIo\Version\Version($contains->getVersion()), $type, $copyright, $requirements, $bundledComponents);
  15240. } catch (\PHPUnit\PharIo\Version\Exception $e) {
  15241. throw new \PHPUnit\PharIo\Manifest\ManifestDocumentMapperException($e->getMessage(), $e->getCode(), $e);
  15242. } catch (\PHPUnit\PharIo\Manifest\Exception $e) {
  15243. throw new \PHPUnit\PharIo\Manifest\ManifestDocumentMapperException($e->getMessage(), $e->getCode(), $e);
  15244. }
  15245. }
  15246. /**
  15247. * @param ContainsElement $contains
  15248. *
  15249. * @return Type
  15250. *
  15251. * @throws ManifestDocumentMapperException
  15252. */
  15253. private function mapType(\PHPUnit\PharIo\Manifest\ContainsElement $contains)
  15254. {
  15255. switch ($contains->getType()) {
  15256. case 'application':
  15257. return \PHPUnit\PharIo\Manifest\Type::application();
  15258. case 'library':
  15259. return \PHPUnit\PharIo\Manifest\Type::library();
  15260. case 'extension':
  15261. return $this->mapExtension($contains->getExtensionElement());
  15262. }
  15263. throw new \PHPUnit\PharIo\Manifest\ManifestDocumentMapperException(\sprintf('Unsupported type %s', $contains->getType()));
  15264. }
  15265. /**
  15266. * @param CopyrightElement $copyright
  15267. *
  15268. * @return CopyrightInformation
  15269. *
  15270. * @throws InvalidUrlException
  15271. * @throws InvalidEmailException
  15272. */
  15273. private function mapCopyright(\PHPUnit\PharIo\Manifest\CopyrightElement $copyright)
  15274. {
  15275. $authors = new \PHPUnit\PharIo\Manifest\AuthorCollection();
  15276. foreach ($copyright->getAuthorElements() as $authorElement) {
  15277. $authors->add(new \PHPUnit\PharIo\Manifest\Author($authorElement->getName(), new \PHPUnit\PharIo\Manifest\Email($authorElement->getEmail())));
  15278. }
  15279. $licenseElement = $copyright->getLicenseElement();
  15280. $license = new \PHPUnit\PharIo\Manifest\License($licenseElement->getType(), new \PHPUnit\PharIo\Manifest\Url($licenseElement->getUrl()));
  15281. return new \PHPUnit\PharIo\Manifest\CopyrightInformation($authors, $license);
  15282. }
  15283. /**
  15284. * @param RequiresElement $requires
  15285. *
  15286. * @return RequirementCollection
  15287. *
  15288. * @throws ManifestDocumentMapperException
  15289. */
  15290. private function mapRequirements(\PHPUnit\PharIo\Manifest\RequiresElement $requires)
  15291. {
  15292. $collection = new \PHPUnit\PharIo\Manifest\RequirementCollection();
  15293. $phpElement = $requires->getPHPElement();
  15294. $parser = new \PHPUnit\PharIo\Version\VersionConstraintParser();
  15295. try {
  15296. $versionConstraint = $parser->parse($phpElement->getVersion());
  15297. } catch (\PHPUnit\PharIo\Version\Exception $e) {
  15298. throw new \PHPUnit\PharIo\Manifest\ManifestDocumentMapperException(\sprintf('Unsupported version constraint - %s', $e->getMessage()), $e->getCode(), $e);
  15299. }
  15300. $collection->add(new \PHPUnit\PharIo\Manifest\PhpVersionRequirement($versionConstraint));
  15301. if (!$phpElement->hasExtElements()) {
  15302. return $collection;
  15303. }
  15304. foreach ($phpElement->getExtElements() as $extElement) {
  15305. $collection->add(new \PHPUnit\PharIo\Manifest\PhpExtensionRequirement($extElement->getName()));
  15306. }
  15307. return $collection;
  15308. }
  15309. /**
  15310. * @param ManifestDocument $document
  15311. *
  15312. * @return BundledComponentCollection
  15313. */
  15314. private function mapBundledComponents(\PHPUnit\PharIo\Manifest\ManifestDocument $document)
  15315. {
  15316. $collection = new \PHPUnit\PharIo\Manifest\BundledComponentCollection();
  15317. if (!$document->hasBundlesElement()) {
  15318. return $collection;
  15319. }
  15320. foreach ($document->getBundlesElement()->getComponentElements() as $componentElement) {
  15321. $collection->add(new \PHPUnit\PharIo\Manifest\BundledComponent($componentElement->getName(), new \PHPUnit\PharIo\Version\Version($componentElement->getVersion())));
  15322. }
  15323. return $collection;
  15324. }
  15325. /**
  15326. * @param ExtensionElement $extension
  15327. *
  15328. * @return Extension
  15329. *
  15330. * @throws ManifestDocumentMapperException
  15331. */
  15332. private function mapExtension(\PHPUnit\PharIo\Manifest\ExtensionElement $extension)
  15333. {
  15334. try {
  15335. $parser = new \PHPUnit\PharIo\Version\VersionConstraintParser();
  15336. $versionConstraint = $parser->parse($extension->getCompatible());
  15337. return \PHPUnit\PharIo\Manifest\Type::extension(new \PHPUnit\PharIo\Manifest\ApplicationName($extension->getFor()), $versionConstraint);
  15338. } catch (\PHPUnit\PharIo\Version\Exception $e) {
  15339. throw new \PHPUnit\PharIo\Manifest\ManifestDocumentMapperException(\sprintf('Unsupported version constraint - %s', $e->getMessage()), $e->getCode(), $e);
  15340. }
  15341. }
  15342. }
  15343. <?php
  15344. namespace PHPUnit\PharIo\Manifest;
  15345. class ManifestDocumentMapperException extends \RuntimeException implements \PHPUnit\PharIo\Manifest\Exception
  15346. {
  15347. }
  15348. <?php
  15349. /*
  15350. * This file is part of PharIo\Manifest.
  15351. *
  15352. * (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>
  15353. *
  15354. * For the full copyright and license information, please view the LICENSE
  15355. * file that was distributed with this source code.
  15356. */
  15357. namespace PHPUnit\PharIo\Manifest;
  15358. class InvalidUrlException extends \InvalidArgumentException implements \PHPUnit\PharIo\Manifest\Exception
  15359. {
  15360. }
  15361. <?php
  15362. /*
  15363. * This file is part of PharIo\Manifest.
  15364. *
  15365. * (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>
  15366. *
  15367. * For the full copyright and license information, please view the LICENSE
  15368. * file that was distributed with this source code.
  15369. */
  15370. namespace PHPUnit\PharIo\Manifest;
  15371. class InvalidApplicationNameException extends \InvalidArgumentException implements \PHPUnit\PharIo\Manifest\Exception
  15372. {
  15373. const NotAString = 1;
  15374. const InvalidFormat = 2;
  15375. }
  15376. <?php
  15377. namespace PHPUnit\PharIo\Manifest;
  15378. class ManifestElementException extends \RuntimeException implements \PHPUnit\PharIo\Manifest\Exception
  15379. {
  15380. }
  15381. <?php
  15382. namespace PHPUnit\PharIo\Manifest;
  15383. class ManifestLoaderException extends \Exception implements \PHPUnit\PharIo\Manifest\Exception
  15384. {
  15385. }
  15386. <?php
  15387. namespace PHPUnit\PharIo\Manifest;
  15388. class ManifestDocumentException extends \RuntimeException implements \PHPUnit\PharIo\Manifest\Exception
  15389. {
  15390. }
  15391. <?php
  15392. /*
  15393. * This file is part of PharIo\Manifest.
  15394. *
  15395. * (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>
  15396. *
  15397. * For the full copyright and license information, please view the LICENSE
  15398. * file that was distributed with this source code.
  15399. */
  15400. namespace PHPUnit\PharIo\Manifest;
  15401. class InvalidEmailException extends \InvalidArgumentException implements \PHPUnit\PharIo\Manifest\Exception
  15402. {
  15403. }
  15404. <?php
  15405. /*
  15406. * This file is part of PharIo\Manifest.
  15407. *
  15408. * (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>
  15409. *
  15410. * For the full copyright and license information, please view the LICENSE
  15411. * file that was distributed with this source code.
  15412. */
  15413. namespace PHPUnit\PharIo\Manifest;
  15414. interface Exception
  15415. {
  15416. }
  15417. <?php
  15418. /*
  15419. * This file is part of PharIo\Manifest.
  15420. *
  15421. * (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>
  15422. *
  15423. * For the full copyright and license information, please view the LICENSE
  15424. * file that was distributed with this source code.
  15425. */
  15426. namespace PHPUnit\PharIo\Manifest;
  15427. use PHPUnit\PharIo\Version\AnyVersionConstraint;
  15428. use PHPUnit\PharIo\Version\Version;
  15429. use PHPUnit\PharIo\Version\VersionConstraint;
  15430. use XMLWriter;
  15431. class ManifestSerializer
  15432. {
  15433. /**
  15434. * @var XMLWriter
  15435. */
  15436. private $xmlWriter;
  15437. public function serializeToFile(\PHPUnit\PharIo\Manifest\Manifest $manifest, $filename)
  15438. {
  15439. \file_put_contents($filename, $this->serializeToString($manifest));
  15440. }
  15441. public function serializeToString(\PHPUnit\PharIo\Manifest\Manifest $manifest)
  15442. {
  15443. $this->startDocument();
  15444. $this->addContains($manifest->getName(), $manifest->getVersion(), $manifest->getType());
  15445. $this->addCopyright($manifest->getCopyrightInformation());
  15446. $this->addRequirements($manifest->getRequirements());
  15447. $this->addBundles($manifest->getBundledComponents());
  15448. return $this->finishDocument();
  15449. }
  15450. private function startDocument()
  15451. {
  15452. $xmlWriter = new \XMLWriter();
  15453. $xmlWriter->openMemory();
  15454. $xmlWriter->setIndent(\true);
  15455. $xmlWriter->setIndentString(\str_repeat(' ', 4));
  15456. $xmlWriter->startDocument('1.0', 'UTF-8');
  15457. $xmlWriter->startElement('phar');
  15458. $xmlWriter->writeAttribute('xmlns', 'https://phar.io/xml/manifest/1.0');
  15459. $this->xmlWriter = $xmlWriter;
  15460. }
  15461. private function finishDocument()
  15462. {
  15463. $this->xmlWriter->endElement();
  15464. $this->xmlWriter->endDocument();
  15465. return $this->xmlWriter->outputMemory();
  15466. }
  15467. private function addContains($name, \PHPUnit\PharIo\Version\Version $version, \PHPUnit\PharIo\Manifest\Type $type)
  15468. {
  15469. $this->xmlWriter->startElement('contains');
  15470. $this->xmlWriter->writeAttribute('name', $name);
  15471. $this->xmlWriter->writeAttribute('version', $version->getVersionString());
  15472. switch (\true) {
  15473. case $type->isApplication():
  15474. $this->xmlWriter->writeAttribute('type', 'application');
  15475. break;
  15476. case $type->isLibrary():
  15477. $this->xmlWriter->writeAttribute('type', 'library');
  15478. break;
  15479. case $type->isExtension():
  15480. /* @var $type Extension */
  15481. $this->xmlWriter->writeAttribute('type', 'extension');
  15482. $this->addExtension($type->getApplicationName(), $type->getVersionConstraint());
  15483. break;
  15484. default:
  15485. $this->xmlWriter->writeAttribute('type', 'custom');
  15486. }
  15487. $this->xmlWriter->endElement();
  15488. }
  15489. private function addCopyright(\PHPUnit\PharIo\Manifest\CopyrightInformation $copyrightInformation)
  15490. {
  15491. $this->xmlWriter->startElement('copyright');
  15492. foreach ($copyrightInformation->getAuthors() as $author) {
  15493. $this->xmlWriter->startElement('author');
  15494. $this->xmlWriter->writeAttribute('name', $author->getName());
  15495. $this->xmlWriter->writeAttribute('email', (string) $author->getEmail());
  15496. $this->xmlWriter->endElement();
  15497. }
  15498. $license = $copyrightInformation->getLicense();
  15499. $this->xmlWriter->startElement('license');
  15500. $this->xmlWriter->writeAttribute('type', $license->getName());
  15501. $this->xmlWriter->writeAttribute('url', $license->getUrl());
  15502. $this->xmlWriter->endElement();
  15503. $this->xmlWriter->endElement();
  15504. }
  15505. private function addRequirements(\PHPUnit\PharIo\Manifest\RequirementCollection $requirementCollection)
  15506. {
  15507. $phpRequirement = new \PHPUnit\PharIo\Version\AnyVersionConstraint();
  15508. $extensions = [];
  15509. foreach ($requirementCollection as $requirement) {
  15510. if ($requirement instanceof \PHPUnit\PharIo\Manifest\PhpVersionRequirement) {
  15511. $phpRequirement = $requirement->getVersionConstraint();
  15512. continue;
  15513. }
  15514. if ($requirement instanceof \PHPUnit\PharIo\Manifest\PhpExtensionRequirement) {
  15515. $extensions[] = (string) $requirement;
  15516. }
  15517. }
  15518. $this->xmlWriter->startElement('requires');
  15519. $this->xmlWriter->startElement('php');
  15520. $this->xmlWriter->writeAttribute('version', $phpRequirement->asString());
  15521. foreach ($extensions as $extension) {
  15522. $this->xmlWriter->startElement('ext');
  15523. $this->xmlWriter->writeAttribute('name', $extension);
  15524. $this->xmlWriter->endElement();
  15525. }
  15526. $this->xmlWriter->endElement();
  15527. $this->xmlWriter->endElement();
  15528. }
  15529. private function addBundles(\PHPUnit\PharIo\Manifest\BundledComponentCollection $bundledComponentCollection)
  15530. {
  15531. if (\count($bundledComponentCollection) === 0) {
  15532. return;
  15533. }
  15534. $this->xmlWriter->startElement('bundles');
  15535. foreach ($bundledComponentCollection as $bundledComponent) {
  15536. $this->xmlWriter->startElement('component');
  15537. $this->xmlWriter->writeAttribute('name', $bundledComponent->getName());
  15538. $this->xmlWriter->writeAttribute('version', $bundledComponent->getVersion()->getVersionString());
  15539. $this->xmlWriter->endElement();
  15540. }
  15541. $this->xmlWriter->endElement();
  15542. }
  15543. private function addExtension($application, \PHPUnit\PharIo\Version\VersionConstraint $versionConstraint)
  15544. {
  15545. $this->xmlWriter->startElement('extension');
  15546. $this->xmlWriter->writeAttribute('for', $application);
  15547. $this->xmlWriter->writeAttribute('compatible', $versionConstraint->asString());
  15548. $this->xmlWriter->endElement();
  15549. }
  15550. }
  15551. <?php
  15552. /*
  15553. * This file is part of PharIo\Manifest.
  15554. *
  15555. * (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>
  15556. *
  15557. * For the full copyright and license information, please view the LICENSE
  15558. * file that was distributed with this source code.
  15559. */
  15560. namespace PHPUnit\PharIo\Manifest;
  15561. class ExtElement extends \PHPUnit\PharIo\Manifest\ManifestElement
  15562. {
  15563. public function getName()
  15564. {
  15565. return $this->getAttributeValue('name');
  15566. }
  15567. }
  15568. <?php
  15569. /*
  15570. * This file is part of PharIo\Manifest.
  15571. *
  15572. * (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>
  15573. *
  15574. * For the full copyright and license information, please view the LICENSE
  15575. * file that was distributed with this source code.
  15576. */
  15577. namespace PHPUnit\PharIo\Manifest;
  15578. class CopyrightElement extends \PHPUnit\PharIo\Manifest\ManifestElement
  15579. {
  15580. public function getAuthorElements()
  15581. {
  15582. return new \PHPUnit\PharIo\Manifest\AuthorElementCollection($this->getChildrenByName('author'));
  15583. }
  15584. public function getLicenseElement()
  15585. {
  15586. return new \PHPUnit\PharIo\Manifest\LicenseElement($this->getChildByName('license'));
  15587. }
  15588. }
  15589. <?php
  15590. /*
  15591. * This file is part of PharIo\Manifest.
  15592. *
  15593. * (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>
  15594. *
  15595. * For the full copyright and license information, please view the LICENSE
  15596. * file that was distributed with this source code.
  15597. */
  15598. namespace PHPUnit\PharIo\Manifest;
  15599. class PhpElement extends \PHPUnit\PharIo\Manifest\ManifestElement
  15600. {
  15601. public function getVersion()
  15602. {
  15603. return $this->getAttributeValue('version');
  15604. }
  15605. public function hasExtElements()
  15606. {
  15607. return $this->hasChild('ext');
  15608. }
  15609. public function getExtElements()
  15610. {
  15611. return new \PHPUnit\PharIo\Manifest\ExtElementCollection($this->getChildrenByName('ext'));
  15612. }
  15613. }
  15614. <?php
  15615. /*
  15616. * This file is part of PharIo\Manifest.
  15617. *
  15618. * (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>
  15619. *
  15620. * For the full copyright and license information, please view the LICENSE
  15621. * file that was distributed with this source code.
  15622. */
  15623. namespace PHPUnit\PharIo\Manifest;
  15624. class AuthorElementCollection extends \PHPUnit\PharIo\Manifest\ElementCollection
  15625. {
  15626. public function current()
  15627. {
  15628. return new \PHPUnit\PharIo\Manifest\AuthorElement($this->getCurrentElement());
  15629. }
  15630. }
  15631. <?php
  15632. /*
  15633. * This file is part of PharIo\Manifest.
  15634. *
  15635. * (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>
  15636. *
  15637. * For the full copyright and license information, please view the LICENSE
  15638. * file that was distributed with this source code.
  15639. */
  15640. namespace PHPUnit\PharIo\Manifest;
  15641. use DOMElement;
  15642. use DOMNodeList;
  15643. abstract class ElementCollection implements \Iterator
  15644. {
  15645. /**
  15646. * @var DOMNodeList
  15647. */
  15648. private $nodeList;
  15649. private $position;
  15650. /**
  15651. * ElementCollection constructor.
  15652. *
  15653. * @param DOMNodeList $nodeList
  15654. */
  15655. public function __construct(\DOMNodeList $nodeList)
  15656. {
  15657. $this->nodeList = $nodeList;
  15658. $this->position = 0;
  15659. }
  15660. public abstract function current();
  15661. /**
  15662. * @return DOMElement
  15663. */
  15664. protected function getCurrentElement()
  15665. {
  15666. return $this->nodeList->item($this->position);
  15667. }
  15668. public function next()
  15669. {
  15670. $this->position++;
  15671. }
  15672. public function key()
  15673. {
  15674. return $this->position;
  15675. }
  15676. public function valid()
  15677. {
  15678. return $this->position < $this->nodeList->length;
  15679. }
  15680. public function rewind()
  15681. {
  15682. $this->position = 0;
  15683. }
  15684. }
  15685. <?php
  15686. /*
  15687. * This file is part of PharIo\Manifest.
  15688. *
  15689. * (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>
  15690. *
  15691. * For the full copyright and license information, please view the LICENSE
  15692. * file that was distributed with this source code.
  15693. */
  15694. namespace PHPUnit\PharIo\Manifest;
  15695. class ExtensionElement extends \PHPUnit\PharIo\Manifest\ManifestElement
  15696. {
  15697. public function getFor()
  15698. {
  15699. return $this->getAttributeValue('for');
  15700. }
  15701. public function getCompatible()
  15702. {
  15703. return $this->getAttributeValue('compatible');
  15704. }
  15705. }
  15706. <?php
  15707. /*
  15708. * This file is part of PharIo\Manifest.
  15709. *
  15710. * (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>
  15711. *
  15712. * For the full copyright and license information, please view the LICENSE
  15713. * file that was distributed with this source code.
  15714. */
  15715. namespace PHPUnit\PharIo\Manifest;
  15716. class LicenseElement extends \PHPUnit\PharIo\Manifest\ManifestElement
  15717. {
  15718. public function getType()
  15719. {
  15720. return $this->getAttributeValue('type');
  15721. }
  15722. public function getUrl()
  15723. {
  15724. return $this->getAttributeValue('url');
  15725. }
  15726. }
  15727. <?php
  15728. /*
  15729. * This file is part of PharIo\Manifest.
  15730. *
  15731. * (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>
  15732. *
  15733. * For the full copyright and license information, please view the LICENSE
  15734. * file that was distributed with this source code.
  15735. */
  15736. namespace PHPUnit\PharIo\Manifest;
  15737. class ExtElementCollection extends \PHPUnit\PharIo\Manifest\ElementCollection
  15738. {
  15739. public function current()
  15740. {
  15741. return new \PHPUnit\PharIo\Manifest\ExtElement($this->getCurrentElement());
  15742. }
  15743. }
  15744. <?php
  15745. /*
  15746. * This file is part of PharIo\Manifest.
  15747. *
  15748. * (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>
  15749. *
  15750. * For the full copyright and license information, please view the LICENSE
  15751. * file that was distributed with this source code.
  15752. */
  15753. namespace PHPUnit\PharIo\Manifest;
  15754. class RequiresElement extends \PHPUnit\PharIo\Manifest\ManifestElement
  15755. {
  15756. public function getPHPElement()
  15757. {
  15758. return new \PHPUnit\PharIo\Manifest\PhpElement($this->getChildByName('php'));
  15759. }
  15760. }
  15761. <?php
  15762. /*
  15763. * This file is part of PharIo\Manifest.
  15764. *
  15765. * (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>
  15766. *
  15767. * For the full copyright and license information, please view the LICENSE
  15768. * file that was distributed with this source code.
  15769. */
  15770. namespace PHPUnit\PharIo\Manifest;
  15771. class BundlesElement extends \PHPUnit\PharIo\Manifest\ManifestElement
  15772. {
  15773. public function getComponentElements()
  15774. {
  15775. return new \PHPUnit\PharIo\Manifest\ComponentElementCollection($this->getChildrenByName('component'));
  15776. }
  15777. }
  15778. <?php
  15779. /*
  15780. * This file is part of PharIo\Manifest.
  15781. *
  15782. * (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>
  15783. *
  15784. * For the full copyright and license information, please view the LICENSE
  15785. * file that was distributed with this source code.
  15786. */
  15787. namespace PHPUnit\PharIo\Manifest;
  15788. class ContainsElement extends \PHPUnit\PharIo\Manifest\ManifestElement
  15789. {
  15790. public function getName()
  15791. {
  15792. return $this->getAttributeValue('name');
  15793. }
  15794. public function getVersion()
  15795. {
  15796. return $this->getAttributeValue('version');
  15797. }
  15798. public function getType()
  15799. {
  15800. return $this->getAttributeValue('type');
  15801. }
  15802. public function getExtensionElement()
  15803. {
  15804. return new \PHPUnit\PharIo\Manifest\ExtensionElement($this->getChildByName('extension'));
  15805. }
  15806. }
  15807. <?php
  15808. /*
  15809. * This file is part of PharIo\Manifest.
  15810. *
  15811. * (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>
  15812. *
  15813. * For the full copyright and license information, please view the LICENSE
  15814. * file that was distributed with this source code.
  15815. */
  15816. namespace PHPUnit\PharIo\Manifest;
  15817. use DOMDocument;
  15818. use DOMElement;
  15819. class ManifestDocument
  15820. {
  15821. const XMLNS = 'https://phar.io/xml/manifest/1.0';
  15822. /**
  15823. * @var DOMDocument
  15824. */
  15825. private $dom;
  15826. /**
  15827. * ManifestDocument constructor.
  15828. *
  15829. * @param DOMDocument $dom
  15830. */
  15831. private function __construct(\DOMDocument $dom)
  15832. {
  15833. $this->ensureCorrectDocumentType($dom);
  15834. $this->dom = $dom;
  15835. }
  15836. public static function fromFile($filename)
  15837. {
  15838. if (!\file_exists($filename)) {
  15839. throw new \PHPUnit\PharIo\Manifest\ManifestDocumentException(\sprintf('File "%s" not found', $filename));
  15840. }
  15841. return self::fromString(\file_get_contents($filename));
  15842. }
  15843. public static function fromString($xmlString)
  15844. {
  15845. $prev = \libxml_use_internal_errors(\true);
  15846. \libxml_clear_errors();
  15847. $dom = new \DOMDocument();
  15848. $dom->loadXML($xmlString);
  15849. $errors = \libxml_get_errors();
  15850. \libxml_use_internal_errors($prev);
  15851. if (\count($errors) !== 0) {
  15852. throw new \PHPUnit\PharIo\Manifest\ManifestDocumentLoadingException($errors);
  15853. }
  15854. return new self($dom);
  15855. }
  15856. public function getContainsElement()
  15857. {
  15858. return new \PHPUnit\PharIo\Manifest\ContainsElement($this->fetchElementByName('contains'));
  15859. }
  15860. public function getCopyrightElement()
  15861. {
  15862. return new \PHPUnit\PharIo\Manifest\CopyrightElement($this->fetchElementByName('copyright'));
  15863. }
  15864. public function getRequiresElement()
  15865. {
  15866. return new \PHPUnit\PharIo\Manifest\RequiresElement($this->fetchElementByName('requires'));
  15867. }
  15868. public function hasBundlesElement()
  15869. {
  15870. return $this->dom->getElementsByTagNameNS(self::XMLNS, 'bundles')->length === 1;
  15871. }
  15872. public function getBundlesElement()
  15873. {
  15874. return new \PHPUnit\PharIo\Manifest\BundlesElement($this->fetchElementByName('bundles'));
  15875. }
  15876. private function ensureCorrectDocumentType(\DOMDocument $dom)
  15877. {
  15878. $root = $dom->documentElement;
  15879. if ($root->localName !== 'phar' || $root->namespaceURI !== self::XMLNS) {
  15880. throw new \PHPUnit\PharIo\Manifest\ManifestDocumentException('Not a phar.io manifest document');
  15881. }
  15882. }
  15883. /**
  15884. * @param $elementName
  15885. *
  15886. * @return DOMElement
  15887. *
  15888. * @throws ManifestDocumentException
  15889. */
  15890. private function fetchElementByName($elementName)
  15891. {
  15892. $element = $this->dom->getElementsByTagNameNS(self::XMLNS, $elementName)->item(0);
  15893. if (!$element instanceof \DOMElement) {
  15894. throw new \PHPUnit\PharIo\Manifest\ManifestDocumentException(\sprintf('Element %s missing', $elementName));
  15895. }
  15896. return $element;
  15897. }
  15898. }
  15899. <?php
  15900. /*
  15901. * This file is part of PharIo\Manifest.
  15902. *
  15903. * (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>
  15904. *
  15905. * For the full copyright and license information, please view the LICENSE
  15906. * file that was distributed with this source code.
  15907. */
  15908. namespace PHPUnit\PharIo\Manifest;
  15909. class ComponentElement extends \PHPUnit\PharIo\Manifest\ManifestElement
  15910. {
  15911. public function getName()
  15912. {
  15913. return $this->getAttributeValue('name');
  15914. }
  15915. public function getVersion()
  15916. {
  15917. return $this->getAttributeValue('version');
  15918. }
  15919. }
  15920. <?php
  15921. /*
  15922. * This file is part of PharIo\Manifest.
  15923. *
  15924. * (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>
  15925. *
  15926. * For the full copyright and license information, please view the LICENSE
  15927. * file that was distributed with this source code.
  15928. */
  15929. namespace PHPUnit\PharIo\Manifest;
  15930. use DOMElement;
  15931. use DOMNodeList;
  15932. class ManifestElement
  15933. {
  15934. const XMLNS = 'https://phar.io/xml/manifest/1.0';
  15935. /**
  15936. * @var DOMElement
  15937. */
  15938. private $element;
  15939. /**
  15940. * ContainsElement constructor.
  15941. *
  15942. * @param DOMElement $element
  15943. */
  15944. public function __construct(\DOMElement $element)
  15945. {
  15946. $this->element = $element;
  15947. }
  15948. /**
  15949. * @param string $name
  15950. *
  15951. * @return string
  15952. *
  15953. * @throws ManifestElementException
  15954. */
  15955. protected function getAttributeValue($name)
  15956. {
  15957. if (!$this->element->hasAttribute($name)) {
  15958. throw new \PHPUnit\PharIo\Manifest\ManifestElementException(\sprintf('Attribute %s not set on element %s', $name, $this->element->localName));
  15959. }
  15960. return $this->element->getAttribute($name);
  15961. }
  15962. /**
  15963. * @param $elementName
  15964. *
  15965. * @return DOMElement
  15966. *
  15967. * @throws ManifestElementException
  15968. */
  15969. protected function getChildByName($elementName)
  15970. {
  15971. $element = $this->element->getElementsByTagNameNS(self::XMLNS, $elementName)->item(0);
  15972. if (!$element instanceof \DOMElement) {
  15973. throw new \PHPUnit\PharIo\Manifest\ManifestElementException(\sprintf('Element %s missing', $elementName));
  15974. }
  15975. return $element;
  15976. }
  15977. /**
  15978. * @param $elementName
  15979. *
  15980. * @return DOMNodeList
  15981. *
  15982. * @throws ManifestElementException
  15983. */
  15984. protected function getChildrenByName($elementName)
  15985. {
  15986. $elementList = $this->element->getElementsByTagNameNS(self::XMLNS, $elementName);
  15987. if ($elementList->length === 0) {
  15988. throw new \PHPUnit\PharIo\Manifest\ManifestElementException(\sprintf('Element(s) %s missing', $elementName));
  15989. }
  15990. return $elementList;
  15991. }
  15992. /**
  15993. * @param string $elementName
  15994. *
  15995. * @return bool
  15996. */
  15997. protected function hasChild($elementName)
  15998. {
  15999. return $this->element->getElementsByTagNameNS(self::XMLNS, $elementName)->length !== 0;
  16000. }
  16001. }
  16002. <?php
  16003. /*
  16004. * This file is part of PharIo\Manifest.
  16005. *
  16006. * (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>
  16007. *
  16008. * For the full copyright and license information, please view the LICENSE
  16009. * file that was distributed with this source code.
  16010. */
  16011. namespace PHPUnit\PharIo\Manifest;
  16012. class AuthorElement extends \PHPUnit\PharIo\Manifest\ManifestElement
  16013. {
  16014. public function getName()
  16015. {
  16016. return $this->getAttributeValue('name');
  16017. }
  16018. public function getEmail()
  16019. {
  16020. return $this->getAttributeValue('email');
  16021. }
  16022. }
  16023. <?php
  16024. /*
  16025. * This file is part of PharIo\Manifest.
  16026. *
  16027. * (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>
  16028. *
  16029. * For the full copyright and license information, please view the LICENSE
  16030. * file that was distributed with this source code.
  16031. */
  16032. namespace PHPUnit\PharIo\Manifest;
  16033. use LibXMLError;
  16034. class ManifestDocumentLoadingException extends \Exception implements \PHPUnit\PharIo\Manifest\Exception
  16035. {
  16036. /**
  16037. * @var LibXMLError[]
  16038. */
  16039. private $libxmlErrors;
  16040. /**
  16041. * ManifestDocumentLoadingException constructor.
  16042. *
  16043. * @param LibXMLError[] $libxmlErrors
  16044. */
  16045. public function __construct(array $libxmlErrors)
  16046. {
  16047. $this->libxmlErrors = $libxmlErrors;
  16048. $first = $this->libxmlErrors[0];
  16049. parent::__construct(\sprintf('%s (Line: %d / Column: %d / File: %s)', $first->message, $first->line, $first->column, $first->file), $first->code);
  16050. }
  16051. /**
  16052. * @return LibXMLError[]
  16053. */
  16054. public function getLibxmlErrors()
  16055. {
  16056. return $this->libxmlErrors;
  16057. }
  16058. }
  16059. <?php
  16060. /*
  16061. * This file is part of PharIo\Manifest.
  16062. *
  16063. * (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>
  16064. *
  16065. * For the full copyright and license information, please view the LICENSE
  16066. * file that was distributed with this source code.
  16067. */
  16068. namespace PHPUnit\PharIo\Manifest;
  16069. class ComponentElementCollection extends \PHPUnit\PharIo\Manifest\ElementCollection
  16070. {
  16071. public function current()
  16072. {
  16073. return new \PHPUnit\PharIo\Manifest\ComponentElement($this->getCurrentElement());
  16074. }
  16075. }
  16076. manifest
  16077. Copyright (c) 2016 Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>, and contributors
  16078. All rights reserved.
  16079. Redistribution and use in source and binary forms, with or without modification,
  16080. are permitted provided that the following conditions are met:
  16081. * Redistributions of source code must retain the above copyright notice,
  16082. this list of conditions and the following disclaimer.
  16083. * Redistributions in binary form must reproduce the above copyright notice,
  16084. this list of conditions and the following disclaimer in the documentation
  16085. and/or other materials provided with the distribution.
  16086. * Neither the name of Arne Blankerts nor the names of contributors
  16087. may be used to endorse or promote products derived from this software
  16088. without specific prior written permission.
  16089. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  16090. AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO,
  16091. THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  16092. PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS
  16093. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
  16094. OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  16095. SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  16096. INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  16097. CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  16098. ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  16099. POSSIBILITY OF SUCH DAMAGE.
  16100. <?php
  16101. /*
  16102. * This file is part of PharIo\Manifest.
  16103. *
  16104. * (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>
  16105. *
  16106. * For the full copyright and license information, please view the LICENSE
  16107. * file that was distributed with this source code.
  16108. */
  16109. namespace PHPUnit\PharIo\Manifest;
  16110. use PHPUnit\PharIo\Version\Version;
  16111. class Manifest
  16112. {
  16113. /**
  16114. * @var ApplicationName
  16115. */
  16116. private $name;
  16117. /**
  16118. * @var Version
  16119. */
  16120. private $version;
  16121. /**
  16122. * @var Type
  16123. */
  16124. private $type;
  16125. /**
  16126. * @var CopyrightInformation
  16127. */
  16128. private $copyrightInformation;
  16129. /**
  16130. * @var RequirementCollection
  16131. */
  16132. private $requirements;
  16133. /**
  16134. * @var BundledComponentCollection
  16135. */
  16136. private $bundledComponents;
  16137. public function __construct(\PHPUnit\PharIo\Manifest\ApplicationName $name, \PHPUnit\PharIo\Version\Version $version, \PHPUnit\PharIo\Manifest\Type $type, \PHPUnit\PharIo\Manifest\CopyrightInformation $copyrightInformation, \PHPUnit\PharIo\Manifest\RequirementCollection $requirements, \PHPUnit\PharIo\Manifest\BundledComponentCollection $bundledComponents)
  16138. {
  16139. $this->name = $name;
  16140. $this->version = $version;
  16141. $this->type = $type;
  16142. $this->copyrightInformation = $copyrightInformation;
  16143. $this->requirements = $requirements;
  16144. $this->bundledComponents = $bundledComponents;
  16145. }
  16146. /**
  16147. * @return ApplicationName
  16148. */
  16149. public function getName()
  16150. {
  16151. return $this->name;
  16152. }
  16153. /**
  16154. * @return Version
  16155. */
  16156. public function getVersion()
  16157. {
  16158. return $this->version;
  16159. }
  16160. /**
  16161. * @return Type
  16162. */
  16163. public function getType()
  16164. {
  16165. return $this->type;
  16166. }
  16167. /**
  16168. * @return CopyrightInformation
  16169. */
  16170. public function getCopyrightInformation()
  16171. {
  16172. return $this->copyrightInformation;
  16173. }
  16174. /**
  16175. * @return RequirementCollection
  16176. */
  16177. public function getRequirements()
  16178. {
  16179. return $this->requirements;
  16180. }
  16181. /**
  16182. * @return BundledComponentCollection
  16183. */
  16184. public function getBundledComponents()
  16185. {
  16186. return $this->bundledComponents;
  16187. }
  16188. /**
  16189. * @return bool
  16190. */
  16191. public function isApplication()
  16192. {
  16193. return $this->type->isApplication();
  16194. }
  16195. /**
  16196. * @return bool
  16197. */
  16198. public function isLibrary()
  16199. {
  16200. return $this->type->isLibrary();
  16201. }
  16202. /**
  16203. * @return bool
  16204. */
  16205. public function isExtension()
  16206. {
  16207. return $this->type->isExtension();
  16208. }
  16209. /**
  16210. * @param ApplicationName $application
  16211. * @param Version|null $version
  16212. *
  16213. * @return bool
  16214. */
  16215. public function isExtensionFor(\PHPUnit\PharIo\Manifest\ApplicationName $application, \PHPUnit\PharIo\Version\Version $version = null)
  16216. {
  16217. if (!$this->isExtension()) {
  16218. return \false;
  16219. }
  16220. /** @var Extension $type */
  16221. $type = $this->type;
  16222. if ($version !== null) {
  16223. return $type->isCompatibleWith($application, $version);
  16224. }
  16225. return $type->isExtensionFor($application);
  16226. }
  16227. }
  16228. <?php
  16229. /*
  16230. * This file is part of PharIo\Manifest.
  16231. *
  16232. * (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>
  16233. *
  16234. * For the full copyright and license information, please view the LICENSE
  16235. * file that was distributed with this source code.
  16236. */
  16237. namespace PHPUnit\PharIo\Manifest;
  16238. class Url
  16239. {
  16240. /**
  16241. * @var string
  16242. */
  16243. private $url;
  16244. /**
  16245. * @param string $url
  16246. *
  16247. * @throws InvalidUrlException
  16248. */
  16249. public function __construct($url)
  16250. {
  16251. $this->ensureUrlIsValid($url);
  16252. $this->url = $url;
  16253. }
  16254. /**
  16255. * @return string
  16256. */
  16257. public function __toString()
  16258. {
  16259. return $this->url;
  16260. }
  16261. /**
  16262. * @param string $url
  16263. *
  16264. * @throws InvalidUrlException
  16265. */
  16266. private function ensureUrlIsValid($url)
  16267. {
  16268. if (\filter_var($url, \FILTER_VALIDATE_URL) === \false) {
  16269. throw new \PHPUnit\PharIo\Manifest\InvalidUrlException();
  16270. }
  16271. }
  16272. }
  16273. <?php
  16274. /*
  16275. * This file is part of PharIo\Manifest.
  16276. *
  16277. * (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>
  16278. *
  16279. * For the full copyright and license information, please view the LICENSE
  16280. * file that was distributed with this source code.
  16281. */
  16282. namespace PHPUnit\PharIo\Manifest;
  16283. class AuthorCollectionIterator implements \Iterator
  16284. {
  16285. /**
  16286. * @var Author[]
  16287. */
  16288. private $authors = [];
  16289. /**
  16290. * @var int
  16291. */
  16292. private $position;
  16293. public function __construct(\PHPUnit\PharIo\Manifest\AuthorCollection $authors)
  16294. {
  16295. $this->authors = $authors->getAuthors();
  16296. }
  16297. public function rewind()
  16298. {
  16299. $this->position = 0;
  16300. }
  16301. /**
  16302. * @return bool
  16303. */
  16304. public function valid()
  16305. {
  16306. return $this->position < \count($this->authors);
  16307. }
  16308. /**
  16309. * @return int
  16310. */
  16311. public function key()
  16312. {
  16313. return $this->position;
  16314. }
  16315. /**
  16316. * @return Author
  16317. */
  16318. public function current()
  16319. {
  16320. return $this->authors[$this->position];
  16321. }
  16322. public function next()
  16323. {
  16324. $this->position++;
  16325. }
  16326. }
  16327. <?php
  16328. /*
  16329. * This file is part of PharIo\Manifest.
  16330. *
  16331. * (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>
  16332. *
  16333. * For the full copyright and license information, please view the LICENSE
  16334. * file that was distributed with this source code.
  16335. */
  16336. namespace PHPUnit\PharIo\Manifest;
  16337. class Author
  16338. {
  16339. /**
  16340. * @var string
  16341. */
  16342. private $name;
  16343. /**
  16344. * @var Email
  16345. */
  16346. private $email;
  16347. /**
  16348. * @param string $name
  16349. * @param Email $email
  16350. */
  16351. public function __construct($name, \PHPUnit\PharIo\Manifest\Email $email)
  16352. {
  16353. $this->name = $name;
  16354. $this->email = $email;
  16355. }
  16356. /**
  16357. * @return string
  16358. */
  16359. public function getName()
  16360. {
  16361. return $this->name;
  16362. }
  16363. /**
  16364. * @return Email
  16365. */
  16366. public function getEmail()
  16367. {
  16368. return $this->email;
  16369. }
  16370. /**
  16371. * @return string
  16372. */
  16373. public function __toString()
  16374. {
  16375. return \sprintf('%s <%s>', $this->name, $this->email);
  16376. }
  16377. }
  16378. <?php
  16379. /*
  16380. * This file is part of PharIo\Manifest.
  16381. *
  16382. * (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>
  16383. *
  16384. * For the full copyright and license information, please view the LICENSE
  16385. * file that was distributed with this source code.
  16386. */
  16387. namespace PHPUnit\PharIo\Manifest;
  16388. class ApplicationName
  16389. {
  16390. /**
  16391. * @var string
  16392. */
  16393. private $name;
  16394. /**
  16395. * ApplicationName constructor.
  16396. *
  16397. * @param string $name
  16398. *
  16399. * @throws InvalidApplicationNameException
  16400. */
  16401. public function __construct($name)
  16402. {
  16403. $this->ensureIsString($name);
  16404. $this->ensureValidFormat($name);
  16405. $this->name = $name;
  16406. }
  16407. /**
  16408. * @return string
  16409. */
  16410. public function __toString()
  16411. {
  16412. return $this->name;
  16413. }
  16414. public function isEqual(\PHPUnit\PharIo\Manifest\ApplicationName $name)
  16415. {
  16416. return $this->name === $name->name;
  16417. }
  16418. /**
  16419. * @param string $name
  16420. *
  16421. * @throws InvalidApplicationNameException
  16422. */
  16423. private function ensureValidFormat($name)
  16424. {
  16425. if (!\preg_match('#\\w/\\w#', $name)) {
  16426. throw new \PHPUnit\PharIo\Manifest\InvalidApplicationNameException(\sprintf('Format of name "%s" is not valid - expected: vendor/packagename', $name), \PHPUnit\PharIo\Manifest\InvalidApplicationNameException::InvalidFormat);
  16427. }
  16428. }
  16429. private function ensureIsString($name)
  16430. {
  16431. if (!\is_string($name)) {
  16432. throw new \PHPUnit\PharIo\Manifest\InvalidApplicationNameException('Name must be a string', \PHPUnit\PharIo\Manifest\InvalidApplicationNameException::NotAString);
  16433. }
  16434. }
  16435. }
  16436. <?php
  16437. /*
  16438. * This file is part of PharIo\Manifest.
  16439. *
  16440. * (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>
  16441. *
  16442. * For the full copyright and license information, please view the LICENSE
  16443. * file that was distributed with this source code.
  16444. */
  16445. namespace PHPUnit\PharIo\Manifest;
  16446. class Application extends \PHPUnit\PharIo\Manifest\Type
  16447. {
  16448. /**
  16449. * @return bool
  16450. */
  16451. public function isApplication()
  16452. {
  16453. return \true;
  16454. }
  16455. }
  16456. <?php
  16457. /*
  16458. * This file is part of PharIo\Manifest.
  16459. *
  16460. * (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>
  16461. *
  16462. * For the full copyright and license information, please view the LICENSE
  16463. * file that was distributed with this source code.
  16464. */
  16465. namespace PHPUnit\PharIo\Manifest;
  16466. use PHPUnit\PharIo\Version\VersionConstraint;
  16467. class PhpVersionRequirement implements \PHPUnit\PharIo\Manifest\Requirement
  16468. {
  16469. /**
  16470. * @var VersionConstraint
  16471. */
  16472. private $versionConstraint;
  16473. public function __construct(\PHPUnit\PharIo\Version\VersionConstraint $versionConstraint)
  16474. {
  16475. $this->versionConstraint = $versionConstraint;
  16476. }
  16477. /**
  16478. * @return VersionConstraint
  16479. */
  16480. public function getVersionConstraint()
  16481. {
  16482. return $this->versionConstraint;
  16483. }
  16484. }
  16485. <?php
  16486. /*
  16487. * This file is part of PharIo\Manifest.
  16488. *
  16489. * (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>
  16490. *
  16491. * For the full copyright and license information, please view the LICENSE
  16492. * file that was distributed with this source code.
  16493. */
  16494. namespace PHPUnit\PharIo\Manifest;
  16495. class License
  16496. {
  16497. /**
  16498. * @var string
  16499. */
  16500. private $name;
  16501. /**
  16502. * @var Url
  16503. */
  16504. private $url;
  16505. public function __construct($name, \PHPUnit\PharIo\Manifest\Url $url)
  16506. {
  16507. $this->name = $name;
  16508. $this->url = $url;
  16509. }
  16510. /**
  16511. * @return string
  16512. */
  16513. public function getName()
  16514. {
  16515. return $this->name;
  16516. }
  16517. /**
  16518. * @return Url
  16519. */
  16520. public function getUrl()
  16521. {
  16522. return $this->url;
  16523. }
  16524. }
  16525. <?php
  16526. /*
  16527. * This file is part of PharIo\Manifest.
  16528. *
  16529. * (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>
  16530. *
  16531. * For the full copyright and license information, please view the LICENSE
  16532. * file that was distributed with this source code.
  16533. */
  16534. namespace PHPUnit\PharIo\Manifest;
  16535. class Library extends \PHPUnit\PharIo\Manifest\Type
  16536. {
  16537. /**
  16538. * @return bool
  16539. */
  16540. public function isLibrary()
  16541. {
  16542. return \true;
  16543. }
  16544. }
  16545. <?php
  16546. /*
  16547. * This file is part of PharIo\Manifest.
  16548. *
  16549. * (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>
  16550. *
  16551. * For the full copyright and license information, please view the LICENSE
  16552. * file that was distributed with this source code.
  16553. */
  16554. namespace PHPUnit\PharIo\Manifest;
  16555. class AuthorCollection implements \Countable, \IteratorAggregate
  16556. {
  16557. /**
  16558. * @var Author[]
  16559. */
  16560. private $authors = [];
  16561. public function add(\PHPUnit\PharIo\Manifest\Author $author)
  16562. {
  16563. $this->authors[] = $author;
  16564. }
  16565. /**
  16566. * @return Author[]
  16567. */
  16568. public function getAuthors()
  16569. {
  16570. return $this->authors;
  16571. }
  16572. /**
  16573. * @return int
  16574. */
  16575. public function count()
  16576. {
  16577. return \count($this->authors);
  16578. }
  16579. /**
  16580. * @return AuthorCollectionIterator
  16581. */
  16582. public function getIterator()
  16583. {
  16584. return new \PHPUnit\PharIo\Manifest\AuthorCollectionIterator($this);
  16585. }
  16586. }
  16587. <?php
  16588. /*
  16589. * This file is part of PharIo\Manifest.
  16590. *
  16591. * (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>
  16592. *
  16593. * For the full copyright and license information, please view the LICENSE
  16594. * file that was distributed with this source code.
  16595. */
  16596. namespace PHPUnit\PharIo\Manifest;
  16597. interface Requirement
  16598. {
  16599. }
  16600. <?php
  16601. /*
  16602. * This file is part of PharIo\Manifest.
  16603. *
  16604. * (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>
  16605. *
  16606. * For the full copyright and license information, please view the LICENSE
  16607. * file that was distributed with this source code.
  16608. */
  16609. namespace PHPUnit\PharIo\Manifest;
  16610. use PHPUnit\PharIo\Version\Version;
  16611. use PHPUnit\PharIo\Version\VersionConstraint;
  16612. class Extension extends \PHPUnit\PharIo\Manifest\Type
  16613. {
  16614. /**
  16615. * @var ApplicationName
  16616. */
  16617. private $application;
  16618. /**
  16619. * @var VersionConstraint
  16620. */
  16621. private $versionConstraint;
  16622. /**
  16623. * @param ApplicationName $application
  16624. * @param VersionConstraint $versionConstraint
  16625. */
  16626. public function __construct(\PHPUnit\PharIo\Manifest\ApplicationName $application, \PHPUnit\PharIo\Version\VersionConstraint $versionConstraint)
  16627. {
  16628. $this->application = $application;
  16629. $this->versionConstraint = $versionConstraint;
  16630. }
  16631. /**
  16632. * @return ApplicationName
  16633. */
  16634. public function getApplicationName()
  16635. {
  16636. return $this->application;
  16637. }
  16638. /**
  16639. * @return VersionConstraint
  16640. */
  16641. public function getVersionConstraint()
  16642. {
  16643. return $this->versionConstraint;
  16644. }
  16645. /**
  16646. * @return bool
  16647. */
  16648. public function isExtension()
  16649. {
  16650. return \true;
  16651. }
  16652. /**
  16653. * @param ApplicationName $name
  16654. *
  16655. * @return bool
  16656. */
  16657. public function isExtensionFor(\PHPUnit\PharIo\Manifest\ApplicationName $name)
  16658. {
  16659. return $this->application->isEqual($name);
  16660. }
  16661. /**
  16662. * @param ApplicationName $name
  16663. * @param Version $version
  16664. *
  16665. * @return bool
  16666. */
  16667. public function isCompatibleWith(\PHPUnit\PharIo\Manifest\ApplicationName $name, \PHPUnit\PharIo\Version\Version $version)
  16668. {
  16669. return $this->isExtensionFor($name) && $this->versionConstraint->complies($version);
  16670. }
  16671. }
  16672. <?php
  16673. /*
  16674. * This file is part of PharIo\Manifest.
  16675. *
  16676. * (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>
  16677. *
  16678. * For the full copyright and license information, please view the LICENSE
  16679. * file that was distributed with this source code.
  16680. */
  16681. namespace PHPUnit\PharIo\Manifest;
  16682. class BundledComponentCollectionIterator implements \Iterator
  16683. {
  16684. /**
  16685. * @var BundledComponent[]
  16686. */
  16687. private $bundledComponents = [];
  16688. /**
  16689. * @var int
  16690. */
  16691. private $position;
  16692. public function __construct(\PHPUnit\PharIo\Manifest\BundledComponentCollection $bundledComponents)
  16693. {
  16694. $this->bundledComponents = $bundledComponents->getBundledComponents();
  16695. }
  16696. public function rewind()
  16697. {
  16698. $this->position = 0;
  16699. }
  16700. /**
  16701. * @return bool
  16702. */
  16703. public function valid()
  16704. {
  16705. return $this->position < \count($this->bundledComponents);
  16706. }
  16707. /**
  16708. * @return int
  16709. */
  16710. public function key()
  16711. {
  16712. return $this->position;
  16713. }
  16714. /**
  16715. * @return BundledComponent
  16716. */
  16717. public function current()
  16718. {
  16719. return $this->bundledComponents[$this->position];
  16720. }
  16721. public function next()
  16722. {
  16723. $this->position++;
  16724. }
  16725. }
  16726. <?php
  16727. /*
  16728. * This file is part of PharIo\Manifest.
  16729. *
  16730. * (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>
  16731. *
  16732. * For the full copyright and license information, please view the LICENSE
  16733. * file that was distributed with this source code.
  16734. */
  16735. namespace PHPUnit\PharIo\Manifest;
  16736. class RequirementCollection implements \Countable, \IteratorAggregate
  16737. {
  16738. /**
  16739. * @var Requirement[]
  16740. */
  16741. private $requirements = [];
  16742. public function add(\PHPUnit\PharIo\Manifest\Requirement $requirement)
  16743. {
  16744. $this->requirements[] = $requirement;
  16745. }
  16746. /**
  16747. * @return Requirement[]
  16748. */
  16749. public function getRequirements()
  16750. {
  16751. return $this->requirements;
  16752. }
  16753. /**
  16754. * @return int
  16755. */
  16756. public function count()
  16757. {
  16758. return \count($this->requirements);
  16759. }
  16760. /**
  16761. * @return RequirementCollectionIterator
  16762. */
  16763. public function getIterator()
  16764. {
  16765. return new \PHPUnit\PharIo\Manifest\RequirementCollectionIterator($this);
  16766. }
  16767. }
  16768. <?php
  16769. /*
  16770. * This file is part of PharIo\Manifest.
  16771. *
  16772. * (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>
  16773. *
  16774. * For the full copyright and license information, please view the LICENSE
  16775. * file that was distributed with this source code.
  16776. */
  16777. namespace PHPUnit\PharIo\Manifest;
  16778. class RequirementCollectionIterator implements \Iterator
  16779. {
  16780. /**
  16781. * @var Requirement[]
  16782. */
  16783. private $requirements = [];
  16784. /**
  16785. * @var int
  16786. */
  16787. private $position;
  16788. public function __construct(\PHPUnit\PharIo\Manifest\RequirementCollection $requirements)
  16789. {
  16790. $this->requirements = $requirements->getRequirements();
  16791. }
  16792. public function rewind()
  16793. {
  16794. $this->position = 0;
  16795. }
  16796. /**
  16797. * @return bool
  16798. */
  16799. public function valid()
  16800. {
  16801. return $this->position < \count($this->requirements);
  16802. }
  16803. /**
  16804. * @return int
  16805. */
  16806. public function key()
  16807. {
  16808. return $this->position;
  16809. }
  16810. /**
  16811. * @return Requirement
  16812. */
  16813. public function current()
  16814. {
  16815. return $this->requirements[$this->position];
  16816. }
  16817. public function next()
  16818. {
  16819. $this->position++;
  16820. }
  16821. }
  16822. <?php
  16823. /*
  16824. * This file is part of PharIo\Manifest.
  16825. *
  16826. * (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>
  16827. *
  16828. * For the full copyright and license information, please view the LICENSE
  16829. * file that was distributed with this source code.
  16830. */
  16831. namespace PHPUnit\PharIo\Manifest;
  16832. class Email
  16833. {
  16834. /**
  16835. * @var string
  16836. */
  16837. private $email;
  16838. /**
  16839. * @param string $email
  16840. *
  16841. * @throws InvalidEmailException
  16842. */
  16843. public function __construct($email)
  16844. {
  16845. $this->ensureEmailIsValid($email);
  16846. $this->email = $email;
  16847. }
  16848. /**
  16849. * @return string
  16850. */
  16851. public function __toString()
  16852. {
  16853. return $this->email;
  16854. }
  16855. /**
  16856. * @param string $url
  16857. *
  16858. * @throws InvalidEmailException
  16859. */
  16860. private function ensureEmailIsValid($url)
  16861. {
  16862. if (\filter_var($url, \FILTER_VALIDATE_EMAIL) === \false) {
  16863. throw new \PHPUnit\PharIo\Manifest\InvalidEmailException();
  16864. }
  16865. }
  16866. }
  16867. <?php
  16868. /*
  16869. * This file is part of PharIo\Manifest.
  16870. *
  16871. * (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>
  16872. *
  16873. * For the full copyright and license information, please view the LICENSE
  16874. * file that was distributed with this source code.
  16875. */
  16876. namespace PHPUnit\PharIo\Manifest;
  16877. use PHPUnit\PharIo\Version\VersionConstraint;
  16878. abstract class Type
  16879. {
  16880. /**
  16881. * @return Application
  16882. */
  16883. public static function application()
  16884. {
  16885. return new \PHPUnit\PharIo\Manifest\Application();
  16886. }
  16887. /**
  16888. * @return Library
  16889. */
  16890. public static function library()
  16891. {
  16892. return new \PHPUnit\PharIo\Manifest\Library();
  16893. }
  16894. /**
  16895. * @param ApplicationName $application
  16896. * @param VersionConstraint $versionConstraint
  16897. *
  16898. * @return Extension
  16899. */
  16900. public static function extension(\PHPUnit\PharIo\Manifest\ApplicationName $application, \PHPUnit\PharIo\Version\VersionConstraint $versionConstraint)
  16901. {
  16902. return new \PHPUnit\PharIo\Manifest\Extension($application, $versionConstraint);
  16903. }
  16904. /**
  16905. * @return bool
  16906. */
  16907. public function isApplication()
  16908. {
  16909. return \false;
  16910. }
  16911. /**
  16912. * @return bool
  16913. */
  16914. public function isLibrary()
  16915. {
  16916. return \false;
  16917. }
  16918. /**
  16919. * @return bool
  16920. */
  16921. public function isExtension()
  16922. {
  16923. return \false;
  16924. }
  16925. }
  16926. <?php
  16927. /*
  16928. * This file is part of PharIo\Manifest.
  16929. *
  16930. * (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>
  16931. *
  16932. * For the full copyright and license information, please view the LICENSE
  16933. * file that was distributed with this source code.
  16934. */
  16935. namespace PHPUnit\PharIo\Manifest;
  16936. class BundledComponentCollection implements \Countable, \IteratorAggregate
  16937. {
  16938. /**
  16939. * @var BundledComponent[]
  16940. */
  16941. private $bundledComponents = [];
  16942. public function add(\PHPUnit\PharIo\Manifest\BundledComponent $bundledComponent)
  16943. {
  16944. $this->bundledComponents[] = $bundledComponent;
  16945. }
  16946. /**
  16947. * @return BundledComponent[]
  16948. */
  16949. public function getBundledComponents()
  16950. {
  16951. return $this->bundledComponents;
  16952. }
  16953. /**
  16954. * @return int
  16955. */
  16956. public function count()
  16957. {
  16958. return \count($this->bundledComponents);
  16959. }
  16960. /**
  16961. * @return BundledComponentCollectionIterator
  16962. */
  16963. public function getIterator()
  16964. {
  16965. return new \PHPUnit\PharIo\Manifest\BundledComponentCollectionIterator($this);
  16966. }
  16967. }
  16968. <?php
  16969. /*
  16970. * This file is part of PharIo\Manifest.
  16971. *
  16972. * (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>
  16973. *
  16974. * For the full copyright and license information, please view the LICENSE
  16975. * file that was distributed with this source code.
  16976. */
  16977. namespace PHPUnit\PharIo\Manifest;
  16978. class PhpExtensionRequirement implements \PHPUnit\PharIo\Manifest\Requirement
  16979. {
  16980. /**
  16981. * @var string
  16982. */
  16983. private $extension;
  16984. /**
  16985. * @param string $extension
  16986. */
  16987. public function __construct($extension)
  16988. {
  16989. $this->extension = $extension;
  16990. }
  16991. /**
  16992. * @return string
  16993. */
  16994. public function __toString()
  16995. {
  16996. return $this->extension;
  16997. }
  16998. }
  16999. <?php
  17000. /*
  17001. * This file is part of PharIo\Manifest.
  17002. *
  17003. * (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>
  17004. *
  17005. * For the full copyright and license information, please view the LICENSE
  17006. * file that was distributed with this source code.
  17007. */
  17008. namespace PHPUnit\PharIo\Manifest;
  17009. use PHPUnit\PharIo\Version\Version;
  17010. class BundledComponent
  17011. {
  17012. /**
  17013. * @var string
  17014. */
  17015. private $name;
  17016. /**
  17017. * @var Version
  17018. */
  17019. private $version;
  17020. /**
  17021. * @param string $name
  17022. * @param Version $version
  17023. */
  17024. public function __construct($name, \PHPUnit\PharIo\Version\Version $version)
  17025. {
  17026. $this->name = $name;
  17027. $this->version = $version;
  17028. }
  17029. /**
  17030. * @return string
  17031. */
  17032. public function getName()
  17033. {
  17034. return $this->name;
  17035. }
  17036. /**
  17037. * @return Version
  17038. */
  17039. public function getVersion()
  17040. {
  17041. return $this->version;
  17042. }
  17043. }
  17044. <?php
  17045. /*
  17046. * This file is part of PharIo\Manifest.
  17047. *
  17048. * (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>
  17049. *
  17050. * For the full copyright and license information, please view the LICENSE
  17051. * file that was distributed with this source code.
  17052. */
  17053. namespace PHPUnit\PharIo\Manifest;
  17054. class CopyrightInformation
  17055. {
  17056. /**
  17057. * @var AuthorCollection
  17058. */
  17059. private $authors;
  17060. /**
  17061. * @var License
  17062. */
  17063. private $license;
  17064. public function __construct(\PHPUnit\PharIo\Manifest\AuthorCollection $authors, \PHPUnit\PharIo\Manifest\License $license)
  17065. {
  17066. $this->authors = $authors;
  17067. $this->license = $license;
  17068. }
  17069. /**
  17070. * @return AuthorCollection
  17071. */
  17072. public function getAuthors()
  17073. {
  17074. return $this->authors;
  17075. }
  17076. /**
  17077. * @return License
  17078. */
  17079. public function getLicense()
  17080. {
  17081. return $this->license;
  17082. }
  17083. }
  17084. <?php
  17085. /*
  17086. * This file is part of PharIo\Manifest.
  17087. *
  17088. * (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>
  17089. *
  17090. * For the full copyright and license information, please view the LICENSE
  17091. * file that was distributed with this source code.
  17092. */
  17093. namespace PHPUnit\PharIo\Manifest;
  17094. class ManifestLoader
  17095. {
  17096. /**
  17097. * @param string $filename
  17098. *
  17099. * @return Manifest
  17100. *
  17101. * @throws ManifestLoaderException
  17102. */
  17103. public static function fromFile($filename)
  17104. {
  17105. try {
  17106. return (new \PHPUnit\PharIo\Manifest\ManifestDocumentMapper())->map(\PHPUnit\PharIo\Manifest\ManifestDocument::fromFile($filename));
  17107. } catch (\PHPUnit\PharIo\Manifest\Exception $e) {
  17108. throw new \PHPUnit\PharIo\Manifest\ManifestLoaderException(\sprintf('Loading %s failed.', $filename), $e->getCode(), $e);
  17109. }
  17110. }
  17111. /**
  17112. * @param string $filename
  17113. *
  17114. * @return Manifest
  17115. *
  17116. * @throws ManifestLoaderException
  17117. */
  17118. public static function fromPhar($filename)
  17119. {
  17120. return self::fromFile('phar://' . $filename . '/manifest.xml');
  17121. }
  17122. /**
  17123. * @param string $manifest
  17124. *
  17125. * @return Manifest
  17126. *
  17127. * @throws ManifestLoaderException
  17128. */
  17129. public static function fromString($manifest)
  17130. {
  17131. try {
  17132. return (new \PHPUnit\PharIo\Manifest\ManifestDocumentMapper())->map(\PHPUnit\PharIo\Manifest\ManifestDocument::fromString($manifest));
  17133. } catch (\PHPUnit\PharIo\Manifest\Exception $e) {
  17134. throw new \PHPUnit\PharIo\Manifest\ManifestLoaderException('Processing string failed', $e->getCode(), $e);
  17135. }
  17136. }
  17137. }
  17138. <?php
  17139. namespace PHPUnit;
  17140. /*
  17141. * This file is part of the Symfony package.
  17142. *
  17143. * (c) Fabien Potencier <fabien@symfony.com>
  17144. *
  17145. * For the full copyright and license information, please view the LICENSE
  17146. * file that was distributed with this source code.
  17147. */
  17148. use PHPUnit\Symfony\Polyfill\Ctype as p;
  17149. if (!\function_exists('ctype_alnum')) {
  17150. function ctype_alnum($text)
  17151. {
  17152. return \PHPUnit\Symfony\Polyfill\Ctype\Ctype::ctype_alnum($text);
  17153. }
  17154. }
  17155. if (!\function_exists('ctype_alpha')) {
  17156. function ctype_alpha($text)
  17157. {
  17158. return \PHPUnit\Symfony\Polyfill\Ctype\Ctype::ctype_alpha($text);
  17159. }
  17160. }
  17161. if (!\function_exists('ctype_cntrl')) {
  17162. function ctype_cntrl($text)
  17163. {
  17164. return \PHPUnit\Symfony\Polyfill\Ctype\Ctype::ctype_cntrl($text);
  17165. }
  17166. }
  17167. if (!\function_exists('ctype_digit')) {
  17168. function ctype_digit($text)
  17169. {
  17170. return \PHPUnit\Symfony\Polyfill\Ctype\Ctype::ctype_digit($text);
  17171. }
  17172. }
  17173. if (!\function_exists('ctype_graph')) {
  17174. function ctype_graph($text)
  17175. {
  17176. return \PHPUnit\Symfony\Polyfill\Ctype\Ctype::ctype_graph($text);
  17177. }
  17178. }
  17179. if (!\function_exists('ctype_lower')) {
  17180. function ctype_lower($text)
  17181. {
  17182. return \PHPUnit\Symfony\Polyfill\Ctype\Ctype::ctype_lower($text);
  17183. }
  17184. }
  17185. if (!\function_exists('ctype_print')) {
  17186. function ctype_print($text)
  17187. {
  17188. return \PHPUnit\Symfony\Polyfill\Ctype\Ctype::ctype_print($text);
  17189. }
  17190. }
  17191. if (!\function_exists('ctype_punct')) {
  17192. function ctype_punct($text)
  17193. {
  17194. return \PHPUnit\Symfony\Polyfill\Ctype\Ctype::ctype_punct($text);
  17195. }
  17196. }
  17197. if (!\function_exists('ctype_space')) {
  17198. function ctype_space($text)
  17199. {
  17200. return \PHPUnit\Symfony\Polyfill\Ctype\Ctype::ctype_space($text);
  17201. }
  17202. }
  17203. if (!\function_exists('ctype_upper')) {
  17204. function ctype_upper($text)
  17205. {
  17206. return \PHPUnit\Symfony\Polyfill\Ctype\Ctype::ctype_upper($text);
  17207. }
  17208. }
  17209. if (!\function_exists('ctype_xdigit')) {
  17210. function ctype_xdigit($text)
  17211. {
  17212. return \PHPUnit\Symfony\Polyfill\Ctype\Ctype::ctype_xdigit($text);
  17213. }
  17214. }
  17215. <?php
  17216. /*
  17217. * This file is part of the Symfony package.
  17218. *
  17219. * (c) Fabien Potencier <fabien@symfony.com>
  17220. *
  17221. * For the full copyright and license information, please view the LICENSE
  17222. * file that was distributed with this source code.
  17223. */
  17224. namespace PHPUnit\Symfony\Polyfill\Ctype;
  17225. /**
  17226. * Ctype implementation through regex.
  17227. *
  17228. * @internal
  17229. *
  17230. * @author Gert de Pagter <BackEndTea@gmail.com>
  17231. */
  17232. final class Ctype
  17233. {
  17234. /**
  17235. * Returns TRUE if every character in text is either a letter or a digit, FALSE otherwise.
  17236. *
  17237. * @see https://php.net/ctype-alnum
  17238. *
  17239. * @param string|int $text
  17240. *
  17241. * @return bool
  17242. */
  17243. public static function ctype_alnum($text)
  17244. {
  17245. $text = self::convert_int_to_char_for_ctype($text);
  17246. return \is_string($text) && '' !== $text && !\preg_match('/[^A-Za-z0-9]/', $text);
  17247. }
  17248. /**
  17249. * Returns TRUE if every character in text is a letter, FALSE otherwise.
  17250. *
  17251. * @see https://php.net/ctype-alpha
  17252. *
  17253. * @param string|int $text
  17254. *
  17255. * @return bool
  17256. */
  17257. public static function ctype_alpha($text)
  17258. {
  17259. $text = self::convert_int_to_char_for_ctype($text);
  17260. return \is_string($text) && '' !== $text && !\preg_match('/[^A-Za-z]/', $text);
  17261. }
  17262. /**
  17263. * Returns TRUE if every character in text is a control character from the current locale, FALSE otherwise.
  17264. *
  17265. * @see https://php.net/ctype-cntrl
  17266. *
  17267. * @param string|int $text
  17268. *
  17269. * @return bool
  17270. */
  17271. public static function ctype_cntrl($text)
  17272. {
  17273. $text = self::convert_int_to_char_for_ctype($text);
  17274. return \is_string($text) && '' !== $text && !\preg_match('/[^\\x00-\\x1f\\x7f]/', $text);
  17275. }
  17276. /**
  17277. * Returns TRUE if every character in the string text is a decimal digit, FALSE otherwise.
  17278. *
  17279. * @see https://php.net/ctype-digit
  17280. *
  17281. * @param string|int $text
  17282. *
  17283. * @return bool
  17284. */
  17285. public static function ctype_digit($text)
  17286. {
  17287. $text = self::convert_int_to_char_for_ctype($text);
  17288. return \is_string($text) && '' !== $text && !\preg_match('/[^0-9]/', $text);
  17289. }
  17290. /**
  17291. * Returns TRUE if every character in text is printable and actually creates visible output (no white space), FALSE otherwise.
  17292. *
  17293. * @see https://php.net/ctype-graph
  17294. *
  17295. * @param string|int $text
  17296. *
  17297. * @return bool
  17298. */
  17299. public static function ctype_graph($text)
  17300. {
  17301. $text = self::convert_int_to_char_for_ctype($text);
  17302. return \is_string($text) && '' !== $text && !\preg_match('/[^!-~]/', $text);
  17303. }
  17304. /**
  17305. * Returns TRUE if every character in text is a lowercase letter.
  17306. *
  17307. * @see https://php.net/ctype-lower
  17308. *
  17309. * @param string|int $text
  17310. *
  17311. * @return bool
  17312. */
  17313. public static function ctype_lower($text)
  17314. {
  17315. $text = self::convert_int_to_char_for_ctype($text);
  17316. return \is_string($text) && '' !== $text && !\preg_match('/[^a-z]/', $text);
  17317. }
  17318. /**
  17319. * Returns TRUE if every character in text will actually create output (including blanks). Returns FALSE if text contains control characters or characters that do not have any output or control function at all.
  17320. *
  17321. * @see https://php.net/ctype-print
  17322. *
  17323. * @param string|int $text
  17324. *
  17325. * @return bool
  17326. */
  17327. public static function ctype_print($text)
  17328. {
  17329. $text = self::convert_int_to_char_for_ctype($text);
  17330. return \is_string($text) && '' !== $text && !\preg_match('/[^ -~]/', $text);
  17331. }
  17332. /**
  17333. * Returns TRUE if every character in text is printable, but neither letter, digit or blank, FALSE otherwise.
  17334. *
  17335. * @see https://php.net/ctype-punct
  17336. *
  17337. * @param string|int $text
  17338. *
  17339. * @return bool
  17340. */
  17341. public static function ctype_punct($text)
  17342. {
  17343. $text = self::convert_int_to_char_for_ctype($text);
  17344. return \is_string($text) && '' !== $text && !\preg_match('/[^!-\\/\\:-@\\[-`\\{-~]/', $text);
  17345. }
  17346. /**
  17347. * Returns TRUE if every character in text creates some sort of white space, FALSE otherwise. Besides the blank character this also includes tab, vertical tab, line feed, carriage return and form feed characters.
  17348. *
  17349. * @see https://php.net/ctype-space
  17350. *
  17351. * @param string|int $text
  17352. *
  17353. * @return bool
  17354. */
  17355. public static function ctype_space($text)
  17356. {
  17357. $text = self::convert_int_to_char_for_ctype($text);
  17358. return \is_string($text) && '' !== $text && !\preg_match('/[^\\s]/', $text);
  17359. }
  17360. /**
  17361. * Returns TRUE if every character in text is an uppercase letter.
  17362. *
  17363. * @see https://php.net/ctype-upper
  17364. *
  17365. * @param string|int $text
  17366. *
  17367. * @return bool
  17368. */
  17369. public static function ctype_upper($text)
  17370. {
  17371. $text = self::convert_int_to_char_for_ctype($text);
  17372. return \is_string($text) && '' !== $text && !\preg_match('/[^A-Z]/', $text);
  17373. }
  17374. /**
  17375. * Returns TRUE if every character in text is a hexadecimal 'digit', that is a decimal digit or a character from [A-Fa-f] , FALSE otherwise.
  17376. *
  17377. * @see https://php.net/ctype-xdigit
  17378. *
  17379. * @param string|int $text
  17380. *
  17381. * @return bool
  17382. */
  17383. public static function ctype_xdigit($text)
  17384. {
  17385. $text = self::convert_int_to_char_for_ctype($text);
  17386. return \is_string($text) && '' !== $text && !\preg_match('/[^A-Fa-f0-9]/', $text);
  17387. }
  17388. /**
  17389. * Converts integers to their char versions according to normal ctype behaviour, if needed.
  17390. *
  17391. * If an integer between -128 and 255 inclusive is provided,
  17392. * it is interpreted as the ASCII value of a single character
  17393. * (negative values have 256 added in order to allow characters in the Extended ASCII range).
  17394. * Any other integer is interpreted as a string containing the decimal digits of the integer.
  17395. *
  17396. * @param string|int $int
  17397. *
  17398. * @return mixed
  17399. */
  17400. private static function convert_int_to_char_for_ctype($int)
  17401. {
  17402. if (!\is_int($int)) {
  17403. return $int;
  17404. }
  17405. if ($int < -128 || $int > 255) {
  17406. return (string) $int;
  17407. }
  17408. if ($int < 0) {
  17409. $int += 256;
  17410. }
  17411. return \chr($int);
  17412. }
  17413. }
  17414. Copyright (c) 2018-2019 Fabien Potencier
  17415. Permission is hereby granted, free of charge, to any person obtaining a copy
  17416. of this software and associated documentation files (the "Software"), to deal
  17417. in the Software without restriction, including without limitation the rights
  17418. to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  17419. copies of the Software, and to permit persons to whom the Software is furnished
  17420. to do so, subject to the following conditions:
  17421. The above copyright notice and this permission notice shall be included in all
  17422. copies or substantial portions of the Software.
  17423. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17424. IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17425. FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17426. AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  17427. LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  17428. OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  17429. THE SOFTWARE.
  17430. <?php
  17431. namespace PHPUnit;
  17432. /*
  17433. * This file is part of phpunit/php-token-stream.
  17434. *
  17435. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  17436. *
  17437. * For the full copyright and license information, please view the LICENSE
  17438. * file that was distributed with this source code.
  17439. */
  17440. /**
  17441. * A PHP token.
  17442. */
  17443. abstract class PHP_Token
  17444. {
  17445. /**
  17446. * @var string
  17447. */
  17448. protected $text;
  17449. /**
  17450. * @var int
  17451. */
  17452. protected $line;
  17453. /**
  17454. * @var PHP_Token_Stream
  17455. */
  17456. protected $tokenStream;
  17457. /**
  17458. * @var int
  17459. */
  17460. protected $id;
  17461. /**
  17462. * @param string $text
  17463. * @param int $line
  17464. * @param int $id
  17465. */
  17466. public function __construct($text, $line, \PHPUnit\PHP_Token_Stream $tokenStream, $id)
  17467. {
  17468. $this->text = $text;
  17469. $this->line = $line;
  17470. $this->tokenStream = $tokenStream;
  17471. $this->id = $id;
  17472. }
  17473. /**
  17474. * @return string
  17475. */
  17476. public function __toString()
  17477. {
  17478. return $this->text;
  17479. }
  17480. /**
  17481. * @return int
  17482. */
  17483. public function getLine()
  17484. {
  17485. return $this->line;
  17486. }
  17487. /**
  17488. * @return int
  17489. */
  17490. public function getId()
  17491. {
  17492. return $this->id;
  17493. }
  17494. }
  17495. /*
  17496. * This file is part of phpunit/php-token-stream.
  17497. *
  17498. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  17499. *
  17500. * For the full copyright and license information, please view the LICENSE
  17501. * file that was distributed with this source code.
  17502. */
  17503. /**
  17504. * A PHP token.
  17505. */
  17506. \class_alias('PHPUnit\\PHP_Token', 'PHP_Token', \false);
  17507. abstract class PHP_TokenWithScope extends \PHPUnit\PHP_Token
  17508. {
  17509. /**
  17510. * @var int
  17511. */
  17512. protected $endTokenId;
  17513. /**
  17514. * Get the docblock for this token
  17515. *
  17516. * This method will fetch the docblock belonging to the current token. The
  17517. * docblock must be placed on the line directly above the token to be
  17518. * recognized.
  17519. *
  17520. * @return null|string Returns the docblock as a string if found
  17521. */
  17522. public function getDocblock()
  17523. {
  17524. $tokens = $this->tokenStream->tokens();
  17525. $currentLineNumber = $tokens[$this->id]->getLine();
  17526. $prevLineNumber = $currentLineNumber - 1;
  17527. for ($i = $this->id - 1; $i; $i--) {
  17528. if (!isset($tokens[$i])) {
  17529. return;
  17530. }
  17531. if ($tokens[$i] instanceof \PHPUnit\PHP_Token_FUNCTION || $tokens[$i] instanceof \PHPUnit\PHP_Token_CLASS || $tokens[$i] instanceof \PHPUnit\PHP_Token_TRAIT) {
  17532. // Some other trait, class or function, no docblock can be
  17533. // used for the current token
  17534. break;
  17535. }
  17536. $line = $tokens[$i]->getLine();
  17537. if ($line == $currentLineNumber || $line == $prevLineNumber && $tokens[$i] instanceof \PHPUnit\PHP_Token_WHITESPACE) {
  17538. continue;
  17539. }
  17540. if ($line < $currentLineNumber && !$tokens[$i] instanceof \PHPUnit\PHP_Token_DOC_COMMENT) {
  17541. break;
  17542. }
  17543. return (string) $tokens[$i];
  17544. }
  17545. }
  17546. /**
  17547. * @return int
  17548. */
  17549. public function getEndTokenId()
  17550. {
  17551. $block = 0;
  17552. $i = $this->id;
  17553. $tokens = $this->tokenStream->tokens();
  17554. while ($this->endTokenId === null && isset($tokens[$i])) {
  17555. if ($tokens[$i] instanceof \PHPUnit\PHP_Token_OPEN_CURLY || $tokens[$i] instanceof \PHPUnit\PHP_Token_DOLLAR_OPEN_CURLY_BRACES || $tokens[$i] instanceof \PHPUnit\PHP_Token_CURLY_OPEN) {
  17556. $block++;
  17557. } elseif ($tokens[$i] instanceof \PHPUnit\PHP_Token_CLOSE_CURLY) {
  17558. $block--;
  17559. if ($block === 0) {
  17560. $this->endTokenId = $i;
  17561. }
  17562. } elseif (($this instanceof \PHPUnit\PHP_Token_FUNCTION || $this instanceof \PHPUnit\PHP_Token_NAMESPACE) && $tokens[$i] instanceof \PHPUnit\PHP_Token_SEMICOLON) {
  17563. if ($block === 0) {
  17564. $this->endTokenId = $i;
  17565. }
  17566. }
  17567. $i++;
  17568. }
  17569. if ($this->endTokenId === null) {
  17570. $this->endTokenId = $this->id;
  17571. }
  17572. return $this->endTokenId;
  17573. }
  17574. /**
  17575. * @return int
  17576. */
  17577. public function getEndLine()
  17578. {
  17579. return $this->tokenStream[$this->getEndTokenId()]->getLine();
  17580. }
  17581. }
  17582. \class_alias('PHPUnit\\PHP_TokenWithScope', 'PHP_TokenWithScope', \false);
  17583. abstract class PHP_TokenWithScopeAndVisibility extends \PHPUnit\PHP_TokenWithScope
  17584. {
  17585. /**
  17586. * @return string
  17587. */
  17588. public function getVisibility()
  17589. {
  17590. $tokens = $this->tokenStream->tokens();
  17591. for ($i = $this->id - 2; $i > $this->id - 7; $i -= 2) {
  17592. if (isset($tokens[$i]) && ($tokens[$i] instanceof \PHPUnit\PHP_Token_PRIVATE || $tokens[$i] instanceof \PHPUnit\PHP_Token_PROTECTED || $tokens[$i] instanceof \PHPUnit\PHP_Token_PUBLIC)) {
  17593. return \strtolower(\str_replace('PHP_Token_', '', \PHPUnit\PHP_Token_Util::getClass($tokens[$i])));
  17594. }
  17595. if (isset($tokens[$i]) && !($tokens[$i] instanceof \PHPUnit\PHP_Token_STATIC || $tokens[$i] instanceof \PHPUnit\PHP_Token_FINAL || $tokens[$i] instanceof \PHPUnit\PHP_Token_ABSTRACT)) {
  17596. // no keywords; stop visibility search
  17597. break;
  17598. }
  17599. }
  17600. }
  17601. /**
  17602. * @return string
  17603. */
  17604. public function getKeywords()
  17605. {
  17606. $keywords = [];
  17607. $tokens = $this->tokenStream->tokens();
  17608. for ($i = $this->id - 2; $i > $this->id - 7; $i -= 2) {
  17609. if (isset($tokens[$i]) && ($tokens[$i] instanceof \PHPUnit\PHP_Token_PRIVATE || $tokens[$i] instanceof \PHPUnit\PHP_Token_PROTECTED || $tokens[$i] instanceof \PHPUnit\PHP_Token_PUBLIC)) {
  17610. continue;
  17611. }
  17612. if (isset($tokens[$i]) && ($tokens[$i] instanceof \PHPUnit\PHP_Token_STATIC || $tokens[$i] instanceof \PHPUnit\PHP_Token_FINAL || $tokens[$i] instanceof \PHPUnit\PHP_Token_ABSTRACT)) {
  17613. $keywords[] = \strtolower(\str_replace('PHP_Token_', '', \PHPUnit\PHP_Token_Util::getClass($tokens[$i])));
  17614. }
  17615. }
  17616. return \implode(',', $keywords);
  17617. }
  17618. }
  17619. \class_alias('PHPUnit\\PHP_TokenWithScopeAndVisibility', 'PHP_TokenWithScopeAndVisibility', \false);
  17620. abstract class PHP_Token_Includes extends \PHPUnit\PHP_Token
  17621. {
  17622. /**
  17623. * @var string
  17624. */
  17625. protected $name;
  17626. /**
  17627. * @var string
  17628. */
  17629. protected $type;
  17630. /**
  17631. * @return string
  17632. */
  17633. public function getName()
  17634. {
  17635. if ($this->name === null) {
  17636. $this->process();
  17637. }
  17638. return $this->name;
  17639. }
  17640. /**
  17641. * @return string
  17642. */
  17643. public function getType()
  17644. {
  17645. if ($this->type === null) {
  17646. $this->process();
  17647. }
  17648. return $this->type;
  17649. }
  17650. private function process() : void
  17651. {
  17652. $tokens = $this->tokenStream->tokens();
  17653. if ($tokens[$this->id + 2] instanceof \PHPUnit\PHP_Token_CONSTANT_ENCAPSED_STRING) {
  17654. $this->name = \trim($tokens[$this->id + 2], "'\"");
  17655. $this->type = \strtolower(\str_replace('PHP_Token_', '', \PHPUnit\PHP_Token_Util::getClass($tokens[$this->id])));
  17656. }
  17657. }
  17658. }
  17659. \class_alias('PHPUnit\\PHP_Token_Includes', 'PHP_Token_Includes', \false);
  17660. class PHP_Token_FUNCTION extends \PHPUnit\PHP_TokenWithScopeAndVisibility
  17661. {
  17662. /**
  17663. * @var array
  17664. */
  17665. protected $arguments;
  17666. /**
  17667. * @var int
  17668. */
  17669. protected $ccn;
  17670. /**
  17671. * @var string
  17672. */
  17673. protected $name;
  17674. /**
  17675. * @var string
  17676. */
  17677. protected $signature;
  17678. /**
  17679. * @var bool
  17680. */
  17681. private $anonymous = \false;
  17682. /**
  17683. * @return array
  17684. */
  17685. public function getArguments()
  17686. {
  17687. if ($this->arguments !== null) {
  17688. return $this->arguments;
  17689. }
  17690. $this->arguments = [];
  17691. $tokens = $this->tokenStream->tokens();
  17692. $typeDeclaration = null;
  17693. // Search for first token inside brackets
  17694. $i = $this->id + 2;
  17695. while (!$tokens[$i - 1] instanceof \PHPUnit\PHP_Token_OPEN_BRACKET) {
  17696. $i++;
  17697. }
  17698. while (!$tokens[$i] instanceof \PHPUnit\PHP_Token_CLOSE_BRACKET) {
  17699. if ($tokens[$i] instanceof \PHPUnit\PHP_Token_STRING) {
  17700. $typeDeclaration = (string) $tokens[$i];
  17701. } elseif ($tokens[$i] instanceof \PHPUnit\PHP_Token_VARIABLE) {
  17702. $this->arguments[(string) $tokens[$i]] = $typeDeclaration;
  17703. $typeDeclaration = null;
  17704. }
  17705. $i++;
  17706. }
  17707. return $this->arguments;
  17708. }
  17709. /**
  17710. * @return string
  17711. */
  17712. public function getName()
  17713. {
  17714. if ($this->name !== null) {
  17715. return $this->name;
  17716. }
  17717. $tokens = $this->tokenStream->tokens();
  17718. $i = $this->id + 1;
  17719. if ($tokens[$i] instanceof \PHPUnit\PHP_Token_WHITESPACE) {
  17720. $i++;
  17721. }
  17722. if ($tokens[$i] instanceof \PHPUnit\PHP_Token_AMPERSAND) {
  17723. $i++;
  17724. }
  17725. if ($tokens[$i + 1] instanceof \PHPUnit\PHP_Token_OPEN_BRACKET) {
  17726. $this->name = (string) $tokens[$i];
  17727. } elseif ($tokens[$i + 1] instanceof \PHPUnit\PHP_Token_WHITESPACE && $tokens[$i + 2] instanceof \PHPUnit\PHP_Token_OPEN_BRACKET) {
  17728. $this->name = (string) $tokens[$i];
  17729. } else {
  17730. $this->anonymous = \true;
  17731. $this->name = \sprintf('anonymousFunction:%s#%s', $this->getLine(), $this->getId());
  17732. }
  17733. if (!$this->isAnonymous()) {
  17734. for ($i = $this->id; $i; --$i) {
  17735. if ($tokens[$i] instanceof \PHPUnit\PHP_Token_NAMESPACE) {
  17736. $this->name = $tokens[$i]->getName() . '\\' . $this->name;
  17737. break;
  17738. }
  17739. if ($tokens[$i] instanceof \PHPUnit\PHP_Token_INTERFACE) {
  17740. break;
  17741. }
  17742. }
  17743. }
  17744. return $this->name;
  17745. }
  17746. /**
  17747. * @return int
  17748. */
  17749. public function getCCN()
  17750. {
  17751. if ($this->ccn !== null) {
  17752. return $this->ccn;
  17753. }
  17754. $this->ccn = 1;
  17755. $end = $this->getEndTokenId();
  17756. $tokens = $this->tokenStream->tokens();
  17757. for ($i = $this->id; $i <= $end; $i++) {
  17758. switch (\get_class($tokens[$i])) {
  17759. case \PHPUnit\PHP_Token_IF::class:
  17760. case \PHPUnit\PHP_Token_ELSEIF::class:
  17761. case \PHPUnit\PHP_Token_FOR::class:
  17762. case \PHPUnit\PHP_Token_FOREACH::class:
  17763. case \PHPUnit\PHP_Token_WHILE::class:
  17764. case \PHPUnit\PHP_Token_CASE::class:
  17765. case \PHPUnit\PHP_Token_CATCH::class:
  17766. case \PHPUnit\PHP_Token_BOOLEAN_AND::class:
  17767. case \PHPUnit\PHP_Token_LOGICAL_AND::class:
  17768. case \PHPUnit\PHP_Token_BOOLEAN_OR::class:
  17769. case \PHPUnit\PHP_Token_LOGICAL_OR::class:
  17770. case \PHPUnit\PHP_Token_QUESTION_MARK::class:
  17771. $this->ccn++;
  17772. break;
  17773. }
  17774. }
  17775. return $this->ccn;
  17776. }
  17777. /**
  17778. * @return string
  17779. */
  17780. public function getSignature()
  17781. {
  17782. if ($this->signature !== null) {
  17783. return $this->signature;
  17784. }
  17785. if ($this->isAnonymous()) {
  17786. $this->signature = 'anonymousFunction';
  17787. $i = $this->id + 1;
  17788. } else {
  17789. $this->signature = '';
  17790. $i = $this->id + 2;
  17791. }
  17792. $tokens = $this->tokenStream->tokens();
  17793. while (isset($tokens[$i]) && !$tokens[$i] instanceof \PHPUnit\PHP_Token_OPEN_CURLY && !$tokens[$i] instanceof \PHPUnit\PHP_Token_SEMICOLON) {
  17794. $this->signature .= $tokens[$i++];
  17795. }
  17796. $this->signature = \trim($this->signature);
  17797. return $this->signature;
  17798. }
  17799. /**
  17800. * @return bool
  17801. */
  17802. public function isAnonymous()
  17803. {
  17804. return $this->anonymous;
  17805. }
  17806. }
  17807. \class_alias('PHPUnit\\PHP_Token_FUNCTION', 'PHP_Token_FUNCTION', \false);
  17808. class PHP_Token_INTERFACE extends \PHPUnit\PHP_TokenWithScopeAndVisibility
  17809. {
  17810. /**
  17811. * @var array
  17812. */
  17813. protected $interfaces;
  17814. /**
  17815. * @return string
  17816. */
  17817. public function getName()
  17818. {
  17819. return (string) $this->tokenStream[$this->id + 2];
  17820. }
  17821. /**
  17822. * @return bool
  17823. */
  17824. public function hasParent()
  17825. {
  17826. return $this->tokenStream[$this->id + 4] instanceof \PHPUnit\PHP_Token_EXTENDS;
  17827. }
  17828. /**
  17829. * @return array
  17830. */
  17831. public function getPackage()
  17832. {
  17833. $className = $this->getName();
  17834. $docComment = $this->getDocblock();
  17835. $result = ['namespace' => '', 'fullPackage' => '', 'category' => '', 'package' => '', 'subpackage' => ''];
  17836. for ($i = $this->id; $i; --$i) {
  17837. if ($this->tokenStream[$i] instanceof \PHPUnit\PHP_Token_NAMESPACE) {
  17838. $result['namespace'] = $this->tokenStream[$i]->getName();
  17839. break;
  17840. }
  17841. }
  17842. if (\preg_match('/@category[\\s]+([\\.\\w]+)/', $docComment, $matches)) {
  17843. $result['category'] = $matches[1];
  17844. }
  17845. if (\preg_match('/@package[\\s]+([\\.\\w]+)/', $docComment, $matches)) {
  17846. $result['package'] = $matches[1];
  17847. $result['fullPackage'] = $matches[1];
  17848. }
  17849. if (\preg_match('/@subpackage[\\s]+([\\.\\w]+)/', $docComment, $matches)) {
  17850. $result['subpackage'] = $matches[1];
  17851. $result['fullPackage'] .= '.' . $matches[1];
  17852. }
  17853. if (empty($result['fullPackage'])) {
  17854. $result['fullPackage'] = $this->arrayToName(\explode('_', \str_replace('\\', '_', $className)), '.');
  17855. }
  17856. return $result;
  17857. }
  17858. /**
  17859. * @return bool|string
  17860. */
  17861. public function getParent()
  17862. {
  17863. if (!$this->hasParent()) {
  17864. return \false;
  17865. }
  17866. $i = $this->id + 6;
  17867. $tokens = $this->tokenStream->tokens();
  17868. $className = (string) $tokens[$i];
  17869. while (isset($tokens[$i + 1]) && !$tokens[$i + 1] instanceof \PHPUnit\PHP_Token_WHITESPACE) {
  17870. $className .= (string) $tokens[++$i];
  17871. }
  17872. return $className;
  17873. }
  17874. /**
  17875. * @return bool
  17876. */
  17877. public function hasInterfaces()
  17878. {
  17879. return isset($this->tokenStream[$this->id + 4]) && $this->tokenStream[$this->id + 4] instanceof \PHPUnit\PHP_Token_IMPLEMENTS || isset($this->tokenStream[$this->id + 8]) && $this->tokenStream[$this->id + 8] instanceof \PHPUnit\PHP_Token_IMPLEMENTS;
  17880. }
  17881. /**
  17882. * @return array|bool
  17883. */
  17884. public function getInterfaces()
  17885. {
  17886. if ($this->interfaces !== null) {
  17887. return $this->interfaces;
  17888. }
  17889. if (!$this->hasInterfaces()) {
  17890. return $this->interfaces = \false;
  17891. }
  17892. if ($this->tokenStream[$this->id + 4] instanceof \PHPUnit\PHP_Token_IMPLEMENTS) {
  17893. $i = $this->id + 3;
  17894. } else {
  17895. $i = $this->id + 7;
  17896. }
  17897. $tokens = $this->tokenStream->tokens();
  17898. while (!$tokens[$i + 1] instanceof \PHPUnit\PHP_Token_OPEN_CURLY) {
  17899. $i++;
  17900. if ($tokens[$i] instanceof \PHPUnit\PHP_Token_STRING) {
  17901. $this->interfaces[] = (string) $tokens[$i];
  17902. }
  17903. }
  17904. return $this->interfaces;
  17905. }
  17906. /**
  17907. * @param string $join
  17908. *
  17909. * @return string
  17910. */
  17911. protected function arrayToName(array $parts, $join = '\\')
  17912. {
  17913. $result = '';
  17914. if (\count($parts) > 1) {
  17915. \array_pop($parts);
  17916. $result = \implode($join, $parts);
  17917. }
  17918. return $result;
  17919. }
  17920. }
  17921. \class_alias('PHPUnit\\PHP_Token_INTERFACE', 'PHP_Token_INTERFACE', \false);
  17922. class PHP_Token_ABSTRACT extends \PHPUnit\PHP_Token
  17923. {
  17924. }
  17925. \class_alias('PHPUnit\\PHP_Token_ABSTRACT', 'PHP_Token_ABSTRACT', \false);
  17926. class PHP_Token_AMPERSAND extends \PHPUnit\PHP_Token
  17927. {
  17928. }
  17929. \class_alias('PHPUnit\\PHP_Token_AMPERSAND', 'PHP_Token_AMPERSAND', \false);
  17930. class PHP_Token_AND_EQUAL extends \PHPUnit\PHP_Token
  17931. {
  17932. }
  17933. \class_alias('PHPUnit\\PHP_Token_AND_EQUAL', 'PHP_Token_AND_EQUAL', \false);
  17934. class PHP_Token_ARRAY extends \PHPUnit\PHP_Token
  17935. {
  17936. }
  17937. \class_alias('PHPUnit\\PHP_Token_ARRAY', 'PHP_Token_ARRAY', \false);
  17938. class PHP_Token_ARRAY_CAST extends \PHPUnit\PHP_Token
  17939. {
  17940. }
  17941. \class_alias('PHPUnit\\PHP_Token_ARRAY_CAST', 'PHP_Token_ARRAY_CAST', \false);
  17942. class PHP_Token_AS extends \PHPUnit\PHP_Token
  17943. {
  17944. }
  17945. \class_alias('PHPUnit\\PHP_Token_AS', 'PHP_Token_AS', \false);
  17946. class PHP_Token_AT extends \PHPUnit\PHP_Token
  17947. {
  17948. }
  17949. \class_alias('PHPUnit\\PHP_Token_AT', 'PHP_Token_AT', \false);
  17950. class PHP_Token_BACKTICK extends \PHPUnit\PHP_Token
  17951. {
  17952. }
  17953. \class_alias('PHPUnit\\PHP_Token_BACKTICK', 'PHP_Token_BACKTICK', \false);
  17954. class PHP_Token_BAD_CHARACTER extends \PHPUnit\PHP_Token
  17955. {
  17956. }
  17957. \class_alias('PHPUnit\\PHP_Token_BAD_CHARACTER', 'PHP_Token_BAD_CHARACTER', \false);
  17958. class PHP_Token_BOOLEAN_AND extends \PHPUnit\PHP_Token
  17959. {
  17960. }
  17961. \class_alias('PHPUnit\\PHP_Token_BOOLEAN_AND', 'PHP_Token_BOOLEAN_AND', \false);
  17962. class PHP_Token_BOOLEAN_OR extends \PHPUnit\PHP_Token
  17963. {
  17964. }
  17965. \class_alias('PHPUnit\\PHP_Token_BOOLEAN_OR', 'PHP_Token_BOOLEAN_OR', \false);
  17966. class PHP_Token_BOOL_CAST extends \PHPUnit\PHP_Token
  17967. {
  17968. }
  17969. \class_alias('PHPUnit\\PHP_Token_BOOL_CAST', 'PHP_Token_BOOL_CAST', \false);
  17970. class PHP_Token_BREAK extends \PHPUnit\PHP_Token
  17971. {
  17972. }
  17973. \class_alias('PHPUnit\\PHP_Token_BREAK', 'PHP_Token_BREAK', \false);
  17974. class PHP_Token_CARET extends \PHPUnit\PHP_Token
  17975. {
  17976. }
  17977. \class_alias('PHPUnit\\PHP_Token_CARET', 'PHP_Token_CARET', \false);
  17978. class PHP_Token_CASE extends \PHPUnit\PHP_Token
  17979. {
  17980. }
  17981. \class_alias('PHPUnit\\PHP_Token_CASE', 'PHP_Token_CASE', \false);
  17982. class PHP_Token_CATCH extends \PHPUnit\PHP_Token
  17983. {
  17984. }
  17985. \class_alias('PHPUnit\\PHP_Token_CATCH', 'PHP_Token_CATCH', \false);
  17986. class PHP_Token_CHARACTER extends \PHPUnit\PHP_Token
  17987. {
  17988. }
  17989. \class_alias('PHPUnit\\PHP_Token_CHARACTER', 'PHP_Token_CHARACTER', \false);
  17990. class PHP_Token_CLASS extends \PHPUnit\PHP_Token_INTERFACE
  17991. {
  17992. /**
  17993. * @var bool
  17994. */
  17995. private $anonymous = \false;
  17996. /**
  17997. * @var string
  17998. */
  17999. private $name;
  18000. /**
  18001. * @return string
  18002. */
  18003. public function getName()
  18004. {
  18005. if ($this->name !== null) {
  18006. return $this->name;
  18007. }
  18008. $next = $this->tokenStream[$this->id + 1];
  18009. if ($next instanceof \PHPUnit\PHP_Token_WHITESPACE) {
  18010. $next = $this->tokenStream[$this->id + 2];
  18011. }
  18012. if ($next instanceof \PHPUnit\PHP_Token_STRING) {
  18013. $this->name = (string) $next;
  18014. return $this->name;
  18015. }
  18016. if ($next instanceof \PHPUnit\PHP_Token_OPEN_CURLY || $next instanceof \PHPUnit\PHP_Token_EXTENDS || $next instanceof \PHPUnit\PHP_Token_IMPLEMENTS) {
  18017. $this->name = \sprintf('AnonymousClass:%s#%s', $this->getLine(), $this->getId());
  18018. $this->anonymous = \true;
  18019. return $this->name;
  18020. }
  18021. }
  18022. public function isAnonymous()
  18023. {
  18024. return $this->anonymous;
  18025. }
  18026. }
  18027. \class_alias('PHPUnit\\PHP_Token_CLASS', 'PHP_Token_CLASS', \false);
  18028. class PHP_Token_CLASS_C extends \PHPUnit\PHP_Token
  18029. {
  18030. }
  18031. \class_alias('PHPUnit\\PHP_Token_CLASS_C', 'PHP_Token_CLASS_C', \false);
  18032. class PHP_Token_CLASS_NAME_CONSTANT extends \PHPUnit\PHP_Token
  18033. {
  18034. }
  18035. \class_alias('PHPUnit\\PHP_Token_CLASS_NAME_CONSTANT', 'PHP_Token_CLASS_NAME_CONSTANT', \false);
  18036. class PHP_Token_CLONE extends \PHPUnit\PHP_Token
  18037. {
  18038. }
  18039. \class_alias('PHPUnit\\PHP_Token_CLONE', 'PHP_Token_CLONE', \false);
  18040. class PHP_Token_CLOSE_BRACKET extends \PHPUnit\PHP_Token
  18041. {
  18042. }
  18043. \class_alias('PHPUnit\\PHP_Token_CLOSE_BRACKET', 'PHP_Token_CLOSE_BRACKET', \false);
  18044. class PHP_Token_CLOSE_CURLY extends \PHPUnit\PHP_Token
  18045. {
  18046. }
  18047. \class_alias('PHPUnit\\PHP_Token_CLOSE_CURLY', 'PHP_Token_CLOSE_CURLY', \false);
  18048. class PHP_Token_CLOSE_SQUARE extends \PHPUnit\PHP_Token
  18049. {
  18050. }
  18051. \class_alias('PHPUnit\\PHP_Token_CLOSE_SQUARE', 'PHP_Token_CLOSE_SQUARE', \false);
  18052. class PHP_Token_CLOSE_TAG extends \PHPUnit\PHP_Token
  18053. {
  18054. }
  18055. \class_alias('PHPUnit\\PHP_Token_CLOSE_TAG', 'PHP_Token_CLOSE_TAG', \false);
  18056. class PHP_Token_COLON extends \PHPUnit\PHP_Token
  18057. {
  18058. }
  18059. \class_alias('PHPUnit\\PHP_Token_COLON', 'PHP_Token_COLON', \false);
  18060. class PHP_Token_COMMA extends \PHPUnit\PHP_Token
  18061. {
  18062. }
  18063. \class_alias('PHPUnit\\PHP_Token_COMMA', 'PHP_Token_COMMA', \false);
  18064. class PHP_Token_COMMENT extends \PHPUnit\PHP_Token
  18065. {
  18066. }
  18067. \class_alias('PHPUnit\\PHP_Token_COMMENT', 'PHP_Token_COMMENT', \false);
  18068. class PHP_Token_CONCAT_EQUAL extends \PHPUnit\PHP_Token
  18069. {
  18070. }
  18071. \class_alias('PHPUnit\\PHP_Token_CONCAT_EQUAL', 'PHP_Token_CONCAT_EQUAL', \false);
  18072. class PHP_Token_CONST extends \PHPUnit\PHP_Token
  18073. {
  18074. }
  18075. \class_alias('PHPUnit\\PHP_Token_CONST', 'PHP_Token_CONST', \false);
  18076. class PHP_Token_CONSTANT_ENCAPSED_STRING extends \PHPUnit\PHP_Token
  18077. {
  18078. }
  18079. \class_alias('PHPUnit\\PHP_Token_CONSTANT_ENCAPSED_STRING', 'PHP_Token_CONSTANT_ENCAPSED_STRING', \false);
  18080. class PHP_Token_CONTINUE extends \PHPUnit\PHP_Token
  18081. {
  18082. }
  18083. \class_alias('PHPUnit\\PHP_Token_CONTINUE', 'PHP_Token_CONTINUE', \false);
  18084. class PHP_Token_CURLY_OPEN extends \PHPUnit\PHP_Token
  18085. {
  18086. }
  18087. \class_alias('PHPUnit\\PHP_Token_CURLY_OPEN', 'PHP_Token_CURLY_OPEN', \false);
  18088. class PHP_Token_DEC extends \PHPUnit\PHP_Token
  18089. {
  18090. }
  18091. \class_alias('PHPUnit\\PHP_Token_DEC', 'PHP_Token_DEC', \false);
  18092. class PHP_Token_DECLARE extends \PHPUnit\PHP_Token
  18093. {
  18094. }
  18095. \class_alias('PHPUnit\\PHP_Token_DECLARE', 'PHP_Token_DECLARE', \false);
  18096. class PHP_Token_DEFAULT extends \PHPUnit\PHP_Token
  18097. {
  18098. }
  18099. \class_alias('PHPUnit\\PHP_Token_DEFAULT', 'PHP_Token_DEFAULT', \false);
  18100. class PHP_Token_DIV extends \PHPUnit\PHP_Token
  18101. {
  18102. }
  18103. \class_alias('PHPUnit\\PHP_Token_DIV', 'PHP_Token_DIV', \false);
  18104. class PHP_Token_DIV_EQUAL extends \PHPUnit\PHP_Token
  18105. {
  18106. }
  18107. \class_alias('PHPUnit\\PHP_Token_DIV_EQUAL', 'PHP_Token_DIV_EQUAL', \false);
  18108. class PHP_Token_DNUMBER extends \PHPUnit\PHP_Token
  18109. {
  18110. }
  18111. \class_alias('PHPUnit\\PHP_Token_DNUMBER', 'PHP_Token_DNUMBER', \false);
  18112. class PHP_Token_DO extends \PHPUnit\PHP_Token
  18113. {
  18114. }
  18115. \class_alias('PHPUnit\\PHP_Token_DO', 'PHP_Token_DO', \false);
  18116. class PHP_Token_DOC_COMMENT extends \PHPUnit\PHP_Token
  18117. {
  18118. }
  18119. \class_alias('PHPUnit\\PHP_Token_DOC_COMMENT', 'PHP_Token_DOC_COMMENT', \false);
  18120. class PHP_Token_DOLLAR extends \PHPUnit\PHP_Token
  18121. {
  18122. }
  18123. \class_alias('PHPUnit\\PHP_Token_DOLLAR', 'PHP_Token_DOLLAR', \false);
  18124. class PHP_Token_DOLLAR_OPEN_CURLY_BRACES extends \PHPUnit\PHP_Token
  18125. {
  18126. }
  18127. \class_alias('PHPUnit\\PHP_Token_DOLLAR_OPEN_CURLY_BRACES', 'PHP_Token_DOLLAR_OPEN_CURLY_BRACES', \false);
  18128. class PHP_Token_DOT extends \PHPUnit\PHP_Token
  18129. {
  18130. }
  18131. \class_alias('PHPUnit\\PHP_Token_DOT', 'PHP_Token_DOT', \false);
  18132. class PHP_Token_DOUBLE_ARROW extends \PHPUnit\PHP_Token
  18133. {
  18134. }
  18135. \class_alias('PHPUnit\\PHP_Token_DOUBLE_ARROW', 'PHP_Token_DOUBLE_ARROW', \false);
  18136. class PHP_Token_DOUBLE_CAST extends \PHPUnit\PHP_Token
  18137. {
  18138. }
  18139. \class_alias('PHPUnit\\PHP_Token_DOUBLE_CAST', 'PHP_Token_DOUBLE_CAST', \false);
  18140. class PHP_Token_DOUBLE_COLON extends \PHPUnit\PHP_Token
  18141. {
  18142. }
  18143. \class_alias('PHPUnit\\PHP_Token_DOUBLE_COLON', 'PHP_Token_DOUBLE_COLON', \false);
  18144. class PHP_Token_DOUBLE_QUOTES extends \PHPUnit\PHP_Token
  18145. {
  18146. }
  18147. \class_alias('PHPUnit\\PHP_Token_DOUBLE_QUOTES', 'PHP_Token_DOUBLE_QUOTES', \false);
  18148. class PHP_Token_ECHO extends \PHPUnit\PHP_Token
  18149. {
  18150. }
  18151. \class_alias('PHPUnit\\PHP_Token_ECHO', 'PHP_Token_ECHO', \false);
  18152. class PHP_Token_ELSE extends \PHPUnit\PHP_Token
  18153. {
  18154. }
  18155. \class_alias('PHPUnit\\PHP_Token_ELSE', 'PHP_Token_ELSE', \false);
  18156. class PHP_Token_ELSEIF extends \PHPUnit\PHP_Token
  18157. {
  18158. }
  18159. \class_alias('PHPUnit\\PHP_Token_ELSEIF', 'PHP_Token_ELSEIF', \false);
  18160. class PHP_Token_EMPTY extends \PHPUnit\PHP_Token
  18161. {
  18162. }
  18163. \class_alias('PHPUnit\\PHP_Token_EMPTY', 'PHP_Token_EMPTY', \false);
  18164. class PHP_Token_ENCAPSED_AND_WHITESPACE extends \PHPUnit\PHP_Token
  18165. {
  18166. }
  18167. \class_alias('PHPUnit\\PHP_Token_ENCAPSED_AND_WHITESPACE', 'PHP_Token_ENCAPSED_AND_WHITESPACE', \false);
  18168. class PHP_Token_ENDDECLARE extends \PHPUnit\PHP_Token
  18169. {
  18170. }
  18171. \class_alias('PHPUnit\\PHP_Token_ENDDECLARE', 'PHP_Token_ENDDECLARE', \false);
  18172. class PHP_Token_ENDFOR extends \PHPUnit\PHP_Token
  18173. {
  18174. }
  18175. \class_alias('PHPUnit\\PHP_Token_ENDFOR', 'PHP_Token_ENDFOR', \false);
  18176. class PHP_Token_ENDFOREACH extends \PHPUnit\PHP_Token
  18177. {
  18178. }
  18179. \class_alias('PHPUnit\\PHP_Token_ENDFOREACH', 'PHP_Token_ENDFOREACH', \false);
  18180. class PHP_Token_ENDIF extends \PHPUnit\PHP_Token
  18181. {
  18182. }
  18183. \class_alias('PHPUnit\\PHP_Token_ENDIF', 'PHP_Token_ENDIF', \false);
  18184. class PHP_Token_ENDSWITCH extends \PHPUnit\PHP_Token
  18185. {
  18186. }
  18187. \class_alias('PHPUnit\\PHP_Token_ENDSWITCH', 'PHP_Token_ENDSWITCH', \false);
  18188. class PHP_Token_ENDWHILE extends \PHPUnit\PHP_Token
  18189. {
  18190. }
  18191. \class_alias('PHPUnit\\PHP_Token_ENDWHILE', 'PHP_Token_ENDWHILE', \false);
  18192. class PHP_Token_END_HEREDOC extends \PHPUnit\PHP_Token
  18193. {
  18194. }
  18195. \class_alias('PHPUnit\\PHP_Token_END_HEREDOC', 'PHP_Token_END_HEREDOC', \false);
  18196. class PHP_Token_EQUAL extends \PHPUnit\PHP_Token
  18197. {
  18198. }
  18199. \class_alias('PHPUnit\\PHP_Token_EQUAL', 'PHP_Token_EQUAL', \false);
  18200. class PHP_Token_EVAL extends \PHPUnit\PHP_Token
  18201. {
  18202. }
  18203. \class_alias('PHPUnit\\PHP_Token_EVAL', 'PHP_Token_EVAL', \false);
  18204. class PHP_Token_EXCLAMATION_MARK extends \PHPUnit\PHP_Token
  18205. {
  18206. }
  18207. \class_alias('PHPUnit\\PHP_Token_EXCLAMATION_MARK', 'PHP_Token_EXCLAMATION_MARK', \false);
  18208. class PHP_Token_EXIT extends \PHPUnit\PHP_Token
  18209. {
  18210. }
  18211. \class_alias('PHPUnit\\PHP_Token_EXIT', 'PHP_Token_EXIT', \false);
  18212. class PHP_Token_EXTENDS extends \PHPUnit\PHP_Token
  18213. {
  18214. }
  18215. \class_alias('PHPUnit\\PHP_Token_EXTENDS', 'PHP_Token_EXTENDS', \false);
  18216. class PHP_Token_FILE extends \PHPUnit\PHP_Token
  18217. {
  18218. }
  18219. \class_alias('PHPUnit\\PHP_Token_FILE', 'PHP_Token_FILE', \false);
  18220. class PHP_Token_FINAL extends \PHPUnit\PHP_Token
  18221. {
  18222. }
  18223. \class_alias('PHPUnit\\PHP_Token_FINAL', 'PHP_Token_FINAL', \false);
  18224. class PHP_Token_FOR extends \PHPUnit\PHP_Token
  18225. {
  18226. }
  18227. \class_alias('PHPUnit\\PHP_Token_FOR', 'PHP_Token_FOR', \false);
  18228. class PHP_Token_FOREACH extends \PHPUnit\PHP_Token
  18229. {
  18230. }
  18231. \class_alias('PHPUnit\\PHP_Token_FOREACH', 'PHP_Token_FOREACH', \false);
  18232. class PHP_Token_FUNC_C extends \PHPUnit\PHP_Token
  18233. {
  18234. }
  18235. \class_alias('PHPUnit\\PHP_Token_FUNC_C', 'PHP_Token_FUNC_C', \false);
  18236. class PHP_Token_GLOBAL extends \PHPUnit\PHP_Token
  18237. {
  18238. }
  18239. \class_alias('PHPUnit\\PHP_Token_GLOBAL', 'PHP_Token_GLOBAL', \false);
  18240. class PHP_Token_GT extends \PHPUnit\PHP_Token
  18241. {
  18242. }
  18243. \class_alias('PHPUnit\\PHP_Token_GT', 'PHP_Token_GT', \false);
  18244. class PHP_Token_IF extends \PHPUnit\PHP_Token
  18245. {
  18246. }
  18247. \class_alias('PHPUnit\\PHP_Token_IF', 'PHP_Token_IF', \false);
  18248. class PHP_Token_IMPLEMENTS extends \PHPUnit\PHP_Token
  18249. {
  18250. }
  18251. \class_alias('PHPUnit\\PHP_Token_IMPLEMENTS', 'PHP_Token_IMPLEMENTS', \false);
  18252. class PHP_Token_INC extends \PHPUnit\PHP_Token
  18253. {
  18254. }
  18255. \class_alias('PHPUnit\\PHP_Token_INC', 'PHP_Token_INC', \false);
  18256. class PHP_Token_INCLUDE extends \PHPUnit\PHP_Token_Includes
  18257. {
  18258. }
  18259. \class_alias('PHPUnit\\PHP_Token_INCLUDE', 'PHP_Token_INCLUDE', \false);
  18260. class PHP_Token_INCLUDE_ONCE extends \PHPUnit\PHP_Token_Includes
  18261. {
  18262. }
  18263. \class_alias('PHPUnit\\PHP_Token_INCLUDE_ONCE', 'PHP_Token_INCLUDE_ONCE', \false);
  18264. class PHP_Token_INLINE_HTML extends \PHPUnit\PHP_Token
  18265. {
  18266. }
  18267. \class_alias('PHPUnit\\PHP_Token_INLINE_HTML', 'PHP_Token_INLINE_HTML', \false);
  18268. class PHP_Token_INSTANCEOF extends \PHPUnit\PHP_Token
  18269. {
  18270. }
  18271. \class_alias('PHPUnit\\PHP_Token_INSTANCEOF', 'PHP_Token_INSTANCEOF', \false);
  18272. class PHP_Token_INT_CAST extends \PHPUnit\PHP_Token
  18273. {
  18274. }
  18275. \class_alias('PHPUnit\\PHP_Token_INT_CAST', 'PHP_Token_INT_CAST', \false);
  18276. class PHP_Token_ISSET extends \PHPUnit\PHP_Token
  18277. {
  18278. }
  18279. \class_alias('PHPUnit\\PHP_Token_ISSET', 'PHP_Token_ISSET', \false);
  18280. class PHP_Token_IS_EQUAL extends \PHPUnit\PHP_Token
  18281. {
  18282. }
  18283. \class_alias('PHPUnit\\PHP_Token_IS_EQUAL', 'PHP_Token_IS_EQUAL', \false);
  18284. class PHP_Token_IS_GREATER_OR_EQUAL extends \PHPUnit\PHP_Token
  18285. {
  18286. }
  18287. \class_alias('PHPUnit\\PHP_Token_IS_GREATER_OR_EQUAL', 'PHP_Token_IS_GREATER_OR_EQUAL', \false);
  18288. class PHP_Token_IS_IDENTICAL extends \PHPUnit\PHP_Token
  18289. {
  18290. }
  18291. \class_alias('PHPUnit\\PHP_Token_IS_IDENTICAL', 'PHP_Token_IS_IDENTICAL', \false);
  18292. class PHP_Token_IS_NOT_EQUAL extends \PHPUnit\PHP_Token
  18293. {
  18294. }
  18295. \class_alias('PHPUnit\\PHP_Token_IS_NOT_EQUAL', 'PHP_Token_IS_NOT_EQUAL', \false);
  18296. class PHP_Token_IS_NOT_IDENTICAL extends \PHPUnit\PHP_Token
  18297. {
  18298. }
  18299. \class_alias('PHPUnit\\PHP_Token_IS_NOT_IDENTICAL', 'PHP_Token_IS_NOT_IDENTICAL', \false);
  18300. class PHP_Token_IS_SMALLER_OR_EQUAL extends \PHPUnit\PHP_Token
  18301. {
  18302. }
  18303. \class_alias('PHPUnit\\PHP_Token_IS_SMALLER_OR_EQUAL', 'PHP_Token_IS_SMALLER_OR_EQUAL', \false);
  18304. class PHP_Token_LINE extends \PHPUnit\PHP_Token
  18305. {
  18306. }
  18307. \class_alias('PHPUnit\\PHP_Token_LINE', 'PHP_Token_LINE', \false);
  18308. class PHP_Token_LIST extends \PHPUnit\PHP_Token
  18309. {
  18310. }
  18311. \class_alias('PHPUnit\\PHP_Token_LIST', 'PHP_Token_LIST', \false);
  18312. class PHP_Token_LNUMBER extends \PHPUnit\PHP_Token
  18313. {
  18314. }
  18315. \class_alias('PHPUnit\\PHP_Token_LNUMBER', 'PHP_Token_LNUMBER', \false);
  18316. class PHP_Token_LOGICAL_AND extends \PHPUnit\PHP_Token
  18317. {
  18318. }
  18319. \class_alias('PHPUnit\\PHP_Token_LOGICAL_AND', 'PHP_Token_LOGICAL_AND', \false);
  18320. class PHP_Token_LOGICAL_OR extends \PHPUnit\PHP_Token
  18321. {
  18322. }
  18323. \class_alias('PHPUnit\\PHP_Token_LOGICAL_OR', 'PHP_Token_LOGICAL_OR', \false);
  18324. class PHP_Token_LOGICAL_XOR extends \PHPUnit\PHP_Token
  18325. {
  18326. }
  18327. \class_alias('PHPUnit\\PHP_Token_LOGICAL_XOR', 'PHP_Token_LOGICAL_XOR', \false);
  18328. class PHP_Token_LT extends \PHPUnit\PHP_Token
  18329. {
  18330. }
  18331. \class_alias('PHPUnit\\PHP_Token_LT', 'PHP_Token_LT', \false);
  18332. class PHP_Token_METHOD_C extends \PHPUnit\PHP_Token
  18333. {
  18334. }
  18335. \class_alias('PHPUnit\\PHP_Token_METHOD_C', 'PHP_Token_METHOD_C', \false);
  18336. class PHP_Token_MINUS extends \PHPUnit\PHP_Token
  18337. {
  18338. }
  18339. \class_alias('PHPUnit\\PHP_Token_MINUS', 'PHP_Token_MINUS', \false);
  18340. class PHP_Token_MINUS_EQUAL extends \PHPUnit\PHP_Token
  18341. {
  18342. }
  18343. \class_alias('PHPUnit\\PHP_Token_MINUS_EQUAL', 'PHP_Token_MINUS_EQUAL', \false);
  18344. class PHP_Token_MOD_EQUAL extends \PHPUnit\PHP_Token
  18345. {
  18346. }
  18347. \class_alias('PHPUnit\\PHP_Token_MOD_EQUAL', 'PHP_Token_MOD_EQUAL', \false);
  18348. class PHP_Token_MULT extends \PHPUnit\PHP_Token
  18349. {
  18350. }
  18351. \class_alias('PHPUnit\\PHP_Token_MULT', 'PHP_Token_MULT', \false);
  18352. class PHP_Token_MUL_EQUAL extends \PHPUnit\PHP_Token
  18353. {
  18354. }
  18355. \class_alias('PHPUnit\\PHP_Token_MUL_EQUAL', 'PHP_Token_MUL_EQUAL', \false);
  18356. class PHP_Token_NEW extends \PHPUnit\PHP_Token
  18357. {
  18358. }
  18359. \class_alias('PHPUnit\\PHP_Token_NEW', 'PHP_Token_NEW', \false);
  18360. class PHP_Token_NUM_STRING extends \PHPUnit\PHP_Token
  18361. {
  18362. }
  18363. \class_alias('PHPUnit\\PHP_Token_NUM_STRING', 'PHP_Token_NUM_STRING', \false);
  18364. class PHP_Token_OBJECT_CAST extends \PHPUnit\PHP_Token
  18365. {
  18366. }
  18367. \class_alias('PHPUnit\\PHP_Token_OBJECT_CAST', 'PHP_Token_OBJECT_CAST', \false);
  18368. class PHP_Token_OBJECT_OPERATOR extends \PHPUnit\PHP_Token
  18369. {
  18370. }
  18371. \class_alias('PHPUnit\\PHP_Token_OBJECT_OPERATOR', 'PHP_Token_OBJECT_OPERATOR', \false);
  18372. class PHP_Token_OPEN_BRACKET extends \PHPUnit\PHP_Token
  18373. {
  18374. }
  18375. \class_alias('PHPUnit\\PHP_Token_OPEN_BRACKET', 'PHP_Token_OPEN_BRACKET', \false);
  18376. class PHP_Token_OPEN_CURLY extends \PHPUnit\PHP_Token
  18377. {
  18378. }
  18379. \class_alias('PHPUnit\\PHP_Token_OPEN_CURLY', 'PHP_Token_OPEN_CURLY', \false);
  18380. class PHP_Token_OPEN_SQUARE extends \PHPUnit\PHP_Token
  18381. {
  18382. }
  18383. \class_alias('PHPUnit\\PHP_Token_OPEN_SQUARE', 'PHP_Token_OPEN_SQUARE', \false);
  18384. class PHP_Token_OPEN_TAG extends \PHPUnit\PHP_Token
  18385. {
  18386. }
  18387. \class_alias('PHPUnit\\PHP_Token_OPEN_TAG', 'PHP_Token_OPEN_TAG', \false);
  18388. class PHP_Token_OPEN_TAG_WITH_ECHO extends \PHPUnit\PHP_Token
  18389. {
  18390. }
  18391. \class_alias('PHPUnit\\PHP_Token_OPEN_TAG_WITH_ECHO', 'PHP_Token_OPEN_TAG_WITH_ECHO', \false);
  18392. class PHP_Token_OR_EQUAL extends \PHPUnit\PHP_Token
  18393. {
  18394. }
  18395. \class_alias('PHPUnit\\PHP_Token_OR_EQUAL', 'PHP_Token_OR_EQUAL', \false);
  18396. class PHP_Token_PAAMAYIM_NEKUDOTAYIM extends \PHPUnit\PHP_Token
  18397. {
  18398. }
  18399. \class_alias('PHPUnit\\PHP_Token_PAAMAYIM_NEKUDOTAYIM', 'PHP_Token_PAAMAYIM_NEKUDOTAYIM', \false);
  18400. class PHP_Token_PERCENT extends \PHPUnit\PHP_Token
  18401. {
  18402. }
  18403. \class_alias('PHPUnit\\PHP_Token_PERCENT', 'PHP_Token_PERCENT', \false);
  18404. class PHP_Token_PIPE extends \PHPUnit\PHP_Token
  18405. {
  18406. }
  18407. \class_alias('PHPUnit\\PHP_Token_PIPE', 'PHP_Token_PIPE', \false);
  18408. class PHP_Token_PLUS extends \PHPUnit\PHP_Token
  18409. {
  18410. }
  18411. \class_alias('PHPUnit\\PHP_Token_PLUS', 'PHP_Token_PLUS', \false);
  18412. class PHP_Token_PLUS_EQUAL extends \PHPUnit\PHP_Token
  18413. {
  18414. }
  18415. \class_alias('PHPUnit\\PHP_Token_PLUS_EQUAL', 'PHP_Token_PLUS_EQUAL', \false);
  18416. class PHP_Token_PRINT extends \PHPUnit\PHP_Token
  18417. {
  18418. }
  18419. \class_alias('PHPUnit\\PHP_Token_PRINT', 'PHP_Token_PRINT', \false);
  18420. class PHP_Token_PRIVATE extends \PHPUnit\PHP_Token
  18421. {
  18422. }
  18423. \class_alias('PHPUnit\\PHP_Token_PRIVATE', 'PHP_Token_PRIVATE', \false);
  18424. class PHP_Token_PROTECTED extends \PHPUnit\PHP_Token
  18425. {
  18426. }
  18427. \class_alias('PHPUnit\\PHP_Token_PROTECTED', 'PHP_Token_PROTECTED', \false);
  18428. class PHP_Token_PUBLIC extends \PHPUnit\PHP_Token
  18429. {
  18430. }
  18431. \class_alias('PHPUnit\\PHP_Token_PUBLIC', 'PHP_Token_PUBLIC', \false);
  18432. class PHP_Token_QUESTION_MARK extends \PHPUnit\PHP_Token
  18433. {
  18434. }
  18435. \class_alias('PHPUnit\\PHP_Token_QUESTION_MARK', 'PHP_Token_QUESTION_MARK', \false);
  18436. class PHP_Token_REQUIRE extends \PHPUnit\PHP_Token_Includes
  18437. {
  18438. }
  18439. \class_alias('PHPUnit\\PHP_Token_REQUIRE', 'PHP_Token_REQUIRE', \false);
  18440. class PHP_Token_REQUIRE_ONCE extends \PHPUnit\PHP_Token_Includes
  18441. {
  18442. }
  18443. \class_alias('PHPUnit\\PHP_Token_REQUIRE_ONCE', 'PHP_Token_REQUIRE_ONCE', \false);
  18444. class PHP_Token_RETURN extends \PHPUnit\PHP_Token
  18445. {
  18446. }
  18447. \class_alias('PHPUnit\\PHP_Token_RETURN', 'PHP_Token_RETURN', \false);
  18448. class PHP_Token_SEMICOLON extends \PHPUnit\PHP_Token
  18449. {
  18450. }
  18451. \class_alias('PHPUnit\\PHP_Token_SEMICOLON', 'PHP_Token_SEMICOLON', \false);
  18452. class PHP_Token_SL extends \PHPUnit\PHP_Token
  18453. {
  18454. }
  18455. \class_alias('PHPUnit\\PHP_Token_SL', 'PHP_Token_SL', \false);
  18456. class PHP_Token_SL_EQUAL extends \PHPUnit\PHP_Token
  18457. {
  18458. }
  18459. \class_alias('PHPUnit\\PHP_Token_SL_EQUAL', 'PHP_Token_SL_EQUAL', \false);
  18460. class PHP_Token_SR extends \PHPUnit\PHP_Token
  18461. {
  18462. }
  18463. \class_alias('PHPUnit\\PHP_Token_SR', 'PHP_Token_SR', \false);
  18464. class PHP_Token_SR_EQUAL extends \PHPUnit\PHP_Token
  18465. {
  18466. }
  18467. \class_alias('PHPUnit\\PHP_Token_SR_EQUAL', 'PHP_Token_SR_EQUAL', \false);
  18468. class PHP_Token_START_HEREDOC extends \PHPUnit\PHP_Token
  18469. {
  18470. }
  18471. \class_alias('PHPUnit\\PHP_Token_START_HEREDOC', 'PHP_Token_START_HEREDOC', \false);
  18472. class PHP_Token_STATIC extends \PHPUnit\PHP_Token
  18473. {
  18474. }
  18475. \class_alias('PHPUnit\\PHP_Token_STATIC', 'PHP_Token_STATIC', \false);
  18476. class PHP_Token_STRING extends \PHPUnit\PHP_Token
  18477. {
  18478. }
  18479. \class_alias('PHPUnit\\PHP_Token_STRING', 'PHP_Token_STRING', \false);
  18480. class PHP_Token_STRING_CAST extends \PHPUnit\PHP_Token
  18481. {
  18482. }
  18483. \class_alias('PHPUnit\\PHP_Token_STRING_CAST', 'PHP_Token_STRING_CAST', \false);
  18484. class PHP_Token_STRING_VARNAME extends \PHPUnit\PHP_Token
  18485. {
  18486. }
  18487. \class_alias('PHPUnit\\PHP_Token_STRING_VARNAME', 'PHP_Token_STRING_VARNAME', \false);
  18488. class PHP_Token_SWITCH extends \PHPUnit\PHP_Token
  18489. {
  18490. }
  18491. \class_alias('PHPUnit\\PHP_Token_SWITCH', 'PHP_Token_SWITCH', \false);
  18492. class PHP_Token_THROW extends \PHPUnit\PHP_Token
  18493. {
  18494. }
  18495. \class_alias('PHPUnit\\PHP_Token_THROW', 'PHP_Token_THROW', \false);
  18496. class PHP_Token_TILDE extends \PHPUnit\PHP_Token
  18497. {
  18498. }
  18499. \class_alias('PHPUnit\\PHP_Token_TILDE', 'PHP_Token_TILDE', \false);
  18500. class PHP_Token_TRY extends \PHPUnit\PHP_Token
  18501. {
  18502. }
  18503. \class_alias('PHPUnit\\PHP_Token_TRY', 'PHP_Token_TRY', \false);
  18504. class PHP_Token_UNSET extends \PHPUnit\PHP_Token
  18505. {
  18506. }
  18507. \class_alias('PHPUnit\\PHP_Token_UNSET', 'PHP_Token_UNSET', \false);
  18508. class PHP_Token_UNSET_CAST extends \PHPUnit\PHP_Token
  18509. {
  18510. }
  18511. \class_alias('PHPUnit\\PHP_Token_UNSET_CAST', 'PHP_Token_UNSET_CAST', \false);
  18512. class PHP_Token_USE extends \PHPUnit\PHP_Token
  18513. {
  18514. }
  18515. \class_alias('PHPUnit\\PHP_Token_USE', 'PHP_Token_USE', \false);
  18516. class PHP_Token_USE_FUNCTION extends \PHPUnit\PHP_Token
  18517. {
  18518. }
  18519. \class_alias('PHPUnit\\PHP_Token_USE_FUNCTION', 'PHP_Token_USE_FUNCTION', \false);
  18520. class PHP_Token_VAR extends \PHPUnit\PHP_Token
  18521. {
  18522. }
  18523. \class_alias('PHPUnit\\PHP_Token_VAR', 'PHP_Token_VAR', \false);
  18524. class PHP_Token_VARIABLE extends \PHPUnit\PHP_Token
  18525. {
  18526. }
  18527. \class_alias('PHPUnit\\PHP_Token_VARIABLE', 'PHP_Token_VARIABLE', \false);
  18528. class PHP_Token_WHILE extends \PHPUnit\PHP_Token
  18529. {
  18530. }
  18531. \class_alias('PHPUnit\\PHP_Token_WHILE', 'PHP_Token_WHILE', \false);
  18532. class PHP_Token_WHITESPACE extends \PHPUnit\PHP_Token
  18533. {
  18534. }
  18535. \class_alias('PHPUnit\\PHP_Token_WHITESPACE', 'PHP_Token_WHITESPACE', \false);
  18536. class PHP_Token_XOR_EQUAL extends \PHPUnit\PHP_Token
  18537. {
  18538. }
  18539. \class_alias('PHPUnit\\PHP_Token_XOR_EQUAL', 'PHP_Token_XOR_EQUAL', \false);
  18540. // Tokens introduced in PHP 5.1
  18541. class PHP_Token_HALT_COMPILER extends \PHPUnit\PHP_Token
  18542. {
  18543. }
  18544. // Tokens introduced in PHP 5.1
  18545. \class_alias('PHPUnit\\PHP_Token_HALT_COMPILER', 'PHP_Token_HALT_COMPILER', \false);
  18546. // Tokens introduced in PHP 5.3
  18547. class PHP_Token_DIR extends \PHPUnit\PHP_Token
  18548. {
  18549. }
  18550. // Tokens introduced in PHP 5.3
  18551. \class_alias('PHPUnit\\PHP_Token_DIR', 'PHP_Token_DIR', \false);
  18552. class PHP_Token_GOTO extends \PHPUnit\PHP_Token
  18553. {
  18554. }
  18555. \class_alias('PHPUnit\\PHP_Token_GOTO', 'PHP_Token_GOTO', \false);
  18556. class PHP_Token_NAMESPACE extends \PHPUnit\PHP_TokenWithScope
  18557. {
  18558. /**
  18559. * @return string
  18560. */
  18561. public function getName()
  18562. {
  18563. $tokens = $this->tokenStream->tokens();
  18564. $namespace = (string) $tokens[$this->id + 2];
  18565. for ($i = $this->id + 3;; $i += 2) {
  18566. if (isset($tokens[$i]) && $tokens[$i] instanceof \PHPUnit\PHP_Token_NS_SEPARATOR) {
  18567. $namespace .= '\\' . $tokens[$i + 1];
  18568. } else {
  18569. break;
  18570. }
  18571. }
  18572. return $namespace;
  18573. }
  18574. }
  18575. \class_alias('PHPUnit\\PHP_Token_NAMESPACE', 'PHP_Token_NAMESPACE', \false);
  18576. class PHP_Token_NS_C extends \PHPUnit\PHP_Token
  18577. {
  18578. }
  18579. \class_alias('PHPUnit\\PHP_Token_NS_C', 'PHP_Token_NS_C', \false);
  18580. class PHP_Token_NS_SEPARATOR extends \PHPUnit\PHP_Token
  18581. {
  18582. }
  18583. \class_alias('PHPUnit\\PHP_Token_NS_SEPARATOR', 'PHP_Token_NS_SEPARATOR', \false);
  18584. // Tokens introduced in PHP 5.4
  18585. class PHP_Token_CALLABLE extends \PHPUnit\PHP_Token
  18586. {
  18587. }
  18588. // Tokens introduced in PHP 5.4
  18589. \class_alias('PHPUnit\\PHP_Token_CALLABLE', 'PHP_Token_CALLABLE', \false);
  18590. class PHP_Token_INSTEADOF extends \PHPUnit\PHP_Token
  18591. {
  18592. }
  18593. \class_alias('PHPUnit\\PHP_Token_INSTEADOF', 'PHP_Token_INSTEADOF', \false);
  18594. class PHP_Token_TRAIT extends \PHPUnit\PHP_Token_INTERFACE
  18595. {
  18596. }
  18597. \class_alias('PHPUnit\\PHP_Token_TRAIT', 'PHP_Token_TRAIT', \false);
  18598. class PHP_Token_TRAIT_C extends \PHPUnit\PHP_Token
  18599. {
  18600. }
  18601. \class_alias('PHPUnit\\PHP_Token_TRAIT_C', 'PHP_Token_TRAIT_C', \false);
  18602. // Tokens introduced in PHP 5.5
  18603. class PHP_Token_FINALLY extends \PHPUnit\PHP_Token
  18604. {
  18605. }
  18606. // Tokens introduced in PHP 5.5
  18607. \class_alias('PHPUnit\\PHP_Token_FINALLY', 'PHP_Token_FINALLY', \false);
  18608. class PHP_Token_YIELD extends \PHPUnit\PHP_Token
  18609. {
  18610. }
  18611. \class_alias('PHPUnit\\PHP_Token_YIELD', 'PHP_Token_YIELD', \false);
  18612. // Tokens introduced in PHP 5.6
  18613. class PHP_Token_ELLIPSIS extends \PHPUnit\PHP_Token
  18614. {
  18615. }
  18616. // Tokens introduced in PHP 5.6
  18617. \class_alias('PHPUnit\\PHP_Token_ELLIPSIS', 'PHP_Token_ELLIPSIS', \false);
  18618. class PHP_Token_POW extends \PHPUnit\PHP_Token
  18619. {
  18620. }
  18621. \class_alias('PHPUnit\\PHP_Token_POW', 'PHP_Token_POW', \false);
  18622. class PHP_Token_POW_EQUAL extends \PHPUnit\PHP_Token
  18623. {
  18624. }
  18625. \class_alias('PHPUnit\\PHP_Token_POW_EQUAL', 'PHP_Token_POW_EQUAL', \false);
  18626. // Tokens introduced in PHP 7.0
  18627. class PHP_Token_COALESCE extends \PHPUnit\PHP_Token
  18628. {
  18629. }
  18630. // Tokens introduced in PHP 7.0
  18631. \class_alias('PHPUnit\\PHP_Token_COALESCE', 'PHP_Token_COALESCE', \false);
  18632. class PHP_Token_SPACESHIP extends \PHPUnit\PHP_Token
  18633. {
  18634. }
  18635. \class_alias('PHPUnit\\PHP_Token_SPACESHIP', 'PHP_Token_SPACESHIP', \false);
  18636. class PHP_Token_YIELD_FROM extends \PHPUnit\PHP_Token
  18637. {
  18638. }
  18639. \class_alias('PHPUnit\\PHP_Token_YIELD_FROM', 'PHP_Token_YIELD_FROM', \false);
  18640. // Tokens introduced in PHP 7.4
  18641. class PHP_Token_COALESCE_EQUAL extends \PHPUnit\PHP_Token
  18642. {
  18643. }
  18644. // Tokens introduced in PHP 7.4
  18645. \class_alias('PHPUnit\\PHP_Token_COALESCE_EQUAL', 'PHP_Token_COALESCE_EQUAL', \false);
  18646. class PHP_Token_FN extends \PHPUnit\PHP_Token
  18647. {
  18648. }
  18649. \class_alias('PHPUnit\\PHP_Token_FN', 'PHP_Token_FN', \false);
  18650. <?php
  18651. declare (strict_types=1);
  18652. namespace PHPUnit;
  18653. /*
  18654. * This file is part of phpunit/php-token-stream.
  18655. *
  18656. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  18657. *
  18658. * For the full copyright and license information, please view the LICENSE
  18659. * file that was distributed with this source code.
  18660. */
  18661. final class PHP_Token_Util
  18662. {
  18663. public static function getClass($object) : string
  18664. {
  18665. $parts = \explode('\\', \get_class($object));
  18666. return \array_pop($parts);
  18667. }
  18668. }
  18669. /*
  18670. * This file is part of phpunit/php-token-stream.
  18671. *
  18672. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  18673. *
  18674. * For the full copyright and license information, please view the LICENSE
  18675. * file that was distributed with this source code.
  18676. */
  18677. \class_alias('PHPUnit\\PHP_Token_Util', 'PHP_Token_Util', \false);
  18678. <?php
  18679. namespace PHPUnit;
  18680. /*
  18681. * This file is part of phpunit/php-token-stream.
  18682. *
  18683. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  18684. *
  18685. * For the full copyright and license information, please view the LICENSE
  18686. * file that was distributed with this source code.
  18687. */
  18688. /**
  18689. * A caching factory for token stream objects.
  18690. */
  18691. class PHP_Token_Stream_CachingFactory
  18692. {
  18693. /**
  18694. * @var array
  18695. */
  18696. protected static $cache = [];
  18697. /**
  18698. * @param string $filename
  18699. *
  18700. * @return PHP_Token_Stream
  18701. */
  18702. public static function get($filename)
  18703. {
  18704. if (!isset(self::$cache[$filename])) {
  18705. self::$cache[$filename] = new \PHPUnit\PHP_Token_Stream($filename);
  18706. }
  18707. return self::$cache[$filename];
  18708. }
  18709. /**
  18710. * @param string $filename
  18711. */
  18712. public static function clear($filename = null)
  18713. {
  18714. if (\is_string($filename)) {
  18715. unset(self::$cache[$filename]);
  18716. } else {
  18717. self::$cache = [];
  18718. }
  18719. }
  18720. }
  18721. /*
  18722. * This file is part of phpunit/php-token-stream.
  18723. *
  18724. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  18725. *
  18726. * For the full copyright and license information, please view the LICENSE
  18727. * file that was distributed with this source code.
  18728. */
  18729. /**
  18730. * A caching factory for token stream objects.
  18731. */
  18732. \class_alias('PHPUnit\\PHP_Token_Stream_CachingFactory', 'PHP_Token_Stream_CachingFactory', \false);
  18733. <?php
  18734. namespace PHPUnit;
  18735. /*
  18736. * This file is part of phpunit/php-token-stream.
  18737. *
  18738. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  18739. *
  18740. * For the full copyright and license information, please view the LICENSE
  18741. * file that was distributed with this source code.
  18742. */
  18743. /**
  18744. * A stream of PHP tokens.
  18745. */
  18746. class PHP_Token_Stream implements \ArrayAccess, \Countable, \SeekableIterator
  18747. {
  18748. /**
  18749. * @var array<string, class-string<PHP_Token>>
  18750. */
  18751. protected static $customTokens = ['(' => \PHPUnit\PHP_Token_OPEN_BRACKET::class, ')' => \PHPUnit\PHP_Token_CLOSE_BRACKET::class, '[' => \PHPUnit\PHP_Token_OPEN_SQUARE::class, ']' => \PHPUnit\PHP_Token_CLOSE_SQUARE::class, '{' => \PHPUnit\PHP_Token_OPEN_CURLY::class, '}' => \PHPUnit\PHP_Token_CLOSE_CURLY::class, ';' => \PHPUnit\PHP_Token_SEMICOLON::class, '.' => \PHPUnit\PHP_Token_DOT::class, ',' => \PHPUnit\PHP_Token_COMMA::class, '=' => \PHPUnit\PHP_Token_EQUAL::class, '<' => \PHPUnit\PHP_Token_LT::class, '>' => \PHPUnit\PHP_Token_GT::class, '+' => \PHPUnit\PHP_Token_PLUS::class, '-' => \PHPUnit\PHP_Token_MINUS::class, '*' => \PHPUnit\PHP_Token_MULT::class, '/' => \PHPUnit\PHP_Token_DIV::class, '?' => \PHPUnit\PHP_Token_QUESTION_MARK::class, '!' => \PHPUnit\PHP_Token_EXCLAMATION_MARK::class, ':' => \PHPUnit\PHP_Token_COLON::class, '"' => \PHPUnit\PHP_Token_DOUBLE_QUOTES::class, '@' => \PHPUnit\PHP_Token_AT::class, '&' => \PHPUnit\PHP_Token_AMPERSAND::class, '%' => \PHPUnit\PHP_Token_PERCENT::class, '|' => \PHPUnit\PHP_Token_PIPE::class, '$' => \PHPUnit\PHP_Token_DOLLAR::class, '^' => \PHPUnit\PHP_Token_CARET::class, '~' => \PHPUnit\PHP_Token_TILDE::class, '`' => \PHPUnit\PHP_Token_BACKTICK::class];
  18752. /**
  18753. * @var string
  18754. */
  18755. protected $filename;
  18756. /**
  18757. * @var array
  18758. */
  18759. protected $tokens = [];
  18760. /**
  18761. * @var int
  18762. */
  18763. protected $position = 0;
  18764. /**
  18765. * @var array
  18766. */
  18767. protected $linesOfCode = ['loc' => 0, 'cloc' => 0, 'ncloc' => 0];
  18768. /**
  18769. * @var array
  18770. */
  18771. protected $classes;
  18772. /**
  18773. * @var array
  18774. */
  18775. protected $functions;
  18776. /**
  18777. * @var array
  18778. */
  18779. protected $includes;
  18780. /**
  18781. * @var array
  18782. */
  18783. protected $interfaces;
  18784. /**
  18785. * @var array
  18786. */
  18787. protected $traits;
  18788. /**
  18789. * @var array
  18790. */
  18791. protected $lineToFunctionMap = [];
  18792. /**
  18793. * Constructor.
  18794. *
  18795. * @param string $sourceCode
  18796. */
  18797. public function __construct($sourceCode)
  18798. {
  18799. if (\is_file($sourceCode)) {
  18800. $this->filename = $sourceCode;
  18801. $sourceCode = \file_get_contents($sourceCode);
  18802. }
  18803. $this->scan($sourceCode);
  18804. }
  18805. /**
  18806. * Destructor.
  18807. */
  18808. public function __destruct()
  18809. {
  18810. $this->tokens = [];
  18811. }
  18812. /**
  18813. * @return string
  18814. */
  18815. public function __toString()
  18816. {
  18817. $buffer = '';
  18818. foreach ($this as $token) {
  18819. $buffer .= $token;
  18820. }
  18821. return $buffer;
  18822. }
  18823. /**
  18824. * @return string
  18825. */
  18826. public function getFilename()
  18827. {
  18828. return $this->filename;
  18829. }
  18830. /**
  18831. * @return int
  18832. */
  18833. public function count()
  18834. {
  18835. return \count($this->tokens);
  18836. }
  18837. /**
  18838. * @return PHP_Token[]
  18839. */
  18840. public function tokens()
  18841. {
  18842. return $this->tokens;
  18843. }
  18844. /**
  18845. * @return array
  18846. */
  18847. public function getClasses()
  18848. {
  18849. if ($this->classes !== null) {
  18850. return $this->classes;
  18851. }
  18852. $this->parse();
  18853. return $this->classes;
  18854. }
  18855. /**
  18856. * @return array
  18857. */
  18858. public function getFunctions()
  18859. {
  18860. if ($this->functions !== null) {
  18861. return $this->functions;
  18862. }
  18863. $this->parse();
  18864. return $this->functions;
  18865. }
  18866. /**
  18867. * @return array
  18868. */
  18869. public function getInterfaces()
  18870. {
  18871. if ($this->interfaces !== null) {
  18872. return $this->interfaces;
  18873. }
  18874. $this->parse();
  18875. return $this->interfaces;
  18876. }
  18877. /**
  18878. * @return array
  18879. */
  18880. public function getTraits()
  18881. {
  18882. if ($this->traits !== null) {
  18883. return $this->traits;
  18884. }
  18885. $this->parse();
  18886. return $this->traits;
  18887. }
  18888. /**
  18889. * Gets the names of all files that have been included
  18890. * using include(), include_once(), require() or require_once().
  18891. *
  18892. * Parameter $categorize set to TRUE causing this function to return a
  18893. * multi-dimensional array with categories in the keys of the first dimension
  18894. * and constants and their values in the second dimension.
  18895. *
  18896. * Parameter $category allow to filter following specific inclusion type
  18897. *
  18898. * @param bool $categorize OPTIONAL
  18899. * @param string $category OPTIONAL Either 'require_once', 'require',
  18900. * 'include_once', 'include'
  18901. *
  18902. * @return array
  18903. */
  18904. public function getIncludes($categorize = \false, $category = null)
  18905. {
  18906. if ($this->includes === null) {
  18907. $this->includes = ['require_once' => [], 'require' => [], 'include_once' => [], 'include' => []];
  18908. foreach ($this->tokens as $token) {
  18909. switch (\get_class($token)) {
  18910. case \PHPUnit\PHP_Token_REQUIRE_ONCE::class:
  18911. case \PHPUnit\PHP_Token_REQUIRE::class:
  18912. case \PHPUnit\PHP_Token_INCLUDE_ONCE::class:
  18913. case \PHPUnit\PHP_Token_INCLUDE::class:
  18914. $this->includes[$token->getType()][] = $token->getName();
  18915. break;
  18916. }
  18917. }
  18918. }
  18919. if (isset($this->includes[$category])) {
  18920. $includes = $this->includes[$category];
  18921. } elseif ($categorize === \false) {
  18922. $includes = \array_merge($this->includes['require_once'], $this->includes['require'], $this->includes['include_once'], $this->includes['include']);
  18923. } else {
  18924. $includes = $this->includes;
  18925. }
  18926. return $includes;
  18927. }
  18928. /**
  18929. * Returns the name of the function or method a line belongs to.
  18930. *
  18931. * @return string or null if the line is not in a function or method
  18932. */
  18933. public function getFunctionForLine($line)
  18934. {
  18935. $this->parse();
  18936. if (isset($this->lineToFunctionMap[$line])) {
  18937. return $this->lineToFunctionMap[$line];
  18938. }
  18939. }
  18940. /**
  18941. * @return array
  18942. */
  18943. public function getLinesOfCode()
  18944. {
  18945. return $this->linesOfCode;
  18946. }
  18947. public function rewind()
  18948. {
  18949. $this->position = 0;
  18950. }
  18951. /**
  18952. * @return bool
  18953. */
  18954. public function valid()
  18955. {
  18956. return isset($this->tokens[$this->position]);
  18957. }
  18958. /**
  18959. * @return int
  18960. */
  18961. public function key()
  18962. {
  18963. return $this->position;
  18964. }
  18965. /**
  18966. * @return PHP_Token
  18967. */
  18968. public function current()
  18969. {
  18970. return $this->tokens[$this->position];
  18971. }
  18972. public function next()
  18973. {
  18974. $this->position++;
  18975. }
  18976. /**
  18977. * @param int $offset
  18978. *
  18979. * @return bool
  18980. */
  18981. public function offsetExists($offset)
  18982. {
  18983. return isset($this->tokens[$offset]);
  18984. }
  18985. /**
  18986. * @param int $offset
  18987. *
  18988. * @throws OutOfBoundsException
  18989. */
  18990. public function offsetGet($offset)
  18991. {
  18992. if (!$this->offsetExists($offset)) {
  18993. throw new \OutOfBoundsException(\sprintf('No token at position "%s"', $offset));
  18994. }
  18995. return $this->tokens[$offset];
  18996. }
  18997. /**
  18998. * @param int $offset
  18999. */
  19000. public function offsetSet($offset, $value)
  19001. {
  19002. $this->tokens[$offset] = $value;
  19003. }
  19004. /**
  19005. * @param int $offset
  19006. *
  19007. * @throws OutOfBoundsException
  19008. */
  19009. public function offsetUnset($offset)
  19010. {
  19011. if (!$this->offsetExists($offset)) {
  19012. throw new \OutOfBoundsException(\sprintf('No token at position "%s"', $offset));
  19013. }
  19014. unset($this->tokens[$offset]);
  19015. }
  19016. /**
  19017. * Seek to an absolute position.
  19018. *
  19019. * @param int $position
  19020. *
  19021. * @throws OutOfBoundsException
  19022. */
  19023. public function seek($position)
  19024. {
  19025. $this->position = $position;
  19026. if (!$this->valid()) {
  19027. throw new \OutOfBoundsException(\sprintf('No token at position "%s"', $this->position));
  19028. }
  19029. }
  19030. /**
  19031. * Scans the source for sequences of characters and converts them into a
  19032. * stream of tokens.
  19033. *
  19034. * @param string $sourceCode
  19035. */
  19036. protected function scan($sourceCode)
  19037. {
  19038. $id = 0;
  19039. $line = 1;
  19040. $tokens = \token_get_all($sourceCode);
  19041. $numTokens = \count($tokens);
  19042. $lastNonWhitespaceTokenWasDoubleColon = \false;
  19043. $name = null;
  19044. for ($i = 0; $i < $numTokens; ++$i) {
  19045. $token = $tokens[$i];
  19046. $skip = 0;
  19047. if (\is_array($token)) {
  19048. $name = \substr(\token_name($token[0]), 2);
  19049. $text = $token[1];
  19050. if ($lastNonWhitespaceTokenWasDoubleColon && $name == 'CLASS') {
  19051. $name = 'CLASS_NAME_CONSTANT';
  19052. } elseif ($name == 'USE' && isset($tokens[$i + 2][0]) && $tokens[$i + 2][0] == \T_FUNCTION) {
  19053. $name = 'USE_FUNCTION';
  19054. $text .= $tokens[$i + 1][1] . $tokens[$i + 2][1];
  19055. $skip = 2;
  19056. }
  19057. /** @var class-string<PHP_Token> $tokenClass */
  19058. $tokenClass = 'PHP_Token_' . $name;
  19059. } else {
  19060. $text = $token;
  19061. $tokenClass = self::$customTokens[$token];
  19062. }
  19063. $this->tokens[] = new $tokenClass($text, $line, $this, $id++);
  19064. $lines = \substr_count($text, "\n");
  19065. $line += $lines;
  19066. if ($tokenClass == \PHPUnit\PHP_Token_HALT_COMPILER::class) {
  19067. break;
  19068. }
  19069. if ($tokenClass == \PHPUnit\PHP_Token_COMMENT::class || $tokenClass == \PHPUnit\PHP_Token_DOC_COMMENT::class) {
  19070. $this->linesOfCode['cloc'] += $lines + 1;
  19071. }
  19072. if ($name == 'DOUBLE_COLON') {
  19073. $lastNonWhitespaceTokenWasDoubleColon = \true;
  19074. } elseif ($name != 'WHITESPACE') {
  19075. $lastNonWhitespaceTokenWasDoubleColon = \false;
  19076. }
  19077. $i += $skip;
  19078. }
  19079. $this->linesOfCode['loc'] = \substr_count($sourceCode, "\n");
  19080. $this->linesOfCode['ncloc'] = $this->linesOfCode['loc'] - $this->linesOfCode['cloc'];
  19081. }
  19082. protected function parse()
  19083. {
  19084. $this->interfaces = [];
  19085. $this->classes = [];
  19086. $this->traits = [];
  19087. $this->functions = [];
  19088. $class = [];
  19089. $classEndLine = [];
  19090. $trait = \false;
  19091. $traitEndLine = \false;
  19092. $interface = \false;
  19093. $interfaceEndLine = \false;
  19094. foreach ($this->tokens as $token) {
  19095. switch (\get_class($token)) {
  19096. case \PHPUnit\PHP_Token_HALT_COMPILER::class:
  19097. return;
  19098. case \PHPUnit\PHP_Token_INTERFACE::class:
  19099. $interface = $token->getName();
  19100. $interfaceEndLine = $token->getEndLine();
  19101. $this->interfaces[$interface] = ['methods' => [], 'parent' => $token->getParent(), 'keywords' => $token->getKeywords(), 'docblock' => $token->getDocblock(), 'startLine' => $token->getLine(), 'endLine' => $interfaceEndLine, 'package' => $token->getPackage(), 'file' => $this->filename];
  19102. break;
  19103. case \PHPUnit\PHP_Token_CLASS::class:
  19104. case \PHPUnit\PHP_Token_TRAIT::class:
  19105. $tmp = ['methods' => [], 'parent' => $token->getParent(), 'interfaces' => $token->getInterfaces(), 'keywords' => $token->getKeywords(), 'docblock' => $token->getDocblock(), 'startLine' => $token->getLine(), 'endLine' => $token->getEndLine(), 'package' => $token->getPackage(), 'file' => $this->filename];
  19106. if ($token instanceof \PHPUnit\PHP_Token_CLASS) {
  19107. $class[] = $token->getName();
  19108. $classEndLine[] = $token->getEndLine();
  19109. if ($token->getName() !== null) {
  19110. $this->classes[$class[\count($class) - 1]] = $tmp;
  19111. }
  19112. } else {
  19113. $trait = $token->getName();
  19114. $traitEndLine = $token->getEndLine();
  19115. $this->traits[$trait] = $tmp;
  19116. }
  19117. break;
  19118. case \PHPUnit\PHP_Token_FUNCTION::class:
  19119. $name = $token->getName();
  19120. $tmp = ['docblock' => $token->getDocblock(), 'keywords' => $token->getKeywords(), 'visibility' => $token->getVisibility(), 'signature' => $token->getSignature(), 'startLine' => $token->getLine(), 'endLine' => $token->getEndLine(), 'ccn' => $token->getCCN(), 'file' => $this->filename];
  19121. if (empty($class) && $trait === \false && $interface === \false) {
  19122. $this->functions[$name] = $tmp;
  19123. $this->addFunctionToMap($name, $tmp['startLine'], $tmp['endLine']);
  19124. } elseif (!empty($class)) {
  19125. if ($class[\count($class) - 1] !== null) {
  19126. $this->classes[$class[\count($class) - 1]]['methods'][$name] = $tmp;
  19127. $this->addFunctionToMap($class[\count($class) - 1] . '::' . $name, $tmp['startLine'], $tmp['endLine']);
  19128. }
  19129. } elseif ($trait !== \false) {
  19130. $this->traits[$trait]['methods'][$name] = $tmp;
  19131. $this->addFunctionToMap($trait . '::' . $name, $tmp['startLine'], $tmp['endLine']);
  19132. } else {
  19133. $this->interfaces[$interface]['methods'][$name] = $tmp;
  19134. }
  19135. break;
  19136. case \PHPUnit\PHP_Token_CLOSE_CURLY::class:
  19137. if (!empty($classEndLine) && $classEndLine[\count($classEndLine) - 1] == $token->getLine()) {
  19138. \array_pop($classEndLine);
  19139. \array_pop($class);
  19140. } elseif ($traitEndLine !== \false && $traitEndLine == $token->getLine()) {
  19141. $trait = \false;
  19142. $traitEndLine = \false;
  19143. } elseif ($interfaceEndLine !== \false && $interfaceEndLine == $token->getLine()) {
  19144. $interface = \false;
  19145. $interfaceEndLine = \false;
  19146. }
  19147. break;
  19148. }
  19149. }
  19150. }
  19151. /**
  19152. * @param string $name
  19153. * @param int $startLine
  19154. * @param int $endLine
  19155. */
  19156. private function addFunctionToMap($name, $startLine, $endLine) : void
  19157. {
  19158. for ($line = $startLine; $line <= $endLine; $line++) {
  19159. $this->lineToFunctionMap[$line] = $name;
  19160. }
  19161. }
  19162. }
  19163. /*
  19164. * This file is part of phpunit/php-token-stream.
  19165. *
  19166. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  19167. *
  19168. * For the full copyright and license information, please view the LICENSE
  19169. * file that was distributed with this source code.
  19170. */
  19171. /**
  19172. * A stream of PHP tokens.
  19173. */
  19174. \class_alias('PHPUnit\\PHP_Token_Stream', 'PHP_Token_Stream', \false);
  19175. php-token-stream
  19176. Copyright (c) 2009-2020, Sebastian Bergmann <sebastian@phpunit.de>.
  19177. All rights reserved.
  19178. Redistribution and use in source and binary forms, with or without
  19179. modification, are permitted provided that the following conditions
  19180. are met:
  19181. * Redistributions of source code must retain the above copyright
  19182. notice, this list of conditions and the following disclaimer.
  19183. * Redistributions in binary form must reproduce the above copyright
  19184. notice, this list of conditions and the following disclaimer in
  19185. the documentation and/or other materials provided with the
  19186. distribution.
  19187. * Neither the name of Sebastian Bergmann nor the names of his
  19188. contributors may be used to endorse or promote products derived
  19189. from this software without specific prior written permission.
  19190. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  19191. "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  19192. LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  19193. FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  19194. COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  19195. INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  19196. BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  19197. LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  19198. CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  19199. LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
  19200. ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  19201. POSSIBILITY OF SUCH DAMAGE.
  19202. Object Reflector
  19203. Copyright (c) 2017-2020, Sebastian Bergmann <sebastian@phpunit.de>.
  19204. All rights reserved.
  19205. Redistribution and use in source and binary forms, with or without
  19206. modification, are permitted provided that the following conditions
  19207. are met:
  19208. * Redistributions of source code must retain the above copyright
  19209. notice, this list of conditions and the following disclaimer.
  19210. * Redistributions in binary form must reproduce the above copyright
  19211. notice, this list of conditions and the following disclaimer in
  19212. the documentation and/or other materials provided with the
  19213. distribution.
  19214. * Neither the name of Sebastian Bergmann nor the names of his
  19215. contributors may be used to endorse or promote products derived
  19216. from this software without specific prior written permission.
  19217. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  19218. "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  19219. LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  19220. FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  19221. COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  19222. INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  19223. BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  19224. LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  19225. CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  19226. LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
  19227. ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  19228. POSSIBILITY OF SUCH DAMAGE.
  19229. phpunit/phpunit: 9.2.5
  19230. doctrine/instantiator: 1.3.1
  19231. myclabs/deep-copy: 1.9.5
  19232. phar-io/manifest: 1.0.3
  19233. phar-io/version: 2.0.1
  19234. phpdocumentor/reflection-common: 2.1.0
  19235. phpdocumentor/reflection-docblock: 5.1.0
  19236. phpdocumentor/type-resolver: 1.2.0
  19237. phpspec/prophecy: v1.10.3
  19238. phpunit/php-code-coverage: 8.0.2
  19239. phpunit/php-file-iterator: 3.0.2
  19240. phpunit/php-invoker: 3.0.1
  19241. phpunit/php-text-template: 2.0.1
  19242. phpunit/php-timer: 5.0.0
  19243. phpunit/php-token-stream: 4.0.2
  19244. sebastian/code-unit: 1.0.3
  19245. sebastian/code-unit-reverse-lookup: 2.0.1
  19246. sebastian/comparator: 4.0.2
  19247. sebastian/diff: 4.0.1
  19248. sebastian/environment: 5.1.1
  19249. sebastian/exporter: 4.0.1
  19250. sebastian/global-state: 4.0.0
  19251. sebastian/object-enumerator: 4.0.1
  19252. sebastian/object-reflector: 2.0.1
  19253. sebastian/recursion-context: 4.0.1
  19254. sebastian/resource-operations: 3.0.1
  19255. sebastian/type: 2.1.0
  19256. sebastian/version: 3.0.0
  19257. symfony/polyfill-ctype: v1.17.1
  19258. theseer/tokenizer: 1.1.3
  19259. webmozart/assert: 1.9.0
  19260. <?php
  19261. namespace PHPUnit\Doctrine\Instantiator\Exception;
  19262. use Exception;
  19263. use ReflectionClass;
  19264. use UnexpectedValueException as BaseUnexpectedValueException;
  19265. use function sprintf;
  19266. /**
  19267. * Exception for given parameters causing invalid/unexpected state on instantiation
  19268. */
  19269. class UnexpectedValueException extends \UnexpectedValueException implements \PHPUnit\Doctrine\Instantiator\Exception\ExceptionInterface
  19270. {
  19271. public static function fromSerializationTriggeredException(\ReflectionClass $reflectionClass, \Exception $exception) : self
  19272. {
  19273. return new self(\sprintf('An exception was raised while trying to instantiate an instance of "%s" via un-serialization', $reflectionClass->getName()), 0, $exception);
  19274. }
  19275. public static function fromUncleanUnSerialization(\ReflectionClass $reflectionClass, string $errorString, int $errorCode, string $errorFile, int $errorLine) : self
  19276. {
  19277. return new self(\sprintf('Could not produce an instance of "%s" via un-serialization, since an error was triggered ' . 'in file "%s" at line "%d"', $reflectionClass->getName(), $errorFile, $errorLine), 0, new \Exception($errorString, $errorCode));
  19278. }
  19279. }
  19280. <?php
  19281. namespace PHPUnit\Doctrine\Instantiator\Exception;
  19282. use Throwable;
  19283. /**
  19284. * Base exception marker interface for the instantiator component
  19285. */
  19286. interface ExceptionInterface extends \Throwable
  19287. {
  19288. }
  19289. <?php
  19290. namespace PHPUnit\Doctrine\Instantiator\Exception;
  19291. use InvalidArgumentException as BaseInvalidArgumentException;
  19292. use ReflectionClass;
  19293. use const PHP_VERSION_ID;
  19294. use function interface_exists;
  19295. use function sprintf;
  19296. use function trait_exists;
  19297. /**
  19298. * Exception for invalid arguments provided to the instantiator
  19299. */
  19300. class InvalidArgumentException extends \InvalidArgumentException implements \PHPUnit\Doctrine\Instantiator\Exception\ExceptionInterface
  19301. {
  19302. public static function fromNonExistingClass(string $className) : self
  19303. {
  19304. if (\interface_exists($className)) {
  19305. return new self(\sprintf('The provided type "%s" is an interface, and can not be instantiated', $className));
  19306. }
  19307. if (\PHP_VERSION_ID >= 50400 && \trait_exists($className)) {
  19308. return new self(\sprintf('The provided type "%s" is a trait, and can not be instantiated', $className));
  19309. }
  19310. return new self(\sprintf('The provided class "%s" does not exist', $className));
  19311. }
  19312. public static function fromAbstractClass(\ReflectionClass $reflectionClass) : self
  19313. {
  19314. return new self(\sprintf('The provided class "%s" is abstract, and can not be instantiated', $reflectionClass->getName()));
  19315. }
  19316. }
  19317. <?php
  19318. namespace PHPUnit\Doctrine\Instantiator;
  19319. use ArrayIterator;
  19320. use PHPUnit\Doctrine\Instantiator\Exception\InvalidArgumentException;
  19321. use PHPUnit\Doctrine\Instantiator\Exception\UnexpectedValueException;
  19322. use Exception;
  19323. use ReflectionClass;
  19324. use ReflectionException;
  19325. use Serializable;
  19326. use function class_exists;
  19327. use function is_subclass_of;
  19328. use function restore_error_handler;
  19329. use function set_error_handler;
  19330. use function sprintf;
  19331. use function strlen;
  19332. use function unserialize;
  19333. /**
  19334. * {@inheritDoc}
  19335. */
  19336. final class Instantiator implements \PHPUnit\Doctrine\Instantiator\InstantiatorInterface
  19337. {
  19338. /**
  19339. * Markers used internally by PHP to define whether {@see \unserialize} should invoke
  19340. * the method {@see \Serializable::unserialize()} when dealing with classes implementing
  19341. * the {@see \Serializable} interface.
  19342. */
  19343. public const SERIALIZATION_FORMAT_USE_UNSERIALIZER = 'C';
  19344. public const SERIALIZATION_FORMAT_AVOID_UNSERIALIZER = 'O';
  19345. /**
  19346. * Used to instantiate specific classes, indexed by class name.
  19347. *
  19348. * @var callable[]
  19349. */
  19350. private static $cachedInstantiators = [];
  19351. /**
  19352. * Array of objects that can directly be cloned, indexed by class name.
  19353. *
  19354. * @var object[]
  19355. */
  19356. private static $cachedCloneables = [];
  19357. /**
  19358. * {@inheritDoc}
  19359. */
  19360. public function instantiate($className)
  19361. {
  19362. if (isset(self::$cachedCloneables[$className])) {
  19363. return clone self::$cachedCloneables[$className];
  19364. }
  19365. if (isset(self::$cachedInstantiators[$className])) {
  19366. $factory = self::$cachedInstantiators[$className];
  19367. return $factory();
  19368. }
  19369. return $this->buildAndCacheFromFactory($className);
  19370. }
  19371. /**
  19372. * Builds the requested object and caches it in static properties for performance
  19373. *
  19374. * @return object
  19375. */
  19376. private function buildAndCacheFromFactory(string $className)
  19377. {
  19378. $factory = self::$cachedInstantiators[$className] = $this->buildFactory($className);
  19379. $instance = $factory();
  19380. if ($this->isSafeToClone(new \ReflectionClass($instance))) {
  19381. self::$cachedCloneables[$className] = clone $instance;
  19382. }
  19383. return $instance;
  19384. }
  19385. /**
  19386. * Builds a callable capable of instantiating the given $className without
  19387. * invoking its constructor.
  19388. *
  19389. * @throws InvalidArgumentException
  19390. * @throws UnexpectedValueException
  19391. * @throws ReflectionException
  19392. */
  19393. private function buildFactory(string $className) : callable
  19394. {
  19395. $reflectionClass = $this->getReflectionClass($className);
  19396. if ($this->isInstantiableViaReflection($reflectionClass)) {
  19397. return [$reflectionClass, 'newInstanceWithoutConstructor'];
  19398. }
  19399. $serializedString = \sprintf('%s:%d:"%s":0:{}', \is_subclass_of($className, \Serializable::class) ? self::SERIALIZATION_FORMAT_USE_UNSERIALIZER : self::SERIALIZATION_FORMAT_AVOID_UNSERIALIZER, \strlen($className), $className);
  19400. $this->checkIfUnSerializationIsSupported($reflectionClass, $serializedString);
  19401. return static function () use($serializedString) {
  19402. return \unserialize($serializedString);
  19403. };
  19404. }
  19405. /**
  19406. * @throws InvalidArgumentException
  19407. * @throws ReflectionException
  19408. */
  19409. private function getReflectionClass(string $className) : \ReflectionClass
  19410. {
  19411. if (!\class_exists($className)) {
  19412. throw \PHPUnit\Doctrine\Instantiator\Exception\InvalidArgumentException::fromNonExistingClass($className);
  19413. }
  19414. $reflection = new \ReflectionClass($className);
  19415. if ($reflection->isAbstract()) {
  19416. throw \PHPUnit\Doctrine\Instantiator\Exception\InvalidArgumentException::fromAbstractClass($reflection);
  19417. }
  19418. return $reflection;
  19419. }
  19420. /**
  19421. * @throws UnexpectedValueException
  19422. */
  19423. private function checkIfUnSerializationIsSupported(\ReflectionClass $reflectionClass, string $serializedString) : void
  19424. {
  19425. \set_error_handler(static function (int $code, string $message, string $file, int $line) use($reflectionClass, &$error) : bool {
  19426. $error = \PHPUnit\Doctrine\Instantiator\Exception\UnexpectedValueException::fromUncleanUnSerialization($reflectionClass, $message, $code, $file, $line);
  19427. return \true;
  19428. });
  19429. try {
  19430. $this->attemptInstantiationViaUnSerialization($reflectionClass, $serializedString);
  19431. } finally {
  19432. \restore_error_handler();
  19433. }
  19434. if ($error) {
  19435. throw $error;
  19436. }
  19437. }
  19438. /**
  19439. * @throws UnexpectedValueException
  19440. */
  19441. private function attemptInstantiationViaUnSerialization(\ReflectionClass $reflectionClass, string $serializedString) : void
  19442. {
  19443. try {
  19444. \unserialize($serializedString);
  19445. } catch (\Exception $exception) {
  19446. throw \PHPUnit\Doctrine\Instantiator\Exception\UnexpectedValueException::fromSerializationTriggeredException($reflectionClass, $exception);
  19447. }
  19448. }
  19449. private function isInstantiableViaReflection(\ReflectionClass $reflectionClass) : bool
  19450. {
  19451. return !($this->hasInternalAncestors($reflectionClass) && $reflectionClass->isFinal());
  19452. }
  19453. /**
  19454. * Verifies whether the given class is to be considered internal
  19455. */
  19456. private function hasInternalAncestors(\ReflectionClass $reflectionClass) : bool
  19457. {
  19458. do {
  19459. if ($reflectionClass->isInternal()) {
  19460. return \true;
  19461. }
  19462. $reflectionClass = $reflectionClass->getParentClass();
  19463. } while ($reflectionClass);
  19464. return \false;
  19465. }
  19466. /**
  19467. * Checks if a class is cloneable
  19468. *
  19469. * Classes implementing `__clone` cannot be safely cloned, as that may cause side-effects.
  19470. */
  19471. private function isSafeToClone(\ReflectionClass $reflection) : bool
  19472. {
  19473. return $reflection->isCloneable() && !$reflection->hasMethod('__clone') && !$reflection->isSubclassOf(\ArrayIterator::class);
  19474. }
  19475. }
  19476. <?php
  19477. namespace PHPUnit\Doctrine\Instantiator;
  19478. use PHPUnit\Doctrine\Instantiator\Exception\ExceptionInterface;
  19479. /**
  19480. * Instantiator provides utility methods to build objects without invoking their constructors
  19481. */
  19482. interface InstantiatorInterface
  19483. {
  19484. /**
  19485. * @param string $className
  19486. *
  19487. * @return object
  19488. *
  19489. * @throws ExceptionInterface
  19490. */
  19491. public function instantiate($className);
  19492. }
  19493. Copyright (c) 2014 Doctrine Project
  19494. Permission is hereby granted, free of charge, to any person obtaining a copy of
  19495. this software and associated documentation files (the "Software"), to deal in
  19496. the Software without restriction, including without limitation the rights to
  19497. use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
  19498. of the Software, and to permit persons to whom the Software is furnished to do
  19499. so, subject to the following conditions:
  19500. The above copyright notice and this permission notice shall be included in all
  19501. copies or substantial portions of the Software.
  19502. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  19503. IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  19504. FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  19505. AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19506. LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  19507. OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  19508. SOFTWARE.
  19509. <?php
  19510. declare (strict_types=1);
  19511. /*
  19512. * This file is part of resource-operations.
  19513. *
  19514. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  19515. *
  19516. * For the full copyright and license information, please view the LICENSE
  19517. * file that was distributed with this source code.
  19518. */
  19519. namespace PHPUnit\SebastianBergmann\ResourceOperations;
  19520. final class ResourceOperations
  19521. {
  19522. /**
  19523. * @return string[]
  19524. */
  19525. public static function getFunctions() : array
  19526. {
  19527. return ['Directory::close', 'Directory::read', 'Directory::rewind', 'DirectoryIterator::openFile', 'FilesystemIterator::openFile', 'Gmagick::readimagefile', 'HttpResponse::getRequestBodyStream', 'HttpResponse::getStream', 'HttpResponse::setStream', 'Imagick::pingImageFile', 'Imagick::readImageFile', 'Imagick::writeImageFile', 'Imagick::writeImagesFile', 'MongoGridFSCursor::__construct', 'MongoGridFSFile::getResource', 'MysqlndUhConnection::stmtInit', 'MysqlndUhConnection::storeResult', 'MysqlndUhConnection::useResult', 'PDF_activate_item', 'PDF_add_launchlink', 'PDF_add_locallink', 'PDF_add_nameddest', 'PDF_add_note', 'PDF_add_pdflink', 'PDF_add_table_cell', 'PDF_add_textflow', 'PDF_add_thumbnail', 'PDF_add_weblink', 'PDF_arc', 'PDF_arcn', 'PDF_attach_file', 'PDF_begin_document', 'PDF_begin_font', 'PDF_begin_glyph', 'PDF_begin_item', 'PDF_begin_layer', 'PDF_begin_page', 'PDF_begin_page_ext', 'PDF_begin_pattern', 'PDF_begin_template', 'PDF_begin_template_ext', 'PDF_circle', 'PDF_clip', 'PDF_close', 'PDF_close_image', 'PDF_close_pdi', 'PDF_close_pdi_page', 'PDF_closepath', 'PDF_closepath_fill_stroke', 'PDF_closepath_stroke', 'PDF_concat', 'PDF_continue_text', 'PDF_create_3dview', 'PDF_create_action', 'PDF_create_annotation', 'PDF_create_bookmark', 'PDF_create_field', 'PDF_create_fieldgroup', 'PDF_create_gstate', 'PDF_create_pvf', 'PDF_create_textflow', 'PDF_curveto', 'PDF_define_layer', 'PDF_delete', 'PDF_delete_pvf', 'PDF_delete_table', 'PDF_delete_textflow', 'PDF_encoding_set_char', 'PDF_end_document', 'PDF_end_font', 'PDF_end_glyph', 'PDF_end_item', 'PDF_end_layer', 'PDF_end_page', 'PDF_end_page_ext', 'PDF_end_pattern', 'PDF_end_template', 'PDF_endpath', 'PDF_fill', 'PDF_fill_imageblock', 'PDF_fill_pdfblock', 'PDF_fill_stroke', 'PDF_fill_textblock', 'PDF_findfont', 'PDF_fit_image', 'PDF_fit_pdi_page', 'PDF_fit_table', 'PDF_fit_textflow', 'PDF_fit_textline', 'PDF_get_apiname', 'PDF_get_buffer', 'PDF_get_errmsg', 'PDF_get_errnum', 'PDF_get_parameter', 'PDF_get_pdi_parameter', 'PDF_get_pdi_value', 'PDF_get_value', 'PDF_info_font', 'PDF_info_matchbox', 'PDF_info_table', 'PDF_info_textflow', 'PDF_info_textline', 'PDF_initgraphics', 'PDF_lineto', 'PDF_load_3ddata', 'PDF_load_font', 'PDF_load_iccprofile', 'PDF_load_image', 'PDF_makespotcolor', 'PDF_moveto', 'PDF_new', 'PDF_open_ccitt', 'PDF_open_file', 'PDF_open_image', 'PDF_open_image_file', 'PDF_open_memory_image', 'PDF_open_pdi', 'PDF_open_pdi_document', 'PDF_open_pdi_page', 'PDF_pcos_get_number', 'PDF_pcos_get_stream', 'PDF_pcos_get_string', 'PDF_place_image', 'PDF_place_pdi_page', 'PDF_process_pdi', 'PDF_rect', 'PDF_restore', 'PDF_resume_page', 'PDF_rotate', 'PDF_save', 'PDF_scale', 'PDF_set_border_color', 'PDF_set_border_dash', 'PDF_set_border_style', 'PDF_set_gstate', 'PDF_set_info', 'PDF_set_layer_dependency', 'PDF_set_parameter', 'PDF_set_text_pos', 'PDF_set_value', 'PDF_setcolor', 'PDF_setdash', 'PDF_setdashpattern', 'PDF_setflat', 'PDF_setfont', 'PDF_setgray', 'PDF_setgray_fill', 'PDF_setgray_stroke', 'PDF_setlinecap', 'PDF_setlinejoin', 'PDF_setlinewidth', 'PDF_setmatrix', 'PDF_setmiterlimit', 'PDF_setrgbcolor', 'PDF_setrgbcolor_fill', 'PDF_setrgbcolor_stroke', 'PDF_shading', 'PDF_shading_pattern', 'PDF_shfill', 'PDF_show', 'PDF_show_boxed', 'PDF_show_xy', 'PDF_skew', 'PDF_stringwidth', 'PDF_stroke', 'PDF_suspend_page', 'PDF_translate', 'PDF_utf16_to_utf8', 'PDF_utf32_to_utf16', 'PDF_utf8_to_utf16', 'PDO::pgsqlLOBOpen', 'RarEntry::getStream', 'SQLite3::openBlob', 'SWFMovie::saveToFile', 'SplFileInfo::openFile', 'SplFileObject::openFile', 'SplTempFileObject::openFile', 'V8Js::compileString', 'V8Js::executeScript', 'Vtiful\\Kernel\\Excel::setColumn', 'Vtiful\\Kernel\\Excel::setRow', 'Vtiful\\Kernel\\Format::align', 'Vtiful\\Kernel\\Format::bold', 'Vtiful\\Kernel\\Format::italic', 'Vtiful\\Kernel\\Format::underline', 'XMLWriter::openMemory', 'XMLWriter::openURI', 'ZipArchive::getStream', 'Zookeeper::setLogStream', 'apc_bin_dumpfile', 'apc_bin_loadfile', 'bbcode_add_element', 'bbcode_add_smiley', 'bbcode_create', 'bbcode_destroy', 'bbcode_parse', 'bbcode_set_arg_parser', 'bbcode_set_flags', 'bcompiler_read', 'bcompiler_write_class', 'bcompiler_write_constant', 'bcompiler_write_exe_footer', 'bcompiler_write_file', 'bcompiler_write_footer', 'bcompiler_write_function', 'bcompiler_write_functions_from_file', 'bcompiler_write_header', 'bcompiler_write_included_filename', 'bzclose', 'bzerrno', 'bzerror', 'bzerrstr', 'bzflush', 'bzopen', 'bzread', 'bzwrite', 'cairo_surface_write_to_png', 'closedir', 'copy', 'crack_closedict', 'crack_opendict', 'cubrid_bind', 'cubrid_close_prepare', 'cubrid_close_request', 'cubrid_col_get', 'cubrid_col_size', 'cubrid_column_names', 'cubrid_column_types', 'cubrid_commit', 'cubrid_connect', 'cubrid_connect_with_url', 'cubrid_current_oid', 'cubrid_db_parameter', 'cubrid_disconnect', 'cubrid_drop', 'cubrid_fetch', 'cubrid_free_result', 'cubrid_get', 'cubrid_get_autocommit', 'cubrid_get_charset', 'cubrid_get_class_name', 'cubrid_get_db_parameter', 'cubrid_get_query_timeout', 'cubrid_get_server_info', 'cubrid_insert_id', 'cubrid_is_instance', 'cubrid_lob2_bind', 'cubrid_lob2_close', 'cubrid_lob2_export', 'cubrid_lob2_import', 'cubrid_lob2_new', 'cubrid_lob2_read', 'cubrid_lob2_seek', 'cubrid_lob2_seek64', 'cubrid_lob2_size', 'cubrid_lob2_size64', 'cubrid_lob2_tell', 'cubrid_lob2_tell64', 'cubrid_lob2_write', 'cubrid_lob_export', 'cubrid_lob_get', 'cubrid_lob_send', 'cubrid_lob_size', 'cubrid_lock_read', 'cubrid_lock_write', 'cubrid_move_cursor', 'cubrid_next_result', 'cubrid_num_cols', 'cubrid_num_rows', 'cubrid_pconnect', 'cubrid_pconnect_with_url', 'cubrid_prepare', 'cubrid_put', 'cubrid_query', 'cubrid_rollback', 'cubrid_schema', 'cubrid_seq_add', 'cubrid_seq_drop', 'cubrid_seq_insert', 'cubrid_seq_put', 'cubrid_set_add', 'cubrid_set_autocommit', 'cubrid_set_db_parameter', 'cubrid_set_drop', 'cubrid_set_query_timeout', 'cubrid_unbuffered_query', 'curl_close', 'curl_copy_handle', 'curl_errno', 'curl_error', 'curl_escape', 'curl_exec', 'curl_getinfo', 'curl_multi_add_handle', 'curl_multi_close', 'curl_multi_errno', 'curl_multi_exec', 'curl_multi_getcontent', 'curl_multi_info_read', 'curl_multi_remove_handle', 'curl_multi_select', 'curl_multi_setopt', 'curl_pause', 'curl_reset', 'curl_setopt', 'curl_setopt_array', 'curl_share_close', 'curl_share_errno', 'curl_share_init', 'curl_share_setopt', 'curl_unescape', 'cyrus_authenticate', 'cyrus_bind', 'cyrus_close', 'cyrus_connect', 'cyrus_query', 'cyrus_unbind', 'db2_autocommit', 'db2_bind_param', 'db2_client_info', 'db2_close', 'db2_column_privileges', 'db2_columns', 'db2_commit', 'db2_conn_error', 'db2_conn_errormsg', 'db2_connect', 'db2_cursor_type', 'db2_exec', 'db2_execute', 'db2_fetch_array', 'db2_fetch_assoc', 'db2_fetch_both', 'db2_fetch_object', 'db2_fetch_row', 'db2_field_display_size', 'db2_field_name', 'db2_field_num', 'db2_field_precision', 'db2_field_scale', 'db2_field_type', 'db2_field_width', 'db2_foreign_keys', 'db2_free_result', 'db2_free_stmt', 'db2_get_option', 'db2_last_insert_id', 'db2_lob_read', 'db2_next_result', 'db2_num_fields', 'db2_num_rows', 'db2_pclose', 'db2_pconnect', 'db2_prepare', 'db2_primary_keys', 'db2_procedure_columns', 'db2_procedures', 'db2_result', 'db2_rollback', 'db2_server_info', 'db2_set_option', 'db2_special_columns', 'db2_statistics', 'db2_stmt_error', 'db2_stmt_errormsg', 'db2_table_privileges', 'db2_tables', 'dba_close', 'dba_delete', 'dba_exists', 'dba_fetch', 'dba_firstkey', 'dba_insert', 'dba_nextkey', 'dba_open', 'dba_optimize', 'dba_popen', 'dba_replace', 'dba_sync', 'dbplus_add', 'dbplus_aql', 'dbplus_close', 'dbplus_curr', 'dbplus_find', 'dbplus_first', 'dbplus_flush', 'dbplus_freelock', 'dbplus_freerlocks', 'dbplus_getlock', 'dbplus_getunique', 'dbplus_info', 'dbplus_last', 'dbplus_lockrel', 'dbplus_next', 'dbplus_open', 'dbplus_prev', 'dbplus_rchperm', 'dbplus_rcreate', 'dbplus_rcrtexact', 'dbplus_rcrtlike', 'dbplus_restorepos', 'dbplus_rkeys', 'dbplus_ropen', 'dbplus_rquery', 'dbplus_rrename', 'dbplus_rsecindex', 'dbplus_runlink', 'dbplus_rzap', 'dbplus_savepos', 'dbplus_setindex', 'dbplus_setindexbynumber', 'dbplus_sql', 'dbplus_tremove', 'dbplus_undo', 'dbplus_undoprepare', 'dbplus_unlockrel', 'dbplus_unselect', 'dbplus_update', 'dbplus_xlockrel', 'dbplus_xunlockrel', 'deflate_add', 'dio_close', 'dio_fcntl', 'dio_open', 'dio_read', 'dio_seek', 'dio_stat', 'dio_tcsetattr', 'dio_truncate', 'dio_write', 'dir', 'eio_busy', 'eio_cancel', 'eio_chmod', 'eio_chown', 'eio_close', 'eio_custom', 'eio_dup2', 'eio_fallocate', 'eio_fchmod', 'eio_fchown', 'eio_fdatasync', 'eio_fstat', 'eio_fstatvfs', 'eio_fsync', 'eio_ftruncate', 'eio_futime', 'eio_get_last_error', 'eio_grp', 'eio_grp_add', 'eio_grp_cancel', 'eio_grp_limit', 'eio_link', 'eio_lstat', 'eio_mkdir', 'eio_mknod', 'eio_nop', 'eio_open', 'eio_read', 'eio_readahead', 'eio_readdir', 'eio_readlink', 'eio_realpath', 'eio_rename', 'eio_rmdir', 'eio_seek', 'eio_sendfile', 'eio_stat', 'eio_statvfs', 'eio_symlink', 'eio_sync', 'eio_sync_file_range', 'eio_syncfs', 'eio_truncate', 'eio_unlink', 'eio_utime', 'eio_write', 'enchant_broker_describe', 'enchant_broker_dict_exists', 'enchant_broker_free', 'enchant_broker_free_dict', 'enchant_broker_get_dict_path', 'enchant_broker_get_error', 'enchant_broker_init', 'enchant_broker_list_dicts', 'enchant_broker_request_dict', 'enchant_broker_request_pwl_dict', 'enchant_broker_set_dict_path', 'enchant_broker_set_ordering', 'enchant_dict_add_to_personal', 'enchant_dict_add_to_session', 'enchant_dict_check', 'enchant_dict_describe', 'enchant_dict_get_error', 'enchant_dict_is_in_session', 'enchant_dict_quick_check', 'enchant_dict_store_replacement', 'enchant_dict_suggest', 'event_add', 'event_base_free', 'event_base_loop', 'event_base_loopbreak', 'event_base_loopexit', 'event_base_new', 'event_base_priority_init', 'event_base_reinit', 'event_base_set', 'event_buffer_base_set', 'event_buffer_disable', 'event_buffer_enable', 'event_buffer_fd_set', 'event_buffer_free', 'event_buffer_new', 'event_buffer_priority_set', 'event_buffer_read', 'event_buffer_set_callback', 'event_buffer_timeout_set', 'event_buffer_watermark_set', 'event_buffer_write', 'event_del', 'event_free', 'event_new', 'event_priority_set', 'event_set', 'event_timer_add', 'event_timer_del', 'event_timer_pending', 'event_timer_set', 'expect_expectl', 'expect_popen', 'fam_cancel_monitor', 'fam_close', 'fam_monitor_collection', 'fam_monitor_directory', 'fam_monitor_file', 'fam_next_event', 'fam_open', 'fam_pending', 'fam_resume_monitor', 'fam_suspend_monitor', 'fann_cascadetrain_on_data', 'fann_cascadetrain_on_file', 'fann_clear_scaling_params', 'fann_copy', 'fann_create_from_file', 'fann_create_shortcut_array', 'fann_create_standard', 'fann_create_standard_array', 'fann_create_train', 'fann_create_train_from_callback', 'fann_descale_input', 'fann_descale_output', 'fann_descale_train', 'fann_destroy', 'fann_destroy_train', 'fann_duplicate_train_data', 'fann_get_MSE', 'fann_get_activation_function', 'fann_get_activation_steepness', 'fann_get_bias_array', 'fann_get_bit_fail', 'fann_get_bit_fail_limit', 'fann_get_cascade_activation_functions', 'fann_get_cascade_activation_functions_count', 'fann_get_cascade_activation_steepnesses', 'fann_get_cascade_activation_steepnesses_count', 'fann_get_cascade_candidate_change_fraction', 'fann_get_cascade_candidate_limit', 'fann_get_cascade_candidate_stagnation_epochs', 'fann_get_cascade_max_cand_epochs', 'fann_get_cascade_max_out_epochs', 'fann_get_cascade_min_cand_epochs', 'fann_get_cascade_min_out_epochs', 'fann_get_cascade_num_candidate_groups', 'fann_get_cascade_num_candidates', 'fann_get_cascade_output_change_fraction', 'fann_get_cascade_output_stagnation_epochs', 'fann_get_cascade_weight_multiplier', 'fann_get_connection_array', 'fann_get_connection_rate', 'fann_get_errno', 'fann_get_errstr', 'fann_get_layer_array', 'fann_get_learning_momentum', 'fann_get_learning_rate', 'fann_get_network_type', 'fann_get_num_input', 'fann_get_num_layers', 'fann_get_num_output', 'fann_get_quickprop_decay', 'fann_get_quickprop_mu', 'fann_get_rprop_decrease_factor', 'fann_get_rprop_delta_max', 'fann_get_rprop_delta_min', 'fann_get_rprop_delta_zero', 'fann_get_rprop_increase_factor', 'fann_get_sarprop_step_error_shift', 'fann_get_sarprop_step_error_threshold_factor', 'fann_get_sarprop_temperature', 'fann_get_sarprop_weight_decay_shift', 'fann_get_total_connections', 'fann_get_total_neurons', 'fann_get_train_error_function', 'fann_get_train_stop_function', 'fann_get_training_algorithm', 'fann_init_weights', 'fann_length_train_data', 'fann_merge_train_data', 'fann_num_input_train_data', 'fann_num_output_train_data', 'fann_randomize_weights', 'fann_read_train_from_file', 'fann_reset_errno', 'fann_reset_errstr', 'fann_run', 'fann_save', 'fann_save_train', 'fann_scale_input', 'fann_scale_input_train_data', 'fann_scale_output', 'fann_scale_output_train_data', 'fann_scale_train', 'fann_scale_train_data', 'fann_set_activation_function', 'fann_set_activation_function_hidden', 'fann_set_activation_function_layer', 'fann_set_activation_function_output', 'fann_set_activation_steepness', 'fann_set_activation_steepness_hidden', 'fann_set_activation_steepness_layer', 'fann_set_activation_steepness_output', 'fann_set_bit_fail_limit', 'fann_set_callback', 'fann_set_cascade_activation_functions', 'fann_set_cascade_activation_steepnesses', 'fann_set_cascade_candidate_change_fraction', 'fann_set_cascade_candidate_limit', 'fann_set_cascade_candidate_stagnation_epochs', 'fann_set_cascade_max_cand_epochs', 'fann_set_cascade_max_out_epochs', 'fann_set_cascade_min_cand_epochs', 'fann_set_cascade_min_out_epochs', 'fann_set_cascade_num_candidate_groups', 'fann_set_cascade_output_change_fraction', 'fann_set_cascade_output_stagnation_epochs', 'fann_set_cascade_weight_multiplier', 'fann_set_error_log', 'fann_set_input_scaling_params', 'fann_set_learning_momentum', 'fann_set_learning_rate', 'fann_set_output_scaling_params', 'fann_set_quickprop_decay', 'fann_set_quickprop_mu', 'fann_set_rprop_decrease_factor', 'fann_set_rprop_delta_max', 'fann_set_rprop_delta_min', 'fann_set_rprop_delta_zero', 'fann_set_rprop_increase_factor', 'fann_set_sarprop_step_error_shift', 'fann_set_sarprop_step_error_threshold_factor', 'fann_set_sarprop_temperature', 'fann_set_sarprop_weight_decay_shift', 'fann_set_scaling_params', 'fann_set_train_error_function', 'fann_set_train_stop_function', 'fann_set_training_algorithm', 'fann_set_weight', 'fann_set_weight_array', 'fann_shuffle_train_data', 'fann_subset_train_data', 'fann_test', 'fann_test_data', 'fann_train', 'fann_train_epoch', 'fann_train_on_data', 'fann_train_on_file', 'fbsql_affected_rows', 'fbsql_autocommit', 'fbsql_blob_size', 'fbsql_change_user', 'fbsql_clob_size', 'fbsql_close', 'fbsql_commit', 'fbsql_connect', 'fbsql_create_blob', 'fbsql_create_clob', 'fbsql_create_db', 'fbsql_data_seek', 'fbsql_database', 'fbsql_database_password', 'fbsql_db_query', 'fbsql_db_status', 'fbsql_drop_db', 'fbsql_errno', 'fbsql_error', 'fbsql_fetch_array', 'fbsql_fetch_assoc', 'fbsql_fetch_field', 'fbsql_fetch_lengths', 'fbsql_fetch_object', 'fbsql_fetch_row', 'fbsql_field_flags', 'fbsql_field_len', 'fbsql_field_name', 'fbsql_field_seek', 'fbsql_field_table', 'fbsql_field_type', 'fbsql_free_result', 'fbsql_get_autostart_info', 'fbsql_hostname', 'fbsql_insert_id', 'fbsql_list_dbs', 'fbsql_list_fields', 'fbsql_list_tables', 'fbsql_next_result', 'fbsql_num_fields', 'fbsql_num_rows', 'fbsql_password', 'fbsql_pconnect', 'fbsql_query', 'fbsql_read_blob', 'fbsql_read_clob', 'fbsql_result', 'fbsql_rollback', 'fbsql_rows_fetched', 'fbsql_select_db', 'fbsql_set_characterset', 'fbsql_set_lob_mode', 'fbsql_set_password', 'fbsql_set_transaction', 'fbsql_start_db', 'fbsql_stop_db', 'fbsql_table_name', 'fbsql_username', 'fclose', 'fdf_add_doc_javascript', 'fdf_add_template', 'fdf_close', 'fdf_create', 'fdf_enum_values', 'fdf_get_ap', 'fdf_get_attachment', 'fdf_get_encoding', 'fdf_get_file', 'fdf_get_flags', 'fdf_get_opt', 'fdf_get_status', 'fdf_get_value', 'fdf_get_version', 'fdf_next_field_name', 'fdf_open', 'fdf_open_string', 'fdf_remove_item', 'fdf_save', 'fdf_save_string', 'fdf_set_ap', 'fdf_set_encoding', 'fdf_set_file', 'fdf_set_flags', 'fdf_set_javascript_action', 'fdf_set_on_import_javascript', 'fdf_set_opt', 'fdf_set_status', 'fdf_set_submit_form_action', 'fdf_set_target_frame', 'fdf_set_value', 'fdf_set_version', 'feof', 'fflush', 'ffmpeg_frame::__construct', 'ffmpeg_frame::toGDImage', 'fgetc', 'fgetcsv', 'fgets', 'fgetss', 'file', 'file_get_contents', 'file_put_contents', 'finfo::buffer', 'finfo::file', 'finfo_buffer', 'finfo_close', 'finfo_file', 'finfo_open', 'finfo_set_flags', 'flock', 'fopen', 'fpassthru', 'fprintf', 'fputcsv', 'fputs', 'fread', 'fscanf', 'fseek', 'fstat', 'ftell', 'ftp_alloc', 'ftp_append', 'ftp_cdup', 'ftp_chdir', 'ftp_chmod', 'ftp_close', 'ftp_delete', 'ftp_exec', 'ftp_fget', 'ftp_fput', 'ftp_get', 'ftp_get_option', 'ftp_login', 'ftp_mdtm', 'ftp_mkdir', 'ftp_mlsd', 'ftp_nb_continue', 'ftp_nb_fget', 'ftp_nb_fput', 'ftp_nb_get', 'ftp_nb_put', 'ftp_nlist', 'ftp_pasv', 'ftp_put', 'ftp_pwd', 'ftp_quit', 'ftp_raw', 'ftp_rawlist', 'ftp_rename', 'ftp_rmdir', 'ftp_set_option', 'ftp_site', 'ftp_size', 'ftp_systype', 'ftruncate', 'fwrite', 'get_resource_type', 'gmp_div', 'gnupg::init', 'gnupg_adddecryptkey', 'gnupg_addencryptkey', 'gnupg_addsignkey', 'gnupg_cleardecryptkeys', 'gnupg_clearencryptkeys', 'gnupg_clearsignkeys', 'gnupg_decrypt', 'gnupg_decryptverify', 'gnupg_encrypt', 'gnupg_encryptsign', 'gnupg_export', 'gnupg_geterror', 'gnupg_getprotocol', 'gnupg_import', 'gnupg_init', 'gnupg_keyinfo', 'gnupg_setarmor', 'gnupg_seterrormode', 'gnupg_setsignmode', 'gnupg_sign', 'gnupg_verify', 'gupnp_context_get_host_ip', 'gupnp_context_get_port', 'gupnp_context_get_subscription_timeout', 'gupnp_context_host_path', 'gupnp_context_new', 'gupnp_context_set_subscription_timeout', 'gupnp_context_timeout_add', 'gupnp_context_unhost_path', 'gupnp_control_point_browse_start', 'gupnp_control_point_browse_stop', 'gupnp_control_point_callback_set', 'gupnp_control_point_new', 'gupnp_device_action_callback_set', 'gupnp_device_info_get', 'gupnp_device_info_get_service', 'gupnp_root_device_get_available', 'gupnp_root_device_get_relative_location', 'gupnp_root_device_new', 'gupnp_root_device_set_available', 'gupnp_root_device_start', 'gupnp_root_device_stop', 'gupnp_service_action_get', 'gupnp_service_action_return', 'gupnp_service_action_return_error', 'gupnp_service_action_set', 'gupnp_service_freeze_notify', 'gupnp_service_info_get', 'gupnp_service_info_get_introspection', 'gupnp_service_introspection_get_state_variable', 'gupnp_service_notify', 'gupnp_service_proxy_action_get', 'gupnp_service_proxy_action_set', 'gupnp_service_proxy_add_notify', 'gupnp_service_proxy_callback_set', 'gupnp_service_proxy_get_subscribed', 'gupnp_service_proxy_remove_notify', 'gupnp_service_proxy_send_action', 'gupnp_service_proxy_set_subscribed', 'gupnp_service_thaw_notify', 'gzclose', 'gzeof', 'gzgetc', 'gzgets', 'gzgetss', 'gzpassthru', 'gzputs', 'gzread', 'gzrewind', 'gzseek', 'gztell', 'gzwrite', 'hash_update_stream', 'http\\Env\\Response::send', 'http_get_request_body_stream', 'ibase_add_user', 'ibase_affected_rows', 'ibase_backup', 'ibase_blob_add', 'ibase_blob_cancel', 'ibase_blob_close', 'ibase_blob_create', 'ibase_blob_get', 'ibase_blob_open', 'ibase_close', 'ibase_commit', 'ibase_commit_ret', 'ibase_connect', 'ibase_db_info', 'ibase_delete_user', 'ibase_drop_db', 'ibase_execute', 'ibase_fetch_assoc', 'ibase_fetch_object', 'ibase_fetch_row', 'ibase_field_info', 'ibase_free_event_handler', 'ibase_free_query', 'ibase_free_result', 'ibase_gen_id', 'ibase_maintain_db', 'ibase_modify_user', 'ibase_name_result', 'ibase_num_fields', 'ibase_num_params', 'ibase_param_info', 'ibase_pconnect', 'ibase_prepare', 'ibase_query', 'ibase_restore', 'ibase_rollback', 'ibase_rollback_ret', 'ibase_server_info', 'ibase_service_attach', 'ibase_service_detach', 'ibase_set_event_handler', 'ibase_trans', 'ifx_affected_rows', 'ifx_close', 'ifx_connect', 'ifx_do', 'ifx_error', 'ifx_fetch_row', 'ifx_fieldproperties', 'ifx_fieldtypes', 'ifx_free_result', 'ifx_getsqlca', 'ifx_htmltbl_result', 'ifx_num_fields', 'ifx_num_rows', 'ifx_pconnect', 'ifx_prepare', 'ifx_query', 'image2wbmp', 'imageaffine', 'imagealphablending', 'imageantialias', 'imagearc', 'imagebmp', 'imagechar', 'imagecharup', 'imagecolorallocate', 'imagecolorallocatealpha', 'imagecolorat', 'imagecolorclosest', 'imagecolorclosestalpha', 'imagecolorclosesthwb', 'imagecolordeallocate', 'imagecolorexact', 'imagecolorexactalpha', 'imagecolormatch', 'imagecolorresolve', 'imagecolorresolvealpha', 'imagecolorset', 'imagecolorsforindex', 'imagecolorstotal', 'imagecolortransparent', 'imageconvolution', 'imagecopy', 'imagecopymerge', 'imagecopymergegray', 'imagecopyresampled', 'imagecopyresized', 'imagecrop', 'imagecropauto', 'imagedashedline', 'imagedestroy', 'imageellipse', 'imagefill', 'imagefilledarc', 'imagefilledellipse', 'imagefilledpolygon', 'imagefilledrectangle', 'imagefilltoborder', 'imagefilter', 'imageflip', 'imagefttext', 'imagegammacorrect', 'imagegd', 'imagegd2', 'imagegetclip', 'imagegif', 'imagegrabscreen', 'imagegrabwindow', 'imageinterlace', 'imageistruecolor', 'imagejpeg', 'imagelayereffect', 'imageline', 'imageopenpolygon', 'imagepalettecopy', 'imagepalettetotruecolor', 'imagepng', 'imagepolygon', 'imagepsencodefont', 'imagepsextendfont', 'imagepsfreefont', 'imagepsloadfont', 'imagepsslantfont', 'imagepstext', 'imagerectangle', 'imageresolution', 'imagerotate', 'imagesavealpha', 'imagescale', 'imagesetbrush', 'imagesetclip', 'imagesetinterpolation', 'imagesetpixel', 'imagesetstyle', 'imagesetthickness', 'imagesettile', 'imagestring', 'imagestringup', 'imagesx', 'imagesy', 'imagetruecolortopalette', 'imagettftext', 'imagewbmp', 'imagewebp', 'imagexbm', 'imap_append', 'imap_body', 'imap_bodystruct', 'imap_check', 'imap_clearflag_full', 'imap_close', 'imap_create', 'imap_createmailbox', 'imap_delete', 'imap_deletemailbox', 'imap_expunge', 'imap_fetch_overview', 'imap_fetchbody', 'imap_fetchheader', 'imap_fetchmime', 'imap_fetchstructure', 'imap_fetchtext', 'imap_gc', 'imap_get_quota', 'imap_get_quotaroot', 'imap_getacl', 'imap_getmailboxes', 'imap_getsubscribed', 'imap_header', 'imap_headerinfo', 'imap_headers', 'imap_list', 'imap_listmailbox', 'imap_listscan', 'imap_listsubscribed', 'imap_lsub', 'imap_mail_copy', 'imap_mail_move', 'imap_mailboxmsginfo', 'imap_msgno', 'imap_num_msg', 'imap_num_recent', 'imap_ping', 'imap_rename', 'imap_renamemailbox', 'imap_reopen', 'imap_savebody', 'imap_scan', 'imap_scanmailbox', 'imap_search', 'imap_set_quota', 'imap_setacl', 'imap_setflag_full', 'imap_sort', 'imap_status', 'imap_subscribe', 'imap_thread', 'imap_uid', 'imap_undelete', 'imap_unsubscribe', 'inflate_add', 'inflate_get_read_len', 'inflate_get_status', 'ingres_autocommit', 'ingres_autocommit_state', 'ingres_charset', 'ingres_close', 'ingres_commit', 'ingres_connect', 'ingres_cursor', 'ingres_errno', 'ingres_error', 'ingres_errsqlstate', 'ingres_escape_string', 'ingres_execute', 'ingres_fetch_array', 'ingres_fetch_assoc', 'ingres_fetch_object', 'ingres_fetch_proc_return', 'ingres_fetch_row', 'ingres_field_length', 'ingres_field_name', 'ingres_field_nullable', 'ingres_field_precision', 'ingres_field_scale', 'ingres_field_type', 'ingres_free_result', 'ingres_next_error', 'ingres_num_fields', 'ingres_num_rows', 'ingres_pconnect', 'ingres_prepare', 'ingres_query', 'ingres_result_seek', 'ingres_rollback', 'ingres_set_environment', 'ingres_unbuffered_query', 'inotify_add_watch', 'inotify_init', 'inotify_queue_len', 'inotify_read', 'inotify_rm_watch', 'kadm5_chpass_principal', 'kadm5_create_principal', 'kadm5_delete_principal', 'kadm5_destroy', 'kadm5_flush', 'kadm5_get_policies', 'kadm5_get_principal', 'kadm5_get_principals', 'kadm5_init_with_password', 'kadm5_modify_principal', 'ldap_add', 'ldap_bind', 'ldap_close', 'ldap_compare', 'ldap_control_paged_result', 'ldap_control_paged_result_response', 'ldap_count_entries', 'ldap_delete', 'ldap_errno', 'ldap_error', 'ldap_exop', 'ldap_exop_passwd', 'ldap_exop_refresh', 'ldap_exop_whoami', 'ldap_first_attribute', 'ldap_first_entry', 'ldap_first_reference', 'ldap_free_result', 'ldap_get_attributes', 'ldap_get_dn', 'ldap_get_entries', 'ldap_get_option', 'ldap_get_values', 'ldap_get_values_len', 'ldap_mod_add', 'ldap_mod_del', 'ldap_mod_replace', 'ldap_modify', 'ldap_modify_batch', 'ldap_next_attribute', 'ldap_next_entry', 'ldap_next_reference', 'ldap_parse_exop', 'ldap_parse_reference', 'ldap_parse_result', 'ldap_rename', 'ldap_sasl_bind', 'ldap_set_option', 'ldap_set_rebind_proc', 'ldap_sort', 'ldap_start_tls', 'ldap_unbind', 'libxml_set_streams_context', 'm_checkstatus', 'm_completeauthorizations', 'm_connect', 'm_connectionerror', 'm_deletetrans', 'm_destroyconn', 'm_getcell', 'm_getcellbynum', 'm_getcommadelimited', 'm_getheader', 'm_initconn', 'm_iscommadelimited', 'm_maxconntimeout', 'm_monitor', 'm_numcolumns', 'm_numrows', 'm_parsecommadelimited', 'm_responsekeys', 'm_responseparam', 'm_returnstatus', 'm_setblocking', 'm_setdropfile', 'm_setip', 'm_setssl', 'm_setssl_cafile', 'm_setssl_files', 'm_settimeout', 'm_transactionssent', 'm_transinqueue', 'm_transkeyval', 'm_transnew', 'm_transsend', 'm_validateidentifier', 'm_verifyconnection', 'm_verifysslcert', 'mailparse_determine_best_xfer_encoding', 'mailparse_msg_create', 'mailparse_msg_extract_part', 'mailparse_msg_extract_part_file', 'mailparse_msg_extract_whole_part_file', 'mailparse_msg_free', 'mailparse_msg_get_part', 'mailparse_msg_get_part_data', 'mailparse_msg_get_structure', 'mailparse_msg_parse', 'mailparse_msg_parse_file', 'mailparse_stream_encode', 'mailparse_uudecode_all', 'maxdb::use_result', 'maxdb_affected_rows', 'maxdb_connect', 'maxdb_disable_rpl_parse', 'maxdb_dump_debug_info', 'maxdb_embedded_connect', 'maxdb_enable_reads_from_master', 'maxdb_enable_rpl_parse', 'maxdb_errno', 'maxdb_error', 'maxdb_fetch_lengths', 'maxdb_field_tell', 'maxdb_get_host_info', 'maxdb_get_proto_info', 'maxdb_get_server_info', 'maxdb_get_server_version', 'maxdb_info', 'maxdb_init', 'maxdb_insert_id', 'maxdb_master_query', 'maxdb_more_results', 'maxdb_next_result', 'maxdb_num_fields', 'maxdb_num_rows', 'maxdb_rpl_parse_enabled', 'maxdb_rpl_probe', 'maxdb_select_db', 'maxdb_sqlstate', 'maxdb_stmt::result_metadata', 'maxdb_stmt_affected_rows', 'maxdb_stmt_errno', 'maxdb_stmt_error', 'maxdb_stmt_num_rows', 'maxdb_stmt_param_count', 'maxdb_stmt_result_metadata', 'maxdb_stmt_sqlstate', 'maxdb_thread_id', 'maxdb_use_result', 'maxdb_warning_count', 'mcrypt_enc_get_algorithms_name', 'mcrypt_enc_get_block_size', 'mcrypt_enc_get_iv_size', 'mcrypt_enc_get_key_size', 'mcrypt_enc_get_modes_name', 'mcrypt_enc_get_supported_key_sizes', 'mcrypt_enc_is_block_algorithm', 'mcrypt_enc_is_block_algorithm_mode', 'mcrypt_enc_is_block_mode', 'mcrypt_enc_self_test', 'mcrypt_generic', 'mcrypt_generic_deinit', 'mcrypt_generic_end', 'mcrypt_generic_init', 'mcrypt_module_close', 'mcrypt_module_open', 'mdecrypt_generic', 'mkdir', 'mqseries_back', 'mqseries_begin', 'mqseries_close', 'mqseries_cmit', 'mqseries_conn', 'mqseries_connx', 'mqseries_disc', 'mqseries_get', 'mqseries_inq', 'mqseries_open', 'mqseries_put', 'mqseries_put1', 'mqseries_set', 'msg_get_queue', 'msg_receive', 'msg_remove_queue', 'msg_send', 'msg_set_queue', 'msg_stat_queue', 'msql_affected_rows', 'msql_close', 'msql_connect', 'msql_create_db', 'msql_data_seek', 'msql_db_query', 'msql_drop_db', 'msql_fetch_array', 'msql_fetch_field', 'msql_fetch_object', 'msql_fetch_row', 'msql_field_flags', 'msql_field_len', 'msql_field_name', 'msql_field_seek', 'msql_field_table', 'msql_field_type', 'msql_free_result', 'msql_list_dbs', 'msql_list_fields', 'msql_list_tables', 'msql_num_fields', 'msql_num_rows', 'msql_pconnect', 'msql_query', 'msql_result', 'msql_select_db', 'mssql_bind', 'mssql_close', 'mssql_connect', 'mssql_data_seek', 'mssql_execute', 'mssql_fetch_array', 'mssql_fetch_assoc', 'mssql_fetch_batch', 'mssql_fetch_field', 'mssql_fetch_object', 'mssql_fetch_row', 'mssql_field_length', 'mssql_field_name', 'mssql_field_seek', 'mssql_field_type', 'mssql_free_result', 'mssql_free_statement', 'mssql_init', 'mssql_next_result', 'mssql_num_fields', 'mssql_num_rows', 'mssql_pconnect', 'mssql_query', 'mssql_result', 'mssql_rows_affected', 'mssql_select_db', 'mysql_affected_rows', 'mysql_client_encoding', 'mysql_close', 'mysql_connect', 'mysql_create_db', 'mysql_data_seek', 'mysql_db_name', 'mysql_db_query', 'mysql_drop_db', 'mysql_errno', 'mysql_error', 'mysql_fetch_array', 'mysql_fetch_assoc', 'mysql_fetch_field', 'mysql_fetch_lengths', 'mysql_fetch_object', 'mysql_fetch_row', 'mysql_field_flags', 'mysql_field_len', 'mysql_field_name', 'mysql_field_seek', 'mysql_field_table', 'mysql_field_type', 'mysql_free_result', 'mysql_get_host_info', 'mysql_get_proto_info', 'mysql_get_server_info', 'mysql_info', 'mysql_insert_id', 'mysql_list_dbs', 'mysql_list_fields', 'mysql_list_processes', 'mysql_list_tables', 'mysql_num_fields', 'mysql_num_rows', 'mysql_pconnect', 'mysql_ping', 'mysql_query', 'mysql_real_escape_string', 'mysql_result', 'mysql_select_db', 'mysql_set_charset', 'mysql_stat', 'mysql_tablename', 'mysql_thread_id', 'mysql_unbuffered_query', 'mysqlnd_uh_convert_to_mysqlnd', 'ncurses_bottom_panel', 'ncurses_del_panel', 'ncurses_delwin', 'ncurses_getmaxyx', 'ncurses_getyx', 'ncurses_hide_panel', 'ncurses_keypad', 'ncurses_meta', 'ncurses_move_panel', 'ncurses_mvwaddstr', 'ncurses_new_panel', 'ncurses_newpad', 'ncurses_newwin', 'ncurses_panel_above', 'ncurses_panel_below', 'ncurses_panel_window', 'ncurses_pnoutrefresh', 'ncurses_prefresh', 'ncurses_replace_panel', 'ncurses_show_panel', 'ncurses_top_panel', 'ncurses_waddch', 'ncurses_waddstr', 'ncurses_wattroff', 'ncurses_wattron', 'ncurses_wattrset', 'ncurses_wborder', 'ncurses_wclear', 'ncurses_wcolor_set', 'ncurses_werase', 'ncurses_wgetch', 'ncurses_whline', 'ncurses_wmouse_trafo', 'ncurses_wmove', 'ncurses_wnoutrefresh', 'ncurses_wrefresh', 'ncurses_wstandend', 'ncurses_wstandout', 'ncurses_wvline', 'newt_button', 'newt_button_bar', 'newt_checkbox', 'newt_checkbox_get_value', 'newt_checkbox_set_flags', 'newt_checkbox_set_value', 'newt_checkbox_tree', 'newt_checkbox_tree_add_item', 'newt_checkbox_tree_find_item', 'newt_checkbox_tree_get_current', 'newt_checkbox_tree_get_entry_value', 'newt_checkbox_tree_get_multi_selection', 'newt_checkbox_tree_get_selection', 'newt_checkbox_tree_multi', 'newt_checkbox_tree_set_current', 'newt_checkbox_tree_set_entry', 'newt_checkbox_tree_set_entry_value', 'newt_checkbox_tree_set_width', 'newt_compact_button', 'newt_component_add_callback', 'newt_component_takes_focus', 'newt_create_grid', 'newt_draw_form', 'newt_entry', 'newt_entry_get_value', 'newt_entry_set', 'newt_entry_set_filter', 'newt_entry_set_flags', 'newt_form', 'newt_form_add_component', 'newt_form_add_components', 'newt_form_add_hot_key', 'newt_form_destroy', 'newt_form_get_current', 'newt_form_run', 'newt_form_set_background', 'newt_form_set_height', 'newt_form_set_size', 'newt_form_set_timer', 'newt_form_set_width', 'newt_form_watch_fd', 'newt_grid_add_components_to_form', 'newt_grid_basic_window', 'newt_grid_free', 'newt_grid_get_size', 'newt_grid_h_close_stacked', 'newt_grid_h_stacked', 'newt_grid_place', 'newt_grid_set_field', 'newt_grid_simple_window', 'newt_grid_v_close_stacked', 'newt_grid_v_stacked', 'newt_grid_wrapped_window', 'newt_grid_wrapped_window_at', 'newt_label', 'newt_label_set_text', 'newt_listbox', 'newt_listbox_append_entry', 'newt_listbox_clear', 'newt_listbox_clear_selection', 'newt_listbox_delete_entry', 'newt_listbox_get_current', 'newt_listbox_get_selection', 'newt_listbox_insert_entry', 'newt_listbox_item_count', 'newt_listbox_select_item', 'newt_listbox_set_current', 'newt_listbox_set_current_by_key', 'newt_listbox_set_data', 'newt_listbox_set_entry', 'newt_listbox_set_width', 'newt_listitem', 'newt_listitem_get_data', 'newt_listitem_set', 'newt_radio_get_current', 'newt_radiobutton', 'newt_run_form', 'newt_scale', 'newt_scale_set', 'newt_scrollbar_set', 'newt_textbox', 'newt_textbox_get_num_lines', 'newt_textbox_reflowed', 'newt_textbox_set_height', 'newt_textbox_set_text', 'newt_vertical_scrollbar', 'oci_bind_array_by_name', 'oci_bind_by_name', 'oci_cancel', 'oci_close', 'oci_commit', 'oci_connect', 'oci_define_by_name', 'oci_error', 'oci_execute', 'oci_fetch', 'oci_fetch_all', 'oci_fetch_array', 'oci_fetch_assoc', 'oci_fetch_object', 'oci_fetch_row', 'oci_field_is_null', 'oci_field_name', 'oci_field_precision', 'oci_field_scale', 'oci_field_size', 'oci_field_type', 'oci_field_type_raw', 'oci_free_cursor', 'oci_free_statement', 'oci_get_implicit_resultset', 'oci_new_collection', 'oci_new_connect', 'oci_new_cursor', 'oci_new_descriptor', 'oci_num_fields', 'oci_num_rows', 'oci_parse', 'oci_pconnect', 'oci_register_taf_callback', 'oci_result', 'oci_rollback', 'oci_server_version', 'oci_set_action', 'oci_set_client_identifier', 'oci_set_client_info', 'oci_set_module_name', 'oci_set_prefetch', 'oci_statement_type', 'oci_unregister_taf_callback', 'odbc_autocommit', 'odbc_close', 'odbc_columnprivileges', 'odbc_columns', 'odbc_commit', 'odbc_connect', 'odbc_cursor', 'odbc_data_source', 'odbc_do', 'odbc_error', 'odbc_errormsg', 'odbc_exec', 'odbc_execute', 'odbc_fetch_array', 'odbc_fetch_into', 'odbc_fetch_row', 'odbc_field_len', 'odbc_field_name', 'odbc_field_num', 'odbc_field_precision', 'odbc_field_scale', 'odbc_field_type', 'odbc_foreignkeys', 'odbc_free_result', 'odbc_gettypeinfo', 'odbc_next_result', 'odbc_num_fields', 'odbc_num_rows', 'odbc_pconnect', 'odbc_prepare', 'odbc_primarykeys', 'odbc_procedurecolumns', 'odbc_procedures', 'odbc_result', 'odbc_result_all', 'odbc_rollback', 'odbc_setoption', 'odbc_specialcolumns', 'odbc_statistics', 'odbc_tableprivileges', 'odbc_tables', 'openal_buffer_create', 'openal_buffer_data', 'openal_buffer_destroy', 'openal_buffer_get', 'openal_buffer_loadwav', 'openal_context_create', 'openal_context_current', 'openal_context_destroy', 'openal_context_process', 'openal_context_suspend', 'openal_device_close', 'openal_device_open', 'openal_source_create', 'openal_source_destroy', 'openal_source_get', 'openal_source_pause', 'openal_source_play', 'openal_source_rewind', 'openal_source_set', 'openal_source_stop', 'openal_stream', 'opendir', 'openssl_csr_new', 'openssl_dh_compute_key', 'openssl_free_key', 'openssl_pkey_export', 'openssl_pkey_free', 'openssl_pkey_get_details', 'openssl_spki_new', 'openssl_x509_free', 'pclose', 'pfsockopen', 'pg_affected_rows', 'pg_cancel_query', 'pg_client_encoding', 'pg_close', 'pg_connect_poll', 'pg_connection_busy', 'pg_connection_reset', 'pg_connection_status', 'pg_consume_input', 'pg_convert', 'pg_copy_from', 'pg_copy_to', 'pg_dbname', 'pg_delete', 'pg_end_copy', 'pg_escape_bytea', 'pg_escape_identifier', 'pg_escape_literal', 'pg_escape_string', 'pg_execute', 'pg_fetch_all', 'pg_fetch_all_columns', 'pg_fetch_array', 'pg_fetch_assoc', 'pg_fetch_row', 'pg_field_name', 'pg_field_num', 'pg_field_size', 'pg_field_table', 'pg_field_type', 'pg_field_type_oid', 'pg_flush', 'pg_free_result', 'pg_get_notify', 'pg_get_pid', 'pg_get_result', 'pg_host', 'pg_insert', 'pg_last_error', 'pg_last_notice', 'pg_last_oid', 'pg_lo_close', 'pg_lo_create', 'pg_lo_export', 'pg_lo_import', 'pg_lo_open', 'pg_lo_read', 'pg_lo_read_all', 'pg_lo_seek', 'pg_lo_tell', 'pg_lo_truncate', 'pg_lo_unlink', 'pg_lo_write', 'pg_meta_data', 'pg_num_fields', 'pg_num_rows', 'pg_options', 'pg_parameter_status', 'pg_ping', 'pg_port', 'pg_prepare', 'pg_put_line', 'pg_query', 'pg_query_params', 'pg_result_error', 'pg_result_error_field', 'pg_result_seek', 'pg_result_status', 'pg_select', 'pg_send_execute', 'pg_send_prepare', 'pg_send_query', 'pg_send_query_params', 'pg_set_client_encoding', 'pg_set_error_verbosity', 'pg_socket', 'pg_trace', 'pg_transaction_status', 'pg_tty', 'pg_untrace', 'pg_update', 'pg_version', 'php_user_filter::filter', 'proc_close', 'proc_get_status', 'proc_terminate', 'ps_add_bookmark', 'ps_add_launchlink', 'ps_add_locallink', 'ps_add_note', 'ps_add_pdflink', 'ps_add_weblink', 'ps_arc', 'ps_arcn', 'ps_begin_page', 'ps_begin_pattern', 'ps_begin_template', 'ps_circle', 'ps_clip', 'ps_close', 'ps_close_image', 'ps_closepath', 'ps_closepath_stroke', 'ps_continue_text', 'ps_curveto', 'ps_delete', 'ps_end_page', 'ps_end_pattern', 'ps_end_template', 'ps_fill', 'ps_fill_stroke', 'ps_findfont', 'ps_get_buffer', 'ps_get_parameter', 'ps_get_value', 'ps_hyphenate', 'ps_include_file', 'ps_lineto', 'ps_makespotcolor', 'ps_moveto', 'ps_new', 'ps_open_file', 'ps_open_image', 'ps_open_image_file', 'ps_open_memory_image', 'ps_place_image', 'ps_rect', 'ps_restore', 'ps_rotate', 'ps_save', 'ps_scale', 'ps_set_border_color', 'ps_set_border_dash', 'ps_set_border_style', 'ps_set_info', 'ps_set_parameter', 'ps_set_text_pos', 'ps_set_value', 'ps_setcolor', 'ps_setdash', 'ps_setflat', 'ps_setfont', 'ps_setgray', 'ps_setlinecap', 'ps_setlinejoin', 'ps_setlinewidth', 'ps_setmiterlimit', 'ps_setoverprintmode', 'ps_setpolydash', 'ps_shading', 'ps_shading_pattern', 'ps_shfill', 'ps_show', 'ps_show2', 'ps_show_boxed', 'ps_show_xy', 'ps_show_xy2', 'ps_string_geometry', 'ps_stringwidth', 'ps_stroke', 'ps_symbol', 'ps_symbol_name', 'ps_symbol_width', 'ps_translate', 'px_close', 'px_create_fp', 'px_date2string', 'px_delete', 'px_delete_record', 'px_get_field', 'px_get_info', 'px_get_parameter', 'px_get_record', 'px_get_schema', 'px_get_value', 'px_insert_record', 'px_new', 'px_numfields', 'px_numrecords', 'px_open_fp', 'px_put_record', 'px_retrieve_record', 'px_set_blob_file', 'px_set_parameter', 'px_set_tablename', 'px_set_targetencoding', 'px_set_value', 'px_timestamp2string', 'px_update_record', 'radius_acct_open', 'radius_add_server', 'radius_auth_open', 'radius_close', 'radius_config', 'radius_create_request', 'radius_demangle', 'radius_demangle_mppe_key', 'radius_get_attr', 'radius_put_addr', 'radius_put_attr', 'radius_put_int', 'radius_put_string', 'radius_put_vendor_addr', 'radius_put_vendor_attr', 'radius_put_vendor_int', 'radius_put_vendor_string', 'radius_request_authenticator', 'radius_salt_encrypt_attr', 'radius_send_request', 'radius_server_secret', 'radius_strerror', 'readdir', 'readfile', 'recode_file', 'rename', 'rewind', 'rewinddir', 'rmdir', 'rpm_close', 'rpm_get_tag', 'rpm_open', 'sapi_windows_vt100_support', 'scandir', 'sem_acquire', 'sem_get', 'sem_release', 'sem_remove', 'set_file_buffer', 'shm_attach', 'shm_detach', 'shm_get_var', 'shm_has_var', 'shm_put_var', 'shm_remove', 'shm_remove_var', 'shmop_close', 'shmop_delete', 'shmop_open', 'shmop_read', 'shmop_size', 'shmop_write', 'socket_accept', 'socket_addrinfo_bind', 'socket_addrinfo_connect', 'socket_addrinfo_explain', 'socket_bind', 'socket_clear_error', 'socket_close', 'socket_connect', 'socket_export_stream', 'socket_get_option', 'socket_get_status', 'socket_getopt', 'socket_getpeername', 'socket_getsockname', 'socket_import_stream', 'socket_last_error', 'socket_listen', 'socket_read', 'socket_recv', 'socket_recvfrom', 'socket_recvmsg', 'socket_send', 'socket_sendmsg', 'socket_sendto', 'socket_set_block', 'socket_set_blocking', 'socket_set_nonblock', 'socket_set_option', 'socket_set_timeout', 'socket_shutdown', 'socket_write', 'sqlite_close', 'sqlite_fetch_string', 'sqlite_has_more', 'sqlite_open', 'sqlite_popen', 'sqlsrv_begin_transaction', 'sqlsrv_cancel', 'sqlsrv_client_info', 'sqlsrv_close', 'sqlsrv_commit', 'sqlsrv_connect', 'sqlsrv_execute', 'sqlsrv_fetch', 'sqlsrv_fetch_array', 'sqlsrv_fetch_object', 'sqlsrv_field_metadata', 'sqlsrv_free_stmt', 'sqlsrv_get_field', 'sqlsrv_has_rows', 'sqlsrv_next_result', 'sqlsrv_num_fields', 'sqlsrv_num_rows', 'sqlsrv_prepare', 'sqlsrv_query', 'sqlsrv_rollback', 'sqlsrv_rows_affected', 'sqlsrv_send_stream_data', 'sqlsrv_server_info', 'ssh2_auth_agent', 'ssh2_auth_hostbased_file', 'ssh2_auth_none', 'ssh2_auth_password', 'ssh2_auth_pubkey_file', 'ssh2_disconnect', 'ssh2_exec', 'ssh2_fetch_stream', 'ssh2_fingerprint', 'ssh2_methods_negotiated', 'ssh2_publickey_add', 'ssh2_publickey_init', 'ssh2_publickey_list', 'ssh2_publickey_remove', 'ssh2_scp_recv', 'ssh2_scp_send', 'ssh2_sftp', 'ssh2_sftp_chmod', 'ssh2_sftp_lstat', 'ssh2_sftp_mkdir', 'ssh2_sftp_readlink', 'ssh2_sftp_realpath', 'ssh2_sftp_rename', 'ssh2_sftp_rmdir', 'ssh2_sftp_stat', 'ssh2_sftp_symlink', 'ssh2_sftp_unlink', 'ssh2_shell', 'ssh2_tunnel', 'stomp_connect', 'streamWrapper::stream_cast', 'stream_bucket_append', 'stream_bucket_make_writeable', 'stream_bucket_new', 'stream_bucket_prepend', 'stream_context_create', 'stream_context_get_default', 'stream_context_get_options', 'stream_context_get_params', 'stream_context_set_default', 'stream_context_set_params', 'stream_copy_to_stream', 'stream_encoding', 'stream_filter_append', 'stream_filter_prepend', 'stream_filter_remove', 'stream_get_contents', 'stream_get_line', 'stream_get_meta_data', 'stream_isatty', 'stream_set_blocking', 'stream_set_chunk_size', 'stream_set_read_buffer', 'stream_set_timeout', 'stream_set_write_buffer', 'stream_socket_accept', 'stream_socket_client', 'stream_socket_enable_crypto', 'stream_socket_get_name', 'stream_socket_recvfrom', 'stream_socket_sendto', 'stream_socket_server', 'stream_socket_shutdown', 'stream_supports_lock', 'svn_fs_abort_txn', 'svn_fs_apply_text', 'svn_fs_begin_txn2', 'svn_fs_change_node_prop', 'svn_fs_check_path', 'svn_fs_contents_changed', 'svn_fs_copy', 'svn_fs_delete', 'svn_fs_dir_entries', 'svn_fs_file_contents', 'svn_fs_file_length', 'svn_fs_is_dir', 'svn_fs_is_file', 'svn_fs_make_dir', 'svn_fs_make_file', 'svn_fs_node_created_rev', 'svn_fs_node_prop', 'svn_fs_props_changed', 'svn_fs_revision_prop', 'svn_fs_revision_root', 'svn_fs_txn_root', 'svn_fs_youngest_rev', 'svn_repos_create', 'svn_repos_fs', 'svn_repos_fs_begin_txn_for_commit', 'svn_repos_fs_commit_txn', 'svn_repos_open', 'sybase_affected_rows', 'sybase_close', 'sybase_connect', 'sybase_data_seek', 'sybase_fetch_array', 'sybase_fetch_assoc', 'sybase_fetch_field', 'sybase_fetch_object', 'sybase_fetch_row', 'sybase_field_seek', 'sybase_free_result', 'sybase_num_fields', 'sybase_num_rows', 'sybase_pconnect', 'sybase_query', 'sybase_result', 'sybase_select_db', 'sybase_set_message_handler', 'sybase_unbuffered_query', 'tmpfile', 'udm_add_search_limit', 'udm_alloc_agent', 'udm_alloc_agent_array', 'udm_cat_list', 'udm_cat_path', 'udm_check_charset', 'udm_clear_search_limits', 'udm_crc32', 'udm_errno', 'udm_error', 'udm_find', 'udm_free_agent', 'udm_free_res', 'udm_get_doc_count', 'udm_get_res_field', 'udm_get_res_param', 'udm_hash32', 'udm_load_ispell_data', 'udm_set_agent_param', 'unlink', 'vfprintf', 'w32api_init_dtype', 'wddx_add_vars', 'wddx_packet_end', 'wddx_packet_start', 'xml_get_current_byte_index', 'xml_get_current_column_number', 'xml_get_current_line_number', 'xml_get_error_code', 'xml_parse', 'xml_parse_into_struct', 'xml_parser_create', 'xml_parser_create_ns', 'xml_parser_free', 'xml_parser_get_option', 'xml_parser_set_option', 'xml_set_character_data_handler', 'xml_set_default_handler', 'xml_set_element_handler', 'xml_set_end_namespace_decl_handler', 'xml_set_external_entity_ref_handler', 'xml_set_notation_decl_handler', 'xml_set_object', 'xml_set_processing_instruction_handler', 'xml_set_start_namespace_decl_handler', 'xml_set_unparsed_entity_decl_handler', 'xmlrpc_server_add_introspection_data', 'xmlrpc_server_call_method', 'xmlrpc_server_create', 'xmlrpc_server_destroy', 'xmlrpc_server_register_introspection_callback', 'xmlrpc_server_register_method', 'xmlwriter_end_attribute', 'xmlwriter_end_cdata', 'xmlwriter_end_comment', 'xmlwriter_end_document', 'xmlwriter_end_dtd', 'xmlwriter_end_dtd_attlist', 'xmlwriter_end_dtd_element', 'xmlwriter_end_dtd_entity', 'xmlwriter_end_element', 'xmlwriter_end_pi', 'xmlwriter_flush', 'xmlwriter_full_end_element', 'xmlwriter_open_memory', 'xmlwriter_open_uri', 'xmlwriter_output_memory', 'xmlwriter_set_indent', 'xmlwriter_set_indent_string', 'xmlwriter_start_attribute', 'xmlwriter_start_attribute_ns', 'xmlwriter_start_cdata', 'xmlwriter_start_comment', 'xmlwriter_start_document', 'xmlwriter_start_dtd', 'xmlwriter_start_dtd_attlist', 'xmlwriter_start_dtd_element', 'xmlwriter_start_dtd_entity', 'xmlwriter_start_element', 'xmlwriter_start_element_ns', 'xmlwriter_start_pi', 'xmlwriter_text', 'xmlwriter_write_attribute', 'xmlwriter_write_attribute_ns', 'xmlwriter_write_cdata', 'xmlwriter_write_comment', 'xmlwriter_write_dtd', 'xmlwriter_write_dtd_attlist', 'xmlwriter_write_dtd_element', 'xmlwriter_write_dtd_entity', 'xmlwriter_write_element', 'xmlwriter_write_element_ns', 'xmlwriter_write_pi', 'xmlwriter_write_raw', 'xslt_create', 'yaz_addinfo', 'yaz_ccl_conf', 'yaz_ccl_parse', 'yaz_close', 'yaz_database', 'yaz_element', 'yaz_errno', 'yaz_error', 'yaz_es', 'yaz_es_result', 'yaz_get_option', 'yaz_hits', 'yaz_itemorder', 'yaz_present', 'yaz_range', 'yaz_record', 'yaz_scan', 'yaz_scan_result', 'yaz_schema', 'yaz_search', 'yaz_sort', 'yaz_syntax', 'zip_close', 'zip_entry_close', 'zip_entry_compressedsize', 'zip_entry_compressionmethod', 'zip_entry_filesize', 'zip_entry_name', 'zip_entry_open', 'zip_entry_read', 'zip_open', 'zip_read'];
  19528. }
  19529. }
  19530. Resource Operations
  19531. Copyright (c) 2015-2020, Sebastian Bergmann <sebastian@phpunit.de>.
  19532. All rights reserved.
  19533. Redistribution and use in source and binary forms, with or without
  19534. modification, are permitted provided that the following conditions
  19535. are met:
  19536. * Redistributions of source code must retain the above copyright
  19537. notice, this list of conditions and the following disclaimer.
  19538. * Redistributions in binary form must reproduce the above copyright
  19539. notice, this list of conditions and the following disclaimer in
  19540. the documentation and/or other materials provided with the
  19541. distribution.
  19542. * Neither the name of Sebastian Bergmann nor the names of his
  19543. contributors may be used to endorse or promote products derived
  19544. from this software without specific prior written permission.
  19545. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  19546. "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  19547. LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  19548. FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  19549. COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  19550. INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  19551. BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  19552. LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  19553. CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  19554. LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
  19555. ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  19556. POSSIBILITY OF SUCH DAMAGE.
  19557. <?php
  19558. declare (strict_types=1);
  19559. /*
  19560. * This file is part of sebastian/code-unit.
  19561. *
  19562. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  19563. *
  19564. * For the full copyright and license information, please view the LICENSE
  19565. * file that was distributed with this source code.
  19566. */
  19567. namespace PHPUnit\SebastianBergmann\CodeUnit;
  19568. /**
  19569. * @psalm-immutable
  19570. */
  19571. final class FunctionUnit extends \PHPUnit\SebastianBergmann\CodeUnit\CodeUnit
  19572. {
  19573. /**
  19574. * @psalm-assert-if-true FunctionUnit $this
  19575. */
  19576. public function isFunction() : bool
  19577. {
  19578. return \true;
  19579. }
  19580. }
  19581. <?php
  19582. declare (strict_types=1);
  19583. /*
  19584. * This file is part of sebastian/code-unit.
  19585. *
  19586. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  19587. *
  19588. * For the full copyright and license information, please view the LICENSE
  19589. * file that was distributed with this source code.
  19590. */
  19591. namespace PHPUnit\SebastianBergmann\CodeUnit;
  19592. final class CodeUnitCollectionIterator implements \Iterator
  19593. {
  19594. /**
  19595. * @var CodeUnit[]
  19596. */
  19597. private $codeUnits;
  19598. /**
  19599. * @var int
  19600. */
  19601. private $position = 0;
  19602. public function __construct(\PHPUnit\SebastianBergmann\CodeUnit\CodeUnitCollection $collection)
  19603. {
  19604. $this->codeUnits = $collection->asArray();
  19605. }
  19606. public function rewind() : void
  19607. {
  19608. $this->position = 0;
  19609. }
  19610. public function valid() : bool
  19611. {
  19612. return $this->position < \count($this->codeUnits);
  19613. }
  19614. public function key() : int
  19615. {
  19616. return $this->position;
  19617. }
  19618. public function current() : \PHPUnit\SebastianBergmann\CodeUnit\CodeUnit
  19619. {
  19620. return $this->codeUnits[$this->position];
  19621. }
  19622. public function next() : void
  19623. {
  19624. $this->position++;
  19625. }
  19626. }
  19627. <?php
  19628. declare (strict_types=1);
  19629. /*
  19630. * This file is part of sebastian/code-unit.
  19631. *
  19632. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  19633. *
  19634. * For the full copyright and license information, please view the LICENSE
  19635. * file that was distributed with this source code.
  19636. */
  19637. namespace PHPUnit\SebastianBergmann\CodeUnit;
  19638. final class Mapper
  19639. {
  19640. /**
  19641. * @psalm-return array<string,list<int>>
  19642. */
  19643. public function codeUnitsToSourceLines(\PHPUnit\SebastianBergmann\CodeUnit\CodeUnitCollection $codeUnits) : array
  19644. {
  19645. $result = [];
  19646. foreach ($codeUnits as $codeUnit) {
  19647. $sourceFileName = $codeUnit->sourceFileName();
  19648. if (!isset($result[$sourceFileName])) {
  19649. $result[$sourceFileName] = [];
  19650. }
  19651. $result[$sourceFileName] = \array_merge($result[$sourceFileName], $codeUnit->sourceLines());
  19652. }
  19653. foreach (\array_keys($result) as $sourceFileName) {
  19654. $result[$sourceFileName] = \array_values(\array_unique($result[$sourceFileName]));
  19655. \sort($result[$sourceFileName]);
  19656. }
  19657. \ksort($result);
  19658. return $result;
  19659. }
  19660. /**
  19661. * @throws InvalidCodeUnitException
  19662. * @throws ReflectionException
  19663. */
  19664. public function stringToCodeUnits(string $unit) : \PHPUnit\SebastianBergmann\CodeUnit\CodeUnitCollection
  19665. {
  19666. if (\strpos($unit, '::') !== \false) {
  19667. [$firstPart, $secondPart] = \explode('::', $unit);
  19668. if (empty($firstPart) && \function_exists($secondPart)) {
  19669. return \PHPUnit\SebastianBergmann\CodeUnit\CodeUnitCollection::fromList(\PHPUnit\SebastianBergmann\CodeUnit\CodeUnit::forFunction($secondPart));
  19670. }
  19671. if (\class_exists($firstPart)) {
  19672. if ($secondPart === '<public>') {
  19673. return $this->publicMethodsOfClass($firstPart);
  19674. }
  19675. if ($secondPart === '<!public>') {
  19676. return $this->protectedAndPrivateMethodsOfClass($firstPart);
  19677. }
  19678. if ($secondPart === '<protected>') {
  19679. return $this->protectedMethodsOfClass($firstPart);
  19680. }
  19681. if ($secondPart === '<!protected>') {
  19682. return $this->publicAndPrivateMethodsOfClass($firstPart);
  19683. }
  19684. if ($secondPart === '<private>') {
  19685. return $this->privateMethodsOfClass($firstPart);
  19686. }
  19687. if ($secondPart === '<!private>') {
  19688. return $this->publicAndProtectedMethodsOfClass($firstPart);
  19689. }
  19690. if (\method_exists($firstPart, $secondPart)) {
  19691. return \PHPUnit\SebastianBergmann\CodeUnit\CodeUnitCollection::fromList(\PHPUnit\SebastianBergmann\CodeUnit\CodeUnit::forClassMethod($firstPart, $secondPart));
  19692. }
  19693. }
  19694. if (\interface_exists($firstPart)) {
  19695. return \PHPUnit\SebastianBergmann\CodeUnit\CodeUnitCollection::fromList(\PHPUnit\SebastianBergmann\CodeUnit\CodeUnit::forInterfaceMethod($firstPart, $secondPart));
  19696. }
  19697. if (\trait_exists($firstPart)) {
  19698. return \PHPUnit\SebastianBergmann\CodeUnit\CodeUnitCollection::fromList(\PHPUnit\SebastianBergmann\CodeUnit\CodeUnit::forTraitMethod($firstPart, $secondPart));
  19699. }
  19700. } else {
  19701. if (\class_exists($unit)) {
  19702. $units = [\PHPUnit\SebastianBergmann\CodeUnit\CodeUnit::forClass($unit)];
  19703. foreach ($this->reflectorForClass($unit)->getTraits() as $trait) {
  19704. $units[] = \PHPUnit\SebastianBergmann\CodeUnit\CodeUnit::forTrait($trait->getName());
  19705. }
  19706. return \PHPUnit\SebastianBergmann\CodeUnit\CodeUnitCollection::fromArray($units);
  19707. }
  19708. if (\interface_exists($unit)) {
  19709. return \PHPUnit\SebastianBergmann\CodeUnit\CodeUnitCollection::fromList(\PHPUnit\SebastianBergmann\CodeUnit\CodeUnit::forInterface($unit));
  19710. }
  19711. if (\trait_exists($unit)) {
  19712. return \PHPUnit\SebastianBergmann\CodeUnit\CodeUnitCollection::fromList(\PHPUnit\SebastianBergmann\CodeUnit\CodeUnit::forTrait($unit));
  19713. }
  19714. if (\function_exists($unit)) {
  19715. return \PHPUnit\SebastianBergmann\CodeUnit\CodeUnitCollection::fromList(\PHPUnit\SebastianBergmann\CodeUnit\CodeUnit::forFunction($unit));
  19716. }
  19717. if (\strpos($unit, '<extended>') !== \false) {
  19718. $unit = \str_replace('<extended>', '', $unit);
  19719. if (\class_exists($unit)) {
  19720. return $this->classAndParentClassesAndTraits($unit);
  19721. }
  19722. }
  19723. }
  19724. throw new \PHPUnit\SebastianBergmann\CodeUnit\InvalidCodeUnitException(\sprintf('"%s" is not a valid code unit', $unit));
  19725. }
  19726. /**
  19727. * @psalm-param class-string $className
  19728. *
  19729. * @throws ReflectionException
  19730. */
  19731. private function publicMethodsOfClass(string $className) : \PHPUnit\SebastianBergmann\CodeUnit\CodeUnitCollection
  19732. {
  19733. return $this->methodsOfClass($className, \ReflectionMethod::IS_PUBLIC);
  19734. }
  19735. /**
  19736. * @psalm-param class-string $className
  19737. *
  19738. * @throws ReflectionException
  19739. */
  19740. private function publicAndProtectedMethodsOfClass(string $className) : \PHPUnit\SebastianBergmann\CodeUnit\CodeUnitCollection
  19741. {
  19742. return $this->methodsOfClass($className, \ReflectionMethod::IS_PUBLIC | \ReflectionMethod::IS_PROTECTED);
  19743. }
  19744. /**
  19745. * @psalm-param class-string $className
  19746. *
  19747. * @throws ReflectionException
  19748. */
  19749. private function publicAndPrivateMethodsOfClass(string $className) : \PHPUnit\SebastianBergmann\CodeUnit\CodeUnitCollection
  19750. {
  19751. return $this->methodsOfClass($className, \ReflectionMethod::IS_PUBLIC | \ReflectionMethod::IS_PRIVATE);
  19752. }
  19753. /**
  19754. * @psalm-param class-string $className
  19755. *
  19756. * @throws ReflectionException
  19757. */
  19758. private function protectedMethodsOfClass(string $className) : \PHPUnit\SebastianBergmann\CodeUnit\CodeUnitCollection
  19759. {
  19760. return $this->methodsOfClass($className, \ReflectionMethod::IS_PROTECTED);
  19761. }
  19762. /**
  19763. * @psalm-param class-string $className
  19764. *
  19765. * @throws ReflectionException
  19766. */
  19767. private function protectedAndPrivateMethodsOfClass(string $className) : \PHPUnit\SebastianBergmann\CodeUnit\CodeUnitCollection
  19768. {
  19769. return $this->methodsOfClass($className, \ReflectionMethod::IS_PROTECTED | \ReflectionMethod::IS_PRIVATE);
  19770. }
  19771. /**
  19772. * @psalm-param class-string $className
  19773. *
  19774. * @throws ReflectionException
  19775. */
  19776. private function privateMethodsOfClass(string $className) : \PHPUnit\SebastianBergmann\CodeUnit\CodeUnitCollection
  19777. {
  19778. return $this->methodsOfClass($className, \ReflectionMethod::IS_PRIVATE);
  19779. }
  19780. /**
  19781. * @psalm-param class-string $className
  19782. *
  19783. * @throws ReflectionException
  19784. */
  19785. private function methodsOfClass(string $className, int $filter) : \PHPUnit\SebastianBergmann\CodeUnit\CodeUnitCollection
  19786. {
  19787. $units = [];
  19788. foreach ($this->reflectorForClass($className)->getMethods($filter) as $method) {
  19789. $units[] = \PHPUnit\SebastianBergmann\CodeUnit\CodeUnit::forClassMethod($className, $method->getName());
  19790. }
  19791. return \PHPUnit\SebastianBergmann\CodeUnit\CodeUnitCollection::fromArray($units);
  19792. }
  19793. /**
  19794. * @psalm-param class-string $className
  19795. *
  19796. * @throws ReflectionException
  19797. */
  19798. private function classAndParentClassesAndTraits(string $className) : \PHPUnit\SebastianBergmann\CodeUnit\CodeUnitCollection
  19799. {
  19800. $units = [\PHPUnit\SebastianBergmann\CodeUnit\CodeUnit::forClass($className)];
  19801. $reflector = $this->reflectorForClass($className);
  19802. foreach ($this->reflectorForClass($className)->getTraits() as $trait) {
  19803. if ($trait->isInternal()) {
  19804. continue;
  19805. }
  19806. $units[] = \PHPUnit\SebastianBergmann\CodeUnit\CodeUnit::forTrait($trait->getName());
  19807. }
  19808. while ($reflector = $reflector->getParentClass()) {
  19809. if ($reflector->isInternal()) {
  19810. continue;
  19811. }
  19812. $units[] = \PHPUnit\SebastianBergmann\CodeUnit\CodeUnit::forClass($reflector->getName());
  19813. foreach ($reflector->getTraits() as $trait) {
  19814. if ($trait->isInternal()) {
  19815. continue;
  19816. }
  19817. $units[] = \PHPUnit\SebastianBergmann\CodeUnit\CodeUnit::forTrait($trait->getName());
  19818. }
  19819. }
  19820. return \PHPUnit\SebastianBergmann\CodeUnit\CodeUnitCollection::fromArray($units);
  19821. }
  19822. /**
  19823. * @psalm-param class-string $className
  19824. *
  19825. * @throws ReflectionException
  19826. */
  19827. private function reflectorForClass(string $className) : \ReflectionClass
  19828. {
  19829. try {
  19830. return new \ReflectionClass($className);
  19831. // @codeCoverageIgnoreStart
  19832. } catch (\ReflectionException $e) {
  19833. throw new \PHPUnit\SebastianBergmann\CodeUnit\ReflectionException($e->getMessage(), (int) $e->getCode(), $e);
  19834. }
  19835. // @codeCoverageIgnoreEnd
  19836. }
  19837. }
  19838. <?php
  19839. declare (strict_types=1);
  19840. /*
  19841. * This file is part of sebastian/code-unit.
  19842. *
  19843. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  19844. *
  19845. * For the full copyright and license information, please view the LICENSE
  19846. * file that was distributed with this source code.
  19847. */
  19848. namespace PHPUnit\SebastianBergmann\CodeUnit;
  19849. /**
  19850. * @psalm-immutable
  19851. */
  19852. final class InterfaceUnit extends \PHPUnit\SebastianBergmann\CodeUnit\CodeUnit
  19853. {
  19854. /**
  19855. * @psalm-assert-if-true InterfaceUnit $this
  19856. */
  19857. public function isInterface() : bool
  19858. {
  19859. return \true;
  19860. }
  19861. }
  19862. <?php
  19863. declare (strict_types=1);
  19864. /*
  19865. * This file is part of sebastian/code-unit.
  19866. *
  19867. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  19868. *
  19869. * For the full copyright and license information, please view the LICENSE
  19870. * file that was distributed with this source code.
  19871. */
  19872. namespace PHPUnit\SebastianBergmann\CodeUnit;
  19873. /**
  19874. * @psalm-immutable
  19875. */
  19876. abstract class CodeUnit
  19877. {
  19878. /**
  19879. * @var string
  19880. */
  19881. private $name;
  19882. /**
  19883. * @var string
  19884. */
  19885. private $sourceFileName;
  19886. /**
  19887. * @var array
  19888. * @psalm-var list<int>
  19889. */
  19890. private $sourceLines;
  19891. /**
  19892. * @psalm-param class-string $className
  19893. *
  19894. * @throws InvalidCodeUnitException
  19895. * @throws ReflectionException
  19896. */
  19897. public static function forClass(string $className) : \PHPUnit\SebastianBergmann\CodeUnit\ClassUnit
  19898. {
  19899. self::ensureUserDefinedClass($className);
  19900. $reflector = self::reflectorForClass($className);
  19901. return new \PHPUnit\SebastianBergmann\CodeUnit\ClassUnit($className, $reflector->getFileName(), \range((int) $reflector->getStartLine(), (int) $reflector->getEndLine()));
  19902. }
  19903. /**
  19904. * @psalm-param class-string $className
  19905. *
  19906. * @throws InvalidCodeUnitException
  19907. * @throws ReflectionException
  19908. */
  19909. public static function forClassMethod(string $className, string $methodName) : \PHPUnit\SebastianBergmann\CodeUnit\ClassMethodUnit
  19910. {
  19911. self::ensureUserDefinedClass($className);
  19912. $reflector = self::reflectorForClassMethod($className, $methodName);
  19913. return new \PHPUnit\SebastianBergmann\CodeUnit\ClassMethodUnit($className . '::' . $methodName, $reflector->getFileName(), \range((int) $reflector->getStartLine(), (int) $reflector->getEndLine()));
  19914. }
  19915. /**
  19916. * @psalm-param class-string $interfaceName
  19917. *
  19918. * @throws InvalidCodeUnitException
  19919. * @throws ReflectionException
  19920. */
  19921. public static function forInterface(string $interfaceName) : \PHPUnit\SebastianBergmann\CodeUnit\InterfaceUnit
  19922. {
  19923. self::ensureUserDefinedInterface($interfaceName);
  19924. $reflector = self::reflectorForClass($interfaceName);
  19925. return new \PHPUnit\SebastianBergmann\CodeUnit\InterfaceUnit($interfaceName, $reflector->getFileName(), \range((int) $reflector->getStartLine(), (int) $reflector->getEndLine()));
  19926. }
  19927. /**
  19928. * @psalm-param class-string $interfaceName
  19929. *
  19930. * @throws InvalidCodeUnitException
  19931. * @throws ReflectionException
  19932. */
  19933. public static function forInterfaceMethod(string $interfaceName, string $methodName) : \PHPUnit\SebastianBergmann\CodeUnit\InterfaceMethodUnit
  19934. {
  19935. self::ensureUserDefinedInterface($interfaceName);
  19936. $reflector = self::reflectorForClassMethod($interfaceName, $methodName);
  19937. return new \PHPUnit\SebastianBergmann\CodeUnit\InterfaceMethodUnit($interfaceName . '::' . $methodName, $reflector->getFileName(), \range((int) $reflector->getStartLine(), (int) $reflector->getEndLine()));
  19938. }
  19939. /**
  19940. * @psalm-param class-string $traitName
  19941. *
  19942. * @throws InvalidCodeUnitException
  19943. * @throws ReflectionException
  19944. */
  19945. public static function forTrait(string $traitName) : \PHPUnit\SebastianBergmann\CodeUnit\TraitUnit
  19946. {
  19947. self::ensureUserDefinedTrait($traitName);
  19948. $reflector = self::reflectorForClass($traitName);
  19949. return new \PHPUnit\SebastianBergmann\CodeUnit\TraitUnit($traitName, $reflector->getFileName(), \range((int) $reflector->getStartLine(), (int) $reflector->getEndLine()));
  19950. }
  19951. /**
  19952. * @psalm-param class-string $traitName
  19953. *
  19954. * @throws InvalidCodeUnitException
  19955. * @throws ReflectionException
  19956. */
  19957. public static function forTraitMethod(string $traitName, string $methodName) : \PHPUnit\SebastianBergmann\CodeUnit\TraitMethodUnit
  19958. {
  19959. self::ensureUserDefinedTrait($traitName);
  19960. $reflector = self::reflectorForClassMethod($traitName, $methodName);
  19961. return new \PHPUnit\SebastianBergmann\CodeUnit\TraitMethodUnit($traitName . '::' . $methodName, $reflector->getFileName(), \range((int) $reflector->getStartLine(), (int) $reflector->getEndLine()));
  19962. }
  19963. /**
  19964. * @psalm-param callable-string $functionName
  19965. *
  19966. * @throws InvalidCodeUnitException
  19967. * @throws ReflectionException
  19968. */
  19969. public static function forFunction(string $functionName) : \PHPUnit\SebastianBergmann\CodeUnit\FunctionUnit
  19970. {
  19971. $reflector = self::reflectorForFunction($functionName);
  19972. if (!$reflector->isUserDefined()) {
  19973. throw new \PHPUnit\SebastianBergmann\CodeUnit\InvalidCodeUnitException(\sprintf('"%s" is not a user-defined function', $functionName));
  19974. }
  19975. return new \PHPUnit\SebastianBergmann\CodeUnit\FunctionUnit($functionName, $reflector->getFileName(), \range((int) $reflector->getStartLine(), (int) $reflector->getEndLine()));
  19976. }
  19977. /**
  19978. * @psalm-param list<int> $sourceLines
  19979. */
  19980. private function __construct(string $name, string $sourceFileName, array $sourceLines)
  19981. {
  19982. $this->name = $name;
  19983. $this->sourceFileName = $sourceFileName;
  19984. $this->sourceLines = $sourceLines;
  19985. }
  19986. public function name() : string
  19987. {
  19988. return $this->name;
  19989. }
  19990. public function sourceFileName() : string
  19991. {
  19992. return $this->sourceFileName;
  19993. }
  19994. /**
  19995. * @psalm-return list<int>
  19996. */
  19997. public function sourceLines() : array
  19998. {
  19999. return $this->sourceLines;
  20000. }
  20001. public function isClass() : bool
  20002. {
  20003. return \false;
  20004. }
  20005. public function isClassMethod() : bool
  20006. {
  20007. return \false;
  20008. }
  20009. public function isInterface() : bool
  20010. {
  20011. return \false;
  20012. }
  20013. public function isInterfaceMethod() : bool
  20014. {
  20015. return \false;
  20016. }
  20017. public function isTrait() : bool
  20018. {
  20019. return \false;
  20020. }
  20021. public function isTraitMethod() : bool
  20022. {
  20023. return \false;
  20024. }
  20025. public function isFunction() : bool
  20026. {
  20027. return \false;
  20028. }
  20029. /**
  20030. * @psalm-param class-string $className
  20031. *
  20032. * @throws InvalidCodeUnitException
  20033. */
  20034. private static function ensureUserDefinedClass(string $className) : void
  20035. {
  20036. try {
  20037. $reflector = new \ReflectionClass($className);
  20038. if ($reflector->isInterface()) {
  20039. throw new \PHPUnit\SebastianBergmann\CodeUnit\InvalidCodeUnitException(\sprintf('"%s" is an interface and not a class', $className));
  20040. }
  20041. if ($reflector->isTrait()) {
  20042. throw new \PHPUnit\SebastianBergmann\CodeUnit\InvalidCodeUnitException(\sprintf('"%s" is a trait and not a class', $className));
  20043. }
  20044. if (!$reflector->isUserDefined()) {
  20045. throw new \PHPUnit\SebastianBergmann\CodeUnit\InvalidCodeUnitException(\sprintf('"%s" is not a user-defined class', $className));
  20046. }
  20047. // @codeCoverageIgnoreStart
  20048. } catch (\ReflectionException $e) {
  20049. throw new \PHPUnit\SebastianBergmann\CodeUnit\ReflectionException($e->getMessage(), (int) $e->getCode(), $e);
  20050. }
  20051. // @codeCoverageIgnoreEnd
  20052. }
  20053. /**
  20054. * @psalm-param class-string $interfaceName
  20055. *
  20056. * @throws InvalidCodeUnitException
  20057. */
  20058. private static function ensureUserDefinedInterface(string $interfaceName) : void
  20059. {
  20060. try {
  20061. $reflector = new \ReflectionClass($interfaceName);
  20062. if (!$reflector->isInterface()) {
  20063. throw new \PHPUnit\SebastianBergmann\CodeUnit\InvalidCodeUnitException(\sprintf('"%s" is not an interface', $interfaceName));
  20064. }
  20065. if (!$reflector->isUserDefined()) {
  20066. throw new \PHPUnit\SebastianBergmann\CodeUnit\InvalidCodeUnitException(\sprintf('"%s" is not a user-defined interface', $interfaceName));
  20067. }
  20068. // @codeCoverageIgnoreStart
  20069. } catch (\ReflectionException $e) {
  20070. throw new \PHPUnit\SebastianBergmann\CodeUnit\ReflectionException($e->getMessage(), (int) $e->getCode(), $e);
  20071. }
  20072. // @codeCoverageIgnoreEnd
  20073. }
  20074. /**
  20075. * @psalm-param class-string $traitName
  20076. *
  20077. * @throws InvalidCodeUnitException
  20078. */
  20079. private static function ensureUserDefinedTrait(string $traitName) : void
  20080. {
  20081. try {
  20082. $reflector = new \ReflectionClass($traitName);
  20083. if (!$reflector->isTrait()) {
  20084. throw new \PHPUnit\SebastianBergmann\CodeUnit\InvalidCodeUnitException(\sprintf('"%s" is not a trait', $traitName));
  20085. }
  20086. // @codeCoverageIgnoreStart
  20087. if (!$reflector->isUserDefined()) {
  20088. throw new \PHPUnit\SebastianBergmann\CodeUnit\InvalidCodeUnitException(\sprintf('"%s" is not a user-defined trait', $traitName));
  20089. }
  20090. } catch (\ReflectionException $e) {
  20091. throw new \PHPUnit\SebastianBergmann\CodeUnit\ReflectionException($e->getMessage(), (int) $e->getCode(), $e);
  20092. }
  20093. // @codeCoverageIgnoreEnd
  20094. }
  20095. /**
  20096. * @psalm-param class-string $className
  20097. *
  20098. * @throws ReflectionException
  20099. */
  20100. private static function reflectorForClass(string $className) : \ReflectionClass
  20101. {
  20102. try {
  20103. return new \ReflectionClass($className);
  20104. // @codeCoverageIgnoreStart
  20105. } catch (\ReflectionException $e) {
  20106. throw new \PHPUnit\SebastianBergmann\CodeUnit\ReflectionException($e->getMessage(), (int) $e->getCode(), $e);
  20107. }
  20108. // @codeCoverageIgnoreEnd
  20109. }
  20110. /**
  20111. * @psalm-param class-string $className
  20112. *
  20113. * @throws ReflectionException
  20114. */
  20115. private static function reflectorForClassMethod(string $className, string $methodName) : \ReflectionMethod
  20116. {
  20117. try {
  20118. return new \ReflectionMethod($className, $methodName);
  20119. // @codeCoverageIgnoreStart
  20120. } catch (\ReflectionException $e) {
  20121. throw new \PHPUnit\SebastianBergmann\CodeUnit\ReflectionException($e->getMessage(), (int) $e->getCode(), $e);
  20122. }
  20123. // @codeCoverageIgnoreEnd
  20124. }
  20125. /**
  20126. * @psalm-param callable-string $functionName
  20127. *
  20128. * @throws ReflectionException
  20129. */
  20130. private static function reflectorForFunction(string $functionName) : \ReflectionFunction
  20131. {
  20132. try {
  20133. return new \ReflectionFunction($functionName);
  20134. // @codeCoverageIgnoreStart
  20135. } catch (\ReflectionException $e) {
  20136. throw new \PHPUnit\SebastianBergmann\CodeUnit\ReflectionException($e->getMessage(), (int) $e->getCode(), $e);
  20137. }
  20138. // @codeCoverageIgnoreEnd
  20139. }
  20140. }
  20141. <?php
  20142. declare (strict_types=1);
  20143. /*
  20144. * This file is part of sebastian/code-unit.
  20145. *
  20146. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  20147. *
  20148. * For the full copyright and license information, please view the LICENSE
  20149. * file that was distributed with this source code.
  20150. */
  20151. namespace PHPUnit\SebastianBergmann\CodeUnit;
  20152. /**
  20153. * @psalm-immutable
  20154. */
  20155. final class TraitUnit extends \PHPUnit\SebastianBergmann\CodeUnit\CodeUnit
  20156. {
  20157. /**
  20158. * @psalm-assert-if-true TraitUnit $this
  20159. */
  20160. public function isTrait() : bool
  20161. {
  20162. return \true;
  20163. }
  20164. }
  20165. <?php
  20166. declare (strict_types=1);
  20167. /*
  20168. * This file is part of sebastian/code-unit.
  20169. *
  20170. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  20171. *
  20172. * For the full copyright and license information, please view the LICENSE
  20173. * file that was distributed with this source code.
  20174. */
  20175. namespace PHPUnit\SebastianBergmann\CodeUnit;
  20176. /**
  20177. * @psalm-immutable
  20178. */
  20179. final class InterfaceMethodUnit extends \PHPUnit\SebastianBergmann\CodeUnit\CodeUnit
  20180. {
  20181. /**
  20182. * @psalm-assert-if-true InterfaceMethod $this
  20183. */
  20184. public function isInterfaceMethod() : bool
  20185. {
  20186. return \true;
  20187. }
  20188. }
  20189. <?php
  20190. declare (strict_types=1);
  20191. /*
  20192. * This file is part of sebastian/code-unit.
  20193. *
  20194. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  20195. *
  20196. * For the full copyright and license information, please view the LICENSE
  20197. * file that was distributed with this source code.
  20198. */
  20199. namespace PHPUnit\SebastianBergmann\CodeUnit;
  20200. /**
  20201. * @psalm-immutable
  20202. */
  20203. final class ClassMethodUnit extends \PHPUnit\SebastianBergmann\CodeUnit\CodeUnit
  20204. {
  20205. /**
  20206. * @psalm-assert-if-true ClassMethodUnit $this
  20207. */
  20208. public function isClassMethod() : bool
  20209. {
  20210. return \true;
  20211. }
  20212. }
  20213. <?php
  20214. declare (strict_types=1);
  20215. /*
  20216. * This file is part of sebastian/code-unit.
  20217. *
  20218. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  20219. *
  20220. * For the full copyright and license information, please view the LICENSE
  20221. * file that was distributed with this source code.
  20222. */
  20223. namespace PHPUnit\SebastianBergmann\CodeUnit;
  20224. use RuntimeException;
  20225. final class NoTraitException extends \RuntimeException implements \PHPUnit\SebastianBergmann\CodeUnit\Exception
  20226. {
  20227. }
  20228. <?php
  20229. declare (strict_types=1);
  20230. /*
  20231. * This file is part of sebastian/code-unit.
  20232. *
  20233. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  20234. *
  20235. * For the full copyright and license information, please view the LICENSE
  20236. * file that was distributed with this source code.
  20237. */
  20238. namespace PHPUnit\SebastianBergmann\CodeUnit;
  20239. use RuntimeException;
  20240. final class ReflectionException extends \RuntimeException implements \PHPUnit\SebastianBergmann\CodeUnit\Exception
  20241. {
  20242. }
  20243. <?php
  20244. declare (strict_types=1);
  20245. /*
  20246. * This file is part of sebastian/code-unit.
  20247. *
  20248. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  20249. *
  20250. * For the full copyright and license information, please view the LICENSE
  20251. * file that was distributed with this source code.
  20252. */
  20253. namespace PHPUnit\SebastianBergmann\CodeUnit;
  20254. interface Exception
  20255. {
  20256. }
  20257. <?php
  20258. declare (strict_types=1);
  20259. /*
  20260. * This file is part of sebastian/code-unit.
  20261. *
  20262. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  20263. *
  20264. * For the full copyright and license information, please view the LICENSE
  20265. * file that was distributed with this source code.
  20266. */
  20267. namespace PHPUnit\SebastianBergmann\CodeUnit;
  20268. use RuntimeException;
  20269. final class InvalidCodeUnitException extends \RuntimeException implements \PHPUnit\SebastianBergmann\CodeUnit\Exception
  20270. {
  20271. }
  20272. <?php
  20273. declare (strict_types=1);
  20274. /*
  20275. * This file is part of sebastian/code-unit.
  20276. *
  20277. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  20278. *
  20279. * For the full copyright and license information, please view the LICENSE
  20280. * file that was distributed with this source code.
  20281. */
  20282. namespace PHPUnit\SebastianBergmann\CodeUnit;
  20283. /**
  20284. * @psalm-immutable
  20285. */
  20286. final class ClassUnit extends \PHPUnit\SebastianBergmann\CodeUnit\CodeUnit
  20287. {
  20288. /**
  20289. * @psalm-assert-if-true ClassUnit $this
  20290. */
  20291. public function isClass() : bool
  20292. {
  20293. return \true;
  20294. }
  20295. }
  20296. <?php
  20297. declare (strict_types=1);
  20298. /*
  20299. * This file is part of sebastian/code-unit.
  20300. *
  20301. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  20302. *
  20303. * For the full copyright and license information, please view the LICENSE
  20304. * file that was distributed with this source code.
  20305. */
  20306. namespace PHPUnit\SebastianBergmann\CodeUnit;
  20307. /**
  20308. * @psalm-immutable
  20309. */
  20310. final class TraitMethodUnit extends \PHPUnit\SebastianBergmann\CodeUnit\CodeUnit
  20311. {
  20312. /**
  20313. * @psalm-assert-if-true TraitMethodUnit $this
  20314. */
  20315. public function isTraitMethod() : bool
  20316. {
  20317. return \true;
  20318. }
  20319. }
  20320. sebastian/code-unit
  20321. Copyright (c) 2020, Sebastian Bergmann <sebastian@phpunit.de>.
  20322. All rights reserved.
  20323. Redistribution and use in source and binary forms, with or without
  20324. modification, are permitted provided that the following conditions
  20325. are met:
  20326. * Redistributions of source code must retain the above copyright
  20327. notice, this list of conditions and the following disclaimer.
  20328. * Redistributions in binary form must reproduce the above copyright
  20329. notice, this list of conditions and the following disclaimer in
  20330. the documentation and/or other materials provided with the
  20331. distribution.
  20332. * Neither the name of Sebastian Bergmann nor the names of his
  20333. contributors may be used to endorse or promote products derived
  20334. from this software without specific prior written permission.
  20335. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  20336. "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  20337. LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  20338. FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  20339. COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  20340. INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  20341. BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  20342. LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  20343. CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  20344. LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
  20345. ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  20346. POSSIBILITY OF SUCH DAMAGE.
  20347. <?php
  20348. declare (strict_types=1);
  20349. /*
  20350. * This file is part of sebastian/code-unit.
  20351. *
  20352. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  20353. *
  20354. * For the full copyright and license information, please view the LICENSE
  20355. * file that was distributed with this source code.
  20356. */
  20357. namespace PHPUnit\SebastianBergmann\CodeUnit;
  20358. final class CodeUnitCollection implements \Countable, \IteratorAggregate
  20359. {
  20360. /**
  20361. * @var CodeUnit[]
  20362. */
  20363. private $codeUnits = [];
  20364. /**
  20365. * @param CodeUnit[] $items
  20366. */
  20367. public static function fromArray(array $items) : self
  20368. {
  20369. $collection = new self();
  20370. foreach ($items as $item) {
  20371. $collection->add($item);
  20372. }
  20373. return $collection;
  20374. }
  20375. public static function fromList(\PHPUnit\SebastianBergmann\CodeUnit\CodeUnit ...$items) : self
  20376. {
  20377. return self::fromArray($items);
  20378. }
  20379. private function __construct()
  20380. {
  20381. }
  20382. /**
  20383. * @return CodeUnit[]
  20384. */
  20385. public function asArray() : array
  20386. {
  20387. return $this->codeUnits;
  20388. }
  20389. public function getIterator() : \PHPUnit\SebastianBergmann\CodeUnit\CodeUnitCollectionIterator
  20390. {
  20391. return new \PHPUnit\SebastianBergmann\CodeUnit\CodeUnitCollectionIterator($this);
  20392. }
  20393. public function count() : int
  20394. {
  20395. return \count($this->codeUnits);
  20396. }
  20397. public function isEmpty() : bool
  20398. {
  20399. return empty($this->codeUnits);
  20400. }
  20401. public function mergeWith(self $other) : self
  20402. {
  20403. return self::fromArray(\array_merge($this->asArray(), $other->asArray()));
  20404. }
  20405. private function add(\PHPUnit\SebastianBergmann\CodeUnit\CodeUnit $item) : void
  20406. {
  20407. $this->codeUnits[] = $item;
  20408. }
  20409. }
  20410. <?php
  20411. namespace PHPSTORM_META {
  20412. override(
  20413. \PHPUnit\Framework\TestCase::createMock(0),
  20414. map([
  20415. '@&\PHPUnit\Framework\MockObject\MockObject',
  20416. ])
  20417. );
  20418. override(
  20419. \PHPUnit\Framework\TestCase::createStub(0),
  20420. map([
  20421. '@&\PHPUnit\Framework\MockObject\Stub',
  20422. ])
  20423. );
  20424. override(
  20425. \PHPUnit\Framework\TestCase::createConfiguredMock(0),
  20426. map([
  20427. '@&\PHPUnit\Framework\MockObject\MockObject',
  20428. ])
  20429. );
  20430. override(
  20431. \PHPUnit\Framework\TestCase::createPartialMock(0),
  20432. map([
  20433. '@&\PHPUnit\Framework\MockObject\MockObject',
  20434. ])
  20435. );
  20436. override(
  20437. \PHPUnit\Framework\TestCase::createTestProxy(0),
  20438. map([
  20439. '@&\PHPUnit\Framework\MockObject\MockObject',
  20440. ])
  20441. );
  20442. override(
  20443. \PHPUnit\Framework\TestCase::getMockForAbstractClass(0),
  20444. map([
  20445. '@&\PHPUnit\Framework\MockObject\MockObject',
  20446. ])
  20447. );
  20448. }
  20449. <?php
  20450. declare (strict_types=1);
  20451. /*
  20452. * This file is part of phpunit/php-code-coverage.
  20453. *
  20454. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  20455. *
  20456. * For the full copyright and license information, please view the LICENSE
  20457. * file that was distributed with this source code.
  20458. */
  20459. namespace PHPUnit\SebastianBergmann\CodeCoverage;
  20460. /**
  20461. * Exception that is raised when covered code is not executed.
  20462. */
  20463. final class CoveredCodeNotExecutedException extends \PHPUnit\SebastianBergmann\CodeCoverage\RuntimeException
  20464. {
  20465. }
  20466. <?php
  20467. declare (strict_types=1);
  20468. /*
  20469. * This file is part of phpunit/php-code-coverage.
  20470. *
  20471. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  20472. *
  20473. * For the full copyright and license information, please view the LICENSE
  20474. * file that was distributed with this source code.
  20475. */
  20476. namespace PHPUnit\SebastianBergmann\CodeCoverage;
  20477. final class DirectoryCouldNotBeCreatedException extends \PHPUnit\SebastianBergmann\CodeCoverage\RuntimeException
  20478. {
  20479. }
  20480. <?php
  20481. declare (strict_types=1);
  20482. /*
  20483. * This file is part of phpunit/php-code-coverage.
  20484. *
  20485. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  20486. *
  20487. * For the full copyright and license information, please view the LICENSE
  20488. * file that was distributed with this source code.
  20489. */
  20490. namespace PHPUnit\SebastianBergmann\CodeCoverage;
  20491. /**
  20492. * Exception that is raised when @covers must be used but is not.
  20493. */
  20494. final class MissingCoversAnnotationException extends \PHPUnit\SebastianBergmann\CodeCoverage\RuntimeException
  20495. {
  20496. }
  20497. <?php
  20498. declare (strict_types=1);
  20499. /*
  20500. * This file is part of phpunit/php-code-coverage.
  20501. *
  20502. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  20503. *
  20504. * For the full copyright and license information, please view the LICENSE
  20505. * file that was distributed with this source code.
  20506. */
  20507. namespace PHPUnit\SebastianBergmann\CodeCoverage;
  20508. class RuntimeException extends \RuntimeException implements \PHPUnit\SebastianBergmann\CodeCoverage\Exception
  20509. {
  20510. }
  20511. <?php
  20512. declare (strict_types=1);
  20513. /*
  20514. * This file is part of phpunit/php-code-coverage.
  20515. *
  20516. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  20517. *
  20518. * For the full copyright and license information, please view the LICENSE
  20519. * file that was distributed with this source code.
  20520. */
  20521. namespace PHPUnit\SebastianBergmann\CodeCoverage;
  20522. /**
  20523. * Exception interface for php-code-coverage component.
  20524. */
  20525. interface Exception
  20526. {
  20527. }
  20528. <?php
  20529. declare (strict_types=1);
  20530. /*
  20531. * This file is part of phpunit/php-code-coverage.
  20532. *
  20533. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  20534. *
  20535. * For the full copyright and license information, please view the LICENSE
  20536. * file that was distributed with this source code.
  20537. */
  20538. namespace PHPUnit\SebastianBergmann\CodeCoverage;
  20539. /**
  20540. * Exception that is raised when code is unintentionally covered.
  20541. */
  20542. final class UnintentionallyCoveredCodeException extends \PHPUnit\SebastianBergmann\CodeCoverage\RuntimeException
  20543. {
  20544. /**
  20545. * @var array
  20546. */
  20547. private $unintentionallyCoveredUnits = [];
  20548. public function __construct(array $unintentionallyCoveredUnits)
  20549. {
  20550. $this->unintentionallyCoveredUnits = $unintentionallyCoveredUnits;
  20551. parent::__construct($this->toString());
  20552. }
  20553. public function getUnintentionallyCoveredUnits() : array
  20554. {
  20555. return $this->unintentionallyCoveredUnits;
  20556. }
  20557. private function toString() : string
  20558. {
  20559. $message = '';
  20560. foreach ($this->unintentionallyCoveredUnits as $unit) {
  20561. $message .= '- ' . $unit . "\n";
  20562. }
  20563. return $message;
  20564. }
  20565. }
  20566. <?php
  20567. declare (strict_types=1);
  20568. /*
  20569. * This file is part of phpunit/php-code-coverage.
  20570. *
  20571. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  20572. *
  20573. * For the full copyright and license information, please view the LICENSE
  20574. * file that was distributed with this source code.
  20575. */
  20576. namespace PHPUnit\SebastianBergmann\CodeCoverage;
  20577. final class InvalidArgumentException extends \InvalidArgumentException implements \PHPUnit\SebastianBergmann\CodeCoverage\Exception
  20578. {
  20579. /**
  20580. * @param int $argument
  20581. * @param string $type
  20582. * @param null|mixed $value
  20583. *
  20584. * @return InvalidArgumentException
  20585. */
  20586. public static function create($argument, $type, $value = null) : self
  20587. {
  20588. $stack = \debug_backtrace(0);
  20589. return new self(\sprintf('Argument #%d%sof %s::%s() must be a %s', $argument, $value !== null ? ' (' . \gettype($value) . '#' . $value . ')' : ' (No Value) ', $stack[1]['class'], $stack[1]['function'], $type));
  20590. }
  20591. }
  20592. <?php
  20593. declare (strict_types=1);
  20594. /*
  20595. * This file is part of phpunit/php-code-coverage.
  20596. *
  20597. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  20598. *
  20599. * For the full copyright and license information, please view the LICENSE
  20600. * file that was distributed with this source code.
  20601. */
  20602. namespace PHPUnit\SebastianBergmann\CodeCoverage;
  20603. final class Percentage
  20604. {
  20605. /**
  20606. * @var float
  20607. */
  20608. private $fraction;
  20609. /**
  20610. * @var float
  20611. */
  20612. private $total;
  20613. public static function fromFractionAndTotal(float $fraction, float $total) : self
  20614. {
  20615. return new self($fraction, $total);
  20616. }
  20617. private function __construct(float $fraction, float $total)
  20618. {
  20619. $this->fraction = $fraction;
  20620. $this->total = $total;
  20621. }
  20622. public function asFloat() : float
  20623. {
  20624. if ($this->total > 0) {
  20625. return (float) ($this->fraction / $this->total) * 100;
  20626. }
  20627. return 100.0;
  20628. }
  20629. public function asString() : string
  20630. {
  20631. if ($this->total > 0) {
  20632. return \sprintf('%01.2F%%', $this->asFloat());
  20633. }
  20634. return '';
  20635. }
  20636. public function asFixedWidthString() : string
  20637. {
  20638. if ($this->total > 0) {
  20639. return \sprintf('%6.2F%%', $this->asFloat());
  20640. }
  20641. return '';
  20642. }
  20643. }
  20644. <?php
  20645. declare (strict_types=1);
  20646. /*
  20647. * This file is part of phpunit/php-code-coverage.
  20648. *
  20649. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  20650. *
  20651. * For the full copyright and license information, please view the LICENSE
  20652. * file that was distributed with this source code.
  20653. */
  20654. namespace PHPUnit\SebastianBergmann\CodeCoverage;
  20655. use PHPUnit\SebastianBergmann\FileIterator\Facade as FileIteratorFacade;
  20656. /**
  20657. * Filter for whitelisting of code coverage information.
  20658. */
  20659. final class Filter
  20660. {
  20661. /**
  20662. * Source files that are whitelisted.
  20663. *
  20664. * @var array
  20665. */
  20666. private $whitelistedFiles = [];
  20667. /**
  20668. * Remembers the result of the `is_file()` calls.
  20669. *
  20670. * @var bool[]
  20671. */
  20672. private $isFileCallsCache = [];
  20673. /**
  20674. * Adds a directory to the whitelist (recursively).
  20675. */
  20676. public function addDirectoryToWhitelist(string $directory, string $suffix = '.php', string $prefix = '') : void
  20677. {
  20678. $facade = new \PHPUnit\SebastianBergmann\FileIterator\Facade();
  20679. $files = $facade->getFilesAsArray($directory, $suffix, $prefix);
  20680. foreach ($files as $file) {
  20681. $this->addFileToWhitelist($file);
  20682. }
  20683. }
  20684. /**
  20685. * Adds a file to the whitelist.
  20686. */
  20687. public function addFileToWhitelist(string $filename) : void
  20688. {
  20689. $filename = \realpath($filename);
  20690. if (!$filename) {
  20691. return;
  20692. }
  20693. $this->whitelistedFiles[$filename] = \true;
  20694. }
  20695. /**
  20696. * Adds files to the whitelist.
  20697. *
  20698. * @param string[] $files
  20699. */
  20700. public function addFilesToWhitelist(array $files) : void
  20701. {
  20702. foreach ($files as $file) {
  20703. $this->addFileToWhitelist($file);
  20704. }
  20705. }
  20706. /**
  20707. * Removes a directory from the whitelist (recursively).
  20708. */
  20709. public function removeDirectoryFromWhitelist(string $directory, string $suffix = '.php', string $prefix = '') : void
  20710. {
  20711. $facade = new \PHPUnit\SebastianBergmann\FileIterator\Facade();
  20712. $files = $facade->getFilesAsArray($directory, $suffix, $prefix);
  20713. foreach ($files as $file) {
  20714. $this->removeFileFromWhitelist($file);
  20715. }
  20716. }
  20717. /**
  20718. * Removes a file from the whitelist.
  20719. */
  20720. public function removeFileFromWhitelist(string $filename) : void
  20721. {
  20722. $filename = \realpath($filename);
  20723. if (!$filename || !isset($this->whitelistedFiles[$filename])) {
  20724. return;
  20725. }
  20726. unset($this->whitelistedFiles[$filename]);
  20727. }
  20728. /**
  20729. * Checks whether a filename is a real filename.
  20730. */
  20731. public function isFile(string $filename) : bool
  20732. {
  20733. if (isset($this->isFileCallsCache[$filename])) {
  20734. return $this->isFileCallsCache[$filename];
  20735. }
  20736. if ($filename === '-' || \strpos($filename, 'vfs://') === 0 || \strpos($filename, 'xdebug://debug-eval') !== \false || \strpos($filename, 'eval()\'d code') !== \false || \strpos($filename, 'runtime-created function') !== \false || \strpos($filename, 'runkit created function') !== \false || \strpos($filename, 'assert code') !== \false || \strpos($filename, 'regexp code') !== \false || \strpos($filename, 'Standard input code') !== \false) {
  20737. $isFile = \false;
  20738. } else {
  20739. $isFile = \file_exists($filename);
  20740. }
  20741. $this->isFileCallsCache[$filename] = $isFile;
  20742. return $isFile;
  20743. }
  20744. /**
  20745. * Checks whether or not a file is filtered.
  20746. */
  20747. public function isFiltered(string $filename) : bool
  20748. {
  20749. if (!$this->isFile($filename)) {
  20750. return \true;
  20751. }
  20752. return !isset($this->whitelistedFiles[$filename]);
  20753. }
  20754. /**
  20755. * Returns the list of whitelisted files.
  20756. *
  20757. * @return string[]
  20758. */
  20759. public function getWhitelist() : array
  20760. {
  20761. return \array_keys($this->whitelistedFiles);
  20762. }
  20763. /**
  20764. * Returns whether this filter has a whitelist.
  20765. */
  20766. public function hasWhitelist() : bool
  20767. {
  20768. return !empty($this->whitelistedFiles);
  20769. }
  20770. /**
  20771. * Returns the whitelisted files.
  20772. *
  20773. * @return string[]
  20774. */
  20775. public function getWhitelistedFiles() : array
  20776. {
  20777. return $this->whitelistedFiles;
  20778. }
  20779. /**
  20780. * Sets the whitelisted files.
  20781. */
  20782. public function setWhitelistedFiles(array $whitelistedFiles) : void
  20783. {
  20784. $this->whitelistedFiles = $whitelistedFiles;
  20785. }
  20786. }
  20787. <?php
  20788. declare (strict_types=1);
  20789. /*
  20790. * This file is part of phpunit/php-code-coverage.
  20791. *
  20792. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  20793. *
  20794. * For the full copyright and license information, please view the LICENSE
  20795. * file that was distributed with this source code.
  20796. */
  20797. namespace PHPUnit\SebastianBergmann\CodeCoverage\Driver;
  20798. use PHPUnit\SebastianBergmann\CodeCoverage\Filter;
  20799. use PHPUnit\SebastianBergmann\CodeCoverage\RuntimeException;
  20800. /**
  20801. * Driver for Xdebug's code coverage functionality.
  20802. */
  20803. final class Xdebug implements \PHPUnit\SebastianBergmann\CodeCoverage\Driver\Driver
  20804. {
  20805. /**
  20806. * @var array
  20807. */
  20808. private $cacheNumLines = [];
  20809. /**
  20810. * @var Filter
  20811. */
  20812. private $filter;
  20813. /**
  20814. * @throws RuntimeException
  20815. */
  20816. public function __construct(\PHPUnit\SebastianBergmann\CodeCoverage\Filter $filter = null)
  20817. {
  20818. if (!\extension_loaded('xdebug')) {
  20819. throw new \PHPUnit\SebastianBergmann\CodeCoverage\RuntimeException('This driver requires Xdebug');
  20820. }
  20821. if (!\ini_get('xdebug.coverage_enable')) {
  20822. throw new \PHPUnit\SebastianBergmann\CodeCoverage\RuntimeException('xdebug.coverage_enable=On has to be set in php.ini');
  20823. }
  20824. if ($filter === null) {
  20825. $filter = new \PHPUnit\SebastianBergmann\CodeCoverage\Filter();
  20826. }
  20827. $this->filter = $filter;
  20828. }
  20829. /**
  20830. * Start collection of code coverage information.
  20831. */
  20832. public function start(bool $determineUnusedAndDead = \true) : void
  20833. {
  20834. if ($determineUnusedAndDead) {
  20835. \xdebug_start_code_coverage(\XDEBUG_CC_UNUSED | \XDEBUG_CC_DEAD_CODE);
  20836. } else {
  20837. \xdebug_start_code_coverage();
  20838. }
  20839. }
  20840. /**
  20841. * Stop collection of code coverage information.
  20842. */
  20843. public function stop() : array
  20844. {
  20845. $data = \xdebug_get_code_coverage();
  20846. \xdebug_stop_code_coverage();
  20847. return $this->cleanup($data);
  20848. }
  20849. private function cleanup(array $data) : array
  20850. {
  20851. foreach (\array_keys($data) as $file) {
  20852. unset($data[$file][0]);
  20853. if (!$this->filter->isFile($file)) {
  20854. continue;
  20855. }
  20856. $numLines = $this->getNumberOfLinesInFile($file);
  20857. foreach (\array_keys($data[$file]) as $line) {
  20858. if ($line > $numLines) {
  20859. unset($data[$file][$line]);
  20860. }
  20861. }
  20862. }
  20863. return $data;
  20864. }
  20865. private function getNumberOfLinesInFile(string $fileName) : int
  20866. {
  20867. if (!isset($this->cacheNumLines[$fileName])) {
  20868. $buffer = \file_get_contents($fileName);
  20869. $lines = \substr_count($buffer, "\n");
  20870. if (\substr($buffer, -1) !== "\n") {
  20871. $lines++;
  20872. }
  20873. $this->cacheNumLines[$fileName] = $lines;
  20874. }
  20875. return $this->cacheNumLines[$fileName];
  20876. }
  20877. }
  20878. <?php
  20879. declare (strict_types=1);
  20880. /*
  20881. * This file is part of phpunit/php-code-coverage.
  20882. *
  20883. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  20884. *
  20885. * For the full copyright and license information, please view the LICENSE
  20886. * file that was distributed with this source code.
  20887. */
  20888. namespace PHPUnit\SebastianBergmann\CodeCoverage\Driver;
  20889. use PHPUnit\SebastianBergmann\CodeCoverage\RuntimeException;
  20890. /**
  20891. * Driver for PHPDBG's code coverage functionality.
  20892. */
  20893. final class PHPDBG implements \PHPUnit\SebastianBergmann\CodeCoverage\Driver\Driver
  20894. {
  20895. /**
  20896. * @throws RuntimeException
  20897. */
  20898. public function __construct()
  20899. {
  20900. if (\PHP_SAPI !== 'phpdbg') {
  20901. throw new \PHPUnit\SebastianBergmann\CodeCoverage\RuntimeException('This driver requires the PHPDBG SAPI');
  20902. }
  20903. if (!\function_exists('phpdbg_start_oplog')) {
  20904. throw new \PHPUnit\SebastianBergmann\CodeCoverage\RuntimeException('This build of PHPDBG does not support code coverage');
  20905. }
  20906. }
  20907. /**
  20908. * Start collection of code coverage information.
  20909. */
  20910. public function start(bool $determineUnusedAndDead = \true) : void
  20911. {
  20912. \phpdbg_start_oplog();
  20913. }
  20914. /**
  20915. * Stop collection of code coverage information.
  20916. */
  20917. public function stop() : array
  20918. {
  20919. static $fetchedLines = [];
  20920. $dbgData = \phpdbg_end_oplog();
  20921. if ($fetchedLines == []) {
  20922. $sourceLines = \phpdbg_get_executable();
  20923. } else {
  20924. $newFiles = \array_diff(\get_included_files(), \array_keys($fetchedLines));
  20925. $sourceLines = [];
  20926. if ($newFiles) {
  20927. $sourceLines = \phpdbg_get_executable(['files' => $newFiles]);
  20928. }
  20929. }
  20930. foreach ($sourceLines as $file => $lines) {
  20931. foreach ($lines as $lineNo => $numExecuted) {
  20932. $sourceLines[$file][$lineNo] = self::LINE_NOT_EXECUTED;
  20933. }
  20934. }
  20935. $fetchedLines = \array_merge($fetchedLines, $sourceLines);
  20936. return $this->detectExecutedLines($fetchedLines, $dbgData);
  20937. }
  20938. /**
  20939. * Convert phpdbg based data into the format CodeCoverage expects
  20940. */
  20941. private function detectExecutedLines(array $sourceLines, array $dbgData) : array
  20942. {
  20943. foreach ($dbgData as $file => $coveredLines) {
  20944. foreach ($coveredLines as $lineNo => $numExecuted) {
  20945. // phpdbg also reports $lineNo=0 when e.g. exceptions get thrown.
  20946. // make sure we only mark lines executed which are actually executable.
  20947. if (isset($sourceLines[$file][$lineNo])) {
  20948. $sourceLines[$file][$lineNo] = self::LINE_EXECUTED;
  20949. }
  20950. }
  20951. }
  20952. return $sourceLines;
  20953. }
  20954. }
  20955. <?php
  20956. declare (strict_types=1);
  20957. /*
  20958. * This file is part of phpunit/php-code-coverage.
  20959. *
  20960. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  20961. *
  20962. * For the full copyright and license information, please view the LICENSE
  20963. * file that was distributed with this source code.
  20964. */
  20965. namespace PHPUnit\SebastianBergmann\CodeCoverage\Driver;
  20966. /**
  20967. * Interface for code coverage drivers.
  20968. */
  20969. interface Driver
  20970. {
  20971. /**
  20972. * @var int
  20973. *
  20974. * @see http://xdebug.org/docs/code_coverage
  20975. */
  20976. public const LINE_EXECUTED = 1;
  20977. /**
  20978. * @var int
  20979. *
  20980. * @see http://xdebug.org/docs/code_coverage
  20981. */
  20982. public const LINE_NOT_EXECUTED = -1;
  20983. /**
  20984. * @var int
  20985. *
  20986. * @see http://xdebug.org/docs/code_coverage
  20987. */
  20988. public const LINE_NOT_EXECUTABLE = -2;
  20989. /**
  20990. * Start collection of code coverage information.
  20991. */
  20992. public function start(bool $determineUnusedAndDead = \true) : void;
  20993. /**
  20994. * Stop collection of code coverage information.
  20995. */
  20996. public function stop() : array;
  20997. }
  20998. <?php
  20999. declare (strict_types=1);
  21000. /*
  21001. * This file is part of phpunit/php-code-coverage.
  21002. *
  21003. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  21004. *
  21005. * For the full copyright and license information, please view the LICENSE
  21006. * file that was distributed with this source code.
  21007. */
  21008. namespace PHPUnit\SebastianBergmann\CodeCoverage\Driver;
  21009. /**
  21010. * Driver for PCOV code coverage functionality.
  21011. */
  21012. final class PCOV implements \PHPUnit\SebastianBergmann\CodeCoverage\Driver\Driver
  21013. {
  21014. /**
  21015. * Start collection of code coverage information.
  21016. */
  21017. public function start(bool $determineUnusedAndDead = \true) : void
  21018. {
  21019. \pcov\start();
  21020. }
  21021. /**
  21022. * Stop collection of code coverage information.
  21023. */
  21024. public function stop() : array
  21025. {
  21026. \pcov\stop();
  21027. $waiting = \pcov\waiting();
  21028. $collect = [];
  21029. if ($waiting) {
  21030. $collect = \pcov\collect(\pcov\inclusive, $waiting);
  21031. \pcov\clear();
  21032. }
  21033. return $collect;
  21034. }
  21035. }
  21036. <?php
  21037. declare (strict_types=1);
  21038. /*
  21039. * This file is part of phpunit/php-code-coverage.
  21040. *
  21041. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  21042. *
  21043. * For the full copyright and license information, please view the LICENSE
  21044. * file that was distributed with this source code.
  21045. */
  21046. namespace PHPUnit\SebastianBergmann\CodeCoverage;
  21047. use PHPUnit\SebastianBergmann\Version as VersionId;
  21048. final class Version
  21049. {
  21050. /**
  21051. * @var string
  21052. */
  21053. private static $version;
  21054. public static function id() : string
  21055. {
  21056. if (self::$version === null) {
  21057. $version = new \PHPUnit\SebastianBergmann\Version('8.0.2', \dirname(__DIR__));
  21058. self::$version = $version->getVersion();
  21059. }
  21060. return self::$version;
  21061. }
  21062. }
  21063. <?php
  21064. declare (strict_types=1);
  21065. /*
  21066. * This file is part of phpunit/php-code-coverage.
  21067. *
  21068. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  21069. *
  21070. * For the full copyright and license information, please view the LICENSE
  21071. * file that was distributed with this source code.
  21072. */
  21073. namespace PHPUnit\SebastianBergmann\CodeCoverage;
  21074. use PHPUnit\Framework\TestCase;
  21075. use PHPUnit\Runner\PhptTestCase;
  21076. use PHPUnit\Util\Test;
  21077. use PHPUnit\SebastianBergmann\CodeCoverage\Driver\Driver;
  21078. use PHPUnit\SebastianBergmann\CodeCoverage\Driver\PCOV;
  21079. use PHPUnit\SebastianBergmann\CodeCoverage\Driver\PHPDBG;
  21080. use PHPUnit\SebastianBergmann\CodeCoverage\Driver\Xdebug;
  21081. use PHPUnit\SebastianBergmann\CodeCoverage\Node\Builder;
  21082. use PHPUnit\SebastianBergmann\CodeCoverage\Node\Directory;
  21083. use PHPUnit\SebastianBergmann\CodeUnitReverseLookup\Wizard;
  21084. use PHPUnit\SebastianBergmann\Environment\Runtime;
  21085. /**
  21086. * Provides collection functionality for PHP code coverage information.
  21087. */
  21088. final class CodeCoverage
  21089. {
  21090. /**
  21091. * @var Driver
  21092. */
  21093. private $driver;
  21094. /**
  21095. * @var Filter
  21096. */
  21097. private $filter;
  21098. /**
  21099. * @var Wizard
  21100. */
  21101. private $wizard;
  21102. /**
  21103. * @var bool
  21104. */
  21105. private $cacheTokens = \false;
  21106. /**
  21107. * @var bool
  21108. */
  21109. private $checkForUnintentionallyCoveredCode = \false;
  21110. /**
  21111. * @var bool
  21112. */
  21113. private $forceCoversAnnotation = \false;
  21114. /**
  21115. * @var bool
  21116. */
  21117. private $checkForUnexecutedCoveredCode = \false;
  21118. /**
  21119. * @var bool
  21120. */
  21121. private $checkForMissingCoversAnnotation = \false;
  21122. /**
  21123. * @var bool
  21124. */
  21125. private $addUncoveredFilesFromWhitelist = \true;
  21126. /**
  21127. * @var bool
  21128. */
  21129. private $processUncoveredFilesFromWhitelist = \false;
  21130. /**
  21131. * @var bool
  21132. */
  21133. private $ignoreDeprecatedCode = \false;
  21134. /**
  21135. * @var PhptTestCase|string|TestCase
  21136. */
  21137. private $currentId;
  21138. /**
  21139. * Code coverage data.
  21140. *
  21141. * @var array
  21142. */
  21143. private $data = [];
  21144. /**
  21145. * @var array
  21146. */
  21147. private $ignoredLines = [];
  21148. /**
  21149. * @var bool
  21150. */
  21151. private $disableIgnoredLines = \false;
  21152. /**
  21153. * Test data.
  21154. *
  21155. * @var array
  21156. */
  21157. private $tests = [];
  21158. /**
  21159. * @var string[]
  21160. */
  21161. private $unintentionallyCoveredSubclassesWhitelist = [];
  21162. /**
  21163. * Determine if the data has been initialized or not
  21164. *
  21165. * @var bool
  21166. */
  21167. private $isInitialized = \false;
  21168. /**
  21169. * Determine whether we need to check for dead and unused code on each test
  21170. *
  21171. * @var bool
  21172. */
  21173. private $shouldCheckForDeadAndUnused = \true;
  21174. /**
  21175. * @var Directory
  21176. */
  21177. private $report;
  21178. /**
  21179. * @throws RuntimeException
  21180. */
  21181. public function __construct(\PHPUnit\SebastianBergmann\CodeCoverage\Driver\Driver $driver = null, \PHPUnit\SebastianBergmann\CodeCoverage\Filter $filter = null)
  21182. {
  21183. if ($filter === null) {
  21184. $filter = new \PHPUnit\SebastianBergmann\CodeCoverage\Filter();
  21185. }
  21186. if ($driver === null) {
  21187. $driver = $this->selectDriver($filter);
  21188. }
  21189. $this->driver = $driver;
  21190. $this->filter = $filter;
  21191. $this->wizard = new \PHPUnit\SebastianBergmann\CodeUnitReverseLookup\Wizard();
  21192. }
  21193. /**
  21194. * Returns the code coverage information as a graph of node objects.
  21195. */
  21196. public function getReport() : \PHPUnit\SebastianBergmann\CodeCoverage\Node\Directory
  21197. {
  21198. if ($this->report === null) {
  21199. $this->report = (new \PHPUnit\SebastianBergmann\CodeCoverage\Node\Builder())->build($this);
  21200. }
  21201. return $this->report;
  21202. }
  21203. /**
  21204. * Clears collected code coverage data.
  21205. */
  21206. public function clear() : void
  21207. {
  21208. $this->isInitialized = \false;
  21209. $this->currentId = null;
  21210. $this->data = [];
  21211. $this->tests = [];
  21212. $this->report = null;
  21213. }
  21214. /**
  21215. * Returns the filter object used.
  21216. */
  21217. public function filter() : \PHPUnit\SebastianBergmann\CodeCoverage\Filter
  21218. {
  21219. return $this->filter;
  21220. }
  21221. /**
  21222. * Returns the collected code coverage data.
  21223. */
  21224. public function getData(bool $raw = \false) : array
  21225. {
  21226. if (!$raw && $this->addUncoveredFilesFromWhitelist) {
  21227. $this->addUncoveredFilesFromWhitelist();
  21228. }
  21229. return $this->data;
  21230. }
  21231. /**
  21232. * Sets the coverage data.
  21233. */
  21234. public function setData(array $data) : void
  21235. {
  21236. $this->data = $data;
  21237. $this->report = null;
  21238. }
  21239. /**
  21240. * Returns the test data.
  21241. */
  21242. public function getTests() : array
  21243. {
  21244. return $this->tests;
  21245. }
  21246. /**
  21247. * Sets the test data.
  21248. */
  21249. public function setTests(array $tests) : void
  21250. {
  21251. $this->tests = $tests;
  21252. }
  21253. /**
  21254. * Start collection of code coverage information.
  21255. *
  21256. * @param PhptTestCase|string|TestCase $id
  21257. *
  21258. * @throws RuntimeException
  21259. */
  21260. public function start($id, bool $clear = \false) : void
  21261. {
  21262. if ($clear) {
  21263. $this->clear();
  21264. }
  21265. if ($this->isInitialized === \false) {
  21266. $this->initializeData();
  21267. }
  21268. $this->currentId = $id;
  21269. $this->driver->start($this->shouldCheckForDeadAndUnused);
  21270. }
  21271. /**
  21272. * Stop collection of code coverage information.
  21273. *
  21274. * @param array|false $linesToBeCovered
  21275. *
  21276. * @throws MissingCoversAnnotationException
  21277. * @throws CoveredCodeNotExecutedException
  21278. * @throws RuntimeException
  21279. * @throws InvalidArgumentException
  21280. * @throws \ReflectionException
  21281. */
  21282. public function stop(bool $append = \true, $linesToBeCovered = [], array $linesToBeUsed = [], bool $ignoreForceCoversAnnotation = \false) : array
  21283. {
  21284. if (!\is_array($linesToBeCovered) && $linesToBeCovered !== \false) {
  21285. throw \PHPUnit\SebastianBergmann\CodeCoverage\InvalidArgumentException::create(2, 'array or false');
  21286. }
  21287. $data = $this->driver->stop();
  21288. $this->append($data, null, $append, $linesToBeCovered, $linesToBeUsed, $ignoreForceCoversAnnotation);
  21289. $this->currentId = null;
  21290. return $data;
  21291. }
  21292. /**
  21293. * Appends code coverage data.
  21294. *
  21295. * @param PhptTestCase|string|TestCase $id
  21296. * @param array|false $linesToBeCovered
  21297. *
  21298. * @throws \SebastianBergmann\CodeCoverage\UnintentionallyCoveredCodeException
  21299. * @throws \SebastianBergmann\CodeCoverage\MissingCoversAnnotationException
  21300. * @throws \SebastianBergmann\CodeCoverage\CoveredCodeNotExecutedException
  21301. * @throws \ReflectionException
  21302. * @throws \SebastianBergmann\CodeCoverage\InvalidArgumentException
  21303. * @throws RuntimeException
  21304. */
  21305. public function append(array $data, $id = null, bool $append = \true, $linesToBeCovered = [], array $linesToBeUsed = [], bool $ignoreForceCoversAnnotation = \false) : void
  21306. {
  21307. if ($id === null) {
  21308. $id = $this->currentId;
  21309. }
  21310. if ($id === null) {
  21311. throw new \PHPUnit\SebastianBergmann\CodeCoverage\RuntimeException();
  21312. }
  21313. $this->applyWhitelistFilter($data);
  21314. $this->applyIgnoredLinesFilter($data);
  21315. $this->initializeFilesThatAreSeenTheFirstTime($data);
  21316. if (!$append) {
  21317. return;
  21318. }
  21319. if ($id !== 'UNCOVERED_FILES_FROM_WHITELIST') {
  21320. $this->applyCoversAnnotationFilter($data, $linesToBeCovered, $linesToBeUsed, $ignoreForceCoversAnnotation);
  21321. }
  21322. if (empty($data)) {
  21323. return;
  21324. }
  21325. $size = 'unknown';
  21326. $status = -1;
  21327. if ($id instanceof \PHPUnit\Framework\TestCase) {
  21328. $_size = $id->getSize();
  21329. if ($_size === \PHPUnit\Util\Test::SMALL) {
  21330. $size = 'small';
  21331. } elseif ($_size === \PHPUnit\Util\Test::MEDIUM) {
  21332. $size = 'medium';
  21333. } elseif ($_size === \PHPUnit\Util\Test::LARGE) {
  21334. $size = 'large';
  21335. }
  21336. $status = $id->getStatus();
  21337. $id = \get_class($id) . '::' . $id->getName();
  21338. } elseif ($id instanceof \PHPUnit\Runner\PhptTestCase) {
  21339. $size = 'large';
  21340. $id = $id->getName();
  21341. }
  21342. $this->tests[$id] = ['size' => $size, 'status' => $status];
  21343. foreach ($data as $file => $lines) {
  21344. if (!$this->filter->isFile($file)) {
  21345. continue;
  21346. }
  21347. foreach ($lines as $k => $v) {
  21348. if ($v === \PHPUnit\SebastianBergmann\CodeCoverage\Driver\Driver::LINE_EXECUTED) {
  21349. if (empty($this->data[$file][$k]) || !\in_array($id, $this->data[$file][$k])) {
  21350. $this->data[$file][$k][] = $id;
  21351. }
  21352. }
  21353. }
  21354. }
  21355. $this->report = null;
  21356. }
  21357. /**
  21358. * Merges the data from another instance.
  21359. *
  21360. * @param CodeCoverage $that
  21361. */
  21362. public function merge(self $that) : void
  21363. {
  21364. $this->filter->setWhitelistedFiles(\array_merge($this->filter->getWhitelistedFiles(), $that->filter()->getWhitelistedFiles()));
  21365. foreach ($that->data as $file => $lines) {
  21366. if (!isset($this->data[$file])) {
  21367. if (!$this->filter->isFiltered($file)) {
  21368. $this->data[$file] = $lines;
  21369. }
  21370. continue;
  21371. }
  21372. // we should compare the lines if any of two contains data
  21373. $compareLineNumbers = \array_unique(\array_merge(\array_keys($this->data[$file]), \array_keys($that->data[$file])));
  21374. foreach ($compareLineNumbers as $line) {
  21375. $thatPriority = $this->getLinePriority($that->data[$file], $line);
  21376. $thisPriority = $this->getLinePriority($this->data[$file], $line);
  21377. if ($thatPriority > $thisPriority) {
  21378. $this->data[$file][$line] = $that->data[$file][$line];
  21379. } elseif ($thatPriority === $thisPriority && \is_array($this->data[$file][$line])) {
  21380. $this->data[$file][$line] = \array_unique(\array_merge($this->data[$file][$line], $that->data[$file][$line]));
  21381. }
  21382. }
  21383. }
  21384. $this->tests = \array_merge($this->tests, $that->getTests());
  21385. $this->report = null;
  21386. }
  21387. public function setCacheTokens(bool $flag) : void
  21388. {
  21389. $this->cacheTokens = $flag;
  21390. }
  21391. public function getCacheTokens() : bool
  21392. {
  21393. return $this->cacheTokens;
  21394. }
  21395. public function setCheckForUnintentionallyCoveredCode(bool $flag) : void
  21396. {
  21397. $this->checkForUnintentionallyCoveredCode = $flag;
  21398. }
  21399. public function setForceCoversAnnotation(bool $flag) : void
  21400. {
  21401. $this->forceCoversAnnotation = $flag;
  21402. }
  21403. public function setCheckForMissingCoversAnnotation(bool $flag) : void
  21404. {
  21405. $this->checkForMissingCoversAnnotation = $flag;
  21406. }
  21407. public function setCheckForUnexecutedCoveredCode(bool $flag) : void
  21408. {
  21409. $this->checkForUnexecutedCoveredCode = $flag;
  21410. }
  21411. public function setAddUncoveredFilesFromWhitelist(bool $flag) : void
  21412. {
  21413. $this->addUncoveredFilesFromWhitelist = $flag;
  21414. }
  21415. public function setProcessUncoveredFilesFromWhitelist(bool $flag) : void
  21416. {
  21417. $this->processUncoveredFilesFromWhitelist = $flag;
  21418. }
  21419. public function setDisableIgnoredLines(bool $flag) : void
  21420. {
  21421. $this->disableIgnoredLines = $flag;
  21422. }
  21423. public function setIgnoreDeprecatedCode(bool $flag) : void
  21424. {
  21425. $this->ignoreDeprecatedCode = $flag;
  21426. }
  21427. public function setUnintentionallyCoveredSubclassesWhitelist(array $whitelist) : void
  21428. {
  21429. $this->unintentionallyCoveredSubclassesWhitelist = $whitelist;
  21430. }
  21431. /**
  21432. * Determine the priority for a line
  21433. *
  21434. * 1 = the line is not set
  21435. * 2 = the line has not been tested
  21436. * 3 = the line is dead code
  21437. * 4 = the line has been tested
  21438. *
  21439. * During a merge, a higher number is better.
  21440. *
  21441. * @param array $data
  21442. * @param int $line
  21443. *
  21444. * @return int
  21445. */
  21446. private function getLinePriority($data, $line)
  21447. {
  21448. if (!\array_key_exists($line, $data)) {
  21449. return 1;
  21450. }
  21451. if (\is_array($data[$line]) && \count($data[$line]) === 0) {
  21452. return 2;
  21453. }
  21454. if ($data[$line] === null) {
  21455. return 3;
  21456. }
  21457. return 4;
  21458. }
  21459. /**
  21460. * Applies the @covers annotation filtering.
  21461. *
  21462. * @param array|false $linesToBeCovered
  21463. *
  21464. * @throws \SebastianBergmann\CodeCoverage\CoveredCodeNotExecutedException
  21465. * @throws \ReflectionException
  21466. * @throws MissingCoversAnnotationException
  21467. * @throws UnintentionallyCoveredCodeException
  21468. */
  21469. private function applyCoversAnnotationFilter(array &$data, $linesToBeCovered, array $linesToBeUsed, bool $ignoreForceCoversAnnotation) : void
  21470. {
  21471. if ($linesToBeCovered === \false || $this->forceCoversAnnotation && empty($linesToBeCovered) && !$ignoreForceCoversAnnotation) {
  21472. if ($this->checkForMissingCoversAnnotation) {
  21473. throw new \PHPUnit\SebastianBergmann\CodeCoverage\MissingCoversAnnotationException();
  21474. }
  21475. $data = [];
  21476. return;
  21477. }
  21478. if (empty($linesToBeCovered)) {
  21479. return;
  21480. }
  21481. if ($this->checkForUnintentionallyCoveredCode && (!$this->currentId instanceof \PHPUnit\Framework\TestCase || !$this->currentId->isMedium() && !$this->currentId->isLarge())) {
  21482. $this->performUnintentionallyCoveredCodeCheck($data, $linesToBeCovered, $linesToBeUsed);
  21483. }
  21484. if ($this->checkForUnexecutedCoveredCode) {
  21485. $this->performUnexecutedCoveredCodeCheck($data, $linesToBeCovered, $linesToBeUsed);
  21486. }
  21487. $data = \array_intersect_key($data, $linesToBeCovered);
  21488. foreach (\array_keys($data) as $filename) {
  21489. $_linesToBeCovered = \array_flip($linesToBeCovered[$filename]);
  21490. $data[$filename] = \array_intersect_key($data[$filename], $_linesToBeCovered);
  21491. }
  21492. }
  21493. private function applyWhitelistFilter(array &$data) : void
  21494. {
  21495. foreach (\array_keys($data) as $filename) {
  21496. if ($this->filter->isFiltered($filename)) {
  21497. unset($data[$filename]);
  21498. }
  21499. }
  21500. }
  21501. /**
  21502. * @throws \SebastianBergmann\CodeCoverage\InvalidArgumentException
  21503. */
  21504. private function applyIgnoredLinesFilter(array &$data) : void
  21505. {
  21506. foreach (\array_keys($data) as $filename) {
  21507. if (!$this->filter->isFile($filename)) {
  21508. continue;
  21509. }
  21510. foreach ($this->getLinesToBeIgnored($filename) as $line) {
  21511. unset($data[$filename][$line]);
  21512. }
  21513. }
  21514. }
  21515. private function initializeFilesThatAreSeenTheFirstTime(array $data) : void
  21516. {
  21517. foreach ($data as $file => $lines) {
  21518. if (!isset($this->data[$file]) && $this->filter->isFile($file)) {
  21519. $this->data[$file] = [];
  21520. foreach ($lines as $k => $v) {
  21521. $this->data[$file][$k] = $v === -2 ? null : [];
  21522. }
  21523. }
  21524. }
  21525. }
  21526. /**
  21527. * @throws CoveredCodeNotExecutedException
  21528. * @throws InvalidArgumentException
  21529. * @throws MissingCoversAnnotationException
  21530. * @throws RuntimeException
  21531. * @throws UnintentionallyCoveredCodeException
  21532. * @throws \ReflectionException
  21533. */
  21534. private function addUncoveredFilesFromWhitelist() : void
  21535. {
  21536. $data = [];
  21537. $uncoveredFiles = \array_diff($this->filter->getWhitelist(), \array_keys($this->data));
  21538. foreach ($uncoveredFiles as $uncoveredFile) {
  21539. if (!\file_exists($uncoveredFile)) {
  21540. continue;
  21541. }
  21542. $data[$uncoveredFile] = [];
  21543. $lines = \count(\file($uncoveredFile));
  21544. for ($i = 1; $i <= $lines; $i++) {
  21545. $data[$uncoveredFile][$i] = \PHPUnit\SebastianBergmann\CodeCoverage\Driver\Driver::LINE_NOT_EXECUTED;
  21546. }
  21547. }
  21548. $this->append($data, 'UNCOVERED_FILES_FROM_WHITELIST');
  21549. }
  21550. private function getLinesToBeIgnored(string $fileName) : array
  21551. {
  21552. if (isset($this->ignoredLines[$fileName])) {
  21553. return $this->ignoredLines[$fileName];
  21554. }
  21555. try {
  21556. return $this->getLinesToBeIgnoredInner($fileName);
  21557. } catch (\OutOfBoundsException $e) {
  21558. // This can happen with PHP_Token_Stream if the file is syntactically invalid,
  21559. // and probably affects a file that wasn't executed.
  21560. return [];
  21561. }
  21562. }
  21563. private function getLinesToBeIgnoredInner(string $fileName) : array
  21564. {
  21565. $this->ignoredLines[$fileName] = [];
  21566. $lines = \file($fileName);
  21567. foreach ($lines as $index => $line) {
  21568. if (!\trim($line)) {
  21569. $this->ignoredLines[$fileName][] = $index + 1;
  21570. }
  21571. }
  21572. if ($this->cacheTokens) {
  21573. $tokens = \PHPUnit\PHP_Token_Stream_CachingFactory::get($fileName);
  21574. } else {
  21575. $tokens = new \PHPUnit\PHP_Token_Stream($fileName);
  21576. }
  21577. foreach ($tokens->getInterfaces() as $interface) {
  21578. $interfaceStartLine = $interface['startLine'];
  21579. $interfaceEndLine = $interface['endLine'];
  21580. foreach (\range($interfaceStartLine, $interfaceEndLine) as $line) {
  21581. $this->ignoredLines[$fileName][] = $line;
  21582. }
  21583. }
  21584. foreach (\array_merge($tokens->getClasses(), $tokens->getTraits()) as $classOrTrait) {
  21585. $classOrTraitStartLine = $classOrTrait['startLine'];
  21586. $classOrTraitEndLine = $classOrTrait['endLine'];
  21587. if (empty($classOrTrait['methods'])) {
  21588. foreach (\range($classOrTraitStartLine, $classOrTraitEndLine) as $line) {
  21589. $this->ignoredLines[$fileName][] = $line;
  21590. }
  21591. continue;
  21592. }
  21593. $firstMethod = \array_shift($classOrTrait['methods']);
  21594. $firstMethodStartLine = $firstMethod['startLine'];
  21595. $lastMethodEndLine = $firstMethod['endLine'];
  21596. do {
  21597. $lastMethod = \array_pop($classOrTrait['methods']);
  21598. } while ($lastMethod !== null && 0 === \strpos($lastMethod['signature'], 'anonymousFunction'));
  21599. if ($lastMethod !== null) {
  21600. $lastMethodEndLine = $lastMethod['endLine'];
  21601. }
  21602. foreach (\range($classOrTraitStartLine, $firstMethodStartLine) as $line) {
  21603. $this->ignoredLines[$fileName][] = $line;
  21604. }
  21605. foreach (\range($lastMethodEndLine + 1, $classOrTraitEndLine) as $line) {
  21606. $this->ignoredLines[$fileName][] = $line;
  21607. }
  21608. }
  21609. if ($this->disableIgnoredLines) {
  21610. $this->ignoredLines[$fileName] = \array_unique($this->ignoredLines[$fileName]);
  21611. \sort($this->ignoredLines[$fileName]);
  21612. return $this->ignoredLines[$fileName];
  21613. }
  21614. $ignore = \false;
  21615. $stop = \false;
  21616. foreach ($tokens->tokens() as $token) {
  21617. switch (\get_class($token)) {
  21618. case \PHPUnit\PHP_Token_COMMENT::class:
  21619. case \PHPUnit\PHP_Token_DOC_COMMENT::class:
  21620. $_token = \trim((string) $token);
  21621. $_line = \trim($lines[$token->getLine() - 1]);
  21622. if ($_token === '// @codeCoverageIgnore' || $_token === '//@codeCoverageIgnore') {
  21623. $ignore = \true;
  21624. $stop = \true;
  21625. } elseif ($_token === '// @codeCoverageIgnoreStart' || $_token === '//@codeCoverageIgnoreStart') {
  21626. $ignore = \true;
  21627. } elseif ($_token === '// @codeCoverageIgnoreEnd' || $_token === '//@codeCoverageIgnoreEnd') {
  21628. $stop = \true;
  21629. }
  21630. if (!$ignore) {
  21631. $start = $token->getLine();
  21632. $end = $start + \substr_count((string) $token, "\n");
  21633. // Do not ignore the first line when there is a token
  21634. // before the comment
  21635. if (0 !== \strpos($_token, $_line)) {
  21636. $start++;
  21637. }
  21638. for ($i = $start; $i < $end; $i++) {
  21639. $this->ignoredLines[$fileName][] = $i;
  21640. }
  21641. // A DOC_COMMENT token or a COMMENT token starting with "/*"
  21642. // does not contain the final \n character in its text
  21643. if (isset($lines[$i - 1]) && 0 === \strpos($_token, '/*') && '*/' === \substr(\trim($lines[$i - 1]), -2)) {
  21644. $this->ignoredLines[$fileName][] = $i;
  21645. }
  21646. }
  21647. break;
  21648. case \PHPUnit\PHP_Token_INTERFACE::class:
  21649. case \PHPUnit\PHP_Token_TRAIT::class:
  21650. case \PHPUnit\PHP_Token_CLASS::class:
  21651. case \PHPUnit\PHP_Token_FUNCTION::class:
  21652. /* @var \PHP_Token_Interface $token */
  21653. $docblock = (string) $token->getDocblock();
  21654. $this->ignoredLines[$fileName][] = $token->getLine();
  21655. if (\strpos($docblock, '@codeCoverageIgnore') || $this->ignoreDeprecatedCode && \strpos($docblock, '@deprecated')) {
  21656. $endLine = $token->getEndLine();
  21657. for ($i = $token->getLine(); $i <= $endLine; $i++) {
  21658. $this->ignoredLines[$fileName][] = $i;
  21659. }
  21660. }
  21661. break;
  21662. /* @noinspection PhpMissingBreakStatementInspection */
  21663. case \PHPUnit\PHP_Token_NAMESPACE::class:
  21664. $this->ignoredLines[$fileName][] = $token->getEndLine();
  21665. // Intentional fallthrough
  21666. case \PHPUnit\PHP_Token_DECLARE::class:
  21667. case \PHPUnit\PHP_Token_OPEN_TAG::class:
  21668. case \PHPUnit\PHP_Token_CLOSE_TAG::class:
  21669. case \PHPUnit\PHP_Token_USE::class:
  21670. case \PHPUnit\PHP_Token_USE_FUNCTION::class:
  21671. $this->ignoredLines[$fileName][] = $token->getLine();
  21672. break;
  21673. }
  21674. if ($ignore) {
  21675. $this->ignoredLines[$fileName][] = $token->getLine();
  21676. if ($stop) {
  21677. $ignore = \false;
  21678. $stop = \false;
  21679. }
  21680. }
  21681. }
  21682. $this->ignoredLines[$fileName][] = \count($lines) + 1;
  21683. $this->ignoredLines[$fileName] = \array_unique($this->ignoredLines[$fileName]);
  21684. $this->ignoredLines[$fileName] = \array_unique($this->ignoredLines[$fileName]);
  21685. \sort($this->ignoredLines[$fileName]);
  21686. return $this->ignoredLines[$fileName];
  21687. }
  21688. /**
  21689. * @throws \ReflectionException
  21690. * @throws UnintentionallyCoveredCodeException
  21691. */
  21692. private function performUnintentionallyCoveredCodeCheck(array &$data, array $linesToBeCovered, array $linesToBeUsed) : void
  21693. {
  21694. $allowedLines = $this->getAllowedLines($linesToBeCovered, $linesToBeUsed);
  21695. $unintentionallyCoveredUnits = [];
  21696. foreach ($data as $file => $_data) {
  21697. foreach ($_data as $line => $flag) {
  21698. if ($flag === 1 && !isset($allowedLines[$file][$line])) {
  21699. $unintentionallyCoveredUnits[] = $this->wizard->lookup($file, $line);
  21700. }
  21701. }
  21702. }
  21703. $unintentionallyCoveredUnits = $this->processUnintentionallyCoveredUnits($unintentionallyCoveredUnits);
  21704. if (!empty($unintentionallyCoveredUnits)) {
  21705. throw new \PHPUnit\SebastianBergmann\CodeCoverage\UnintentionallyCoveredCodeException($unintentionallyCoveredUnits);
  21706. }
  21707. }
  21708. /**
  21709. * @throws CoveredCodeNotExecutedException
  21710. */
  21711. private function performUnexecutedCoveredCodeCheck(array &$data, array $linesToBeCovered, array $linesToBeUsed) : void
  21712. {
  21713. $executedCodeUnits = $this->coverageToCodeUnits($data);
  21714. $message = '';
  21715. foreach ($this->linesToCodeUnits($linesToBeCovered) as $codeUnit) {
  21716. if (!\in_array($codeUnit, $executedCodeUnits)) {
  21717. $message .= \sprintf('- %s is expected to be executed (@covers) but was not executed' . "\n", $codeUnit);
  21718. }
  21719. }
  21720. foreach ($this->linesToCodeUnits($linesToBeUsed) as $codeUnit) {
  21721. if (!\in_array($codeUnit, $executedCodeUnits)) {
  21722. $message .= \sprintf('- %s is expected to be executed (@uses) but was not executed' . "\n", $codeUnit);
  21723. }
  21724. }
  21725. if (!empty($message)) {
  21726. throw new \PHPUnit\SebastianBergmann\CodeCoverage\CoveredCodeNotExecutedException($message);
  21727. }
  21728. }
  21729. private function getAllowedLines(array $linesToBeCovered, array $linesToBeUsed) : array
  21730. {
  21731. $allowedLines = [];
  21732. foreach (\array_keys($linesToBeCovered) as $file) {
  21733. if (!isset($allowedLines[$file])) {
  21734. $allowedLines[$file] = [];
  21735. }
  21736. $allowedLines[$file] = \array_merge($allowedLines[$file], $linesToBeCovered[$file]);
  21737. }
  21738. foreach (\array_keys($linesToBeUsed) as $file) {
  21739. if (!isset($allowedLines[$file])) {
  21740. $allowedLines[$file] = [];
  21741. }
  21742. $allowedLines[$file] = \array_merge($allowedLines[$file], $linesToBeUsed[$file]);
  21743. }
  21744. foreach (\array_keys($allowedLines) as $file) {
  21745. $allowedLines[$file] = \array_flip(\array_unique($allowedLines[$file]));
  21746. }
  21747. return $allowedLines;
  21748. }
  21749. /**
  21750. * @throws RuntimeException
  21751. */
  21752. private function selectDriver(\PHPUnit\SebastianBergmann\CodeCoverage\Filter $filter) : \PHPUnit\SebastianBergmann\CodeCoverage\Driver\Driver
  21753. {
  21754. $runtime = new \PHPUnit\SebastianBergmann\Environment\Runtime();
  21755. if ($runtime->hasPHPDBGCodeCoverage()) {
  21756. return new \PHPUnit\SebastianBergmann\CodeCoverage\Driver\PHPDBG();
  21757. }
  21758. if ($runtime->hasPCOV()) {
  21759. return new \PHPUnit\SebastianBergmann\CodeCoverage\Driver\PCOV();
  21760. }
  21761. if ($runtime->hasXdebug()) {
  21762. return new \PHPUnit\SebastianBergmann\CodeCoverage\Driver\Xdebug($filter);
  21763. }
  21764. throw new \PHPUnit\SebastianBergmann\CodeCoverage\RuntimeException('No code coverage driver available');
  21765. }
  21766. private function processUnintentionallyCoveredUnits(array $unintentionallyCoveredUnits) : array
  21767. {
  21768. $unintentionallyCoveredUnits = \array_unique($unintentionallyCoveredUnits);
  21769. \sort($unintentionallyCoveredUnits);
  21770. foreach (\array_keys($unintentionallyCoveredUnits) as $k => $v) {
  21771. $unit = \explode('::', $unintentionallyCoveredUnits[$k]);
  21772. if (\count($unit) !== 2) {
  21773. continue;
  21774. }
  21775. $class = new \ReflectionClass($unit[0]);
  21776. foreach ($this->unintentionallyCoveredSubclassesWhitelist as $whitelisted) {
  21777. if ($class->isSubclassOf($whitelisted)) {
  21778. unset($unintentionallyCoveredUnits[$k]);
  21779. break;
  21780. }
  21781. }
  21782. }
  21783. return \array_values($unintentionallyCoveredUnits);
  21784. }
  21785. /**
  21786. * @throws CoveredCodeNotExecutedException
  21787. * @throws InvalidArgumentException
  21788. * @throws MissingCoversAnnotationException
  21789. * @throws RuntimeException
  21790. * @throws UnintentionallyCoveredCodeException
  21791. * @throws \ReflectionException
  21792. */
  21793. private function initializeData() : void
  21794. {
  21795. $this->isInitialized = \true;
  21796. if ($this->processUncoveredFilesFromWhitelist) {
  21797. $this->shouldCheckForDeadAndUnused = \false;
  21798. $this->driver->start();
  21799. foreach ($this->filter->getWhitelist() as $file) {
  21800. if ($this->filter->isFile($file)) {
  21801. include_once $file;
  21802. }
  21803. }
  21804. $data = [];
  21805. foreach ($this->driver->stop() as $file => $fileCoverage) {
  21806. if ($this->filter->isFiltered($file)) {
  21807. continue;
  21808. }
  21809. foreach (\array_keys($fileCoverage) as $key) {
  21810. if ($fileCoverage[$key] === \PHPUnit\SebastianBergmann\CodeCoverage\Driver\Driver::LINE_EXECUTED) {
  21811. $fileCoverage[$key] = \PHPUnit\SebastianBergmann\CodeCoverage\Driver\Driver::LINE_NOT_EXECUTED;
  21812. }
  21813. }
  21814. $data[$file] = $fileCoverage;
  21815. }
  21816. $this->append($data, 'UNCOVERED_FILES_FROM_WHITELIST');
  21817. }
  21818. }
  21819. private function coverageToCodeUnits(array $data) : array
  21820. {
  21821. $codeUnits = [];
  21822. foreach ($data as $filename => $lines) {
  21823. foreach ($lines as $line => $flag) {
  21824. if ($flag === 1) {
  21825. $codeUnits[] = $this->wizard->lookup($filename, $line);
  21826. }
  21827. }
  21828. }
  21829. return \array_unique($codeUnits);
  21830. }
  21831. private function linesToCodeUnits(array $data) : array
  21832. {
  21833. $codeUnits = [];
  21834. foreach ($data as $filename => $lines) {
  21835. foreach ($lines as $line) {
  21836. $codeUnits[] = $this->wizard->lookup($filename, $line);
  21837. }
  21838. }
  21839. return \array_unique($codeUnits);
  21840. }
  21841. }
  21842. <?php
  21843. declare (strict_types=1);
  21844. /*
  21845. * This file is part of phpunit/php-code-coverage.
  21846. *
  21847. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  21848. *
  21849. * For the full copyright and license information, please view the LICENSE
  21850. * file that was distributed with this source code.
  21851. */
  21852. namespace PHPUnit\SebastianBergmann\CodeCoverage\Report;
  21853. use PHPUnit\SebastianBergmann\CodeCoverage\CodeCoverage;
  21854. use PHPUnit\SebastianBergmann\CodeCoverage\Directory;
  21855. use PHPUnit\SebastianBergmann\CodeCoverage\Node\File;
  21856. use PHPUnit\SebastianBergmann\CodeCoverage\RuntimeException;
  21857. final class Crap4j
  21858. {
  21859. /**
  21860. * @var int
  21861. */
  21862. private $threshold;
  21863. public function __construct(int $threshold = 30)
  21864. {
  21865. $this->threshold = $threshold;
  21866. }
  21867. /**
  21868. * @throws \RuntimeException
  21869. */
  21870. public function process(\PHPUnit\SebastianBergmann\CodeCoverage\CodeCoverage $coverage, ?string $target = null, ?string $name = null) : string
  21871. {
  21872. $document = new \DOMDocument('1.0', 'UTF-8');
  21873. $document->formatOutput = \true;
  21874. $root = $document->createElement('crap_result');
  21875. $document->appendChild($root);
  21876. $project = $document->createElement('project', \is_string($name) ? $name : '');
  21877. $root->appendChild($project);
  21878. $root->appendChild($document->createElement('timestamp', \date('Y-m-d H:i:s')));
  21879. $stats = $document->createElement('stats');
  21880. $methodsNode = $document->createElement('methods');
  21881. $report = $coverage->getReport();
  21882. unset($coverage);
  21883. $fullMethodCount = 0;
  21884. $fullCrapMethodCount = 0;
  21885. $fullCrapLoad = 0;
  21886. $fullCrap = 0;
  21887. foreach ($report as $item) {
  21888. $namespace = 'global';
  21889. if (!$item instanceof \PHPUnit\SebastianBergmann\CodeCoverage\Node\File) {
  21890. continue;
  21891. }
  21892. $file = $document->createElement('file');
  21893. $file->setAttribute('name', $item->getPath());
  21894. $classes = $item->getClassesAndTraits();
  21895. foreach ($classes as $className => $class) {
  21896. foreach ($class['methods'] as $methodName => $method) {
  21897. $crapLoad = $this->getCrapLoad((float) $method['crap'], $method['ccn'], $method['coverage']);
  21898. $fullCrap += $method['crap'];
  21899. $fullCrapLoad += $crapLoad;
  21900. $fullMethodCount++;
  21901. if ($method['crap'] >= $this->threshold) {
  21902. $fullCrapMethodCount++;
  21903. }
  21904. $methodNode = $document->createElement('method');
  21905. if (!empty($class['package']['namespace'])) {
  21906. $namespace = $class['package']['namespace'];
  21907. }
  21908. $methodNode->appendChild($document->createElement('package', $namespace));
  21909. $methodNode->appendChild($document->createElement('className', $className));
  21910. $methodNode->appendChild($document->createElement('methodName', $methodName));
  21911. $methodNode->appendChild($document->createElement('methodSignature', \htmlspecialchars($method['signature'])));
  21912. $methodNode->appendChild($document->createElement('fullMethod', \htmlspecialchars($method['signature'])));
  21913. $methodNode->appendChild($document->createElement('crap', (string) $this->roundValue((float) $method['crap'])));
  21914. $methodNode->appendChild($document->createElement('complexity', (string) $method['ccn']));
  21915. $methodNode->appendChild($document->createElement('coverage', (string) $this->roundValue($method['coverage'])));
  21916. $methodNode->appendChild($document->createElement('crapLoad', (string) \round($crapLoad)));
  21917. $methodsNode->appendChild($methodNode);
  21918. }
  21919. }
  21920. }
  21921. $stats->appendChild($document->createElement('name', 'Method Crap Stats'));
  21922. $stats->appendChild($document->createElement('methodCount', (string) $fullMethodCount));
  21923. $stats->appendChild($document->createElement('crapMethodCount', (string) $fullCrapMethodCount));
  21924. $stats->appendChild($document->createElement('crapLoad', (string) \round($fullCrapLoad)));
  21925. $stats->appendChild($document->createElement('totalCrap', (string) $fullCrap));
  21926. $crapMethodPercent = 0;
  21927. if ($fullMethodCount > 0) {
  21928. $crapMethodPercent = $this->roundValue(100 * $fullCrapMethodCount / $fullMethodCount);
  21929. }
  21930. $stats->appendChild($document->createElement('crapMethodPercent', (string) $crapMethodPercent));
  21931. $root->appendChild($stats);
  21932. $root->appendChild($methodsNode);
  21933. $buffer = $document->saveXML();
  21934. if ($target !== null) {
  21935. \PHPUnit\SebastianBergmann\CodeCoverage\Directory::create(\dirname($target));
  21936. if (@\file_put_contents($target, $buffer) === \false) {
  21937. throw new \PHPUnit\SebastianBergmann\CodeCoverage\RuntimeException(\sprintf('Could not write to "%s', $target));
  21938. }
  21939. }
  21940. return $buffer;
  21941. }
  21942. private function getCrapLoad(float $crapValue, int $cyclomaticComplexity, float $coveragePercent) : float
  21943. {
  21944. $crapLoad = 0;
  21945. if ($crapValue >= $this->threshold) {
  21946. $crapLoad += $cyclomaticComplexity * (1.0 - $coveragePercent / 100);
  21947. $crapLoad += $cyclomaticComplexity / $this->threshold;
  21948. }
  21949. return $crapLoad;
  21950. }
  21951. private function roundValue(float $value) : float
  21952. {
  21953. return \round($value, 2);
  21954. }
  21955. }
  21956. <?php
  21957. declare (strict_types=1);
  21958. /*
  21959. * This file is part of phpunit/php-code-coverage.
  21960. *
  21961. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  21962. *
  21963. * For the full copyright and license information, please view the LICENSE
  21964. * file that was distributed with this source code.
  21965. */
  21966. namespace PHPUnit\SebastianBergmann\CodeCoverage\Report;
  21967. use PHPUnit\SebastianBergmann\CodeCoverage\CodeCoverage;
  21968. use PHPUnit\SebastianBergmann\CodeCoverage\Node\File;
  21969. use PHPUnit\SebastianBergmann\CodeCoverage\Percentage;
  21970. /**
  21971. * Generates human readable output from a code coverage object.
  21972. *
  21973. * The output gets put into a text file our written to the CLI.
  21974. */
  21975. final class Text
  21976. {
  21977. /**
  21978. * @var string
  21979. */
  21980. private const COLOR_GREEN = "\33[30;42m";
  21981. /**
  21982. * @var string
  21983. */
  21984. private const COLOR_YELLOW = "\33[30;43m";
  21985. /**
  21986. * @var string
  21987. */
  21988. private const COLOR_RED = "\33[37;41m";
  21989. /**
  21990. * @var string
  21991. */
  21992. private const COLOR_HEADER = "\33[1;37;40m";
  21993. /**
  21994. * @var string
  21995. */
  21996. private const COLOR_RESET = "\33[0m";
  21997. /**
  21998. * @var string
  21999. */
  22000. private const COLOR_EOL = "\33[2K";
  22001. /**
  22002. * @var int
  22003. */
  22004. private $lowUpperBound;
  22005. /**
  22006. * @var int
  22007. */
  22008. private $highLowerBound;
  22009. /**
  22010. * @var bool
  22011. */
  22012. private $showUncoveredFiles;
  22013. /**
  22014. * @var bool
  22015. */
  22016. private $showOnlySummary;
  22017. public function __construct(int $lowUpperBound = 50, int $highLowerBound = 90, bool $showUncoveredFiles = \false, bool $showOnlySummary = \false)
  22018. {
  22019. $this->lowUpperBound = $lowUpperBound;
  22020. $this->highLowerBound = $highLowerBound;
  22021. $this->showUncoveredFiles = $showUncoveredFiles;
  22022. $this->showOnlySummary = $showOnlySummary;
  22023. }
  22024. public function process(\PHPUnit\SebastianBergmann\CodeCoverage\CodeCoverage $coverage, bool $showColors = \false) : string
  22025. {
  22026. $output = \PHP_EOL . \PHP_EOL;
  22027. $report = $coverage->getReport();
  22028. $colors = ['header' => '', 'classes' => '', 'methods' => '', 'lines' => '', 'reset' => '', 'eol' => ''];
  22029. if ($showColors) {
  22030. $colors['classes'] = $this->getCoverageColor($report->getNumTestedClassesAndTraits(), $report->getNumClassesAndTraits());
  22031. $colors['methods'] = $this->getCoverageColor($report->getNumTestedMethods(), $report->getNumMethods());
  22032. $colors['lines'] = $this->getCoverageColor($report->getNumExecutedLines(), $report->getNumExecutableLines());
  22033. $colors['reset'] = self::COLOR_RESET;
  22034. $colors['header'] = self::COLOR_HEADER;
  22035. $colors['eol'] = self::COLOR_EOL;
  22036. }
  22037. $classes = \sprintf(' Classes: %6s (%d/%d)', \PHPUnit\SebastianBergmann\CodeCoverage\Percentage::fromFractionAndTotal($report->getNumTestedClassesAndTraits(), $report->getNumClassesAndTraits())->asString(), $report->getNumTestedClassesAndTraits(), $report->getNumClassesAndTraits());
  22038. $methods = \sprintf(' Methods: %6s (%d/%d)', \PHPUnit\SebastianBergmann\CodeCoverage\Percentage::fromFractionAndTotal($report->getNumTestedMethods(), $report->getNumMethods())->asString(), $report->getNumTestedMethods(), $report->getNumMethods());
  22039. $lines = \sprintf(' Lines: %6s (%d/%d)', \PHPUnit\SebastianBergmann\CodeCoverage\Percentage::fromFractionAndTotal($report->getNumExecutedLines(), $report->getNumExecutableLines())->asString(), $report->getNumExecutedLines(), $report->getNumExecutableLines());
  22040. $padding = \max(\array_map('strlen', [$classes, $methods, $lines]));
  22041. if ($this->showOnlySummary) {
  22042. $title = 'Code Coverage Report Summary:';
  22043. $padding = \max($padding, \strlen($title));
  22044. $output .= $this->format($colors['header'], $padding, $title);
  22045. } else {
  22046. $date = \date(' Y-m-d H:i:s');
  22047. $title = 'Code Coverage Report:';
  22048. $output .= $this->format($colors['header'], $padding, $title);
  22049. $output .= $this->format($colors['header'], $padding, $date);
  22050. $output .= $this->format($colors['header'], $padding, '');
  22051. $output .= $this->format($colors['header'], $padding, ' Summary:');
  22052. }
  22053. $output .= $this->format($colors['classes'], $padding, $classes);
  22054. $output .= $this->format($colors['methods'], $padding, $methods);
  22055. $output .= $this->format($colors['lines'], $padding, $lines);
  22056. if ($this->showOnlySummary) {
  22057. return $output . \PHP_EOL;
  22058. }
  22059. $classCoverage = [];
  22060. foreach ($report as $item) {
  22061. if (!$item instanceof \PHPUnit\SebastianBergmann\CodeCoverage\Node\File) {
  22062. continue;
  22063. }
  22064. $classes = $item->getClassesAndTraits();
  22065. foreach ($classes as $className => $class) {
  22066. $classStatements = 0;
  22067. $coveredClassStatements = 0;
  22068. $coveredMethods = 0;
  22069. $classMethods = 0;
  22070. foreach ($class['methods'] as $method) {
  22071. if ($method['executableLines'] == 0) {
  22072. continue;
  22073. }
  22074. $classMethods++;
  22075. $classStatements += $method['executableLines'];
  22076. $coveredClassStatements += $method['executedLines'];
  22077. if ($method['coverage'] == 100) {
  22078. $coveredMethods++;
  22079. }
  22080. }
  22081. $package = '';
  22082. if (!empty($class['package']['fullPackage'])) {
  22083. $package = '@' . $class['package']['fullPackage'] . '::';
  22084. }
  22085. $classCoverage[$package . $className] = ['namespace' => $class['package']['namespace'], 'className ' => $className, 'methodsCovered' => $coveredMethods, 'methodCount' => $classMethods, 'statementsCovered' => $coveredClassStatements, 'statementCount' => $classStatements];
  22086. }
  22087. }
  22088. \ksort($classCoverage);
  22089. $methodColor = '';
  22090. $linesColor = '';
  22091. $resetColor = '';
  22092. foreach ($classCoverage as $fullQualifiedPath => $classInfo) {
  22093. if ($this->showUncoveredFiles || $classInfo['statementsCovered'] != 0) {
  22094. if ($showColors) {
  22095. $methodColor = $this->getCoverageColor($classInfo['methodsCovered'], $classInfo['methodCount']);
  22096. $linesColor = $this->getCoverageColor($classInfo['statementsCovered'], $classInfo['statementCount']);
  22097. $resetColor = $colors['reset'];
  22098. }
  22099. $output .= \PHP_EOL . $fullQualifiedPath . \PHP_EOL . ' ' . $methodColor . 'Methods: ' . $this->printCoverageCounts($classInfo['methodsCovered'], $classInfo['methodCount'], 2) . $resetColor . ' ' . ' ' . $linesColor . 'Lines: ' . $this->printCoverageCounts($classInfo['statementsCovered'], $classInfo['statementCount'], 3) . $resetColor;
  22100. }
  22101. }
  22102. return $output . \PHP_EOL;
  22103. }
  22104. private function getCoverageColor(int $numberOfCoveredElements, int $totalNumberOfElements) : string
  22105. {
  22106. $coverage = \PHPUnit\SebastianBergmann\CodeCoverage\Percentage::fromFractionAndTotal($numberOfCoveredElements, $totalNumberOfElements);
  22107. if ($coverage->asFloat() >= $this->highLowerBound) {
  22108. return self::COLOR_GREEN;
  22109. }
  22110. if ($coverage->asFloat() > $this->lowUpperBound) {
  22111. return self::COLOR_YELLOW;
  22112. }
  22113. return self::COLOR_RED;
  22114. }
  22115. private function printCoverageCounts(int $numberOfCoveredElements, int $totalNumberOfElements, int $precision) : string
  22116. {
  22117. $format = '%' . $precision . 's';
  22118. return \PHPUnit\SebastianBergmann\CodeCoverage\Percentage::fromFractionAndTotal($numberOfCoveredElements, $totalNumberOfElements)->asFixedWidthString() . ' (' . \sprintf($format, $numberOfCoveredElements) . '/' . \sprintf($format, $totalNumberOfElements) . ')';
  22119. }
  22120. /**
  22121. * @param false|string $string
  22122. */
  22123. private function format(string $color, int $padding, $string) : string
  22124. {
  22125. $reset = $color ? self::COLOR_RESET : '';
  22126. return $color . \str_pad((string) $string, $padding) . $reset . \PHP_EOL;
  22127. }
  22128. }
  22129. <?php
  22130. declare (strict_types=1);
  22131. /*
  22132. * This file is part of phpunit/php-code-coverage.
  22133. *
  22134. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  22135. *
  22136. * For the full copyright and license information, please view the LICENSE
  22137. * file that was distributed with this source code.
  22138. */
  22139. namespace PHPUnit\SebastianBergmann\CodeCoverage\Report\Html;
  22140. use PHPUnit\SebastianBergmann\CodeCoverage\CodeCoverage;
  22141. use PHPUnit\SebastianBergmann\CodeCoverage\Directory as DirectoryUtil;
  22142. use PHPUnit\SebastianBergmann\CodeCoverage\Node\Directory as DirectoryNode;
  22143. use PHPUnit\SebastianBergmann\CodeCoverage\RuntimeException;
  22144. /**
  22145. * Generates an HTML report from a code coverage object.
  22146. */
  22147. final class Facade
  22148. {
  22149. /**
  22150. * @var string
  22151. */
  22152. private $templatePath;
  22153. /**
  22154. * @var string
  22155. */
  22156. private $generator;
  22157. /**
  22158. * @var int
  22159. */
  22160. private $lowUpperBound;
  22161. /**
  22162. * @var int
  22163. */
  22164. private $highLowerBound;
  22165. public function __construct(int $lowUpperBound = 50, int $highLowerBound = 90, string $generator = '')
  22166. {
  22167. $this->generator = $generator;
  22168. $this->highLowerBound = $highLowerBound;
  22169. $this->lowUpperBound = $lowUpperBound;
  22170. $this->templatePath = __DIR__ . '/Renderer/Template/';
  22171. }
  22172. /**
  22173. * @throws RuntimeException
  22174. * @throws \InvalidArgumentException
  22175. * @throws \RuntimeException
  22176. */
  22177. public function process(\PHPUnit\SebastianBergmann\CodeCoverage\CodeCoverage $coverage, string $target) : void
  22178. {
  22179. $target = $this->getDirectory($target);
  22180. $report = $coverage->getReport();
  22181. $date = (string) \date('D M j G:i:s T Y');
  22182. $dashboard = new \PHPUnit\SebastianBergmann\CodeCoverage\Report\Html\Dashboard($this->templatePath, $this->generator, $date, $this->lowUpperBound, $this->highLowerBound);
  22183. $directory = new \PHPUnit\SebastianBergmann\CodeCoverage\Report\Html\Directory($this->templatePath, $this->generator, $date, $this->lowUpperBound, $this->highLowerBound);
  22184. $file = new \PHPUnit\SebastianBergmann\CodeCoverage\Report\Html\File($this->templatePath, $this->generator, $date, $this->lowUpperBound, $this->highLowerBound);
  22185. $directory->render($report, $target . 'index.html');
  22186. $dashboard->render($report, $target . 'dashboard.html');
  22187. foreach ($report as $node) {
  22188. $id = $node->getId();
  22189. if ($node instanceof \PHPUnit\SebastianBergmann\CodeCoverage\Node\Directory) {
  22190. \PHPUnit\SebastianBergmann\CodeCoverage\Directory::create($target . $id);
  22191. $directory->render($node, $target . $id . '/index.html');
  22192. $dashboard->render($node, $target . $id . '/dashboard.html');
  22193. } else {
  22194. $dir = \dirname($target . $id);
  22195. \PHPUnit\SebastianBergmann\CodeCoverage\Directory::create($dir);
  22196. $file->render($node, $target . $id . '.html');
  22197. }
  22198. }
  22199. $this->copyFiles($target);
  22200. }
  22201. /**
  22202. * @throws RuntimeException
  22203. */
  22204. private function copyFiles(string $target) : void
  22205. {
  22206. $dir = $this->getDirectory($target . '_css');
  22207. \copy($this->templatePath . 'css/bootstrap.min.css', $dir . 'bootstrap.min.css');
  22208. \copy($this->templatePath . 'css/nv.d3.min.css', $dir . 'nv.d3.min.css');
  22209. \copy($this->templatePath . 'css/style.css', $dir . 'style.css');
  22210. \copy($this->templatePath . 'css/custom.css', $dir . 'custom.css');
  22211. \copy($this->templatePath . 'css/octicons.css', $dir . 'octicons.css');
  22212. $dir = $this->getDirectory($target . '_icons');
  22213. \copy($this->templatePath . 'icons/file-code.svg', $dir . 'file-code.svg');
  22214. \copy($this->templatePath . 'icons/file-directory.svg', $dir . 'file-directory.svg');
  22215. $dir = $this->getDirectory($target . '_js');
  22216. \copy($this->templatePath . 'js/bootstrap.min.js', $dir . 'bootstrap.min.js');
  22217. \copy($this->templatePath . 'js/popper.min.js', $dir . 'popper.min.js');
  22218. \copy($this->templatePath . 'js/d3.min.js', $dir . 'd3.min.js');
  22219. \copy($this->templatePath . 'js/jquery.min.js', $dir . 'jquery.min.js');
  22220. \copy($this->templatePath . 'js/nv.d3.min.js', $dir . 'nv.d3.min.js');
  22221. \copy($this->templatePath . 'js/file.js', $dir . 'file.js');
  22222. }
  22223. /**
  22224. * @throws RuntimeException
  22225. */
  22226. private function getDirectory(string $directory) : string
  22227. {
  22228. if (\substr($directory, -1, 1) != \DIRECTORY_SEPARATOR) {
  22229. $directory .= \DIRECTORY_SEPARATOR;
  22230. }
  22231. \PHPUnit\SebastianBergmann\CodeCoverage\Directory::create($directory);
  22232. return $directory;
  22233. }
  22234. }
  22235. <?php
  22236. declare (strict_types=1);
  22237. /*
  22238. * This file is part of phpunit/php-code-coverage.
  22239. *
  22240. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  22241. *
  22242. * For the full copyright and license information, please view the LICENSE
  22243. * file that was distributed with this source code.
  22244. */
  22245. namespace PHPUnit\SebastianBergmann\CodeCoverage\Report\Html;
  22246. use PHPUnit\SebastianBergmann\CodeCoverage\Node\AbstractNode;
  22247. use PHPUnit\SebastianBergmann\CodeCoverage\Node\Directory as DirectoryNode;
  22248. use PHPUnit\SebastianBergmann\CodeCoverage\Node\File as FileNode;
  22249. use PHPUnit\SebastianBergmann\CodeCoverage\Version;
  22250. use PHPUnit\SebastianBergmann\Environment\Runtime;
  22251. use PHPUnit\SebastianBergmann\Template\Template;
  22252. /**
  22253. * Base class for node renderers.
  22254. */
  22255. abstract class Renderer
  22256. {
  22257. /**
  22258. * @var string
  22259. */
  22260. protected $templatePath;
  22261. /**
  22262. * @var string
  22263. */
  22264. protected $generator;
  22265. /**
  22266. * @var string
  22267. */
  22268. protected $date;
  22269. /**
  22270. * @var int
  22271. */
  22272. protected $lowUpperBound;
  22273. /**
  22274. * @var int
  22275. */
  22276. protected $highLowerBound;
  22277. /**
  22278. * @var string
  22279. */
  22280. protected $version;
  22281. public function __construct(string $templatePath, string $generator, string $date, int $lowUpperBound, int $highLowerBound)
  22282. {
  22283. $this->templatePath = $templatePath;
  22284. $this->generator = $generator;
  22285. $this->date = $date;
  22286. $this->lowUpperBound = $lowUpperBound;
  22287. $this->highLowerBound = $highLowerBound;
  22288. $this->version = \PHPUnit\SebastianBergmann\CodeCoverage\Version::id();
  22289. }
  22290. protected function renderItemTemplate(\PHPUnit\SebastianBergmann\Template\Template $template, array $data) : string
  22291. {
  22292. $numSeparator = '&nbsp;/&nbsp;';
  22293. if (isset($data['numClasses']) && $data['numClasses'] > 0) {
  22294. $classesLevel = $this->getColorLevel($data['testedClassesPercent']);
  22295. $classesNumber = $data['numTestedClasses'] . $numSeparator . $data['numClasses'];
  22296. $classesBar = $this->getCoverageBar($data['testedClassesPercent']);
  22297. } else {
  22298. $classesLevel = '';
  22299. $classesNumber = '0' . $numSeparator . '0';
  22300. $classesBar = '';
  22301. $data['testedClassesPercentAsString'] = 'n/a';
  22302. }
  22303. if ($data['numMethods'] > 0) {
  22304. $methodsLevel = $this->getColorLevel($data['testedMethodsPercent']);
  22305. $methodsNumber = $data['numTestedMethods'] . $numSeparator . $data['numMethods'];
  22306. $methodsBar = $this->getCoverageBar($data['testedMethodsPercent']);
  22307. } else {
  22308. $methodsLevel = '';
  22309. $methodsNumber = '0' . $numSeparator . '0';
  22310. $methodsBar = '';
  22311. $data['testedMethodsPercentAsString'] = 'n/a';
  22312. }
  22313. if ($data['numExecutableLines'] > 0) {
  22314. $linesLevel = $this->getColorLevel($data['linesExecutedPercent']);
  22315. $linesNumber = $data['numExecutedLines'] . $numSeparator . $data['numExecutableLines'];
  22316. $linesBar = $this->getCoverageBar($data['linesExecutedPercent']);
  22317. } else {
  22318. $linesLevel = '';
  22319. $linesNumber = '0' . $numSeparator . '0';
  22320. $linesBar = '';
  22321. $data['linesExecutedPercentAsString'] = 'n/a';
  22322. }
  22323. $template->setVar(['icon' => $data['icon'] ?? '', 'crap' => $data['crap'] ?? '', 'name' => $data['name'], 'lines_bar' => $linesBar, 'lines_executed_percent' => $data['linesExecutedPercentAsString'], 'lines_level' => $linesLevel, 'lines_number' => $linesNumber, 'methods_bar' => $methodsBar, 'methods_tested_percent' => $data['testedMethodsPercentAsString'], 'methods_level' => $methodsLevel, 'methods_number' => $methodsNumber, 'classes_bar' => $classesBar, 'classes_tested_percent' => $data['testedClassesPercentAsString'] ?? '', 'classes_level' => $classesLevel, 'classes_number' => $classesNumber]);
  22324. return $template->render();
  22325. }
  22326. protected function setCommonTemplateVariables(\PHPUnit\SebastianBergmann\Template\Template $template, \PHPUnit\SebastianBergmann\CodeCoverage\Node\AbstractNode $node) : void
  22327. {
  22328. $template->setVar(['id' => $node->getId(), 'full_path' => $node->getPath(), 'path_to_root' => $this->getPathToRoot($node), 'breadcrumbs' => $this->getBreadcrumbs($node), 'date' => $this->date, 'version' => $this->version, 'runtime' => $this->getRuntimeString(), 'generator' => $this->generator, 'low_upper_bound' => $this->lowUpperBound, 'high_lower_bound' => $this->highLowerBound]);
  22329. }
  22330. protected function getBreadcrumbs(\PHPUnit\SebastianBergmann\CodeCoverage\Node\AbstractNode $node) : string
  22331. {
  22332. $breadcrumbs = '';
  22333. $path = $node->getPathAsArray();
  22334. $pathToRoot = [];
  22335. $max = \count($path);
  22336. if ($node instanceof \PHPUnit\SebastianBergmann\CodeCoverage\Node\File) {
  22337. $max--;
  22338. }
  22339. for ($i = 0; $i < $max; $i++) {
  22340. $pathToRoot[] = \str_repeat('../', $i);
  22341. }
  22342. foreach ($path as $step) {
  22343. if ($step !== $node) {
  22344. $breadcrumbs .= $this->getInactiveBreadcrumb($step, \array_pop($pathToRoot));
  22345. } else {
  22346. $breadcrumbs .= $this->getActiveBreadcrumb($step);
  22347. }
  22348. }
  22349. return $breadcrumbs;
  22350. }
  22351. protected function getActiveBreadcrumb(\PHPUnit\SebastianBergmann\CodeCoverage\Node\AbstractNode $node) : string
  22352. {
  22353. $buffer = \sprintf(' <li class="breadcrumb-item active">%s</li>' . "\n", $node->getName());
  22354. if ($node instanceof \PHPUnit\SebastianBergmann\CodeCoverage\Node\Directory) {
  22355. $buffer .= ' <li class="breadcrumb-item">(<a href="dashboard.html">Dashboard</a>)</li>' . "\n";
  22356. }
  22357. return $buffer;
  22358. }
  22359. protected function getInactiveBreadcrumb(\PHPUnit\SebastianBergmann\CodeCoverage\Node\AbstractNode $node, string $pathToRoot) : string
  22360. {
  22361. return \sprintf(' <li class="breadcrumb-item"><a href="%sindex.html">%s</a></li>' . "\n", $pathToRoot, $node->getName());
  22362. }
  22363. protected function getPathToRoot(\PHPUnit\SebastianBergmann\CodeCoverage\Node\AbstractNode $node) : string
  22364. {
  22365. $id = $node->getId();
  22366. $depth = \substr_count($id, '/');
  22367. if ($id !== 'index' && $node instanceof \PHPUnit\SebastianBergmann\CodeCoverage\Node\Directory) {
  22368. $depth++;
  22369. }
  22370. return \str_repeat('../', $depth);
  22371. }
  22372. protected function getCoverageBar(float $percent) : string
  22373. {
  22374. $level = $this->getColorLevel($percent);
  22375. $template = new \PHPUnit\SebastianBergmann\Template\Template($this->templatePath . 'coverage_bar.html', '{{', '}}');
  22376. $template->setVar(['level' => $level, 'percent' => \sprintf('%.2F', $percent)]);
  22377. return $template->render();
  22378. }
  22379. protected function getColorLevel(float $percent) : string
  22380. {
  22381. if ($percent <= $this->lowUpperBound) {
  22382. return 'danger';
  22383. }
  22384. if ($percent > $this->lowUpperBound && $percent < $this->highLowerBound) {
  22385. return 'warning';
  22386. }
  22387. return 'success';
  22388. }
  22389. private function getRuntimeString() : string
  22390. {
  22391. $runtime = new \PHPUnit\SebastianBergmann\Environment\Runtime();
  22392. $buffer = \sprintf('<a href="%s" target="_top">%s %s</a>', $runtime->getVendorUrl(), $runtime->getName(), $runtime->getVersion());
  22393. if ($runtime->hasPHPDBGCodeCoverage()) {
  22394. return $buffer;
  22395. }
  22396. if ($runtime->hasPCOV()) {
  22397. $buffer .= \sprintf(' with <a href="https://github.com/krakjoe/pcov">PCOV %s</a>', \phpversion('pcov'));
  22398. } elseif ($runtime->hasXdebug()) {
  22399. $buffer .= \sprintf(' with <a href="https://xdebug.org/">Xdebug %s</a>', \phpversion('xdebug'));
  22400. }
  22401. return $buffer;
  22402. }
  22403. }
  22404. <!DOCTYPE html>
  22405. <html lang="en">
  22406. <head>
  22407. <meta charset="UTF-8">
  22408. <title>Code Coverage for {{full_path}}</title>
  22409. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  22410. <link href="{{path_to_root}}_css/bootstrap.min.css" rel="stylesheet" type="text/css">
  22411. <link href="{{path_to_root}}_css/octicons.css" rel="stylesheet" type="text/css">
  22412. <link href="{{path_to_root}}_css/style.css" rel="stylesheet" type="text/css">
  22413. <link href="{{path_to_root}}_css/custom.css" rel="stylesheet" type="text/css">
  22414. </head>
  22415. <body>
  22416. <header>
  22417. <div class="container-fluid">
  22418. <div class="row">
  22419. <div class="col-md-12">
  22420. <nav aria-label="breadcrumb">
  22421. <ol class="breadcrumb">
  22422. {{breadcrumbs}}
  22423. </ol>
  22424. </nav>
  22425. </div>
  22426. </div>
  22427. </div>
  22428. </header>
  22429. <div class="container-fluid">
  22430. <div class="table-responsive">
  22431. <table class="table table-bordered">
  22432. <thead>
  22433. <tr>
  22434. <td>&nbsp;</td>
  22435. <td colspan="10"><div align="center"><strong>Code Coverage</strong></div></td>
  22436. </tr>
  22437. <tr>
  22438. <td>&nbsp;</td>
  22439. <td colspan="3"><div align="center"><strong>Classes and Traits</strong></div></td>
  22440. <td colspan="4"><div align="center"><strong>Functions and Methods</strong></div></td>
  22441. <td colspan="3"><div align="center"><strong>Lines</strong></div></td>
  22442. </tr>
  22443. </thead>
  22444. <tbody>
  22445. {{items}}
  22446. </tbody>
  22447. </table>
  22448. </div>
  22449. <table id="code" class="table table-borderless table-condensed">
  22450. <tbody>
  22451. {{lines}}
  22452. </tbody>
  22453. </table>
  22454. <footer>
  22455. <hr/>
  22456. <h4>Legend</h4>
  22457. <p>
  22458. <span class="success"><strong>Executed</strong></span>
  22459. <span class="danger"><strong>Not Executed</strong></span>
  22460. <span class="warning"><strong>Dead Code</strong></span>
  22461. </p>
  22462. <p>
  22463. <small>Generated by <a href="https://github.com/sebastianbergmann/php-code-coverage" target="_top">php-code-coverage {{version}}</a> using {{runtime}}{{generator}} at {{date}}.</small>
  22464. </p>
  22465. <a title="Back to the top" id="toplink" href="#">
  22466. <svg xmlns="http://www.w3.org/2000/svg" width="12" height="16" viewBox="0 0 12 16"><path fill-rule="evenodd" d="M12 11L6 5l-6 6h12z"/></svg>
  22467. </a>
  22468. </footer>
  22469. </div>
  22470. <script src="{{path_to_root}}_js/jquery.min.js" type="text/javascript"></script>
  22471. <script src="{{path_to_root}}_js/popper.min.js" type="text/javascript"></script>
  22472. <script src="{{path_to_root}}_js/bootstrap.min.js" type="text/javascript"></script>
  22473. <script src="{{path_to_root}}_js/file.js" type="text/javascript"></script>
  22474. </body>
  22475. </html>
  22476. <!DOCTYPE html>
  22477. <html lang="en">
  22478. <head>
  22479. <meta charset="UTF-8">
  22480. <title>Dashboard for {{full_path}}</title>
  22481. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  22482. <link href="{{path_to_root}}_css/bootstrap.min.css" rel="stylesheet" type="text/css">
  22483. <link href="{{path_to_root}}_css/nv.d3.min.css" rel="stylesheet" type="text/css">
  22484. <link href="{{path_to_root}}_css/style.css" rel="stylesheet" type="text/css">
  22485. <link href="{{path_to_root}}_css/custom.css" rel="stylesheet" type="text/css">
  22486. </head>
  22487. <body>
  22488. <header>
  22489. <div class="container-fluid">
  22490. <div class="row">
  22491. <div class="col-md-12">
  22492. <nav aria-label="breadcrumb">
  22493. <ol class="breadcrumb">
  22494. {{breadcrumbs}}
  22495. </ol>
  22496. </nav>
  22497. </div>
  22498. </div>
  22499. </div>
  22500. </header>
  22501. <div class="container-fluid">
  22502. <div class="row">
  22503. <div class="col-md-12">
  22504. <h2>Classes</h2>
  22505. </div>
  22506. </div>
  22507. <div class="row">
  22508. <div class="col-md-6">
  22509. <h3>Coverage Distribution</h3>
  22510. <div id="classCoverageDistribution" style="height: 300px;">
  22511. <svg></svg>
  22512. </div>
  22513. </div>
  22514. <div class="col-md-6">
  22515. <h3>Complexity</h3>
  22516. <div id="classComplexity" style="height: 300px;">
  22517. <svg></svg>
  22518. </div>
  22519. </div>
  22520. </div>
  22521. <div class="row">
  22522. <div class="col-md-6">
  22523. <h3>Insufficient Coverage</h3>
  22524. <div class="scrollbox">
  22525. <table class="table">
  22526. <thead>
  22527. <tr>
  22528. <th>Class</th>
  22529. <th class="text-right">Coverage</th>
  22530. </tr>
  22531. </thead>
  22532. <tbody>
  22533. {{insufficient_coverage_classes}}
  22534. </tbody>
  22535. </table>
  22536. </div>
  22537. </div>
  22538. <div class="col-md-6">
  22539. <h3>Project Risks</h3>
  22540. <div class="scrollbox">
  22541. <table class="table">
  22542. <thead>
  22543. <tr>
  22544. <th>Class</th>
  22545. <th class="text-right"><abbr title="Change Risk Anti-Patterns (CRAP) Index">CRAP</abbr></th>
  22546. </tr>
  22547. </thead>
  22548. <tbody>
  22549. {{project_risks_classes}}
  22550. </tbody>
  22551. </table>
  22552. </div>
  22553. </div>
  22554. </div>
  22555. <div class="row">
  22556. <div class="col-md-12">
  22557. <h2>Methods</h2>
  22558. </div>
  22559. </div>
  22560. <div class="row">
  22561. <div class="col-md-6">
  22562. <h3>Coverage Distribution</h3>
  22563. <div id="methodCoverageDistribution" style="height: 300px;">
  22564. <svg></svg>
  22565. </div>
  22566. </div>
  22567. <div class="col-md-6">
  22568. <h3>Complexity</h3>
  22569. <div id="methodComplexity" style="height: 300px;">
  22570. <svg></svg>
  22571. </div>
  22572. </div>
  22573. </div>
  22574. <div class="row">
  22575. <div class="col-md-6">
  22576. <h3>Insufficient Coverage</h3>
  22577. <div class="scrollbox">
  22578. <table class="table">
  22579. <thead>
  22580. <tr>
  22581. <th>Method</th>
  22582. <th class="text-right">Coverage</th>
  22583. </tr>
  22584. </thead>
  22585. <tbody>
  22586. {{insufficient_coverage_methods}}
  22587. </tbody>
  22588. </table>
  22589. </div>
  22590. </div>
  22591. <div class="col-md-6">
  22592. <h3>Project Risks</h3>
  22593. <div class="scrollbox">
  22594. <table class="table">
  22595. <thead>
  22596. <tr>
  22597. <th>Method</th>
  22598. <th class="text-right"><abbr title="Change Risk Anti-Patterns (CRAP) Index">CRAP</abbr></th>
  22599. </tr>
  22600. </thead>
  22601. <tbody>
  22602. {{project_risks_methods}}
  22603. </tbody>
  22604. </table>
  22605. </div>
  22606. </div>
  22607. </div>
  22608. <footer>
  22609. <hr/>
  22610. <p>
  22611. <small>Generated by <a href="https://github.com/sebastianbergmann/php-code-coverage" target="_top">php-code-coverage {{version}}</a> using {{runtime}}{{generator}} at {{date}}.</small>
  22612. </p>
  22613. </footer>
  22614. </div>
  22615. <script src="{{path_to_root}}_js/jquery.min.js" type="text/javascript"></script>
  22616. <script src="{{path_to_root}}_js/d3.min.js" type="text/javascript"></script>
  22617. <script src="{{path_to_root}}_js/nv.d3.min.js" type="text/javascript"></script>
  22618. <script type="text/javascript">
  22619. $(document).ready(function() {
  22620. nv.addGraph(function() {
  22621. var chart = nv.models.multiBarChart();
  22622. chart.tooltips(false)
  22623. .showControls(false)
  22624. .showLegend(false)
  22625. .reduceXTicks(false)
  22626. .staggerLabels(true)
  22627. .yAxis.tickFormat(d3.format('d'));
  22628. d3.select('#classCoverageDistribution svg')
  22629. .datum(getCoverageDistributionData({{class_coverage_distribution}}, "Class Coverage"))
  22630. .transition().duration(500).call(chart);
  22631. nv.utils.windowResize(chart.update);
  22632. return chart;
  22633. });
  22634. nv.addGraph(function() {
  22635. var chart = nv.models.multiBarChart();
  22636. chart.tooltips(false)
  22637. .showControls(false)
  22638. .showLegend(false)
  22639. .reduceXTicks(false)
  22640. .staggerLabels(true)
  22641. .yAxis.tickFormat(d3.format('d'));
  22642. d3.select('#methodCoverageDistribution svg')
  22643. .datum(getCoverageDistributionData({{method_coverage_distribution}}, "Method Coverage"))
  22644. .transition().duration(500).call(chart);
  22645. nv.utils.windowResize(chart.update);
  22646. return chart;
  22647. });
  22648. function getCoverageDistributionData(data, label) {
  22649. var labels = [
  22650. '0%',
  22651. '0-10%',
  22652. '10-20%',
  22653. '20-30%',
  22654. '30-40%',
  22655. '40-50%',
  22656. '50-60%',
  22657. '60-70%',
  22658. '70-80%',
  22659. '80-90%',
  22660. '90-100%',
  22661. '100%'
  22662. ];
  22663. var values = [];
  22664. $.each(labels, function(key) {
  22665. values.push({x: labels[key], y: data[key]});
  22666. });
  22667. return [
  22668. {
  22669. key: label,
  22670. values: values,
  22671. color: "#4572A7"
  22672. }
  22673. ];
  22674. }
  22675. nv.addGraph(function() {
  22676. var chart = nv.models.scatterChart()
  22677. .showDistX(true)
  22678. .showDistY(true)
  22679. .showLegend(false)
  22680. .forceX([0, 100]);
  22681. chart.tooltipContent(function(graph) {
  22682. return '<p>' + graph.point.class + '</p>';
  22683. });
  22684. chart.xAxis.axisLabel('Code Coverage (in percent)');
  22685. chart.yAxis.axisLabel('Cyclomatic Complexity');
  22686. d3.select('#classComplexity svg')
  22687. .datum(getComplexityData({{complexity_class}}, 'Class Complexity'))
  22688. .transition()
  22689. .duration(500)
  22690. .call(chart);
  22691. nv.utils.windowResize(chart.update);
  22692. return chart;
  22693. });
  22694. nv.addGraph(function() {
  22695. var chart = nv.models.scatterChart()
  22696. .showDistX(true)
  22697. .showDistY(true)
  22698. .showLegend(false)
  22699. .forceX([0, 100]);
  22700. chart.tooltipContent(function(graph) {
  22701. return '<p>' + graph.point.class + '</p>';
  22702. });
  22703. chart.xAxis.axisLabel('Code Coverage (in percent)');
  22704. chart.yAxis.axisLabel('Method Complexity');
  22705. d3.select('#methodComplexity svg')
  22706. .datum(getComplexityData({{complexity_method}}, 'Method Complexity'))
  22707. .transition()
  22708. .duration(500)
  22709. .call(chart);
  22710. nv.utils.windowResize(chart.update);
  22711. return chart;
  22712. });
  22713. function getComplexityData(data, label) {
  22714. var values = [];
  22715. $.each(data, function(key) {
  22716. var value = Math.round(data[key][0]*100) / 100;
  22717. values.push({
  22718. x: value,
  22719. y: data[key][1],
  22720. class: data[key][2],
  22721. size: 0.05,
  22722. shape: 'diamond'
  22723. });
  22724. });
  22725. return [
  22726. {
  22727. key: label,
  22728. values: values,
  22729. color: "#4572A7"
  22730. }
  22731. ];
  22732. }
  22733. });
  22734. </script>
  22735. </body>
  22736. </html>
  22737. <!DOCTYPE html>
  22738. <html lang="en">
  22739. <head>
  22740. <meta charset="UTF-8">
  22741. <title>Code Coverage for {{full_path}}</title>
  22742. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  22743. <link href="{{path_to_root}}_css/bootstrap.min.css" rel="stylesheet" type="text/css">
  22744. <link href="{{path_to_root}}_css/octicons.css" rel="stylesheet" type="text/css">
  22745. <link href="{{path_to_root}}_css/style.css" rel="stylesheet" type="text/css">
  22746. <link href="{{path_to_root}}_css/custom.css" rel="stylesheet" type="text/css">
  22747. </head>
  22748. <body>
  22749. <header>
  22750. <div class="container-fluid">
  22751. <div class="row">
  22752. <div class="col-md-12">
  22753. <nav aria-label="breadcrumb">
  22754. <ol class="breadcrumb">
  22755. {{breadcrumbs}}
  22756. </ol>
  22757. </nav>
  22758. </div>
  22759. </div>
  22760. </div>
  22761. </header>
  22762. <div class="container-fluid">
  22763. <div class="table-responsive">
  22764. <table class="table table-bordered">
  22765. <thead>
  22766. <tr>
  22767. <td>&nbsp;</td>
  22768. <td colspan="9"><div align="center"><strong>Code Coverage</strong></div></td>
  22769. </tr>
  22770. <tr>
  22771. <td>&nbsp;</td>
  22772. <td colspan="3"><div align="center"><strong>Lines</strong></div></td>
  22773. <td colspan="3"><div align="center"><strong>Functions and Methods</strong></div></td>
  22774. <td colspan="3"><div align="center"><strong>Classes and Traits</strong></div></td>
  22775. </tr>
  22776. </thead>
  22777. <tbody>
  22778. {{items}}
  22779. </tbody>
  22780. </table>
  22781. </div>
  22782. <footer>
  22783. <hr/>
  22784. <h4>Legend</h4>
  22785. <p>
  22786. <span class="danger"><strong>Low</strong>: 0% to {{low_upper_bound}}%</span>
  22787. <span class="warning"><strong>Medium</strong>: {{low_upper_bound}}% to {{high_lower_bound}}%</span>
  22788. <span class="success"><strong>High</strong>: {{high_lower_bound}}% to 100%</span>
  22789. </p>
  22790. <p>
  22791. <small>Generated by <a href="https://github.com/sebastianbergmann/php-code-coverage" target="_top">php-code-coverage {{version}}</a> using {{runtime}}{{generator}} at {{date}}.</small>
  22792. </p>
  22793. </footer>
  22794. </div>
  22795. </body>
  22796. </html>
  22797. /* nvd3 version 1.8.1 (https://github.com/novus/nvd3) 2015-06-15 */
  22798. !function(){var a={};a.dev=!1,a.tooltip=a.tooltip||{},a.utils=a.utils||{},a.models=a.models||{},a.charts={},a.logs={},a.dom={},a.dispatch=d3.dispatch("render_start","render_end"),Function.prototype.bind||(Function.prototype.bind=function(a){if("function"!=typeof this)throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable");var b=Array.prototype.slice.call(arguments,1),c=this,d=function(){},e=function(){return c.apply(this instanceof d&&a?this:a,b.concat(Array.prototype.slice.call(arguments)))};return d.prototype=this.prototype,e.prototype=new d,e}),a.dev&&(a.dispatch.on("render_start",function(){a.logs.startTime=+new Date}),a.dispatch.on("render_end",function(){a.logs.endTime=+new Date,a.logs.totalTime=a.logs.endTime-a.logs.startTime,a.log("total",a.logs.totalTime)})),a.log=function(){if(a.dev&&window.console&&console.log&&console.log.apply)console.log.apply(console,arguments);else if(a.dev&&window.console&&"function"==typeof console.log&&Function.prototype.bind){var b=Function.prototype.bind.call(console.log,console);b.apply(console,arguments)}return arguments[arguments.length-1]},a.deprecated=function(a,b){console&&console.warn&&console.warn("nvd3 warning: `"+a+"` has been deprecated. ",b||"")},a.render=function(b){b=b||1,a.render.active=!0,a.dispatch.render_start();var c=function(){for(var d,e,f=0;b>f&&(e=a.render.queue[f]);f++)d=e.generate(),typeof e.callback==typeof Function&&e.callback(d);a.render.queue.splice(0,f),a.render.queue.length?setTimeout(c):(a.dispatch.render_end(),a.render.active=!1)};setTimeout(c)},a.render.active=!1,a.render.queue=[],a.addGraph=function(b){typeof arguments[0]==typeof Function&&(b={generate:arguments[0],callback:arguments[1]}),a.render.queue.push(b),a.render.active||a.render()},"undefined"!=typeof module&&"undefined"!=typeof exports&&(module.exports=a),"undefined"!=typeof window&&(window.nv=a),a.dom.write=function(a){return void 0!==window.fastdom?fastdom.write(a):a()},a.dom.read=function(a){return void 0!==window.fastdom?fastdom.read(a):a()},a.interactiveGuideline=function(){"use strict";function b(l){l.each(function(l){function m(){var a=d3.mouse(this),d=a[0],e=a[1],i=!0,j=!1;if(k&&(d=d3.event.offsetX,e=d3.event.offsetY,"svg"!==d3.event.target.tagName&&(i=!1),d3.event.target.className.baseVal.match("nv-legend")&&(j=!0)),i&&(d-=f.left,e-=f.top),0>d||0>e||d>o||e>p||d3.event.relatedTarget&&void 0===d3.event.relatedTarget.ownerSVGElement||j){if(k&&d3.event.relatedTarget&&void 0===d3.event.relatedTarget.ownerSVGElement&&(void 0===d3.event.relatedTarget.className||d3.event.relatedTarget.className.match(c.nvPointerEventsClass)))return;return h.elementMouseout({mouseX:d,mouseY:e}),b.renderGuideLine(null),void c.hidden(!0)}c.hidden(!1);var l=g.invert(d);h.elementMousemove({mouseX:d,mouseY:e,pointXValue:l}),"dblclick"===d3.event.type&&h.elementDblclick({mouseX:d,mouseY:e,pointXValue:l}),"click"===d3.event.type&&h.elementClick({mouseX:d,mouseY:e,pointXValue:l})}var n=d3.select(this),o=d||960,p=e||400,q=n.selectAll("g.nv-wrap.nv-interactiveLineLayer").data([l]),r=q.enter().append("g").attr("class"," nv-wrap nv-interactiveLineLayer");r.append("g").attr("class","nv-interactiveGuideLine"),j&&(j.on("touchmove",m).on("mousemove",m,!0).on("mouseout",m,!0).on("dblclick",m).on("click",m),b.guideLine=null,b.renderGuideLine=function(c){i&&(b.guideLine&&b.guideLine.attr("x1")===c||a.dom.write(function(){var b=q.select(".nv-interactiveGuideLine").selectAll("line").data(null!=c?[a.utils.NaNtoZero(c)]:[],String);b.enter().append("line").attr("class","nv-guideline").attr("x1",function(a){return a}).attr("x2",function(a){return a}).attr("y1",p).attr("y2",0),b.exit().remove()}))})})}var c=a.models.tooltip();c.duration(0).hideDelay(0)._isInteractiveLayer(!0).hidden(!1);var d=null,e=null,f={left:0,top:0},g=d3.scale.linear(),h=d3.dispatch("elementMousemove","elementMouseout","elementClick","elementDblclick"),i=!0,j=null,k="ActiveXObject"in window;return b.dispatch=h,b.tooltip=c,b.margin=function(a){return arguments.length?(f.top="undefined"!=typeof a.top?a.top:f.top,f.left="undefined"!=typeof a.left?a.left:f.left,b):f},b.width=function(a){return arguments.length?(d=a,b):d},b.height=function(a){return arguments.length?(e=a,b):e},b.xScale=function(a){return arguments.length?(g=a,b):g},b.showGuideLine=function(a){return arguments.length?(i=a,b):i},b.svgContainer=function(a){return arguments.length?(j=a,b):j},b},a.interactiveBisect=function(a,b,c){"use strict";if(!(a instanceof Array))return null;var d;d="function"!=typeof c?function(a){return a.x}:c;var e=function(a,b){return d(a)-b},f=d3.bisector(e).left,g=d3.max([0,f(a,b)-1]),h=d(a[g]);if("undefined"==typeof h&&(h=g),h===b)return g;var i=d3.min([g+1,a.length-1]),j=d(a[i]);return"undefined"==typeof j&&(j=i),Math.abs(j-b)>=Math.abs(h-b)?g:i},a.nearestValueIndex=function(a,b,c){"use strict";var d=1/0,e=null;return a.forEach(function(a,f){var g=Math.abs(b-a);null!=a&&d>=g&&c>g&&(d=g,e=f)}),e},function(){"use strict";a.models.tooltip=function(){function b(){if(k){var a=d3.select(k);"svg"!==a.node().tagName&&(a=a.select("svg"));var b=a.node()?a.attr("viewBox"):null;if(b){b=b.split(" ");var c=parseInt(a.style("width"),10)/b[2];p.left=p.left*c,p.top=p.top*c}}}function c(){if(!n){var a;a=k?k:document.body,n=d3.select(a).append("div").attr("class","nvtooltip "+(j?j:"xy-tooltip")).attr("id",v),n.style("top",0).style("left",0),n.style("opacity",0),n.selectAll("div, table, td, tr").classed(w,!0),n.classed(w,!0),o=n.node()}}function d(){if(r&&B(e)){b();var f=p.left,g=null!==i?i:p.top;return a.dom.write(function(){c();var b=A(e);b&&(o.innerHTML=b),k&&u?a.dom.read(function(){var a=k.getElementsByTagName("svg")[0],b={left:0,top:0};if(a){var c=a.getBoundingClientRect(),d=k.getBoundingClientRect(),e=c.top;if(0>e){var i=k.getBoundingClientRect();e=Math.abs(e)>i.height?0:e}b.top=Math.abs(e-d.top),b.left=Math.abs(c.left-d.left)}f+=k.offsetLeft+b.left-2*k.scrollLeft,g+=k.offsetTop+b.top-2*k.scrollTop,h&&h>0&&(g=Math.floor(g/h)*h),C([f,g])}):C([f,g])}),d}}var e=null,f="w",g=25,h=0,i=null,j=null,k=null,l=!0,m=400,n=null,o=null,p={left:null,top:null},q={left:0,top:0},r=!0,s=100,t=!0,u=!1,v="nvtooltip-"+Math.floor(1e5*Math.random()),w="nv-pointer-events-none",x=function(a){return a},y=function(a){return a},z=function(a){return a},A=function(a){if(null===a)return"";var b=d3.select(document.createElement("table"));if(t){var c=b.selectAll("thead").data([a]).enter().append("thead");c.append("tr").append("td").attr("colspan",3).append("strong").classed("x-value",!0).html(y(a.value))}var d=b.selectAll("tbody").data([a]).enter().append("tbody"),e=d.selectAll("tr").data(function(a){return a.series}).enter().append("tr").classed("highlight",function(a){return a.highlight});e.append("td").classed("legend-color-guide",!0).append("div").style("background-color",function(a){return a.color}),e.append("td").classed("key",!0).html(function(a,b){return z(a.key,b)}),e.append("td").classed("value",!0).html(function(a,b){return x(a.value,b)}),e.selectAll("td").each(function(a){if(a.highlight){var b=d3.scale.linear().domain([0,1]).range(["#fff",a.color]),c=.6;d3.select(this).style("border-bottom-color",b(c)).style("border-top-color",b(c))}});var f=b.node().outerHTML;return void 0!==a.footer&&(f+="<div class='footer'>"+a.footer+"</div>"),f},B=function(a){if(a&&a.series){if(a.series instanceof Array)return!!a.series.length;if(a.series instanceof Object)return a.series=[a.series],!0}return!1},C=function(b){o&&a.dom.read(function(){var c,d,e=parseInt(o.offsetHeight,10),h=parseInt(o.offsetWidth,10),i=a.utils.windowSize().width,j=a.utils.windowSize().height,k=window.pageYOffset,p=window.pageXOffset;j=window.innerWidth>=document.body.scrollWidth?j:j-16,i=window.innerHeight>=document.body.scrollHeight?i:i-16;var r,t,u=function(a){var b=d;do isNaN(a.offsetTop)||(b+=a.offsetTop),a=a.offsetParent;while(a);return b},v=function(a){var b=c;do isNaN(a.offsetLeft)||(b+=a.offsetLeft),a=a.offsetParent;while(a);return b};switch(f){case"e":c=b[0]-h-g,d=b[1]-e/2,r=v(o),t=u(o),p>r&&(c=b[0]+g>p?b[0]+g:p-r+c),k>t&&(d=k-t+d),t+e>k+j&&(d=k+j-t+d-e);break;case"w":c=b[0]+g,d=b[1]-e/2,r=v(o),t=u(o),r+h>i&&(c=b[0]-h-g),k>t&&(d=k+5),t+e>k+j&&(d=k+j-t+d-e);break;case"n":c=b[0]-h/2-5,d=b[1]+g,r=v(o),t=u(o),p>r&&(c=p+5),r+h>i&&(c=c-h/2+5),t+e>k+j&&(d=k+j-t+d-e);break;case"s":c=b[0]-h/2,d=b[1]-e-g,r=v(o),t=u(o),p>r&&(c=p+5),r+h>i&&(c=c-h/2+5),k>t&&(d=k);break;case"none":c=b[0],d=b[1]-g,r=v(o),t=u(o)}c-=q.left,d-=q.top;var w=o.getBoundingClientRect(),k=window.pageYOffset||document.documentElement.scrollTop,p=window.pageXOffset||document.documentElement.scrollLeft,x="translate("+(w.left+p)+"px, "+(w.top+k)+"px)",y="translate("+c+"px, "+d+"px)",z=d3.interpolateString(x,y),A=n.style("opacity")<.1;l?n.transition().delay(m).duration(0).style("opacity",0):n.interrupt().transition().duration(A?0:s).styleTween("transform",function(){return z},"important").style("-webkit-transform",y).style("opacity",1)})};return d.nvPointerEventsClass=w,d.options=a.utils.optionsFunc.bind(d),d._options=Object.create({},{duration:{get:function(){return s},set:function(a){s=a}},gravity:{get:function(){return f},set:function(a){f=a}},distance:{get:function(){return g},set:function(a){g=a}},snapDistance:{get:function(){return h},set:function(a){h=a}},classes:{get:function(){return j},set:function(a){j=a}},chartContainer:{get:function(){return k},set:function(a){k=a}},fixedTop:{get:function(){return i},set:function(a){i=a}},enabled:{get:function(){return r},set:function(a){r=a}},hideDelay:{get:function(){return m},set:function(a){m=a}},contentGenerator:{get:function(){return A},set:function(a){A=a}},valueFormatter:{get:function(){return x},set:function(a){x=a}},headerFormatter:{get:function(){return y},set:function(a){y=a}},keyFormatter:{get:function(){return z},set:function(a){z=a}},headerEnabled:{get:function(){return t},set:function(a){t=a}},_isInteractiveLayer:{get:function(){return u},set:function(a){u=!!a}},position:{get:function(){return p},set:function(a){p.left=void 0!==a.left?a.left:p.left,p.top=void 0!==a.top?a.top:p.top}},offset:{get:function(){return q},set:function(a){q.left=void 0!==a.left?a.left:q.left,q.top=void 0!==a.top?a.top:q.top}},hidden:{get:function(){return l},set:function(a){l!=a&&(l=!!a,d())}},data:{get:function(){return e},set:function(a){a.point&&(a.value=a.point.x,a.series=a.series||{},a.series.value=a.point.y,a.series.color=a.point.color||a.series.color),e=a}},tooltipElem:{get:function(){return o},set:function(){}},id:{get:function(){return v},set:function(){}}}),a.utils.initOptions(d),d}}(),a.utils.windowSize=function(){var a={width:640,height:480};return window.innerWidth&&window.innerHeight?(a.width=window.innerWidth,a.height=window.innerHeight,a):"CSS1Compat"==document.compatMode&&document.documentElement&&document.documentElement.offsetWidth?(a.width=document.documentElement.offsetWidth,a.height=document.documentElement.offsetHeight,a):document.body&&document.body.offsetWidth?(a.width=document.body.offsetWidth,a.height=document.body.offsetHeight,a):a},a.utils.windowResize=function(b){return window.addEventListener?window.addEventListener("resize",b):a.log("ERROR: Failed to bind to window.resize with: ",b),{callback:b,clear:function(){window.removeEventListener("resize",b)}}},a.utils.getColor=function(b){if(void 0===b)return a.utils.defaultColor();if(Array.isArray(b)){var c=d3.scale.ordinal().range(b);return function(a,b){var d=void 0===b?a:b;return a.color||c(d)}}return b},a.utils.defaultColor=function(){return a.utils.getColor(d3.scale.category20().range())},a.utils.customTheme=function(a,b,c){b=b||function(a){return a.key},c=c||d3.scale.category20().range();var d=c.length;return function(e){var f=b(e);return"function"==typeof a[f]?a[f]():void 0!==a[f]?a[f]:(d||(d=c.length),d-=1,c[d])}},a.utils.pjax=function(b,c){var d=function(d){d3.html(d,function(d){var e=d3.select(c).node();e.parentNode.replaceChild(d3.select(d).select(c).node(),e),a.utils.pjax(b,c)})};d3.selectAll(b).on("click",function(){history.pushState(this.href,this.textContent,this.href),d(this.href),d3.event.preventDefault()}),d3.select(window).on("popstate",function(){d3.event.state&&d(d3.event.state)})},a.utils.calcApproxTextWidth=function(a){if("function"==typeof a.style&&"function"==typeof a.text){var b=parseInt(a.style("font-size").replace("px",""),10),c=a.text().length;return c*b*.5}return 0},a.utils.NaNtoZero=function(a){return"number"!=typeof a||isNaN(a)||null===a||1/0===a||a===-1/0?0:a},d3.selection.prototype.watchTransition=function(a){var b=[this].concat([].slice.call(arguments,1));return a.transition.apply(a,b)},a.utils.renderWatch=function(b,c){if(!(this instanceof a.utils.renderWatch))return new a.utils.renderWatch(b,c);var d=void 0!==c?c:250,e=[],f=this;this.models=function(a){return a=[].slice.call(arguments,0),a.forEach(function(a){a.__rendered=!1,function(a){a.dispatch.on("renderEnd",function(){a.__rendered=!0,f.renderEnd("model")})}(a),e.indexOf(a)<0&&e.push(a)}),this},this.reset=function(a){void 0!==a&&(d=a),e=[]},this.transition=function(a,b,c){if(b=arguments.length>1?[].slice.call(arguments,1):[],c=b.length>1?b.pop():void 0!==d?d:250,a.__rendered=!1,e.indexOf(a)<0&&e.push(a),0===c)return a.__rendered=!0,a.delay=function(){return this},a.duration=function(){return this},a;a.__rendered=0===a.length?!0:a.every(function(a){return!a.length})?!0:!1;var g=0;return a.transition().duration(c).each(function(){++g}).each("end",function(){0===--g&&(a.__rendered=!0,f.renderEnd.apply(this,b))})},this.renderEnd=function(){e.every(function(a){return a.__rendered})&&(e.forEach(function(a){a.__rendered=!1}),b.renderEnd.apply(this,arguments))}},a.utils.deepExtend=function(b){var c=arguments.length>1?[].slice.call(arguments,1):[];c.forEach(function(c){for(var d in c){var e=b[d]instanceof Array,f="object"==typeof b[d],g="object"==typeof c[d];f&&!e&&g?a.utils.deepExtend(b[d],c[d]):b[d]=c[d]}})},a.utils.state=function(){if(!(this instanceof a.utils.state))return new a.utils.state;var b={},c=function(){},d=function(){return{}},e=null,f=null;this.dispatch=d3.dispatch("change","set"),this.dispatch.on("set",function(a){c(a,!0)}),this.getter=function(a){return d=a,this},this.setter=function(a,b){return b||(b=function(){}),c=function(c,d){a(c),d&&b()},this},this.init=function(b){e=e||{},a.utils.deepExtend(e,b)};var g=function(){var a=d();if(JSON.stringify(a)===JSON.stringify(b))return!1;for(var c in a)void 0===b[c]&&(b[c]={}),b[c]=a[c],f=!0;return!0};this.update=function(){e&&(c(e,!1),e=null),g.call(this)&&this.dispatch.change(b)}},a.utils.optionsFunc=function(a){return a&&d3.map(a).forEach(function(a,b){"function"==typeof this[a]&&this[a](b)}.bind(this)),this},a.utils.calcTicksX=function(b,c){var d=1,e=0;for(e;e<c.length;e+=1){var f=c[e]&&c[e].values?c[e].values.length:0;d=f>d?f:d}return a.log("Requested number of ticks: ",b),a.log("Calculated max values to be: ",d),b=b>d?b=d-1:b,b=1>b?1:b,b=Math.floor(b),a.log("Calculating tick count as: ",b),b},a.utils.calcTicksY=function(b,c){return a.utils.calcTicksX(b,c)},a.utils.initOption=function(a,b){a._calls&&a._calls[b]?a[b]=a._calls[b]:(a[b]=function(c){return arguments.length?(a._overrides[b]=!0,a._options[b]=c,a):a._options[b]},a["_"+b]=function(c){return arguments.length?(a._overrides[b]||(a._options[b]=c),a):a._options[b]})},a.utils.initOptions=function(b){b._overrides=b._overrides||{};var c=Object.getOwnPropertyNames(b._options||{}),d=Object.getOwnPropertyNames(b._calls||{});c=c.concat(d);for(var e in c)a.utils.initOption(b,c[e])},a.utils.inheritOptionsD3=function(a,b,c){a._d3options=c.concat(a._d3options||[]),c.unshift(b),c.unshift(a),d3.rebind.apply(this,c)},a.utils.arrayUnique=function(a){return a.sort().filter(function(b,c){return!c||b!=a[c-1]})},a.utils.symbolMap=d3.map(),a.utils.symbol=function(){function b(b,e){var f=c.call(this,b,e),g=d.call(this,b,e);return-1!==d3.svg.symbolTypes.indexOf(f)?d3.svg.symbol().type(f).size(g)():a.utils.symbolMap.get(f)(g)}var c,d=64;return b.type=function(a){return arguments.length?(c=d3.functor(a),b):c},b.size=function(a){return arguments.length?(d=d3.functor(a),b):d},b},a.utils.inheritOptions=function(b,c){var d=Object.getOwnPropertyNames(c._options||{}),e=Object.getOwnPropertyNames(c._calls||{}),f=c._inherited||[],g=c._d3options||[],h=d.concat(e).concat(f).concat(g);h.unshift(c),h.unshift(b),d3.rebind.apply(this,h),b._inherited=a.utils.arrayUnique(d.concat(e).concat(f).concat(d).concat(b._inherited||[])),b._d3options=a.utils.arrayUnique(g.concat(b._d3options||[]))},a.utils.initSVG=function(a){a.classed({"nvd3-svg":!0})},a.utils.sanitizeHeight=function(a,b){return a||parseInt(b.style("height"),10)||400},a.utils.sanitizeWidth=function(a,b){return a||parseInt(b.style("width"),10)||960},a.utils.availableHeight=function(b,c,d){return a.utils.sanitizeHeight(b,c)-d.top-d.bottom},a.utils.availableWidth=function(b,c,d){return a.utils.sanitizeWidth(b,c)-d.left-d.right},a.utils.noData=function(b,c){var d=b.options(),e=d.margin(),f=d.noData(),g=null==f?["No Data Available."]:[f],h=a.utils.availableHeight(d.height(),c,e),i=a.utils.availableWidth(d.width(),c,e),j=e.left+i/2,k=e.top+h/2;c.selectAll("g").remove();var l=c.selectAll(".nv-noData").data(g);l.enter().append("text").attr("class","nvd3 nv-noData").attr("dy","-.7em").style("text-anchor","middle"),l.attr("x",j).attr("y",k).text(function(a){return a})},a.models.axis=function(){"use strict";function b(g){return s.reset(),g.each(function(b){var g=d3.select(this);a.utils.initSVG(g);var p=g.selectAll("g.nv-wrap.nv-axis").data([b]),q=p.enter().append("g").attr("class","nvd3 nv-wrap nv-axis"),t=(q.append("g"),p.select("g"));null!==n?c.ticks(n):("top"==c.orient()||"bottom"==c.orient())&&c.ticks(Math.abs(d.range()[1]-d.range()[0])/100),t.watchTransition(s,"axis").call(c),r=r||c.scale();var u=c.tickFormat();null==u&&(u=r.tickFormat());var v=t.selectAll("text.nv-axislabel").data([h||null]);v.exit().remove();var w,x,y;switch(c.orient()){case"top":v.enter().append("text").attr("class","nv-axislabel"),y=d.range().length<2?0:2===d.range().length?d.range()[1]:d.range()[d.range().length-1]+(d.range()[1]-d.range()[0]),v.attr("text-anchor","middle").attr("y",0).attr("x",y/2),i&&(x=p.selectAll("g.nv-axisMaxMin").data(d.domain()),x.enter().append("g").attr("class",function(a,b){return["nv-axisMaxMin","nv-axisMaxMin-x",0==b?"nv-axisMin-x":"nv-axisMax-x"].join(" ")}).append("text"),x.exit().remove(),x.attr("transform",function(b){return"translate("+a.utils.NaNtoZero(d(b))+",0)"}).select("text").attr("dy","-0.5em").attr("y",-c.tickPadding()).attr("text-anchor","middle").text(function(a){var b=u(a);return(""+b).match("NaN")?"":b}),x.watchTransition(s,"min-max top").attr("transform",function(b,c){return"translate("+a.utils.NaNtoZero(d.range()[c])+",0)"}));break;case"bottom":w=o+36;var z=30,A=0,B=t.selectAll("g").select("text"),C="";if(j%360){B.each(function(){var a=this.getBoundingClientRect(),b=a.width;A=a.height,b>z&&(z=b)}),C="rotate("+j+" 0,"+(A/2+c.tickPadding())+")";var D=Math.abs(Math.sin(j*Math.PI/180));w=(D?D*z:z)+30,B.attr("transform",C).style("text-anchor",j%360>0?"start":"end")}v.enter().append("text").attr("class","nv-axislabel"),y=d.range().length<2?0:2===d.range().length?d.range()[1]:d.range()[d.range().length-1]+(d.range()[1]-d.range()[0]),v.attr("text-anchor","middle").attr("y",w).attr("x",y/2),i&&(x=p.selectAll("g.nv-axisMaxMin").data([d.domain()[0],d.domain()[d.domain().length-1]]),x.enter().append("g").attr("class",function(a,b){return["nv-axisMaxMin","nv-axisMaxMin-x",0==b?"nv-axisMin-x":"nv-axisMax-x"].join(" ")}).append("text"),x.exit().remove(),x.attr("transform",function(b){return"translate("+a.utils.NaNtoZero(d(b)+(m?d.rangeBand()/2:0))+",0)"}).select("text").attr("dy",".71em").attr("y",c.tickPadding()).attr("transform",C).style("text-anchor",j?j%360>0?"start":"end":"middle").text(function(a){var b=u(a);return(""+b).match("NaN")?"":b}),x.watchTransition(s,"min-max bottom").attr("transform",function(b){return"translate("+a.utils.NaNtoZero(d(b)+(m?d.rangeBand()/2:0))+",0)"})),l&&B.attr("transform",function(a,b){return"translate(0,"+(b%2==0?"0":"12")+")"});break;case"right":v.enter().append("text").attr("class","nv-axislabel"),v.style("text-anchor",k?"middle":"begin").attr("transform",k?"rotate(90)":"").attr("y",k?-Math.max(e.right,f)+12:-10).attr("x",k?d3.max(d.range())/2:c.tickPadding()),i&&(x=p.selectAll("g.nv-axisMaxMin").data(d.domain()),x.enter().append("g").attr("class",function(a,b){return["nv-axisMaxMin","nv-axisMaxMin-y",0==b?"nv-axisMin-y":"nv-axisMax-y"].join(" ")}).append("text").style("opacity",0),x.exit().remove(),x.attr("transform",function(b){return"translate(0,"+a.utils.NaNtoZero(d(b))+")"}).select("text").attr("dy",".32em").attr("y",0).attr("x",c.tickPadding()).style("text-anchor","start").text(function(a){var b=u(a);return(""+b).match("NaN")?"":b}),x.watchTransition(s,"min-max right").attr("transform",function(b,c){return"translate(0,"+a.utils.NaNtoZero(d.range()[c])+")"}).select("text").style("opacity",1));break;case"left":v.enter().append("text").attr("class","nv-axislabel"),v.style("text-anchor",k?"middle":"end").attr("transform",k?"rotate(-90)":"").attr("y",k?-Math.max(e.left,f)+25-(o||0):-10).attr("x",k?-d3.max(d.range())/2:-c.tickPadding()),i&&(x=p.selectAll("g.nv-axisMaxMin").data(d.domain()),x.enter().append("g").attr("class",function(a,b){return["nv-axisMaxMin","nv-axisMaxMin-y",0==b?"nv-axisMin-y":"nv-axisMax-y"].join(" ")}).append("text").style("opacity",0),x.exit().remove(),x.attr("transform",function(b){return"translate(0,"+a.utils.NaNtoZero(r(b))+")"}).select("text").attr("dy",".32em").attr("y",0).attr("x",-c.tickPadding()).attr("text-anchor","end").text(function(a){var b=u(a);return(""+b).match("NaN")?"":b}),x.watchTransition(s,"min-max right").attr("transform",function(b,c){return"translate(0,"+a.utils.NaNtoZero(d.range()[c])+")"}).select("text").style("opacity",1))}if(v.text(function(a){return a}),!i||"left"!==c.orient()&&"right"!==c.orient()||(t.selectAll("g").each(function(a){d3.select(this).select("text").attr("opacity",1),(d(a)<d.range()[1]+10||d(a)>d.range()[0]-10)&&((a>1e-10||-1e-10>a)&&d3.select(this).attr("opacity",0),d3.select(this).select("text").attr("opacity",0))}),d.domain()[0]==d.domain()[1]&&0==d.domain()[0]&&p.selectAll("g.nv-axisMaxMin").style("opacity",function(a,b){return b?0:1})),i&&("top"===c.orient()||"bottom"===c.orient())){var E=[];p.selectAll("g.nv-axisMaxMin").each(function(a,b){try{E.push(b?d(a)-this.getBoundingClientRect().width-4:d(a)+this.getBoundingClientRect().width+4)}catch(c){E.push(b?d(a)-4:d(a)+4)}}),t.selectAll("g").each(function(a){(d(a)<E[0]||d(a)>E[1])&&(a>1e-10||-1e-10>a?d3.select(this).remove():d3.select(this).select("text").remove())})}t.selectAll(".tick").filter(function(a){return!parseFloat(Math.round(1e5*a)/1e6)&&void 0!==a}).classed("zero",!0),r=d.copy()}),s.renderEnd("axis immediate"),b}var c=d3.svg.axis(),d=d3.scale.linear(),e={top:0,right:0,bottom:0,left:0},f=75,g=60,h=null,i=!0,j=0,k=!0,l=!1,m=!1,n=null,o=0,p=250,q=d3.dispatch("renderEnd");c.scale(d).orient("bottom").tickFormat(function(a){return a});var r,s=a.utils.renderWatch(q,p);return b.axis=c,b.dispatch=q,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{axisLabelDistance:{get:function(){return o},set:function(a){o=a}},staggerLabels:{get:function(){return l},set:function(a){l=a}},rotateLabels:{get:function(){return j},set:function(a){j=a}},rotateYLabel:{get:function(){return k},set:function(a){k=a}},showMaxMin:{get:function(){return i},set:function(a){i=a}},axisLabel:{get:function(){return h},set:function(a){h=a}},height:{get:function(){return g},set:function(a){g=a}},ticks:{get:function(){return n},set:function(a){n=a}},width:{get:function(){return f},set:function(a){f=a}},margin:{get:function(){return e},set:function(a){e.top=void 0!==a.top?a.top:e.top,e.right=void 0!==a.right?a.right:e.right,e.bottom=void 0!==a.bottom?a.bottom:e.bottom,e.left=void 0!==a.left?a.left:e.left}},duration:{get:function(){return p},set:function(a){p=a,s.reset(p)}},scale:{get:function(){return d},set:function(e){d=e,c.scale(d),m="function"==typeof d.rangeBands,a.utils.inheritOptionsD3(b,d,["domain","range","rangeBand","rangeBands"])}}}),a.utils.initOptions(b),a.utils.inheritOptionsD3(b,c,["orient","tickValues","tickSubdivide","tickSize","tickPadding","tickFormat"]),a.utils.inheritOptionsD3(b,d,["domain","range","rangeBand","rangeBands"]),b},a.models.boxPlot=function(){"use strict";function b(l){return v.reset(),l.each(function(b){var l=j-i.left-i.right,p=k-i.top-i.bottom;r=d3.select(this),a.utils.initSVG(r),m.domain(c||b.map(function(a,b){return o(a,b)})).rangeBands(e||[0,l],.1);var w=[];if(!d){var x=d3.min(b.map(function(a){var b=[];return b.push(a.values.Q1),a.values.hasOwnProperty("whisker_low")&&null!==a.values.whisker_low&&b.push(a.values.whisker_low),a.values.hasOwnProperty("outliers")&&null!==a.values.outliers&&(b=b.concat(a.values.outliers)),d3.min(b)})),y=d3.max(b.map(function(a){var b=[];return b.push(a.values.Q3),a.values.hasOwnProperty("whisker_high")&&null!==a.values.whisker_high&&b.push(a.values.whisker_high),a.values.hasOwnProperty("outliers")&&null!==a.values.outliers&&(b=b.concat(a.values.outliers)),d3.max(b)}));w=[x,y]}n.domain(d||w),n.range(f||[p,0]),g=g||m,h=h||n.copy().range([n(0),n(0)]);{var z=r.selectAll("g.nv-wrap").data([b]);z.enter().append("g").attr("class","nvd3 nv-wrap")}z.attr("transform","translate("+i.left+","+i.top+")");var A=z.selectAll(".nv-boxplot").data(function(a){return a}),B=A.enter().append("g").style("stroke-opacity",1e-6).style("fill-opacity",1e-6);A.attr("class","nv-boxplot").attr("transform",function(a,b){return"translate("+(m(o(a,b))+.05*m.rangeBand())+", 0)"}).classed("hover",function(a){return a.hover}),A.watchTransition(v,"nv-boxplot: boxplots").style("stroke-opacity",1).style("fill-opacity",.75).delay(function(a,c){return c*t/b.length}).attr("transform",function(a,b){return"translate("+(m(o(a,b))+.05*m.rangeBand())+", 0)"}),A.exit().remove(),B.each(function(a,b){var c=d3.select(this);["low","high"].forEach(function(d){a.values.hasOwnProperty("whisker_"+d)&&null!==a.values["whisker_"+d]&&(c.append("line").style("stroke",a.color?a.color:q(a,b)).attr("class","nv-boxplot-whisker nv-boxplot-"+d),c.append("line").style("stroke",a.color?a.color:q(a,b)).attr("class","nv-boxplot-tick nv-boxplot-"+d))})});var C=A.selectAll(".nv-boxplot-outlier").data(function(a){return a.values.hasOwnProperty("outliers")&&null!==a.values.outliers?a.values.outliers:[]});C.enter().append("circle").style("fill",function(a,b,c){return q(a,c)}).style("stroke",function(a,b,c){return q(a,c)}).on("mouseover",function(a,b,c){d3.select(this).classed("hover",!0),s.elementMouseover({series:{key:a,color:q(a,c)},e:d3.event})}).on("mouseout",function(a,b,c){d3.select(this).classed("hover",!1),s.elementMouseout({series:{key:a,color:q(a,c)},e:d3.event})}).on("mousemove",function(){s.elementMousemove({e:d3.event})}),C.attr("class","nv-boxplot-outlier"),C.watchTransition(v,"nv-boxplot: nv-boxplot-outlier").attr("cx",.45*m.rangeBand()).attr("cy",function(a){return n(a)}).attr("r","3"),C.exit().remove();var D=function(){return null===u?.9*m.rangeBand():Math.min(75,.9*m.rangeBand())},E=function(){return.45*m.rangeBand()-D()/2},F=function(){return.45*m.rangeBand()+D()/2};["low","high"].forEach(function(a){var b="low"===a?"Q1":"Q3";A.select("line.nv-boxplot-whisker.nv-boxplot-"+a).watchTransition(v,"nv-boxplot: boxplots").attr("x1",.45*m.rangeBand()).attr("y1",function(b){return n(b.values["whisker_"+a])}).attr("x2",.45*m.rangeBand()).attr("y2",function(a){return n(a.values[b])}),A.select("line.nv-boxplot-tick.nv-boxplot-"+a).watchTransition(v,"nv-boxplot: boxplots").attr("x1",E).attr("y1",function(b){return n(b.values["whisker_"+a])}).attr("x2",F).attr("y2",function(b){return n(b.values["whisker_"+a])})}),["low","high"].forEach(function(a){B.selectAll(".nv-boxplot-"+a).on("mouseover",function(b,c,d){d3.select(this).classed("hover",!0),s.elementMouseover({series:{key:b.values["whisker_"+a],color:q(b,d)},e:d3.event})}).on("mouseout",function(b,c,d){d3.select(this).classed("hover",!1),s.elementMouseout({series:{key:b.values["whisker_"+a],color:q(b,d)},e:d3.event})}).on("mousemove",function(){s.elementMousemove({e:d3.event})})}),B.append("rect").attr("class","nv-boxplot-box").on("mouseover",function(a,b){d3.select(this).classed("hover",!0),s.elementMouseover({key:a.label,value:a.label,series:[{key:"Q3",value:a.values.Q3,color:a.color||q(a,b)},{key:"Q2",value:a.values.Q2,color:a.color||q(a,b)},{key:"Q1",value:a.values.Q1,color:a.color||q(a,b)}],data:a,index:b,e:d3.event})}).on("mouseout",function(a,b){d3.select(this).classed("hover",!1),s.elementMouseout({key:a.label,value:a.label,series:[{key:"Q3",value:a.values.Q3,color:a.color||q(a,b)},{key:"Q2",value:a.values.Q2,color:a.color||q(a,b)},{key:"Q1",value:a.values.Q1,color:a.color||q(a,b)}],data:a,index:b,e:d3.event})}).on("mousemove",function(){s.elementMousemove({e:d3.event})}),A.select("rect.nv-boxplot-box").watchTransition(v,"nv-boxplot: boxes").attr("y",function(a){return n(a.values.Q3)}).attr("width",D).attr("x",E).attr("height",function(a){return Math.abs(n(a.values.Q3)-n(a.values.Q1))||1}).style("fill",function(a,b){return a.color||q(a,b)}).style("stroke",function(a,b){return a.color||q(a,b)}),B.append("line").attr("class","nv-boxplot-median"),A.select("line.nv-boxplot-median").watchTransition(v,"nv-boxplot: boxplots line").attr("x1",E).attr("y1",function(a){return n(a.values.Q2)}).attr("x2",F).attr("y2",function(a){return n(a.values.Q2)}),g=m.copy(),h=n.copy()}),v.renderEnd("nv-boxplot immediate"),b}var c,d,e,f,g,h,i={top:0,right:0,bottom:0,left:0},j=960,k=500,l=Math.floor(1e4*Math.random()),m=d3.scale.ordinal(),n=d3.scale.linear(),o=function(a){return a.x},p=function(a){return a.y},q=a.utils.defaultColor(),r=null,s=d3.dispatch("elementMouseover","elementMouseout","elementMousemove","renderEnd"),t=250,u=null,v=a.utils.renderWatch(s,t);return b.dispatch=s,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return j},set:function(a){j=a}},height:{get:function(){return k},set:function(a){k=a}},maxBoxWidth:{get:function(){return u},set:function(a){u=a}},x:{get:function(){return o},set:function(a){o=a}},y:{get:function(){return p},set:function(a){p=a}},xScale:{get:function(){return m},set:function(a){m=a}},yScale:{get:function(){return n},set:function(a){n=a}},xDomain:{get:function(){return c},set:function(a){c=a}},yDomain:{get:function(){return d},set:function(a){d=a}},xRange:{get:function(){return e},set:function(a){e=a}},yRange:{get:function(){return f},set:function(a){f=a}},id:{get:function(){return l},set:function(a){l=a}},margin:{get:function(){return i},set:function(a){i.top=void 0!==a.top?a.top:i.top,i.right=void 0!==a.right?a.right:i.right,i.bottom=void 0!==a.bottom?a.bottom:i.bottom,i.left=void 0!==a.left?a.left:i.left}},color:{get:function(){return q},set:function(b){q=a.utils.getColor(b)}},duration:{get:function(){return t},set:function(a){t=a,v.reset(t)}}}),a.utils.initOptions(b),b},a.models.boxPlotChart=function(){"use strict";function b(k){return t.reset(),t.models(e),l&&t.models(f),m&&t.models(g),k.each(function(k){var p=d3.select(this);a.utils.initSVG(p);var t=(i||parseInt(p.style("width"))||960)-h.left-h.right,u=(j||parseInt(p.style("height"))||400)-h.top-h.bottom;if(b.update=function(){r.beforeUpdate(),p.transition().duration(s).call(b)},b.container=this,!(k&&k.length&&k.filter(function(a){return a.values.hasOwnProperty("Q1")&&a.values.hasOwnProperty("Q2")&&a.values.hasOwnProperty("Q3")}).length)){var v=p.selectAll(".nv-noData").data([q]);return v.enter().append("text").attr("class","nvd3 nv-noData").attr("dy","-.7em").style("text-anchor","middle"),v.attr("x",h.left+t/2).attr("y",h.top+u/2).text(function(a){return a}),b}p.selectAll(".nv-noData").remove(),c=e.xScale(),d=e.yScale().clamp(!0);var w=p.selectAll("g.nv-wrap.nv-boxPlotWithAxes").data([k]),x=w.enter().append("g").attr("class","nvd3 nv-wrap nv-boxPlotWithAxes").append("g"),y=x.append("defs"),z=w.select("g");
  22799. x.append("g").attr("class","nv-x nv-axis"),x.append("g").attr("class","nv-y nv-axis").append("g").attr("class","nv-zeroLine").append("line"),x.append("g").attr("class","nv-barsWrap"),z.attr("transform","translate("+h.left+","+h.top+")"),n&&z.select(".nv-y.nv-axis").attr("transform","translate("+t+",0)"),e.width(t).height(u);var A=z.select(".nv-barsWrap").datum(k.filter(function(a){return!a.disabled}));if(A.transition().call(e),y.append("clipPath").attr("id","nv-x-label-clip-"+e.id()).append("rect"),z.select("#nv-x-label-clip-"+e.id()+" rect").attr("width",c.rangeBand()*(o?2:1)).attr("height",16).attr("x",-c.rangeBand()/(o?1:2)),l){f.scale(c).ticks(a.utils.calcTicksX(t/100,k)).tickSize(-u,0),z.select(".nv-x.nv-axis").attr("transform","translate(0,"+d.range()[0]+")"),z.select(".nv-x.nv-axis").call(f);var B=z.select(".nv-x.nv-axis").selectAll("g");o&&B.selectAll("text").attr("transform",function(a,b,c){return"translate(0,"+(c%2==0?"5":"17")+")"})}m&&(g.scale(d).ticks(Math.floor(u/36)).tickSize(-t,0),z.select(".nv-y.nv-axis").call(g)),z.select(".nv-zeroLine line").attr("x1",0).attr("x2",t).attr("y1",d(0)).attr("y2",d(0))}),t.renderEnd("nv-boxplot chart immediate"),b}var c,d,e=a.models.boxPlot(),f=a.models.axis(),g=a.models.axis(),h={top:15,right:10,bottom:50,left:60},i=null,j=null,k=a.utils.getColor(),l=!0,m=!0,n=!1,o=!1,p=a.models.tooltip(),q="No Data Available.",r=d3.dispatch("tooltipShow","tooltipHide","beforeUpdate","renderEnd"),s=250;f.orient("bottom").showMaxMin(!1).tickFormat(function(a){return a}),g.orient(n?"right":"left").tickFormat(d3.format(",.1f")),p.duration(0);var t=a.utils.renderWatch(r,s);return e.dispatch.on("elementMouseover.tooltip",function(a){p.data(a).hidden(!1)}),e.dispatch.on("elementMouseout.tooltip",function(a){p.data(a).hidden(!0)}),e.dispatch.on("elementMousemove.tooltip",function(){p.position({top:d3.event.pageY,left:d3.event.pageX})()}),b.dispatch=r,b.boxplot=e,b.xAxis=f,b.yAxis=g,b.tooltip=p,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return i},set:function(a){i=a}},height:{get:function(){return j},set:function(a){j=a}},staggerLabels:{get:function(){return o},set:function(a){o=a}},showXAxis:{get:function(){return l},set:function(a){l=a}},showYAxis:{get:function(){return m},set:function(a){m=a}},tooltips:{get:function(){return tooltips},set:function(a){tooltips=a}},tooltipContent:{get:function(){return p},set:function(a){p=a}},noData:{get:function(){return q},set:function(a){q=a}},margin:{get:function(){return h},set:function(a){h.top=void 0!==a.top?a.top:h.top,h.right=void 0!==a.right?a.right:h.right,h.bottom=void 0!==a.bottom?a.bottom:h.bottom,h.left=void 0!==a.left?a.left:h.left}},duration:{get:function(){return s},set:function(a){s=a,t.reset(s),e.duration(s),f.duration(s),g.duration(s)}},color:{get:function(){return k},set:function(b){k=a.utils.getColor(b),e.color(k)}},rightAlignYAxis:{get:function(){return n},set:function(a){n=a,g.orient(a?"right":"left")}}}),a.utils.inheritOptions(b,e),a.utils.initOptions(b),b},a.models.bullet=function(){"use strict";function b(d){return d.each(function(b,d){var p=m-c.left-c.right,s=n-c.top-c.bottom;o=d3.select(this),a.utils.initSVG(o);{var t=f.call(this,b,d).slice().sort(d3.descending),u=g.call(this,b,d).slice().sort(d3.descending),v=h.call(this,b,d).slice().sort(d3.descending),w=i.call(this,b,d).slice(),x=j.call(this,b,d).slice(),y=k.call(this,b,d).slice(),z=d3.scale.linear().domain(d3.extent(d3.merge([l,t]))).range(e?[p,0]:[0,p]);this.__chart__||d3.scale.linear().domain([0,1/0]).range(z.range())}this.__chart__=z;var A=d3.min(t),B=d3.max(t),C=t[1],D=o.selectAll("g.nv-wrap.nv-bullet").data([b]),E=D.enter().append("g").attr("class","nvd3 nv-wrap nv-bullet"),F=E.append("g"),G=D.select("g");F.append("rect").attr("class","nv-range nv-rangeMax"),F.append("rect").attr("class","nv-range nv-rangeAvg"),F.append("rect").attr("class","nv-range nv-rangeMin"),F.append("rect").attr("class","nv-measure"),D.attr("transform","translate("+c.left+","+c.top+")");var H=function(a){return Math.abs(z(a)-z(0))},I=function(a){return z(0>a?a:0)};G.select("rect.nv-rangeMax").attr("height",s).attr("width",H(B>0?B:A)).attr("x",I(B>0?B:A)).datum(B>0?B:A),G.select("rect.nv-rangeAvg").attr("height",s).attr("width",H(C)).attr("x",I(C)).datum(C),G.select("rect.nv-rangeMin").attr("height",s).attr("width",H(B)).attr("x",I(B)).attr("width",H(B>0?A:B)).attr("x",I(B>0?A:B)).datum(B>0?A:B),G.select("rect.nv-measure").style("fill",q).attr("height",s/3).attr("y",s/3).attr("width",0>v?z(0)-z(v[0]):z(v[0])-z(0)).attr("x",I(v)).on("mouseover",function(){r.elementMouseover({value:v[0],label:y[0]||"Current",color:d3.select(this).style("fill")})}).on("mousemove",function(){r.elementMousemove({value:v[0],label:y[0]||"Current",color:d3.select(this).style("fill")})}).on("mouseout",function(){r.elementMouseout({value:v[0],label:y[0]||"Current",color:d3.select(this).style("fill")})});var J=s/6,K=u.map(function(a,b){return{value:a,label:x[b]}});F.selectAll("path.nv-markerTriangle").data(K).enter().append("path").attr("class","nv-markerTriangle").attr("transform",function(a){return"translate("+z(a.value)+","+s/2+")"}).attr("d","M0,"+J+"L"+J+","+-J+" "+-J+","+-J+"Z").on("mouseover",function(a){r.elementMouseover({value:a.value,label:a.label||"Previous",color:d3.select(this).style("fill"),pos:[z(a.value),s/2]})}).on("mousemove",function(a){r.elementMousemove({value:a.value,label:a.label||"Previous",color:d3.select(this).style("fill")})}).on("mouseout",function(a){r.elementMouseout({value:a.value,label:a.label||"Previous",color:d3.select(this).style("fill")})}),D.selectAll(".nv-range").on("mouseover",function(a,b){var c=w[b]||(b?1==b?"Mean":"Minimum":"Maximum");r.elementMouseover({value:a,label:c,color:d3.select(this).style("fill")})}).on("mousemove",function(){r.elementMousemove({value:v[0],label:y[0]||"Previous",color:d3.select(this).style("fill")})}).on("mouseout",function(a,b){var c=w[b]||(b?1==b?"Mean":"Minimum":"Maximum");r.elementMouseout({value:a,label:c,color:d3.select(this).style("fill")})})}),b}var c={top:0,right:0,bottom:0,left:0},d="left",e=!1,f=function(a){return a.ranges},g=function(a){return a.markers?a.markers:[0]},h=function(a){return a.measures},i=function(a){return a.rangeLabels?a.rangeLabels:[]},j=function(a){return a.markerLabels?a.markerLabels:[]},k=function(a){return a.measureLabels?a.measureLabels:[]},l=[0],m=380,n=30,o=null,p=null,q=a.utils.getColor(["#1f77b4"]),r=d3.dispatch("elementMouseover","elementMouseout","elementMousemove");return b.dispatch=r,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{ranges:{get:function(){return f},set:function(a){f=a}},markers:{get:function(){return g},set:function(a){g=a}},measures:{get:function(){return h},set:function(a){h=a}},forceX:{get:function(){return l},set:function(a){l=a}},width:{get:function(){return m},set:function(a){m=a}},height:{get:function(){return n},set:function(a){n=a}},tickFormat:{get:function(){return p},set:function(a){p=a}},margin:{get:function(){return c},set:function(a){c.top=void 0!==a.top?a.top:c.top,c.right=void 0!==a.right?a.right:c.right,c.bottom=void 0!==a.bottom?a.bottom:c.bottom,c.left=void 0!==a.left?a.left:c.left}},orient:{get:function(){return d},set:function(a){d=a,e="right"==d||"bottom"==d}},color:{get:function(){return q},set:function(b){q=a.utils.getColor(b)}}}),a.utils.initOptions(b),b},a.models.bulletChart=function(){"use strict";function b(d){return d.each(function(e,o){var p=d3.select(this);a.utils.initSVG(p);var q=a.utils.availableWidth(k,p,g),r=l-g.top-g.bottom;if(b.update=function(){b(d)},b.container=this,!e||!h.call(this,e,o))return a.utils.noData(b,p),b;p.selectAll(".nv-noData").remove();var s=h.call(this,e,o).slice().sort(d3.descending),t=i.call(this,e,o).slice().sort(d3.descending),u=j.call(this,e,o).slice().sort(d3.descending),v=p.selectAll("g.nv-wrap.nv-bulletChart").data([e]),w=v.enter().append("g").attr("class","nvd3 nv-wrap nv-bulletChart"),x=w.append("g"),y=v.select("g");x.append("g").attr("class","nv-bulletWrap"),x.append("g").attr("class","nv-titles"),v.attr("transform","translate("+g.left+","+g.top+")");var z=d3.scale.linear().domain([0,Math.max(s[0],t[0],u[0])]).range(f?[q,0]:[0,q]),A=this.__chart__||d3.scale.linear().domain([0,1/0]).range(z.range());this.__chart__=z;var B=x.select(".nv-titles").append("g").attr("text-anchor","end").attr("transform","translate(-6,"+(l-g.top-g.bottom)/2+")");B.append("text").attr("class","nv-title").text(function(a){return a.title}),B.append("text").attr("class","nv-subtitle").attr("dy","1em").text(function(a){return a.subtitle}),c.width(q).height(r);var C=y.select(".nv-bulletWrap");d3.transition(C).call(c);var D=m||z.tickFormat(q/100),E=y.selectAll("g.nv-tick").data(z.ticks(n?n:q/50),function(a){return this.textContent||D(a)}),F=E.enter().append("g").attr("class","nv-tick").attr("transform",function(a){return"translate("+A(a)+",0)"}).style("opacity",1e-6);F.append("line").attr("y1",r).attr("y2",7*r/6),F.append("text").attr("text-anchor","middle").attr("dy","1em").attr("y",7*r/6).text(D);var G=d3.transition(E).attr("transform",function(a){return"translate("+z(a)+",0)"}).style("opacity",1);G.select("line").attr("y1",r).attr("y2",7*r/6),G.select("text").attr("y",7*r/6),d3.transition(E.exit()).attr("transform",function(a){return"translate("+z(a)+",0)"}).style("opacity",1e-6).remove()}),d3.timer.flush(),b}var c=a.models.bullet(),d=a.models.tooltip(),e="left",f=!1,g={top:5,right:40,bottom:20,left:120},h=function(a){return a.ranges},i=function(a){return a.markers?a.markers:[0]},j=function(a){return a.measures},k=null,l=55,m=null,n=null,o=null,p=d3.dispatch("tooltipShow","tooltipHide");return d.duration(0).headerEnabled(!1),c.dispatch.on("elementMouseover.tooltip",function(a){a.series={key:a.label,value:a.value,color:a.color},d.data(a).hidden(!1)}),c.dispatch.on("elementMouseout.tooltip",function(){d.hidden(!0)}),c.dispatch.on("elementMousemove.tooltip",function(){d.position({top:d3.event.pageY,left:d3.event.pageX})()}),b.bullet=c,b.dispatch=p,b.tooltip=d,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{ranges:{get:function(){return h},set:function(a){h=a}},markers:{get:function(){return i},set:function(a){i=a}},measures:{get:function(){return j},set:function(a){j=a}},width:{get:function(){return k},set:function(a){k=a}},height:{get:function(){return l},set:function(a){l=a}},tickFormat:{get:function(){return m},set:function(a){m=a}},ticks:{get:function(){return n},set:function(a){n=a}},noData:{get:function(){return o},set:function(a){o=a}},tooltips:{get:function(){return d.enabled()},set:function(b){a.deprecated("tooltips","use chart.tooltip.enabled() instead"),d.enabled(!!b)}},tooltipContent:{get:function(){return d.contentGenerator()},set:function(b){a.deprecated("tooltipContent","use chart.tooltip.contentGenerator() instead"),d.contentGenerator(b)}},margin:{get:function(){return g},set:function(a){g.top=void 0!==a.top?a.top:g.top,g.right=void 0!==a.right?a.right:g.right,g.bottom=void 0!==a.bottom?a.bottom:g.bottom,g.left=void 0!==a.left?a.left:g.left}},orient:{get:function(){return e},set:function(a){e=a,f="right"==e||"bottom"==e}}}),a.utils.inheritOptions(b,c),a.utils.initOptions(b),b},a.models.candlestickBar=function(){"use strict";function b(x){return x.each(function(b){c=d3.select(this);var x=a.utils.availableWidth(i,c,h),y=a.utils.availableHeight(j,c,h);a.utils.initSVG(c);var A=x/b[0].values.length*.45;l.domain(d||d3.extent(b[0].values.map(n).concat(t))),l.range(v?f||[.5*x/b[0].values.length,x*(b[0].values.length-.5)/b[0].values.length]:f||[5+A/2,x-A/2-5]),m.domain(e||[d3.min(b[0].values.map(s).concat(u)),d3.max(b[0].values.map(r).concat(u))]).range(g||[y,0]),l.domain()[0]===l.domain()[1]&&l.domain(l.domain()[0]?[l.domain()[0]-.01*l.domain()[0],l.domain()[1]+.01*l.domain()[1]]:[-1,1]),m.domain()[0]===m.domain()[1]&&m.domain(m.domain()[0]?[m.domain()[0]+.01*m.domain()[0],m.domain()[1]-.01*m.domain()[1]]:[-1,1]);var B=d3.select(this).selectAll("g.nv-wrap.nv-candlestickBar").data([b[0].values]),C=B.enter().append("g").attr("class","nvd3 nv-wrap nv-candlestickBar"),D=C.append("defs"),E=C.append("g"),F=B.select("g");E.append("g").attr("class","nv-ticks"),B.attr("transform","translate("+h.left+","+h.top+")"),c.on("click",function(a,b){z.chartClick({data:a,index:b,pos:d3.event,id:k})}),D.append("clipPath").attr("id","nv-chart-clip-path-"+k).append("rect"),B.select("#nv-chart-clip-path-"+k+" rect").attr("width",x).attr("height",y),F.attr("clip-path",w?"url(#nv-chart-clip-path-"+k+")":"");var G=B.select(".nv-ticks").selectAll(".nv-tick").data(function(a){return a});G.exit().remove();{var H=G.enter().append("g").attr("class",function(a,b,c){return(p(a,b)>q(a,b)?"nv-tick negative":"nv-tick positive")+" nv-tick-"+c+"-"+b});H.append("line").attr("class","nv-candlestick-lines").attr("transform",function(a,b){return"translate("+l(n(a,b))+",0)"}).attr("x1",0).attr("y1",function(a,b){return m(r(a,b))}).attr("x2",0).attr("y2",function(a,b){return m(s(a,b))}),H.append("rect").attr("class","nv-candlestick-rects nv-bars").attr("transform",function(a,b){return"translate("+(l(n(a,b))-A/2)+","+(m(o(a,b))-(p(a,b)>q(a,b)?m(q(a,b))-m(p(a,b)):0))+")"}).attr("x",0).attr("y",0).attr("width",A).attr("height",function(a,b){var c=p(a,b),d=q(a,b);return c>d?m(d)-m(c):m(c)-m(d)})}c.selectAll(".nv-candlestick-lines").transition().attr("transform",function(a,b){return"translate("+l(n(a,b))+",0)"}).attr("x1",0).attr("y1",function(a,b){return m(r(a,b))}).attr("x2",0).attr("y2",function(a,b){return m(s(a,b))}),c.selectAll(".nv-candlestick-rects").transition().attr("transform",function(a,b){return"translate("+(l(n(a,b))-A/2)+","+(m(o(a,b))-(p(a,b)>q(a,b)?m(q(a,b))-m(p(a,b)):0))+")"}).attr("x",0).attr("y",0).attr("width",A).attr("height",function(a,b){var c=p(a,b),d=q(a,b);return c>d?m(d)-m(c):m(c)-m(d)})}),b}var c,d,e,f,g,h={top:0,right:0,bottom:0,left:0},i=null,j=null,k=Math.floor(1e4*Math.random()),l=d3.scale.linear(),m=d3.scale.linear(),n=function(a){return a.x},o=function(a){return a.y},p=function(a){return a.open},q=function(a){return a.close},r=function(a){return a.high},s=function(a){return a.low},t=[],u=[],v=!1,w=!0,x=a.utils.defaultColor(),y=!1,z=d3.dispatch("tooltipShow","tooltipHide","stateChange","changeState","renderEnd","chartClick","elementClick","elementDblClick","elementMouseover","elementMouseout","elementMousemove");return b.highlightPoint=function(a,d){b.clearHighlights(),c.select(".nv-candlestickBar .nv-tick-0-"+a).classed("hover",d)},b.clearHighlights=function(){c.select(".nv-candlestickBar .nv-tick.hover").classed("hover",!1)},b.dispatch=z,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return i},set:function(a){i=a}},height:{get:function(){return j},set:function(a){j=a}},xScale:{get:function(){return l},set:function(a){l=a}},yScale:{get:function(){return m},set:function(a){m=a}},xDomain:{get:function(){return d},set:function(a){d=a}},yDomain:{get:function(){return e},set:function(a){e=a}},xRange:{get:function(){return f},set:function(a){f=a}},yRange:{get:function(){return g},set:function(a){g=a}},forceX:{get:function(){return t},set:function(a){t=a}},forceY:{get:function(){return u},set:function(a){u=a}},padData:{get:function(){return v},set:function(a){v=a}},clipEdge:{get:function(){return w},set:function(a){w=a}},id:{get:function(){return k},set:function(a){k=a}},interactive:{get:function(){return y},set:function(a){y=a}},x:{get:function(){return n},set:function(a){n=a}},y:{get:function(){return o},set:function(a){o=a}},open:{get:function(){return p()},set:function(a){p=a}},close:{get:function(){return q()},set:function(a){q=a}},high:{get:function(){return r},set:function(a){r=a}},low:{get:function(){return s},set:function(a){s=a}},margin:{get:function(){return h},set:function(a){h.top=void 0!=a.top?a.top:h.top,h.right=void 0!=a.right?a.right:h.right,h.bottom=void 0!=a.bottom?a.bottom:h.bottom,h.left=void 0!=a.left?a.left:h.left}},color:{get:function(){return x},set:function(b){x=a.utils.getColor(b)}}}),a.utils.initOptions(b),b},a.models.cumulativeLineChart=function(){"use strict";function b(l){return H.reset(),H.models(f),r&&H.models(g),s&&H.models(h),l.each(function(l){function A(){d3.select(b.container).style("cursor","ew-resize")}function E(){G.x=d3.event.x,G.i=Math.round(F.invert(G.x)),K()}function H(){d3.select(b.container).style("cursor","auto"),y.index=G.i,C.stateChange(y)}function K(){bb.data([G]);var a=b.duration();b.duration(0),b.update(),b.duration(a)}var L=d3.select(this);a.utils.initSVG(L),L.classed("nv-chart-"+x,!0);var M=this,N=a.utils.availableWidth(o,L,m),O=a.utils.availableHeight(p,L,m);if(b.update=function(){0===D?L.call(b):L.transition().duration(D).call(b)},b.container=this,y.setter(J(l),b.update).getter(I(l)).update(),y.disabled=l.map(function(a){return!!a.disabled}),!z){var P;z={};for(P in y)z[P]=y[P]instanceof Array?y[P].slice(0):y[P]}var Q=d3.behavior.drag().on("dragstart",A).on("drag",E).on("dragend",H);if(!(l&&l.length&&l.filter(function(a){return a.values.length}).length))return a.utils.noData(b,L),b;if(L.selectAll(".nv-noData").remove(),d=f.xScale(),e=f.yScale(),w)f.yDomain(null);else{var R=l.filter(function(a){return!a.disabled}).map(function(a){var b=d3.extent(a.values,f.y());return b[0]<-.95&&(b[0]=-.95),[(b[0]-b[1])/(1+b[1]),(b[1]-b[0])/(1+b[0])]}),S=[d3.min(R,function(a){return a[0]}),d3.max(R,function(a){return a[1]})];f.yDomain(S)}F.domain([0,l[0].values.length-1]).range([0,N]).clamp(!0);var l=c(G.i,l),T=v?"none":"all",U=L.selectAll("g.nv-wrap.nv-cumulativeLine").data([l]),V=U.enter().append("g").attr("class","nvd3 nv-wrap nv-cumulativeLine").append("g"),W=U.select("g");if(V.append("g").attr("class","nv-interactive"),V.append("g").attr("class","nv-x nv-axis").style("pointer-events","none"),V.append("g").attr("class","nv-y nv-axis"),V.append("g").attr("class","nv-background"),V.append("g").attr("class","nv-linesWrap").style("pointer-events",T),V.append("g").attr("class","nv-avgLinesWrap").style("pointer-events","none"),V.append("g").attr("class","nv-legendWrap"),V.append("g").attr("class","nv-controlsWrap"),q&&(i.width(N),W.select(".nv-legendWrap").datum(l).call(i),m.top!=i.height()&&(m.top=i.height(),O=a.utils.availableHeight(p,L,m)),W.select(".nv-legendWrap").attr("transform","translate(0,"+-m.top+")")),u){var X=[{key:"Re-scale y-axis",disabled:!w}];j.width(140).color(["#444","#444","#444"]).rightAlign(!1).margin({top:5,right:0,bottom:5,left:20}),W.select(".nv-controlsWrap").datum(X).attr("transform","translate(0,"+-m.top+")").call(j)}U.attr("transform","translate("+m.left+","+m.top+")"),t&&W.select(".nv-y.nv-axis").attr("transform","translate("+N+",0)");var Y=l.filter(function(a){return a.tempDisabled});U.select(".tempDisabled").remove(),Y.length&&U.append("text").attr("class","tempDisabled").attr("x",N/2).attr("y","-.71em").style("text-anchor","end").text(Y.map(function(a){return a.key}).join(", ")+" values cannot be calculated for this time period."),v&&(k.width(N).height(O).margin({left:m.left,top:m.top}).svgContainer(L).xScale(d),U.select(".nv-interactive").call(k)),V.select(".nv-background").append("rect"),W.select(".nv-background rect").attr("width",N).attr("height",O),f.y(function(a){return a.display.y}).width(N).height(O).color(l.map(function(a,b){return a.color||n(a,b)}).filter(function(a,b){return!l[b].disabled&&!l[b].tempDisabled}));var Z=W.select(".nv-linesWrap").datum(l.filter(function(a){return!a.disabled&&!a.tempDisabled}));Z.call(f),l.forEach(function(a,b){a.seriesIndex=b});var $=l.filter(function(a){return!a.disabled&&!!B(a)}),_=W.select(".nv-avgLinesWrap").selectAll("line").data($,function(a){return a.key}),ab=function(a){var b=e(B(a));return 0>b?0:b>O?O:b};_.enter().append("line").style("stroke-width",2).style("stroke-dasharray","10,10").style("stroke",function(a){return f.color()(a,a.seriesIndex)}).attr("x1",0).attr("x2",N).attr("y1",ab).attr("y2",ab),_.style("stroke-opacity",function(a){var b=e(B(a));return 0>b||b>O?0:1}).attr("x1",0).attr("x2",N).attr("y1",ab).attr("y2",ab),_.exit().remove();var bb=Z.selectAll(".nv-indexLine").data([G]);bb.enter().append("rect").attr("class","nv-indexLine").attr("width",3).attr("x",-2).attr("fill","red").attr("fill-opacity",.5).style("pointer-events","all").call(Q),bb.attr("transform",function(a){return"translate("+F(a.i)+",0)"}).attr("height",O),r&&(g.scale(d)._ticks(a.utils.calcTicksX(N/70,l)).tickSize(-O,0),W.select(".nv-x.nv-axis").attr("transform","translate(0,"+e.range()[0]+")"),W.select(".nv-x.nv-axis").call(g)),s&&(h.scale(e)._ticks(a.utils.calcTicksY(O/36,l)).tickSize(-N,0),W.select(".nv-y.nv-axis").call(h)),W.select(".nv-background rect").on("click",function(){G.x=d3.mouse(this)[0],G.i=Math.round(F.invert(G.x)),y.index=G.i,C.stateChange(y),K()}),f.dispatch.on("elementClick",function(a){G.i=a.pointIndex,G.x=F(G.i),y.index=G.i,C.stateChange(y),K()}),j.dispatch.on("legendClick",function(a){a.disabled=!a.disabled,w=!a.disabled,y.rescaleY=w,C.stateChange(y),b.update()}),i.dispatch.on("stateChange",function(a){for(var c in a)y[c]=a[c];C.stateChange(y),b.update()}),k.dispatch.on("elementMousemove",function(c){f.clearHighlights();var d,e,i,j=[];if(l.filter(function(a,b){return a.seriesIndex=b,!a.disabled}).forEach(function(g,h){e=a.interactiveBisect(g.values,c.pointXValue,b.x()),f.highlightPoint(h,e,!0);var k=g.values[e];"undefined"!=typeof k&&("undefined"==typeof d&&(d=k),"undefined"==typeof i&&(i=b.xScale()(b.x()(k,e))),j.push({key:g.key,value:b.y()(k,e),color:n(g,g.seriesIndex)}))}),j.length>2){var o=b.yScale().invert(c.mouseY),p=Math.abs(b.yScale().domain()[0]-b.yScale().domain()[1]),q=.03*p,r=a.nearestValueIndex(j.map(function(a){return a.value}),o,q);null!==r&&(j[r].highlight=!0)}var s=g.tickFormat()(b.x()(d,e),e);k.tooltip.position({left:i+m.left,top:c.mouseY+m.top}).chartContainer(M.parentNode).valueFormatter(function(a){return h.tickFormat()(a)}).data({value:s,series:j})(),k.renderGuideLine(i)}),k.dispatch.on("elementMouseout",function(){f.clearHighlights()}),C.on("changeState",function(a){"undefined"!=typeof a.disabled&&(l.forEach(function(b,c){b.disabled=a.disabled[c]}),y.disabled=a.disabled),"undefined"!=typeof a.index&&(G.i=a.index,G.x=F(G.i),y.index=a.index,bb.data([G])),"undefined"!=typeof a.rescaleY&&(w=a.rescaleY),b.update()})}),H.renderEnd("cumulativeLineChart immediate"),b}function c(a,b){return K||(K=f.y()),b.map(function(b){if(!b.values)return b;var c=b.values[a];if(null==c)return b;var d=K(c,a);return-.95>d&&!E?(b.tempDisabled=!0,b):(b.tempDisabled=!1,b.values=b.values.map(function(a,b){return a.display={y:(K(a,b)-d)/(1+d)},a}),b)})}var d,e,f=a.models.line(),g=a.models.axis(),h=a.models.axis(),i=a.models.legend(),j=a.models.legend(),k=a.interactiveGuideline(),l=a.models.tooltip(),m={top:30,right:30,bottom:50,left:60},n=a.utils.defaultColor(),o=null,p=null,q=!0,r=!0,s=!0,t=!1,u=!0,v=!1,w=!0,x=f.id(),y=a.utils.state(),z=null,A=null,B=function(a){return a.average},C=d3.dispatch("stateChange","changeState","renderEnd"),D=250,E=!1;y.index=0,y.rescaleY=w,g.orient("bottom").tickPadding(7),h.orient(t?"right":"left"),l.valueFormatter(function(a,b){return h.tickFormat()(a,b)}).headerFormatter(function(a,b){return g.tickFormat()(a,b)}),j.updateState(!1);var F=d3.scale.linear(),G={i:0,x:0},H=a.utils.renderWatch(C,D),I=function(a){return function(){return{active:a.map(function(a){return!a.disabled}),index:G.i,rescaleY:w}}},J=function(a){return function(b){void 0!==b.index&&(G.i=b.index),void 0!==b.rescaleY&&(w=b.rescaleY),void 0!==b.active&&a.forEach(function(a,c){a.disabled=!b.active[c]})}};f.dispatch.on("elementMouseover.tooltip",function(a){var c={x:b.x()(a.point),y:b.y()(a.point),color:a.point.color};a.point=c,l.data(a).position(a.pos).hidden(!1)}),f.dispatch.on("elementMouseout.tooltip",function(){l.hidden(!0)});var K=null;return b.dispatch=C,b.lines=f,b.legend=i,b.controls=j,b.xAxis=g,b.yAxis=h,b.interactiveLayer=k,b.state=y,b.tooltip=l,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return o},set:function(a){o=a}},height:{get:function(){return p},set:function(a){p=a}},rescaleY:{get:function(){return w},set:function(a){w=a}},showControls:{get:function(){return u},set:function(a){u=a}},showLegend:{get:function(){return q},set:function(a){q=a}},average:{get:function(){return B},set:function(a){B=a}},defaultState:{get:function(){return z},set:function(a){z=a}},noData:{get:function(){return A},set:function(a){A=a}},showXAxis:{get:function(){return r},set:function(a){r=a}},showYAxis:{get:function(){return s},set:function(a){s=a}},noErrorCheck:{get:function(){return E},set:function(a){E=a}},tooltips:{get:function(){return l.enabled()},set:function(b){a.deprecated("tooltips","use chart.tooltip.enabled() instead"),l.enabled(!!b)}},tooltipContent:{get:function(){return l.contentGenerator()},set:function(b){a.deprecated("tooltipContent","use chart.tooltip.contentGenerator() instead"),l.contentGenerator(b)}},margin:{get:function(){return m},set:function(a){m.top=void 0!==a.top?a.top:m.top,m.right=void 0!==a.right?a.right:m.right,m.bottom=void 0!==a.bottom?a.bottom:m.bottom,m.left=void 0!==a.left?a.left:m.left}},color:{get:function(){return n},set:function(b){n=a.utils.getColor(b),i.color(n)}},useInteractiveGuideline:{get:function(){return v},set:function(a){v=a,a===!0&&(b.interactive(!1),b.useVoronoi(!1))}},rightAlignYAxis:{get:function(){return t},set:function(a){t=a,h.orient(a?"right":"left")}},duration:{get:function(){return D},set:function(a){D=a,f.duration(D),g.duration(D),h.duration(D),H.reset(D)}}}),a.utils.inheritOptions(b,f),a.utils.initOptions(b),b},a.models.discreteBar=function(){"use strict";function b(m){return y.reset(),m.each(function(b){var m=k-j.left-j.right,x=l-j.top-j.bottom;c=d3.select(this),a.utils.initSVG(c),b.forEach(function(a,b){a.values.forEach(function(a){a.series=b})});var z=d&&e?[]:b.map(function(a){return a.values.map(function(a,b){return{x:p(a,b),y:q(a,b),y0:a.y0}})});n.domain(d||d3.merge(z).map(function(a){return a.x})).rangeBands(f||[0,m],.1),o.domain(e||d3.extent(d3.merge(z).map(function(a){return a.y}).concat(r))),o.range(t?g||[x-(o.domain()[0]<0?12:0),o.domain()[1]>0?12:0]:g||[x,0]),h=h||n,i=i||o.copy().range([o(0),o(0)]);{var A=c.selectAll("g.nv-wrap.nv-discretebar").data([b]),B=A.enter().append("g").attr("class","nvd3 nv-wrap nv-discretebar"),C=B.append("g");A.select("g")}C.append("g").attr("class","nv-groups"),A.attr("transform","translate("+j.left+","+j.top+")");var D=A.select(".nv-groups").selectAll(".nv-group").data(function(a){return a},function(a){return a.key});D.enter().append("g").style("stroke-opacity",1e-6).style("fill-opacity",1e-6),D.exit().watchTransition(y,"discreteBar: exit groups").style("stroke-opacity",1e-6).style("fill-opacity",1e-6).remove(),D.attr("class",function(a,b){return"nv-group nv-series-"+b}).classed("hover",function(a){return a.hover}),D.watchTransition(y,"discreteBar: groups").style("stroke-opacity",1).style("fill-opacity",.75);var E=D.selectAll("g.nv-bar").data(function(a){return a.values});E.exit().remove();var F=E.enter().append("g").attr("transform",function(a,b){return"translate("+(n(p(a,b))+.05*n.rangeBand())+", "+o(0)+")"}).on("mouseover",function(a,b){d3.select(this).classed("hover",!0),v.elementMouseover({data:a,index:b,color:d3.select(this).style("fill")})}).on("mouseout",function(a,b){d3.select(this).classed("hover",!1),v.elementMouseout({data:a,index:b,color:d3.select(this).style("fill")})}).on("mousemove",function(a,b){v.elementMousemove({data:a,index:b,color:d3.select(this).style("fill")})}).on("click",function(a,b){v.elementClick({data:a,index:b,color:d3.select(this).style("fill")}),d3.event.stopPropagation()}).on("dblclick",function(a,b){v.elementDblClick({data:a,index:b,color:d3.select(this).style("fill")}),d3.event.stopPropagation()});F.append("rect").attr("height",0).attr("width",.9*n.rangeBand()/b.length),t?(F.append("text").attr("text-anchor","middle"),E.select("text").text(function(a,b){return u(q(a,b))}).watchTransition(y,"discreteBar: bars text").attr("x",.9*n.rangeBand()/2).attr("y",function(a,b){return q(a,b)<0?o(q(a,b))-o(0)+12:-4})):E.selectAll("text").remove(),E.attr("class",function(a,b){return q(a,b)<0?"nv-bar negative":"nv-bar positive"}).style("fill",function(a,b){return a.color||s(a,b)}).style("stroke",function(a,b){return a.color||s(a,b)}).select("rect").attr("class",w).watchTransition(y,"discreteBar: bars rect").attr("width",.9*n.rangeBand()/b.length),E.watchTransition(y,"discreteBar: bars").attr("transform",function(a,b){var c=n(p(a,b))+.05*n.rangeBand(),d=q(a,b)<0?o(0):o(0)-o(q(a,b))<1?o(0)-1:o(q(a,b));return"translate("+c+", "+d+")"}).select("rect").attr("height",function(a,b){return Math.max(Math.abs(o(q(a,b))-o(e&&e[0]||0))||1)}),h=n.copy(),i=o.copy()}),y.renderEnd("discreteBar immediate"),b}var c,d,e,f,g,h,i,j={top:0,right:0,bottom:0,left:0},k=960,l=500,m=Math.floor(1e4*Math.random()),n=d3.scale.ordinal(),o=d3.scale.linear(),p=function(a){return a.x},q=function(a){return a.y},r=[0],s=a.utils.defaultColor(),t=!1,u=d3.format(",.2f"),v=d3.dispatch("chartClick","elementClick","elementDblClick","elementMouseover","elementMouseout","elementMousemove","renderEnd"),w="discreteBar",x=250,y=a.utils.renderWatch(v,x);return b.dispatch=v,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return k},set:function(a){k=a}},height:{get:function(){return l},set:function(a){l=a}},forceY:{get:function(){return r},set:function(a){r=a}},showValues:{get:function(){return t},set:function(a){t=a}},x:{get:function(){return p},set:function(a){p=a}},y:{get:function(){return q},set:function(a){q=a}},xScale:{get:function(){return n},set:function(a){n=a}},yScale:{get:function(){return o},set:function(a){o=a}},xDomain:{get:function(){return d},set:function(a){d=a}},yDomain:{get:function(){return e},set:function(a){e=a}},xRange:{get:function(){return f},set:function(a){f=a}},yRange:{get:function(){return g},set:function(a){g=a}},valueFormat:{get:function(){return u},set:function(a){u=a}},id:{get:function(){return m},set:function(a){m=a}},rectClass:{get:function(){return w},set:function(a){w=a}},margin:{get:function(){return j},set:function(a){j.top=void 0!==a.top?a.top:j.top,j.right=void 0!==a.right?a.right:j.right,j.bottom=void 0!==a.bottom?a.bottom:j.bottom,j.left=void 0!==a.left?a.left:j.left}},color:{get:function(){return s},set:function(b){s=a.utils.getColor(b)}},duration:{get:function(){return x},set:function(a){x=a,y.reset(x)}}}),a.utils.initOptions(b),b},a.models.discreteBarChart=function(){"use strict";function b(h){return t.reset(),t.models(e),m&&t.models(f),n&&t.models(g),h.each(function(h){var l=d3.select(this);a.utils.initSVG(l);var q=a.utils.availableWidth(j,l,i),t=a.utils.availableHeight(k,l,i);if(b.update=function(){r.beforeUpdate(),l.transition().duration(s).call(b)},b.container=this,!(h&&h.length&&h.filter(function(a){return a.values.length}).length))return a.utils.noData(b,l),b;l.selectAll(".nv-noData").remove(),c=e.xScale(),d=e.yScale().clamp(!0);var u=l.selectAll("g.nv-wrap.nv-discreteBarWithAxes").data([h]),v=u.enter().append("g").attr("class","nvd3 nv-wrap nv-discreteBarWithAxes").append("g"),w=v.append("defs"),x=u.select("g");v.append("g").attr("class","nv-x nv-axis"),v.append("g").attr("class","nv-y nv-axis").append("g").attr("class","nv-zeroLine").append("line"),v.append("g").attr("class","nv-barsWrap"),x.attr("transform","translate("+i.left+","+i.top+")"),o&&x.select(".nv-y.nv-axis").attr("transform","translate("+q+",0)"),e.width(q).height(t);var y=x.select(".nv-barsWrap").datum(h.filter(function(a){return!a.disabled}));if(y.transition().call(e),w.append("clipPath").attr("id","nv-x-label-clip-"+e.id()).append("rect"),x.select("#nv-x-label-clip-"+e.id()+" rect").attr("width",c.rangeBand()*(p?2:1)).attr("height",16).attr("x",-c.rangeBand()/(p?1:2)),m){f.scale(c)._ticks(a.utils.calcTicksX(q/100,h)).tickSize(-t,0),x.select(".nv-x.nv-axis").attr("transform","translate(0,"+(d.range()[0]+(e.showValues()&&d.domain()[0]<0?16:0))+")"),x.select(".nv-x.nv-axis").call(f);
  22800. var z=x.select(".nv-x.nv-axis").selectAll("g");p&&z.selectAll("text").attr("transform",function(a,b,c){return"translate(0,"+(c%2==0?"5":"17")+")"})}n&&(g.scale(d)._ticks(a.utils.calcTicksY(t/36,h)).tickSize(-q,0),x.select(".nv-y.nv-axis").call(g)),x.select(".nv-zeroLine line").attr("x1",0).attr("x2",q).attr("y1",d(0)).attr("y2",d(0))}),t.renderEnd("discreteBar chart immediate"),b}var c,d,e=a.models.discreteBar(),f=a.models.axis(),g=a.models.axis(),h=a.models.tooltip(),i={top:15,right:10,bottom:50,left:60},j=null,k=null,l=a.utils.getColor(),m=!0,n=!0,o=!1,p=!1,q=null,r=d3.dispatch("beforeUpdate","renderEnd"),s=250;f.orient("bottom").showMaxMin(!1).tickFormat(function(a){return a}),g.orient(o?"right":"left").tickFormat(d3.format(",.1f")),h.duration(0).headerEnabled(!1).valueFormatter(function(a,b){return g.tickFormat()(a,b)}).keyFormatter(function(a,b){return f.tickFormat()(a,b)});var t=a.utils.renderWatch(r,s);return e.dispatch.on("elementMouseover.tooltip",function(a){a.series={key:b.x()(a.data),value:b.y()(a.data),color:a.color},h.data(a).hidden(!1)}),e.dispatch.on("elementMouseout.tooltip",function(){h.hidden(!0)}),e.dispatch.on("elementMousemove.tooltip",function(){h.position({top:d3.event.pageY,left:d3.event.pageX})()}),b.dispatch=r,b.discretebar=e,b.xAxis=f,b.yAxis=g,b.tooltip=h,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return j},set:function(a){j=a}},height:{get:function(){return k},set:function(a){k=a}},staggerLabels:{get:function(){return p},set:function(a){p=a}},showXAxis:{get:function(){return m},set:function(a){m=a}},showYAxis:{get:function(){return n},set:function(a){n=a}},noData:{get:function(){return q},set:function(a){q=a}},tooltips:{get:function(){return h.enabled()},set:function(b){a.deprecated("tooltips","use chart.tooltip.enabled() instead"),h.enabled(!!b)}},tooltipContent:{get:function(){return h.contentGenerator()},set:function(b){a.deprecated("tooltipContent","use chart.tooltip.contentGenerator() instead"),h.contentGenerator(b)}},margin:{get:function(){return i},set:function(a){i.top=void 0!==a.top?a.top:i.top,i.right=void 0!==a.right?a.right:i.right,i.bottom=void 0!==a.bottom?a.bottom:i.bottom,i.left=void 0!==a.left?a.left:i.left}},duration:{get:function(){return s},set:function(a){s=a,t.reset(s),e.duration(s),f.duration(s),g.duration(s)}},color:{get:function(){return l},set:function(b){l=a.utils.getColor(b),e.color(l)}},rightAlignYAxis:{get:function(){return o},set:function(a){o=a,g.orient(a?"right":"left")}}}),a.utils.inheritOptions(b,e),a.utils.initOptions(b),b},a.models.distribution=function(){"use strict";function b(k){return m.reset(),k.each(function(b){var k=(e-("x"===g?d.left+d.right:d.top+d.bottom),"x"==g?"y":"x"),l=d3.select(this);a.utils.initSVG(l),c=c||j;var n=l.selectAll("g.nv-distribution").data([b]),o=n.enter().append("g").attr("class","nvd3 nv-distribution"),p=(o.append("g"),n.select("g"));n.attr("transform","translate("+d.left+","+d.top+")");var q=p.selectAll("g.nv-dist").data(function(a){return a},function(a){return a.key});q.enter().append("g"),q.attr("class",function(a,b){return"nv-dist nv-series-"+b}).style("stroke",function(a,b){return i(a,b)});var r=q.selectAll("line.nv-dist"+g).data(function(a){return a.values});r.enter().append("line").attr(g+"1",function(a,b){return c(h(a,b))}).attr(g+"2",function(a,b){return c(h(a,b))}),m.transition(q.exit().selectAll("line.nv-dist"+g),"dist exit").attr(g+"1",function(a,b){return j(h(a,b))}).attr(g+"2",function(a,b){return j(h(a,b))}).style("stroke-opacity",0).remove(),r.attr("class",function(a,b){return"nv-dist"+g+" nv-dist"+g+"-"+b}).attr(k+"1",0).attr(k+"2",f),m.transition(r,"dist").attr(g+"1",function(a,b){return j(h(a,b))}).attr(g+"2",function(a,b){return j(h(a,b))}),c=j.copy()}),m.renderEnd("distribution immediate"),b}var c,d={top:0,right:0,bottom:0,left:0},e=400,f=8,g="x",h=function(a){return a[g]},i=a.utils.defaultColor(),j=d3.scale.linear(),k=250,l=d3.dispatch("renderEnd"),m=a.utils.renderWatch(l,k);return b.options=a.utils.optionsFunc.bind(b),b.dispatch=l,b.margin=function(a){return arguments.length?(d.top="undefined"!=typeof a.top?a.top:d.top,d.right="undefined"!=typeof a.right?a.right:d.right,d.bottom="undefined"!=typeof a.bottom?a.bottom:d.bottom,d.left="undefined"!=typeof a.left?a.left:d.left,b):d},b.width=function(a){return arguments.length?(e=a,b):e},b.axis=function(a){return arguments.length?(g=a,b):g},b.size=function(a){return arguments.length?(f=a,b):f},b.getData=function(a){return arguments.length?(h=d3.functor(a),b):h},b.scale=function(a){return arguments.length?(j=a,b):j},b.color=function(c){return arguments.length?(i=a.utils.getColor(c),b):i},b.duration=function(a){return arguments.length?(k=a,m.reset(k),b):k},b},a.models.furiousLegend=function(){"use strict";function b(p){function q(a,b){return"furious"!=o?"#000":m?a.disengaged?g(a,b):"#fff":m?void 0:a.disabled?g(a,b):"#fff"}function r(a,b){return m&&"furious"==o?a.disengaged?"#fff":g(a,b):a.disabled?"#fff":g(a,b)}return p.each(function(b){var p=d-c.left-c.right,s=d3.select(this);a.utils.initSVG(s);var t=s.selectAll("g.nv-legend").data([b]),u=(t.enter().append("g").attr("class","nvd3 nv-legend").append("g"),t.select("g"));t.attr("transform","translate("+c.left+","+c.top+")");var v,w=u.selectAll(".nv-series").data(function(a){return"furious"!=o?a:a.filter(function(a){return m?!0:!a.disengaged})}),x=w.enter().append("g").attr("class","nv-series");if("classic"==o)x.append("circle").style("stroke-width",2).attr("class","nv-legend-symbol").attr("r",5),v=w.select("circle");else if("furious"==o){x.append("rect").style("stroke-width",2).attr("class","nv-legend-symbol").attr("rx",3).attr("ry",3),v=w.select("rect"),x.append("g").attr("class","nv-check-box").property("innerHTML",'<path d="M0.5,5 L22.5,5 L22.5,26.5 L0.5,26.5 L0.5,5 Z" class="nv-box"></path><path d="M5.5,12.8618467 L11.9185089,19.2803556 L31,0.198864511" class="nv-check"></path>').attr("transform","translate(-10,-8)scale(0.5)");var y=w.select(".nv-check-box");y.each(function(a,b){d3.select(this).selectAll("path").attr("stroke",q(a,b))})}x.append("text").attr("text-anchor","start").attr("class","nv-legend-text").attr("dy",".32em").attr("dx","8");var z=w.select("text.nv-legend-text");w.on("mouseover",function(a,b){n.legendMouseover(a,b)}).on("mouseout",function(a,b){n.legendMouseout(a,b)}).on("click",function(a,b){n.legendClick(a,b);var c=w.data();if(k){if("classic"==o)l?(c.forEach(function(a){a.disabled=!0}),a.disabled=!1):(a.disabled=!a.disabled,c.every(function(a){return a.disabled})&&c.forEach(function(a){a.disabled=!1}));else if("furious"==o)if(m)a.disengaged=!a.disengaged,a.userDisabled=void 0==a.userDisabled?!!a.disabled:a.userDisabled,a.disabled=a.disengaged||a.userDisabled;else if(!m){a.disabled=!a.disabled,a.userDisabled=a.disabled;var d=c.filter(function(a){return!a.disengaged});d.every(function(a){return a.userDisabled})&&c.forEach(function(a){a.disabled=a.userDisabled=!1})}n.stateChange({disabled:c.map(function(a){return!!a.disabled}),disengaged:c.map(function(a){return!!a.disengaged})})}}).on("dblclick",function(a,b){if(("furious"!=o||!m)&&(n.legendDblclick(a,b),k)){var c=w.data();c.forEach(function(a){a.disabled=!0,"furious"==o&&(a.userDisabled=a.disabled)}),a.disabled=!1,"furious"==o&&(a.userDisabled=a.disabled),n.stateChange({disabled:c.map(function(a){return!!a.disabled})})}}),w.classed("nv-disabled",function(a){return a.userDisabled}),w.exit().remove(),z.attr("fill",q).text(f);var A;switch(o){case"furious":A=23;break;case"classic":A=20}if(h){var B=[];w.each(function(){var b,c=d3.select(this).select("text");try{if(b=c.node().getComputedTextLength(),0>=b)throw Error()}catch(d){b=a.utils.calcApproxTextWidth(c)}B.push(b+i)});for(var C=0,D=0,E=[];p>D&&C<B.length;)E[C]=B[C],D+=B[C++];for(0===C&&(C=1);D>p&&C>1;){E=[],C--;for(var F=0;F<B.length;F++)B[F]>(E[F%C]||0)&&(E[F%C]=B[F]);D=E.reduce(function(a,b){return a+b})}for(var G=[],H=0,I=0;C>H;H++)G[H]=I,I+=E[H];w.attr("transform",function(a,b){return"translate("+G[b%C]+","+(5+Math.floor(b/C)*A)+")"}),j?u.attr("transform","translate("+(d-c.right-D)+","+c.top+")"):u.attr("transform","translate(0,"+c.top+")"),e=c.top+c.bottom+Math.ceil(B.length/C)*A}else{var J,K=5,L=5,M=0;w.attr("transform",function(){var a=d3.select(this).select("text").node().getComputedTextLength()+i;return J=L,d<c.left+c.right+J+a&&(L=J=5,K+=A),L+=a,L>M&&(M=L),"translate("+J+","+K+")"}),u.attr("transform","translate("+(d-c.right-M)+","+c.top+")"),e=c.top+c.bottom+K+15}"furious"==o&&v.attr("width",function(a,b){return z[0][b].getComputedTextLength()+27}).attr("height",18).attr("y",-9).attr("x",-15),v.style("fill",r).style("stroke",function(a,b){return a.color||g(a,b)})}),b}var c={top:5,right:0,bottom:5,left:0},d=400,e=20,f=function(a){return a.key},g=a.utils.getColor(),h=!0,i=28,j=!0,k=!0,l=!1,m=!1,n=d3.dispatch("legendClick","legendDblclick","legendMouseover","legendMouseout","stateChange"),o="classic";return b.dispatch=n,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return d},set:function(a){d=a}},height:{get:function(){return e},set:function(a){e=a}},key:{get:function(){return f},set:function(a){f=a}},align:{get:function(){return h},set:function(a){h=a}},rightAlign:{get:function(){return j},set:function(a){j=a}},padding:{get:function(){return i},set:function(a){i=a}},updateState:{get:function(){return k},set:function(a){k=a}},radioButtonMode:{get:function(){return l},set:function(a){l=a}},expanded:{get:function(){return m},set:function(a){m=a}},vers:{get:function(){return o},set:function(a){o=a}},margin:{get:function(){return c},set:function(a){c.top=void 0!==a.top?a.top:c.top,c.right=void 0!==a.right?a.right:c.right,c.bottom=void 0!==a.bottom?a.bottom:c.bottom,c.left=void 0!==a.left?a.left:c.left}},color:{get:function(){return g},set:function(b){g=a.utils.getColor(b)}}}),a.utils.initOptions(b),b},a.models.historicalBar=function(){"use strict";function b(x){return x.each(function(b){w.reset(),k=d3.select(this);var x=a.utils.availableWidth(h,k,g),y=a.utils.availableHeight(i,k,g);a.utils.initSVG(k),l.domain(c||d3.extent(b[0].values.map(n).concat(p))),l.range(r?e||[.5*x/b[0].values.length,x*(b[0].values.length-.5)/b[0].values.length]:e||[0,x]),m.domain(d||d3.extent(b[0].values.map(o).concat(q))).range(f||[y,0]),l.domain()[0]===l.domain()[1]&&l.domain(l.domain()[0]?[l.domain()[0]-.01*l.domain()[0],l.domain()[1]+.01*l.domain()[1]]:[-1,1]),m.domain()[0]===m.domain()[1]&&m.domain(m.domain()[0]?[m.domain()[0]+.01*m.domain()[0],m.domain()[1]-.01*m.domain()[1]]:[-1,1]);var z=k.selectAll("g.nv-wrap.nv-historicalBar-"+j).data([b[0].values]),A=z.enter().append("g").attr("class","nvd3 nv-wrap nv-historicalBar-"+j),B=A.append("defs"),C=A.append("g"),D=z.select("g");C.append("g").attr("class","nv-bars"),z.attr("transform","translate("+g.left+","+g.top+")"),k.on("click",function(a,b){u.chartClick({data:a,index:b,pos:d3.event,id:j})}),B.append("clipPath").attr("id","nv-chart-clip-path-"+j).append("rect"),z.select("#nv-chart-clip-path-"+j+" rect").attr("width",x).attr("height",y),D.attr("clip-path",s?"url(#nv-chart-clip-path-"+j+")":"");var E=z.select(".nv-bars").selectAll(".nv-bar").data(function(a){return a},function(a,b){return n(a,b)});E.exit().remove(),E.enter().append("rect").attr("x",0).attr("y",function(b,c){return a.utils.NaNtoZero(m(Math.max(0,o(b,c))))}).attr("height",function(b,c){return a.utils.NaNtoZero(Math.abs(m(o(b,c))-m(0)))}).attr("transform",function(a,c){return"translate("+(l(n(a,c))-x/b[0].values.length*.45)+",0)"}).on("mouseover",function(a,b){v&&(d3.select(this).classed("hover",!0),u.elementMouseover({data:a,index:b,color:d3.select(this).style("fill")}))}).on("mouseout",function(a,b){v&&(d3.select(this).classed("hover",!1),u.elementMouseout({data:a,index:b,color:d3.select(this).style("fill")}))}).on("mousemove",function(a,b){v&&u.elementMousemove({data:a,index:b,color:d3.select(this).style("fill")})}).on("click",function(a,b){v&&(u.elementClick({data:a,index:b,color:d3.select(this).style("fill")}),d3.event.stopPropagation())}).on("dblclick",function(a,b){v&&(u.elementDblClick({data:a,index:b,color:d3.select(this).style("fill")}),d3.event.stopPropagation())}),E.attr("fill",function(a,b){return t(a,b)}).attr("class",function(a,b,c){return(o(a,b)<0?"nv-bar negative":"nv-bar positive")+" nv-bar-"+c+"-"+b}).watchTransition(w,"bars").attr("transform",function(a,c){return"translate("+(l(n(a,c))-x/b[0].values.length*.45)+",0)"}).attr("width",x/b[0].values.length*.9),E.watchTransition(w,"bars").attr("y",function(b,c){var d=o(b,c)<0?m(0):m(0)-m(o(b,c))<1?m(0)-1:m(o(b,c));return a.utils.NaNtoZero(d)}).attr("height",function(b,c){return a.utils.NaNtoZero(Math.max(Math.abs(m(o(b,c))-m(0)),1))})}),w.renderEnd("historicalBar immediate"),b}var c,d,e,f,g={top:0,right:0,bottom:0,left:0},h=null,i=null,j=Math.floor(1e4*Math.random()),k=null,l=d3.scale.linear(),m=d3.scale.linear(),n=function(a){return a.x},o=function(a){return a.y},p=[],q=[0],r=!1,s=!0,t=a.utils.defaultColor(),u=d3.dispatch("chartClick","elementClick","elementDblClick","elementMouseover","elementMouseout","elementMousemove","renderEnd"),v=!0,w=a.utils.renderWatch(u,0);return b.highlightPoint=function(a,b){k.select(".nv-bars .nv-bar-0-"+a).classed("hover",b)},b.clearHighlights=function(){k.select(".nv-bars .nv-bar.hover").classed("hover",!1)},b.dispatch=u,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return h},set:function(a){h=a}},height:{get:function(){return i},set:function(a){i=a}},forceX:{get:function(){return p},set:function(a){p=a}},forceY:{get:function(){return q},set:function(a){q=a}},padData:{get:function(){return r},set:function(a){r=a}},x:{get:function(){return n},set:function(a){n=a}},y:{get:function(){return o},set:function(a){o=a}},xScale:{get:function(){return l},set:function(a){l=a}},yScale:{get:function(){return m},set:function(a){m=a}},xDomain:{get:function(){return c},set:function(a){c=a}},yDomain:{get:function(){return d},set:function(a){d=a}},xRange:{get:function(){return e},set:function(a){e=a}},yRange:{get:function(){return f},set:function(a){f=a}},clipEdge:{get:function(){return s},set:function(a){s=a}},id:{get:function(){return j},set:function(a){j=a}},interactive:{get:function(){return v},set:function(a){v=a}},margin:{get:function(){return g},set:function(a){g.top=void 0!==a.top?a.top:g.top,g.right=void 0!==a.right?a.right:g.right,g.bottom=void 0!==a.bottom?a.bottom:g.bottom,g.left=void 0!==a.left?a.left:g.left}},color:{get:function(){return t},set:function(b){t=a.utils.getColor(b)}}}),a.utils.initOptions(b),b},a.models.historicalBarChart=function(b){"use strict";function c(b){return b.each(function(k){z.reset(),z.models(f),q&&z.models(g),r&&z.models(h);var w=d3.select(this),A=this;a.utils.initSVG(w);var B=a.utils.availableWidth(n,w,l),C=a.utils.availableHeight(o,w,l);if(c.update=function(){w.transition().duration(y).call(c)},c.container=this,u.disabled=k.map(function(a){return!!a.disabled}),!v){var D;v={};for(D in u)v[D]=u[D]instanceof Array?u[D].slice(0):u[D]}if(!(k&&k.length&&k.filter(function(a){return a.values.length}).length))return a.utils.noData(c,w),c;w.selectAll(".nv-noData").remove(),d=f.xScale(),e=f.yScale();var E=w.selectAll("g.nv-wrap.nv-historicalBarChart").data([k]),F=E.enter().append("g").attr("class","nvd3 nv-wrap nv-historicalBarChart").append("g"),G=E.select("g");F.append("g").attr("class","nv-x nv-axis"),F.append("g").attr("class","nv-y nv-axis"),F.append("g").attr("class","nv-barsWrap"),F.append("g").attr("class","nv-legendWrap"),F.append("g").attr("class","nv-interactive"),p&&(i.width(B),G.select(".nv-legendWrap").datum(k).call(i),l.top!=i.height()&&(l.top=i.height(),C=a.utils.availableHeight(o,w,l)),E.select(".nv-legendWrap").attr("transform","translate(0,"+-l.top+")")),E.attr("transform","translate("+l.left+","+l.top+")"),s&&G.select(".nv-y.nv-axis").attr("transform","translate("+B+",0)"),t&&(j.width(B).height(C).margin({left:l.left,top:l.top}).svgContainer(w).xScale(d),E.select(".nv-interactive").call(j)),f.width(B).height(C).color(k.map(function(a,b){return a.color||m(a,b)}).filter(function(a,b){return!k[b].disabled}));var H=G.select(".nv-barsWrap").datum(k.filter(function(a){return!a.disabled}));H.transition().call(f),q&&(g.scale(d)._ticks(a.utils.calcTicksX(B/100,k)).tickSize(-C,0),G.select(".nv-x.nv-axis").attr("transform","translate(0,"+e.range()[0]+")"),G.select(".nv-x.nv-axis").transition().call(g)),r&&(h.scale(e)._ticks(a.utils.calcTicksY(C/36,k)).tickSize(-B,0),G.select(".nv-y.nv-axis").transition().call(h)),j.dispatch.on("elementMousemove",function(b){f.clearHighlights();var d,e,i,n=[];k.filter(function(a,b){return a.seriesIndex=b,!a.disabled}).forEach(function(g){e=a.interactiveBisect(g.values,b.pointXValue,c.x()),f.highlightPoint(e,!0);var h=g.values[e];void 0!==h&&(void 0===d&&(d=h),void 0===i&&(i=c.xScale()(c.x()(h,e))),n.push({key:g.key,value:c.y()(h,e),color:m(g,g.seriesIndex),data:g.values[e]}))});var o=g.tickFormat()(c.x()(d,e));j.tooltip.position({left:i+l.left,top:b.mouseY+l.top}).chartContainer(A.parentNode).valueFormatter(function(a){return h.tickFormat()(a)}).data({value:o,index:e,series:n})(),j.renderGuideLine(i)}),j.dispatch.on("elementMouseout",function(){x.tooltipHide(),f.clearHighlights()}),i.dispatch.on("legendClick",function(a){a.disabled=!a.disabled,k.filter(function(a){return!a.disabled}).length||k.map(function(a){return a.disabled=!1,E.selectAll(".nv-series").classed("disabled",!1),a}),u.disabled=k.map(function(a){return!!a.disabled}),x.stateChange(u),b.transition().call(c)}),i.dispatch.on("legendDblclick",function(a){k.forEach(function(a){a.disabled=!0}),a.disabled=!1,u.disabled=k.map(function(a){return!!a.disabled}),x.stateChange(u),c.update()}),x.on("changeState",function(a){"undefined"!=typeof a.disabled&&(k.forEach(function(b,c){b.disabled=a.disabled[c]}),u.disabled=a.disabled),c.update()})}),z.renderEnd("historicalBarChart immediate"),c}var d,e,f=b||a.models.historicalBar(),g=a.models.axis(),h=a.models.axis(),i=a.models.legend(),j=a.interactiveGuideline(),k=a.models.tooltip(),l={top:30,right:90,bottom:50,left:90},m=a.utils.defaultColor(),n=null,o=null,p=!1,q=!0,r=!0,s=!1,t=!1,u={},v=null,w=null,x=d3.dispatch("tooltipHide","stateChange","changeState","renderEnd"),y=250;g.orient("bottom").tickPadding(7),h.orient(s?"right":"left"),k.duration(0).headerEnabled(!1).valueFormatter(function(a,b){return h.tickFormat()(a,b)}).headerFormatter(function(a,b){return g.tickFormat()(a,b)});var z=a.utils.renderWatch(x,0);return f.dispatch.on("elementMouseover.tooltip",function(a){a.series={key:c.x()(a.data),value:c.y()(a.data),color:a.color},k.data(a).hidden(!1)}),f.dispatch.on("elementMouseout.tooltip",function(){k.hidden(!0)}),f.dispatch.on("elementMousemove.tooltip",function(){k.position({top:d3.event.pageY,left:d3.event.pageX})()}),c.dispatch=x,c.bars=f,c.legend=i,c.xAxis=g,c.yAxis=h,c.interactiveLayer=j,c.tooltip=k,c.options=a.utils.optionsFunc.bind(c),c._options=Object.create({},{width:{get:function(){return n},set:function(a){n=a}},height:{get:function(){return o},set:function(a){o=a}},showLegend:{get:function(){return p},set:function(a){p=a}},showXAxis:{get:function(){return q},set:function(a){q=a}},showYAxis:{get:function(){return r},set:function(a){r=a}},defaultState:{get:function(){return v},set:function(a){v=a}},noData:{get:function(){return w},set:function(a){w=a}},tooltips:{get:function(){return k.enabled()},set:function(b){a.deprecated("tooltips","use chart.tooltip.enabled() instead"),k.enabled(!!b)}},tooltipContent:{get:function(){return k.contentGenerator()},set:function(b){a.deprecated("tooltipContent","use chart.tooltip.contentGenerator() instead"),k.contentGenerator(b)}},margin:{get:function(){return l},set:function(a){l.top=void 0!==a.top?a.top:l.top,l.right=void 0!==a.right?a.right:l.right,l.bottom=void 0!==a.bottom?a.bottom:l.bottom,l.left=void 0!==a.left?a.left:l.left}},color:{get:function(){return m},set:function(b){m=a.utils.getColor(b),i.color(m),f.color(m)}},duration:{get:function(){return y},set:function(a){y=a,z.reset(y),h.duration(y),g.duration(y)}},rightAlignYAxis:{get:function(){return s},set:function(a){s=a,h.orient(a?"right":"left")}},useInteractiveGuideline:{get:function(){return t},set:function(a){t=a,a===!0&&c.interactive(!1)}}}),a.utils.inheritOptions(c,f),a.utils.initOptions(c),c},a.models.ohlcBarChart=function(){var b=a.models.historicalBarChart(a.models.ohlcBar());return b.useInteractiveGuideline(!0),b.interactiveLayer.tooltip.contentGenerator(function(a){var c=a.series[0].data,d=c.open<c.close?"2ca02c":"d62728";return'<h3 style="color: #'+d+'">'+a.value+"</h3><table><tr><td>open:</td><td>"+b.yAxis.tickFormat()(c.open)+"</td></tr><tr><td>close:</td><td>"+b.yAxis.tickFormat()(c.close)+"</td></tr><tr><td>high</td><td>"+b.yAxis.tickFormat()(c.high)+"</td></tr><tr><td>low:</td><td>"+b.yAxis.tickFormat()(c.low)+"</td></tr></table>"}),b},a.models.candlestickBarChart=function(){var b=a.models.historicalBarChart(a.models.candlestickBar());return b.useInteractiveGuideline(!0),b.interactiveLayer.tooltip.contentGenerator(function(a){var c=a.series[0].data,d=c.open<c.close?"2ca02c":"d62728";return'<h3 style="color: #'+d+'">'+a.value+"</h3><table><tr><td>open:</td><td>"+b.yAxis.tickFormat()(c.open)+"</td></tr><tr><td>close:</td><td>"+b.yAxis.tickFormat()(c.close)+"</td></tr><tr><td>high</td><td>"+b.yAxis.tickFormat()(c.high)+"</td></tr><tr><td>low:</td><td>"+b.yAxis.tickFormat()(c.low)+"</td></tr></table>"}),b},a.models.legend=function(){"use strict";function b(p){function q(a,b){return"furious"!=o?"#000":m?a.disengaged?"#000":"#fff":m?void 0:(a.color||(a.color=g(a,b)),a.disabled?a.color:"#fff")}function r(a,b){return m&&"furious"==o&&a.disengaged?"#eee":a.color||g(a,b)}function s(a){return m&&"furious"==o?1:a.disabled?0:1}return p.each(function(b){var g=d-c.left-c.right,p=d3.select(this);a.utils.initSVG(p);var t=p.selectAll("g.nv-legend").data([b]),u=t.enter().append("g").attr("class","nvd3 nv-legend").append("g"),v=t.select("g");t.attr("transform","translate("+c.left+","+c.top+")");var w,x,y=v.selectAll(".nv-series").data(function(a){return"furious"!=o?a:a.filter(function(a){return m?!0:!a.disengaged})}),z=y.enter().append("g").attr("class","nv-series");switch(o){case"furious":x=23;break;case"classic":x=20}if("classic"==o)z.append("circle").style("stroke-width",2).attr("class","nv-legend-symbol").attr("r",5),w=y.select("circle");else if("furious"==o){z.append("rect").style("stroke-width",2).attr("class","nv-legend-symbol").attr("rx",3).attr("ry",3),w=y.select(".nv-legend-symbol"),z.append("g").attr("class","nv-check-box").property("innerHTML",'<path d="M0.5,5 L22.5,5 L22.5,26.5 L0.5,26.5 L0.5,5 Z" class="nv-box"></path><path d="M5.5,12.8618467 L11.9185089,19.2803556 L31,0.198864511" class="nv-check"></path>').attr("transform","translate(-10,-8)scale(0.5)");var A=y.select(".nv-check-box");A.each(function(a,b){d3.select(this).selectAll("path").attr("stroke",q(a,b))})}z.append("text").attr("text-anchor","start").attr("class","nv-legend-text").attr("dy",".32em").attr("dx","8");var B=y.select("text.nv-legend-text");y.on("mouseover",function(a,b){n.legendMouseover(a,b)}).on("mouseout",function(a,b){n.legendMouseout(a,b)}).on("click",function(a,b){n.legendClick(a,b);var c=y.data();if(k){if("classic"==o)l?(c.forEach(function(a){a.disabled=!0}),a.disabled=!1):(a.disabled=!a.disabled,c.every(function(a){return a.disabled})&&c.forEach(function(a){a.disabled=!1}));else if("furious"==o)if(m)a.disengaged=!a.disengaged,a.userDisabled=void 0==a.userDisabled?!!a.disabled:a.userDisabled,a.disabled=a.disengaged||a.userDisabled;else if(!m){a.disabled=!a.disabled,a.userDisabled=a.disabled;var d=c.filter(function(a){return!a.disengaged});d.every(function(a){return a.userDisabled})&&c.forEach(function(a){a.disabled=a.userDisabled=!1})}n.stateChange({disabled:c.map(function(a){return!!a.disabled}),disengaged:c.map(function(a){return!!a.disengaged})})}}).on("dblclick",function(a,b){if(("furious"!=o||!m)&&(n.legendDblclick(a,b),k)){var c=y.data();c.forEach(function(a){a.disabled=!0,"furious"==o&&(a.userDisabled=a.disabled)}),a.disabled=!1,"furious"==o&&(a.userDisabled=a.disabled),n.stateChange({disabled:c.map(function(a){return!!a.disabled})})}}),y.classed("nv-disabled",function(a){return a.userDisabled}),y.exit().remove(),B.attr("fill",q).text(f);var C=0;if(h){var D=[];y.each(function(){var b,c=d3.select(this).select("text");try{if(b=c.node().getComputedTextLength(),0>=b)throw Error()}catch(d){b=a.utils.calcApproxTextWidth(c)}D.push(b+i)});var E=0,F=[];for(C=0;g>C&&E<D.length;)F[E]=D[E],C+=D[E++];for(0===E&&(E=1);C>g&&E>1;){F=[],E--;for(var G=0;G<D.length;G++)D[G]>(F[G%E]||0)&&(F[G%E]=D[G]);C=F.reduce(function(a,b){return a+b})}for(var H=[],I=0,J=0;E>I;I++)H[I]=J,J+=F[I];y.attr("transform",function(a,b){return"translate("+H[b%E]+","+(5+Math.floor(b/E)*x)+")"}),j?v.attr("transform","translate("+(d-c.right-C)+","+c.top+")"):v.attr("transform","translate(0,"+c.top+")"),e=c.top+c.bottom+Math.ceil(D.length/E)*x}else{var K,L=5,M=5,N=0;y.attr("transform",function(){var a=d3.select(this).select("text").node().getComputedTextLength()+i;return K=M,d<c.left+c.right+K+a&&(M=K=5,L+=x),M+=a,M>N&&(N=M),K+N>C&&(C=K+N),"translate("+K+","+L+")"}),v.attr("transform","translate("+(d-c.right-N)+","+c.top+")"),e=c.top+c.bottom+L+15}if("furious"==o){w.attr("width",function(a,b){return B[0][b].getComputedTextLength()+27}).attr("height",18).attr("y",-9).attr("x",-15),u.insert("rect",":first-child").attr("class","nv-legend-bg").attr("fill","#eee").attr("opacity",0);var O=v.select(".nv-legend-bg");O.transition().duration(300).attr("x",-x).attr("width",C+x-12).attr("height",e+10).attr("y",-c.top-10).attr("opacity",m?1:0)}w.style("fill",r).style("fill-opacity",s).style("stroke",r)}),b}var c={top:5,right:0,bottom:5,left:0},d=400,e=20,f=function(a){return a.key},g=a.utils.getColor(),h=!0,i=32,j=!0,k=!0,l=!1,m=!1,n=d3.dispatch("legendClick","legendDblclick","legendMouseover","legendMouseout","stateChange"),o="classic";return b.dispatch=n,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return d},set:function(a){d=a}},height:{get:function(){return e},set:function(a){e=a}},key:{get:function(){return f},set:function(a){f=a}},align:{get:function(){return h},set:function(a){h=a}},rightAlign:{get:function(){return j},set:function(a){j=a}},padding:{get:function(){return i},set:function(a){i=a}},updateState:{get:function(){return k},set:function(a){k=a}},radioButtonMode:{get:function(){return l},set:function(a){l=a}},expanded:{get:function(){return m},set:function(a){m=a}},vers:{get:function(){return o},set:function(a){o=a}},margin:{get:function(){return c},set:function(a){c.top=void 0!==a.top?a.top:c.top,c.right=void 0!==a.right?a.right:c.right,c.bottom=void 0!==a.bottom?a.bottom:c.bottom,c.left=void 0!==a.left?a.left:c.left}},color:{get:function(){return g},set:function(b){g=a.utils.getColor(b)}}}),a.utils.initOptions(b),b},a.models.line=function(){"use strict";function b(r){return v.reset(),v.models(e),r.each(function(b){i=d3.select(this);var r=a.utils.availableWidth(g,i,f),s=a.utils.availableHeight(h,i,f);a.utils.initSVG(i),c=e.xScale(),d=e.yScale(),t=t||c,u=u||d;var w=i.selectAll("g.nv-wrap.nv-line").data([b]),x=w.enter().append("g").attr("class","nvd3 nv-wrap nv-line"),y=x.append("defs"),z=x.append("g"),A=w.select("g");z.append("g").attr("class","nv-groups"),z.append("g").attr("class","nv-scatterWrap"),w.attr("transform","translate("+f.left+","+f.top+")"),e.width(r).height(s);var B=w.select(".nv-scatterWrap");B.call(e),y.append("clipPath").attr("id","nv-edge-clip-"+e.id()).append("rect"),w.select("#nv-edge-clip-"+e.id()+" rect").attr("width",r).attr("height",s>0?s:0),A.attr("clip-path",p?"url(#nv-edge-clip-"+e.id()+")":""),B.attr("clip-path",p?"url(#nv-edge-clip-"+e.id()+")":"");var C=w.select(".nv-groups").selectAll(".nv-group").data(function(a){return a},function(a){return a.key});C.enter().append("g").style("stroke-opacity",1e-6).style("stroke-width",function(a){return a.strokeWidth||j}).style("fill-opacity",1e-6),C.exit().remove(),C.attr("class",function(a,b){return(a.classed||"")+" nv-group nv-series-"+b}).classed("hover",function(a){return a.hover}).style("fill",function(a,b){return k(a,b)}).style("stroke",function(a,b){return k(a,b)}),C.watchTransition(v,"line: groups").style("stroke-opacity",1).style("fill-opacity",function(a){return a.fillOpacity||.5});var D=C.selectAll("path.nv-area").data(function(a){return o(a)?[a]:[]});D.enter().append("path").attr("class","nv-area").attr("d",function(b){return d3.svg.area().interpolate(q).defined(n).x(function(b,c){return a.utils.NaNtoZero(t(l(b,c)))}).y0(function(b,c){return a.utils.NaNtoZero(u(m(b,c)))}).y1(function(){return u(d.domain()[0]<=0?d.domain()[1]>=0?0:d.domain()[1]:d.domain()[0])}).apply(this,[b.values])}),C.exit().selectAll("path.nv-area").remove(),D.watchTransition(v,"line: areaPaths").attr("d",function(b){return d3.svg.area().interpolate(q).defined(n).x(function(b,d){return a.utils.NaNtoZero(c(l(b,d)))}).y0(function(b,c){return a.utils.NaNtoZero(d(m(b,c)))}).y1(function(){return d(d.domain()[0]<=0?d.domain()[1]>=0?0:d.domain()[1]:d.domain()[0])}).apply(this,[b.values])});var E=C.selectAll("path.nv-line").data(function(a){return[a.values]});E.enter().append("path").attr("class","nv-line").attr("d",d3.svg.line().interpolate(q).defined(n).x(function(b,c){return a.utils.NaNtoZero(t(l(b,c)))}).y(function(b,c){return a.utils.NaNtoZero(u(m(b,c)))})),E.watchTransition(v,"line: linePaths").attr("d",d3.svg.line().interpolate(q).defined(n).x(function(b,d){return a.utils.NaNtoZero(c(l(b,d)))}).y(function(b,c){return a.utils.NaNtoZero(d(m(b,c)))})),t=c.copy(),u=d.copy()}),v.renderEnd("line immediate"),b}var c,d,e=a.models.scatter(),f={top:0,right:0,bottom:0,left:0},g=960,h=500,i=null,j=1.5,k=a.utils.defaultColor(),l=function(a){return a.x},m=function(a){return a.y},n=function(a,b){return!isNaN(m(a,b))&&null!==m(a,b)},o=function(a){return a.area},p=!1,q="linear",r=250,s=d3.dispatch("elementClick","elementMouseover","elementMouseout","renderEnd");e.pointSize(16).pointDomain([16,256]);var t,u,v=a.utils.renderWatch(s,r);return b.dispatch=s,b.scatter=e,e.dispatch.on("elementClick",function(){s.elementClick.apply(this,arguments)}),e.dispatch.on("elementMouseover",function(){s.elementMouseover.apply(this,arguments)}),e.dispatch.on("elementMouseout",function(){s.elementMouseout.apply(this,arguments)}),b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return g},set:function(a){g=a}},height:{get:function(){return h},set:function(a){h=a}},defined:{get:function(){return n},set:function(a){n=a}},interpolate:{get:function(){return q},set:function(a){q=a}},clipEdge:{get:function(){return p},set:function(a){p=a}},margin:{get:function(){return f},set:function(a){f.top=void 0!==a.top?a.top:f.top,f.right=void 0!==a.right?a.right:f.right,f.bottom=void 0!==a.bottom?a.bottom:f.bottom,f.left=void 0!==a.left?a.left:f.left}},duration:{get:function(){return r},set:function(a){r=a,v.reset(r),e.duration(r)}},isArea:{get:function(){return o},set:function(a){o=d3.functor(a)}},x:{get:function(){return l},set:function(a){l=a,e.x(a)}},y:{get:function(){return m},set:function(a){m=a,e.y(a)}},color:{get:function(){return k},set:function(b){k=a.utils.getColor(b),e.color(k)}}}),a.utils.inheritOptions(b,e),a.utils.initOptions(b),b},a.models.lineChart=function(){"use strict";function b(j){return y.reset(),y.models(e),p&&y.models(f),q&&y.models(g),j.each(function(j){var v=d3.select(this),y=this;a.utils.initSVG(v);var B=a.utils.availableWidth(m,v,k),C=a.utils.availableHeight(n,v,k);if(b.update=function(){0===x?v.call(b):v.transition().duration(x).call(b)},b.container=this,t.setter(A(j),b.update).getter(z(j)).update(),t.disabled=j.map(function(a){return!!a.disabled}),!u){var D;u={};for(D in t)u[D]=t[D]instanceof Array?t[D].slice(0):t[D]
  22801. }if(!(j&&j.length&&j.filter(function(a){return a.values.length}).length))return a.utils.noData(b,v),b;v.selectAll(".nv-noData").remove(),c=e.xScale(),d=e.yScale();var E=v.selectAll("g.nv-wrap.nv-lineChart").data([j]),F=E.enter().append("g").attr("class","nvd3 nv-wrap nv-lineChart").append("g"),G=E.select("g");F.append("rect").style("opacity",0),F.append("g").attr("class","nv-x nv-axis"),F.append("g").attr("class","nv-y nv-axis"),F.append("g").attr("class","nv-linesWrap"),F.append("g").attr("class","nv-legendWrap"),F.append("g").attr("class","nv-interactive"),G.select("rect").attr("width",B).attr("height",C>0?C:0),o&&(h.width(B),G.select(".nv-legendWrap").datum(j).call(h),k.top!=h.height()&&(k.top=h.height(),C=a.utils.availableHeight(n,v,k)),E.select(".nv-legendWrap").attr("transform","translate(0,"+-k.top+")")),E.attr("transform","translate("+k.left+","+k.top+")"),r&&G.select(".nv-y.nv-axis").attr("transform","translate("+B+",0)"),s&&(i.width(B).height(C).margin({left:k.left,top:k.top}).svgContainer(v).xScale(c),E.select(".nv-interactive").call(i)),e.width(B).height(C).color(j.map(function(a,b){return a.color||l(a,b)}).filter(function(a,b){return!j[b].disabled}));var H=G.select(".nv-linesWrap").datum(j.filter(function(a){return!a.disabled}));H.call(e),p&&(f.scale(c)._ticks(a.utils.calcTicksX(B/100,j)).tickSize(-C,0),G.select(".nv-x.nv-axis").attr("transform","translate(0,"+d.range()[0]+")"),G.select(".nv-x.nv-axis").call(f)),q&&(g.scale(d)._ticks(a.utils.calcTicksY(C/36,j)).tickSize(-B,0),G.select(".nv-y.nv-axis").call(g)),h.dispatch.on("stateChange",function(a){for(var c in a)t[c]=a[c];w.stateChange(t),b.update()}),i.dispatch.on("elementMousemove",function(c){e.clearHighlights();var d,h,m,n=[];if(j.filter(function(a,b){return a.seriesIndex=b,!a.disabled}).forEach(function(f,g){h=a.interactiveBisect(f.values,c.pointXValue,b.x());var i=f.values[h],j=b.y()(i,h);null!=j&&e.highlightPoint(g,h,!0),void 0!==i&&(void 0===d&&(d=i),void 0===m&&(m=b.xScale()(b.x()(i,h))),n.push({key:f.key,value:j,color:l(f,f.seriesIndex)}))}),n.length>2){var o=b.yScale().invert(c.mouseY),p=Math.abs(b.yScale().domain()[0]-b.yScale().domain()[1]),q=.03*p,r=a.nearestValueIndex(n.map(function(a){return a.value}),o,q);null!==r&&(n[r].highlight=!0)}var s=f.tickFormat()(b.x()(d,h));i.tooltip.position({left:c.mouseX+k.left,top:c.mouseY+k.top}).chartContainer(y.parentNode).valueFormatter(function(a){return null==a?"N/A":g.tickFormat()(a)}).data({value:s,index:h,series:n})(),i.renderGuideLine(m)}),i.dispatch.on("elementClick",function(c){var d,f=[];j.filter(function(a,b){return a.seriesIndex=b,!a.disabled}).forEach(function(e){var g=a.interactiveBisect(e.values,c.pointXValue,b.x()),h=e.values[g];if("undefined"!=typeof h){"undefined"==typeof d&&(d=b.xScale()(b.x()(h,g)));var i=b.yScale()(b.y()(h,g));f.push({point:h,pointIndex:g,pos:[d,i],seriesIndex:e.seriesIndex,series:e})}}),e.dispatch.elementClick(f)}),i.dispatch.on("elementMouseout",function(){e.clearHighlights()}),w.on("changeState",function(a){"undefined"!=typeof a.disabled&&j.length===a.disabled.length&&(j.forEach(function(b,c){b.disabled=a.disabled[c]}),t.disabled=a.disabled),b.update()})}),y.renderEnd("lineChart immediate"),b}var c,d,e=a.models.line(),f=a.models.axis(),g=a.models.axis(),h=a.models.legend(),i=a.interactiveGuideline(),j=a.models.tooltip(),k={top:30,right:20,bottom:50,left:60},l=a.utils.defaultColor(),m=null,n=null,o=!0,p=!0,q=!0,r=!1,s=!1,t=a.utils.state(),u=null,v=null,w=d3.dispatch("tooltipShow","tooltipHide","stateChange","changeState","renderEnd"),x=250;f.orient("bottom").tickPadding(7),g.orient(r?"right":"left"),j.valueFormatter(function(a,b){return g.tickFormat()(a,b)}).headerFormatter(function(a,b){return f.tickFormat()(a,b)});var y=a.utils.renderWatch(w,x),z=function(a){return function(){return{active:a.map(function(a){return!a.disabled})}}},A=function(a){return function(b){void 0!==b.active&&a.forEach(function(a,c){a.disabled=!b.active[c]})}};return e.dispatch.on("elementMouseover.tooltip",function(a){j.data(a).position(a.pos).hidden(!1)}),e.dispatch.on("elementMouseout.tooltip",function(){j.hidden(!0)}),b.dispatch=w,b.lines=e,b.legend=h,b.xAxis=f,b.yAxis=g,b.interactiveLayer=i,b.tooltip=j,b.dispatch=w,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return m},set:function(a){m=a}},height:{get:function(){return n},set:function(a){n=a}},showLegend:{get:function(){return o},set:function(a){o=a}},showXAxis:{get:function(){return p},set:function(a){p=a}},showYAxis:{get:function(){return q},set:function(a){q=a}},defaultState:{get:function(){return u},set:function(a){u=a}},noData:{get:function(){return v},set:function(a){v=a}},tooltips:{get:function(){return j.enabled()},set:function(b){a.deprecated("tooltips","use chart.tooltip.enabled() instead"),j.enabled(!!b)}},tooltipContent:{get:function(){return j.contentGenerator()},set:function(b){a.deprecated("tooltipContent","use chart.tooltip.contentGenerator() instead"),j.contentGenerator(b)}},margin:{get:function(){return k},set:function(a){k.top=void 0!==a.top?a.top:k.top,k.right=void 0!==a.right?a.right:k.right,k.bottom=void 0!==a.bottom?a.bottom:k.bottom,k.left=void 0!==a.left?a.left:k.left}},duration:{get:function(){return x},set:function(a){x=a,y.reset(x),e.duration(x),f.duration(x),g.duration(x)}},color:{get:function(){return l},set:function(b){l=a.utils.getColor(b),h.color(l),e.color(l)}},rightAlignYAxis:{get:function(){return r},set:function(a){r=a,g.orient(r?"right":"left")}},useInteractiveGuideline:{get:function(){return s},set:function(a){s=a,s&&(e.interactive(!1),e.useVoronoi(!1))}}}),a.utils.inheritOptions(b,e),a.utils.initOptions(b),b},a.models.linePlusBarChart=function(){"use strict";function b(v){return v.each(function(v){function J(a){var b=+("e"==a),c=b?1:-1,d=X/3;return"M"+.5*c+","+d+"A6,6 0 0 "+b+" "+6.5*c+","+(d+6)+"V"+(2*d-6)+"A6,6 0 0 "+b+" "+.5*c+","+2*d+"ZM"+2.5*c+","+(d+8)+"V"+(2*d-8)+"M"+4.5*c+","+(d+8)+"V"+(2*d-8)}function S(){u.empty()||u.extent(I),kb.data([u.empty()?e.domain():I]).each(function(a){var b=e(a[0])-e.range()[0],c=e.range()[1]-e(a[1]);d3.select(this).select(".left").attr("width",0>b?0:b),d3.select(this).select(".right").attr("x",e(a[1])).attr("width",0>c?0:c)})}function T(){I=u.empty()?null:u.extent(),c=u.empty()?e.domain():u.extent(),K.brush({extent:c,brush:u}),S(),l.width(V).height(W).color(v.map(function(a,b){return a.color||C(a,b)}).filter(function(a,b){return!v[b].disabled&&v[b].bar})),j.width(V).height(W).color(v.map(function(a,b){return a.color||C(a,b)}).filter(function(a,b){return!v[b].disabled&&!v[b].bar}));var b=db.select(".nv-focus .nv-barsWrap").datum(Z.length?Z.map(function(a){return{key:a.key,values:a.values.filter(function(a,b){return l.x()(a,b)>=c[0]&&l.x()(a,b)<=c[1]})}}):[{values:[]}]),h=db.select(".nv-focus .nv-linesWrap").datum($[0].disabled?[{values:[]}]:$.map(function(a){return{area:a.area,fillOpacity:a.fillOpacity,key:a.key,values:a.values.filter(function(a,b){return j.x()(a,b)>=c[0]&&j.x()(a,b)<=c[1]})}}));d=Z.length?l.xScale():j.xScale(),n.scale(d)._ticks(a.utils.calcTicksX(V/100,v)).tickSize(-W,0),n.domain([Math.ceil(c[0]),Math.floor(c[1])]),db.select(".nv-x.nv-axis").transition().duration(L).call(n),b.transition().duration(L).call(l),h.transition().duration(L).call(j),db.select(".nv-focus .nv-x.nv-axis").attr("transform","translate(0,"+f.range()[0]+")"),p.scale(f)._ticks(a.utils.calcTicksY(W/36,v)).tickSize(-V,0),q.scale(g)._ticks(a.utils.calcTicksY(W/36,v)).tickSize(Z.length?0:-V,0),db.select(".nv-focus .nv-y1.nv-axis").style("opacity",Z.length?1:0),db.select(".nv-focus .nv-y2.nv-axis").style("opacity",$.length&&!$[0].disabled?1:0).attr("transform","translate("+d.range()[1]+",0)"),db.select(".nv-focus .nv-y1.nv-axis").transition().duration(L).call(p),db.select(".nv-focus .nv-y2.nv-axis").transition().duration(L).call(q)}var U=d3.select(this);a.utils.initSVG(U);var V=a.utils.availableWidth(y,U,w),W=a.utils.availableHeight(z,U,w)-(E?H:0),X=H-x.top-x.bottom;if(b.update=function(){U.transition().duration(L).call(b)},b.container=this,M.setter(R(v),b.update).getter(Q(v)).update(),M.disabled=v.map(function(a){return!!a.disabled}),!N){var Y;N={};for(Y in M)N[Y]=M[Y]instanceof Array?M[Y].slice(0):M[Y]}if(!(v&&v.length&&v.filter(function(a){return a.values.length}).length))return a.utils.noData(b,U),b;U.selectAll(".nv-noData").remove();var Z=v.filter(function(a){return!a.disabled&&a.bar}),$=v.filter(function(a){return!a.bar});d=l.xScale(),e=o.scale(),f=l.yScale(),g=j.yScale(),h=m.yScale(),i=k.yScale();var _=v.filter(function(a){return!a.disabled&&a.bar}).map(function(a){return a.values.map(function(a,b){return{x:A(a,b),y:B(a,b)}})}),ab=v.filter(function(a){return!a.disabled&&!a.bar}).map(function(a){return a.values.map(function(a,b){return{x:A(a,b),y:B(a,b)}})});d.range([0,V]),e.domain(d3.extent(d3.merge(_.concat(ab)),function(a){return a.x})).range([0,V]);var bb=U.selectAll("g.nv-wrap.nv-linePlusBar").data([v]),cb=bb.enter().append("g").attr("class","nvd3 nv-wrap nv-linePlusBar").append("g"),db=bb.select("g");cb.append("g").attr("class","nv-legendWrap");var eb=cb.append("g").attr("class","nv-focus");eb.append("g").attr("class","nv-x nv-axis"),eb.append("g").attr("class","nv-y1 nv-axis"),eb.append("g").attr("class","nv-y2 nv-axis"),eb.append("g").attr("class","nv-barsWrap"),eb.append("g").attr("class","nv-linesWrap");var fb=cb.append("g").attr("class","nv-context");if(fb.append("g").attr("class","nv-x nv-axis"),fb.append("g").attr("class","nv-y1 nv-axis"),fb.append("g").attr("class","nv-y2 nv-axis"),fb.append("g").attr("class","nv-barsWrap"),fb.append("g").attr("class","nv-linesWrap"),fb.append("g").attr("class","nv-brushBackground"),fb.append("g").attr("class","nv-x nv-brush"),D){var gb=t.align()?V/2:V,hb=t.align()?gb:0;t.width(gb),db.select(".nv-legendWrap").datum(v.map(function(a){return a.originalKey=void 0===a.originalKey?a.key:a.originalKey,a.key=a.originalKey+(a.bar?O:P),a})).call(t),w.top!=t.height()&&(w.top=t.height(),W=a.utils.availableHeight(z,U,w)-H),db.select(".nv-legendWrap").attr("transform","translate("+hb+","+-w.top+")")}bb.attr("transform","translate("+w.left+","+w.top+")"),db.select(".nv-context").style("display",E?"initial":"none"),m.width(V).height(X).color(v.map(function(a,b){return a.color||C(a,b)}).filter(function(a,b){return!v[b].disabled&&v[b].bar})),k.width(V).height(X).color(v.map(function(a,b){return a.color||C(a,b)}).filter(function(a,b){return!v[b].disabled&&!v[b].bar}));var ib=db.select(".nv-context .nv-barsWrap").datum(Z.length?Z:[{values:[]}]),jb=db.select(".nv-context .nv-linesWrap").datum($[0].disabled?[{values:[]}]:$);db.select(".nv-context").attr("transform","translate(0,"+(W+w.bottom+x.top)+")"),ib.transition().call(m),jb.transition().call(k),G&&(o._ticks(a.utils.calcTicksX(V/100,v)).tickSize(-X,0),db.select(".nv-context .nv-x.nv-axis").attr("transform","translate(0,"+h.range()[0]+")"),db.select(".nv-context .nv-x.nv-axis").transition().call(o)),F&&(r.scale(h)._ticks(X/36).tickSize(-V,0),s.scale(i)._ticks(X/36).tickSize(Z.length?0:-V,0),db.select(".nv-context .nv-y3.nv-axis").style("opacity",Z.length?1:0).attr("transform","translate(0,"+e.range()[0]+")"),db.select(".nv-context .nv-y2.nv-axis").style("opacity",$.length?1:0).attr("transform","translate("+e.range()[1]+",0)"),db.select(".nv-context .nv-y1.nv-axis").transition().call(r),db.select(".nv-context .nv-y2.nv-axis").transition().call(s)),u.x(e).on("brush",T),I&&u.extent(I);var kb=db.select(".nv-brushBackground").selectAll("g").data([I||u.extent()]),lb=kb.enter().append("g");lb.append("rect").attr("class","left").attr("x",0).attr("y",0).attr("height",X),lb.append("rect").attr("class","right").attr("x",0).attr("y",0).attr("height",X);var mb=db.select(".nv-x.nv-brush").call(u);mb.selectAll("rect").attr("height",X),mb.selectAll(".resize").append("path").attr("d",J),t.dispatch.on("stateChange",function(a){for(var c in a)M[c]=a[c];K.stateChange(M),b.update()}),K.on("changeState",function(a){"undefined"!=typeof a.disabled&&(v.forEach(function(b,c){b.disabled=a.disabled[c]}),M.disabled=a.disabled),b.update()}),T()}),b}var c,d,e,f,g,h,i,j=a.models.line(),k=a.models.line(),l=a.models.historicalBar(),m=a.models.historicalBar(),n=a.models.axis(),o=a.models.axis(),p=a.models.axis(),q=a.models.axis(),r=a.models.axis(),s=a.models.axis(),t=a.models.legend(),u=d3.svg.brush(),v=a.models.tooltip(),w={top:30,right:30,bottom:30,left:60},x={top:0,right:30,bottom:20,left:60},y=null,z=null,A=function(a){return a.x},B=function(a){return a.y},C=a.utils.defaultColor(),D=!0,E=!0,F=!1,G=!0,H=50,I=null,J=null,K=d3.dispatch("brush","stateChange","changeState"),L=0,M=a.utils.state(),N=null,O=" (left axis)",P=" (right axis)";j.clipEdge(!0),k.interactive(!1),n.orient("bottom").tickPadding(5),p.orient("left"),q.orient("right"),o.orient("bottom").tickPadding(5),r.orient("left"),s.orient("right"),v.headerEnabled(!0).headerFormatter(function(a,b){return n.tickFormat()(a,b)});var Q=function(a){return function(){return{active:a.map(function(a){return!a.disabled})}}},R=function(a){return function(b){void 0!==b.active&&a.forEach(function(a,c){a.disabled=!b.active[c]})}};return j.dispatch.on("elementMouseover.tooltip",function(a){v.duration(100).valueFormatter(function(a,b){return q.tickFormat()(a,b)}).data(a).position(a.pos).hidden(!1)}),j.dispatch.on("elementMouseout.tooltip",function(){v.hidden(!0)}),l.dispatch.on("elementMouseover.tooltip",function(a){a.value=b.x()(a.data),a.series={value:b.y()(a.data),color:a.color},v.duration(0).valueFormatter(function(a,b){return p.tickFormat()(a,b)}).data(a).hidden(!1)}),l.dispatch.on("elementMouseout.tooltip",function(){v.hidden(!0)}),l.dispatch.on("elementMousemove.tooltip",function(){v.position({top:d3.event.pageY,left:d3.event.pageX})()}),b.dispatch=K,b.legend=t,b.lines=j,b.lines2=k,b.bars=l,b.bars2=m,b.xAxis=n,b.x2Axis=o,b.y1Axis=p,b.y2Axis=q,b.y3Axis=r,b.y4Axis=s,b.tooltip=v,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return y},set:function(a){y=a}},height:{get:function(){return z},set:function(a){z=a}},showLegend:{get:function(){return D},set:function(a){D=a}},brushExtent:{get:function(){return I},set:function(a){I=a}},noData:{get:function(){return J},set:function(a){J=a}},focusEnable:{get:function(){return E},set:function(a){E=a}},focusHeight:{get:function(){return H},set:function(a){H=a}},focusShowAxisX:{get:function(){return G},set:function(a){G=a}},focusShowAxisY:{get:function(){return F},set:function(a){F=a}},legendLeftAxisHint:{get:function(){return O},set:function(a){O=a}},legendRightAxisHint:{get:function(){return P},set:function(a){P=a}},tooltips:{get:function(){return v.enabled()},set:function(b){a.deprecated("tooltips","use chart.tooltip.enabled() instead"),v.enabled(!!b)}},tooltipContent:{get:function(){return v.contentGenerator()},set:function(b){a.deprecated("tooltipContent","use chart.tooltip.contentGenerator() instead"),v.contentGenerator(b)}},margin:{get:function(){return w},set:function(a){w.top=void 0!==a.top?a.top:w.top,w.right=void 0!==a.right?a.right:w.right,w.bottom=void 0!==a.bottom?a.bottom:w.bottom,w.left=void 0!==a.left?a.left:w.left}},duration:{get:function(){return L},set:function(a){L=a}},color:{get:function(){return C},set:function(b){C=a.utils.getColor(b),t.color(C)}},x:{get:function(){return A},set:function(a){A=a,j.x(a),k.x(a),l.x(a),m.x(a)}},y:{get:function(){return B},set:function(a){B=a,j.y(a),k.y(a),l.y(a),m.y(a)}}}),a.utils.inheritOptions(b,j),a.utils.initOptions(b),b},a.models.lineWithFocusChart=function(){"use strict";function b(o){return o.each(function(o){function z(a){var b=+("e"==a),c=b?1:-1,d=M/3;return"M"+.5*c+","+d+"A6,6 0 0 "+b+" "+6.5*c+","+(d+6)+"V"+(2*d-6)+"A6,6 0 0 "+b+" "+.5*c+","+2*d+"ZM"+2.5*c+","+(d+8)+"V"+(2*d-8)+"M"+4.5*c+","+(d+8)+"V"+(2*d-8)}function G(){n.empty()||n.extent(y),U.data([n.empty()?e.domain():y]).each(function(a){var b=e(a[0])-c.range()[0],d=K-e(a[1]);d3.select(this).select(".left").attr("width",0>b?0:b),d3.select(this).select(".right").attr("x",e(a[1])).attr("width",0>d?0:d)})}function H(){y=n.empty()?null:n.extent();var a=n.empty()?e.domain():n.extent();if(!(Math.abs(a[0]-a[1])<=1)){A.brush({extent:a,brush:n}),G();var b=Q.select(".nv-focus .nv-linesWrap").datum(o.filter(function(a){return!a.disabled}).map(function(b){return{key:b.key,area:b.area,values:b.values.filter(function(b,c){return g.x()(b,c)>=a[0]&&g.x()(b,c)<=a[1]})}}));b.transition().duration(B).call(g),Q.select(".nv-focus .nv-x.nv-axis").transition().duration(B).call(i),Q.select(".nv-focus .nv-y.nv-axis").transition().duration(B).call(j)}}var I=d3.select(this),J=this;a.utils.initSVG(I);var K=a.utils.availableWidth(t,I,q),L=a.utils.availableHeight(u,I,q)-v,M=v-r.top-r.bottom;if(b.update=function(){I.transition().duration(B).call(b)},b.container=this,C.setter(F(o),b.update).getter(E(o)).update(),C.disabled=o.map(function(a){return!!a.disabled}),!D){var N;D={};for(N in C)D[N]=C[N]instanceof Array?C[N].slice(0):C[N]}if(!(o&&o.length&&o.filter(function(a){return a.values.length}).length))return a.utils.noData(b,I),b;I.selectAll(".nv-noData").remove(),c=g.xScale(),d=g.yScale(),e=h.xScale(),f=h.yScale();var O=I.selectAll("g.nv-wrap.nv-lineWithFocusChart").data([o]),P=O.enter().append("g").attr("class","nvd3 nv-wrap nv-lineWithFocusChart").append("g"),Q=O.select("g");P.append("g").attr("class","nv-legendWrap");var R=P.append("g").attr("class","nv-focus");R.append("g").attr("class","nv-x nv-axis"),R.append("g").attr("class","nv-y nv-axis"),R.append("g").attr("class","nv-linesWrap"),R.append("g").attr("class","nv-interactive");var S=P.append("g").attr("class","nv-context");S.append("g").attr("class","nv-x nv-axis"),S.append("g").attr("class","nv-y nv-axis"),S.append("g").attr("class","nv-linesWrap"),S.append("g").attr("class","nv-brushBackground"),S.append("g").attr("class","nv-x nv-brush"),x&&(m.width(K),Q.select(".nv-legendWrap").datum(o).call(m),q.top!=m.height()&&(q.top=m.height(),L=a.utils.availableHeight(u,I,q)-v),Q.select(".nv-legendWrap").attr("transform","translate(0,"+-q.top+")")),O.attr("transform","translate("+q.left+","+q.top+")"),w&&(p.width(K).height(L).margin({left:q.left,top:q.top}).svgContainer(I).xScale(c),O.select(".nv-interactive").call(p)),g.width(K).height(L).color(o.map(function(a,b){return a.color||s(a,b)}).filter(function(a,b){return!o[b].disabled})),h.defined(g.defined()).width(K).height(M).color(o.map(function(a,b){return a.color||s(a,b)}).filter(function(a,b){return!o[b].disabled})),Q.select(".nv-context").attr("transform","translate(0,"+(L+q.bottom+r.top)+")");var T=Q.select(".nv-context .nv-linesWrap").datum(o.filter(function(a){return!a.disabled}));d3.transition(T).call(h),i.scale(c)._ticks(a.utils.calcTicksX(K/100,o)).tickSize(-L,0),j.scale(d)._ticks(a.utils.calcTicksY(L/36,o)).tickSize(-K,0),Q.select(".nv-focus .nv-x.nv-axis").attr("transform","translate(0,"+L+")"),n.x(e).on("brush",function(){H()}),y&&n.extent(y);var U=Q.select(".nv-brushBackground").selectAll("g").data([y||n.extent()]),V=U.enter().append("g");V.append("rect").attr("class","left").attr("x",0).attr("y",0).attr("height",M),V.append("rect").attr("class","right").attr("x",0).attr("y",0).attr("height",M);var W=Q.select(".nv-x.nv-brush").call(n);W.selectAll("rect").attr("height",M),W.selectAll(".resize").append("path").attr("d",z),H(),k.scale(e)._ticks(a.utils.calcTicksX(K/100,o)).tickSize(-M,0),Q.select(".nv-context .nv-x.nv-axis").attr("transform","translate(0,"+f.range()[0]+")"),d3.transition(Q.select(".nv-context .nv-x.nv-axis")).call(k),l.scale(f)._ticks(a.utils.calcTicksY(M/36,o)).tickSize(-K,0),d3.transition(Q.select(".nv-context .nv-y.nv-axis")).call(l),Q.select(".nv-context .nv-x.nv-axis").attr("transform","translate(0,"+f.range()[0]+")"),m.dispatch.on("stateChange",function(a){for(var c in a)C[c]=a[c];A.stateChange(C),b.update()}),p.dispatch.on("elementMousemove",function(c){g.clearHighlights();var d,f,h,k=[];if(o.filter(function(a,b){return a.seriesIndex=b,!a.disabled}).forEach(function(i,j){var l=n.empty()?e.domain():n.extent(),m=i.values.filter(function(a,b){return g.x()(a,b)>=l[0]&&g.x()(a,b)<=l[1]});f=a.interactiveBisect(m,c.pointXValue,g.x());var o=m[f],p=b.y()(o,f);null!=p&&g.highlightPoint(j,f,!0),void 0!==o&&(void 0===d&&(d=o),void 0===h&&(h=b.xScale()(b.x()(o,f))),k.push({key:i.key,value:b.y()(o,f),color:s(i,i.seriesIndex)}))}),k.length>2){var l=b.yScale().invert(c.mouseY),m=Math.abs(b.yScale().domain()[0]-b.yScale().domain()[1]),r=.03*m,t=a.nearestValueIndex(k.map(function(a){return a.value}),l,r);null!==t&&(k[t].highlight=!0)}var u=i.tickFormat()(b.x()(d,f));p.tooltip.position({left:c.mouseX+q.left,top:c.mouseY+q.top}).chartContainer(J.parentNode).valueFormatter(function(a){return null==a?"N/A":j.tickFormat()(a)}).data({value:u,index:f,series:k})(),p.renderGuideLine(h)}),p.dispatch.on("elementMouseout",function(){g.clearHighlights()}),A.on("changeState",function(a){"undefined"!=typeof a.disabled&&o.forEach(function(b,c){b.disabled=a.disabled[c]}),b.update()})}),b}var c,d,e,f,g=a.models.line(),h=a.models.line(),i=a.models.axis(),j=a.models.axis(),k=a.models.axis(),l=a.models.axis(),m=a.models.legend(),n=d3.svg.brush(),o=a.models.tooltip(),p=a.interactiveGuideline(),q={top:30,right:30,bottom:30,left:60},r={top:0,right:30,bottom:20,left:60},s=a.utils.defaultColor(),t=null,u=null,v=50,w=!1,x=!0,y=null,z=null,A=d3.dispatch("brush","stateChange","changeState"),B=250,C=a.utils.state(),D=null;g.clipEdge(!0).duration(0),h.interactive(!1),i.orient("bottom").tickPadding(5),j.orient("left"),k.orient("bottom").tickPadding(5),l.orient("left"),o.valueFormatter(function(a,b){return j.tickFormat()(a,b)}).headerFormatter(function(a,b){return i.tickFormat()(a,b)});var E=function(a){return function(){return{active:a.map(function(a){return!a.disabled})}}},F=function(a){return function(b){void 0!==b.active&&a.forEach(function(a,c){a.disabled=!b.active[c]})}};return g.dispatch.on("elementMouseover.tooltip",function(a){o.data(a).position(a.pos).hidden(!1)}),g.dispatch.on("elementMouseout.tooltip",function(){o.hidden(!0)}),b.dispatch=A,b.legend=m,b.lines=g,b.lines2=h,b.xAxis=i,b.yAxis=j,b.x2Axis=k,b.y2Axis=l,b.interactiveLayer=p,b.tooltip=o,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return t},set:function(a){t=a}},height:{get:function(){return u},set:function(a){u=a}},focusHeight:{get:function(){return v},set:function(a){v=a}},showLegend:{get:function(){return x},set:function(a){x=a}},brushExtent:{get:function(){return y},set:function(a){y=a}},defaultState:{get:function(){return D},set:function(a){D=a}},noData:{get:function(){return z},set:function(a){z=a}},tooltips:{get:function(){return o.enabled()},set:function(b){a.deprecated("tooltips","use chart.tooltip.enabled() instead"),o.enabled(!!b)}},tooltipContent:{get:function(){return o.contentGenerator()},set:function(b){a.deprecated("tooltipContent","use chart.tooltip.contentGenerator() instead"),o.contentGenerator(b)}},margin:{get:function(){return q},set:function(a){q.top=void 0!==a.top?a.top:q.top,q.right=void 0!==a.right?a.right:q.right,q.bottom=void 0!==a.bottom?a.bottom:q.bottom,q.left=void 0!==a.left?a.left:q.left}},color:{get:function(){return s},set:function(b){s=a.utils.getColor(b),m.color(s)}},interpolate:{get:function(){return g.interpolate()},set:function(a){g.interpolate(a),h.interpolate(a)}},xTickFormat:{get:function(){return i.tickFormat()},set:function(a){i.tickFormat(a),k.tickFormat(a)}},yTickFormat:{get:function(){return j.tickFormat()},set:function(a){j.tickFormat(a),l.tickFormat(a)}},duration:{get:function(){return B},set:function(a){B=a,j.duration(B),l.duration(B),i.duration(B),k.duration(B)}},x:{get:function(){return g.x()},set:function(a){g.x(a),h.x(a)}},y:{get:function(){return g.y()},set:function(a){g.y(a),h.y(a)}},useInteractiveGuideline:{get:function(){return w},set:function(a){w=a,w&&(g.interactive(!1),g.useVoronoi(!1))}}}),a.utils.inheritOptions(b,g),a.utils.initOptions(b),b},a.models.multiBar=function(){"use strict";function b(E){return C.reset(),E.each(function(b){var E=k-j.left-j.right,F=l-j.top-j.bottom;p=d3.select(this),a.utils.initSVG(p);var G=0;if(x&&b.length&&(x=[{values:b[0].values.map(function(a){return{x:a.x,y:0,series:a.series,size:.01}})}]),u){var H=d3.layout.stack().offset(v).values(function(a){return a.values}).y(r)(!b.length&&x?x:b);H.forEach(function(a,c){a.nonStackable?(b[c].nonStackableSeries=G++,H[c]=b[c]):c>0&&H[c-1].nonStackable&&H[c].values.map(function(a,b){a.y0-=H[c-1].values[b].y,a.y1=a.y0+a.y})}),b=H}b.forEach(function(a,b){a.values.forEach(function(c){c.series=b,c.key=a.key})}),u&&b[0].values.map(function(a,c){var d=0,e=0;b.map(function(a,f){if(!b[f].nonStackable){var g=a.values[c];g.size=Math.abs(g.y),g.y<0?(g.y1=e,e-=g.size):(g.y1=g.size+d,d+=g.size)}})});var I=d&&e?[]:b.map(function(a,b){return a.values.map(function(a,c){return{x:q(a,c),y:r(a,c),y0:a.y0,y1:a.y1,idx:b}})});m.domain(d||d3.merge(I).map(function(a){return a.x})).rangeBands(f||[0,E],A),n.domain(e||d3.extent(d3.merge(I).map(function(a){var c=a.y;return u&&!b[a.idx].nonStackable&&(c=a.y>0?a.y1:a.y1+a.y),c}).concat(s))).range(g||[F,0]),m.domain()[0]===m.domain()[1]&&m.domain(m.domain()[0]?[m.domain()[0]-.01*m.domain()[0],m.domain()[1]+.01*m.domain()[1]]:[-1,1]),n.domain()[0]===n.domain()[1]&&n.domain(n.domain()[0]?[n.domain()[0]+.01*n.domain()[0],n.domain()[1]-.01*n.domain()[1]]:[-1,1]),h=h||m,i=i||n;var J=p.selectAll("g.nv-wrap.nv-multibar").data([b]),K=J.enter().append("g").attr("class","nvd3 nv-wrap nv-multibar"),L=K.append("defs"),M=K.append("g"),N=J.select("g");M.append("g").attr("class","nv-groups"),J.attr("transform","translate("+j.left+","+j.top+")"),L.append("clipPath").attr("id","nv-edge-clip-"+o).append("rect"),J.select("#nv-edge-clip-"+o+" rect").attr("width",E).attr("height",F),N.attr("clip-path",t?"url(#nv-edge-clip-"+o+")":"");var O=J.select(".nv-groups").selectAll(".nv-group").data(function(a){return a},function(a,b){return b});O.enter().append("g").style("stroke-opacity",1e-6).style("fill-opacity",1e-6);var P=C.transition(O.exit().selectAll("rect.nv-bar"),"multibarExit",Math.min(100,z)).attr("y",function(a){var c=i(0)||0;return u&&b[a.series]&&!b[a.series].nonStackable&&(c=i(a.y0)),c}).attr("height",0).remove();P.delay&&P.delay(function(a,b){var c=b*(z/(D+1))-b;return c}),O.attr("class",function(a,b){return"nv-group nv-series-"+b}).classed("hover",function(a){return a.hover}).style("fill",function(a,b){return w(a,b)}).style("stroke",function(a,b){return w(a,b)}),O.style("stroke-opacity",1).style("fill-opacity",.75);var Q=O.selectAll("rect.nv-bar").data(function(a){return x&&!b.length?x.values:a.values});Q.exit().remove();Q.enter().append("rect").attr("class",function(a,b){return r(a,b)<0?"nv-bar negative":"nv-bar positive"}).attr("x",function(a,c,d){return u&&!b[d].nonStackable?0:d*m.rangeBand()/b.length}).attr("y",function(a,c,d){return i(u&&!b[d].nonStackable?a.y0:0)||0}).attr("height",0).attr("width",function(a,c,d){return m.rangeBand()/(u&&!b[d].nonStackable?1:b.length)}).attr("transform",function(a,b){return"translate("+m(q(a,b))+",0)"});Q.style("fill",function(a,b,c){return w(a,c,b)}).style("stroke",function(a,b,c){return w(a,c,b)}).on("mouseover",function(a,b){d3.select(this).classed("hover",!0),B.elementMouseover({data:a,index:b,color:d3.select(this).style("fill")})}).on("mouseout",function(a,b){d3.select(this).classed("hover",!1),B.elementMouseout({data:a,index:b,color:d3.select(this).style("fill")})}).on("mousemove",function(a,b){B.elementMousemove({data:a,index:b,color:d3.select(this).style("fill")})}).on("click",function(a,b){B.elementClick({data:a,index:b,color:d3.select(this).style("fill")}),d3.event.stopPropagation()}).on("dblclick",function(a,b){B.elementDblClick({data:a,index:b,color:d3.select(this).style("fill")}),d3.event.stopPropagation()}),Q.attr("class",function(a,b){return r(a,b)<0?"nv-bar negative":"nv-bar positive"}).attr("transform",function(a,b){return"translate("+m(q(a,b))+",0)"}),y&&(c||(c=b.map(function(){return!0})),Q.style("fill",function(a,b,d){return d3.rgb(y(a,b)).darker(c.map(function(a,b){return b}).filter(function(a,b){return!c[b]})[d]).toString()}).style("stroke",function(a,b,d){return d3.rgb(y(a,b)).darker(c.map(function(a,b){return b}).filter(function(a,b){return!c[b]})[d]).toString()}));var R=Q.watchTransition(C,"multibar",Math.min(250,z)).delay(function(a,c){return c*z/b[0].values.length});u?R.attr("y",function(a,c,d){var e=0;return e=b[d].nonStackable?r(a,c)<0?n(0):n(0)-n(r(a,c))<-1?n(0)-1:n(r(a,c))||0:n(a.y1)}).attr("height",function(a,c,d){return b[d].nonStackable?Math.max(Math.abs(n(r(a,c))-n(0)),1)||0:Math.max(Math.abs(n(a.y+a.y0)-n(a.y0)),1)}).attr("x",function(a,c,d){var e=0;return b[d].nonStackable&&(e=a.series*m.rangeBand()/b.length,b.length!==G&&(e=b[d].nonStackableSeries*m.rangeBand()/(2*G))),e}).attr("width",function(a,c,d){if(b[d].nonStackable){var e=m.rangeBand()/G;return b.length!==G&&(e=m.rangeBand()/(2*G)),e}return m.rangeBand()}):R.attr("x",function(a){return a.series*m.rangeBand()/b.length}).attr("width",m.rangeBand()/b.length).attr("y",function(a,b){return r(a,b)<0?n(0):n(0)-n(r(a,b))<1?n(0)-1:n(r(a,b))||0}).attr("height",function(a,b){return Math.max(Math.abs(n(r(a,b))-n(0)),1)||0}),h=m.copy(),i=n.copy(),b[0]&&b[0].values&&(D=b[0].values.length)}),C.renderEnd("multibar immediate"),b}var c,d,e,f,g,h,i,j={top:0,right:0,bottom:0,left:0},k=960,l=500,m=d3.scale.ordinal(),n=d3.scale.linear(),o=Math.floor(1e4*Math.random()),p=null,q=function(a){return a.x},r=function(a){return a.y},s=[0],t=!0,u=!1,v="zero",w=a.utils.defaultColor(),x=!1,y=null,z=500,A=.1,B=d3.dispatch("chartClick","elementClick","elementDblClick","elementMouseover","elementMouseout","elementMousemove","renderEnd"),C=a.utils.renderWatch(B,z),D=0;return b.dispatch=B,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return k},set:function(a){k=a}},height:{get:function(){return l},set:function(a){l=a}},x:{get:function(){return q},set:function(a){q=a}},y:{get:function(){return r},set:function(a){r=a}},xScale:{get:function(){return m},set:function(a){m=a}},yScale:{get:function(){return n},set:function(a){n=a}},xDomain:{get:function(){return d},set:function(a){d=a}},yDomain:{get:function(){return e},set:function(a){e=a}},xRange:{get:function(){return f},set:function(a){f=a}},yRange:{get:function(){return g},set:function(a){g=a}},forceY:{get:function(){return s},set:function(a){s=a}},stacked:{get:function(){return u},set:function(a){u=a}},stackOffset:{get:function(){return v},set:function(a){v=a}},clipEdge:{get:function(){return t},set:function(a){t=a}},disabled:{get:function(){return c},set:function(a){c=a}},id:{get:function(){return o},set:function(a){o=a}},hideable:{get:function(){return x},set:function(a){x=a}},groupSpacing:{get:function(){return A},set:function(a){A=a}},margin:{get:function(){return j},set:function(a){j.top=void 0!==a.top?a.top:j.top,j.right=void 0!==a.right?a.right:j.right,j.bottom=void 0!==a.bottom?a.bottom:j.bottom,j.left=void 0!==a.left?a.left:j.left}},duration:{get:function(){return z},set:function(a){z=a,C.reset(z)}},color:{get:function(){return w},set:function(b){w=a.utils.getColor(b)}},barColor:{get:function(){return y},set:function(b){y=b?a.utils.getColor(b):null}}}),a.utils.initOptions(b),b},a.models.multiBarChart=function(){"use strict";function b(j){return D.reset(),D.models(e),r&&D.models(f),s&&D.models(g),j.each(function(j){var z=d3.select(this);a.utils.initSVG(z);var D=a.utils.availableWidth(l,z,k),H=a.utils.availableHeight(m,z,k);if(b.update=function(){0===C?z.call(b):z.transition().duration(C).call(b)},b.container=this,x.setter(G(j),b.update).getter(F(j)).update(),x.disabled=j.map(function(a){return!!a.disabled}),!y){var I;y={};for(I in x)y[I]=x[I]instanceof Array?x[I].slice(0):x[I]}if(!(j&&j.length&&j.filter(function(a){return a.values.length}).length))return a.utils.noData(b,z),b;z.selectAll(".nv-noData").remove(),c=e.xScale(),d=e.yScale();
  22802. var J=z.selectAll("g.nv-wrap.nv-multiBarWithLegend").data([j]),K=J.enter().append("g").attr("class","nvd3 nv-wrap nv-multiBarWithLegend").append("g"),L=J.select("g");if(K.append("g").attr("class","nv-x nv-axis"),K.append("g").attr("class","nv-y nv-axis"),K.append("g").attr("class","nv-barsWrap"),K.append("g").attr("class","nv-legendWrap"),K.append("g").attr("class","nv-controlsWrap"),q&&(h.width(D-B()),L.select(".nv-legendWrap").datum(j).call(h),k.top!=h.height()&&(k.top=h.height(),H=a.utils.availableHeight(m,z,k)),L.select(".nv-legendWrap").attr("transform","translate("+B()+","+-k.top+")")),o){var M=[{key:p.grouped||"Grouped",disabled:e.stacked()},{key:p.stacked||"Stacked",disabled:!e.stacked()}];i.width(B()).color(["#444","#444","#444"]),L.select(".nv-controlsWrap").datum(M).attr("transform","translate(0,"+-k.top+")").call(i)}J.attr("transform","translate("+k.left+","+k.top+")"),t&&L.select(".nv-y.nv-axis").attr("transform","translate("+D+",0)"),e.disabled(j.map(function(a){return a.disabled})).width(D).height(H).color(j.map(function(a,b){return a.color||n(a,b)}).filter(function(a,b){return!j[b].disabled}));var N=L.select(".nv-barsWrap").datum(j.filter(function(a){return!a.disabled}));if(N.call(e),r){f.scale(c)._ticks(a.utils.calcTicksX(D/100,j)).tickSize(-H,0),L.select(".nv-x.nv-axis").attr("transform","translate(0,"+d.range()[0]+")"),L.select(".nv-x.nv-axis").call(f);var O=L.select(".nv-x.nv-axis > g").selectAll("g");if(O.selectAll("line, text").style("opacity",1),v){var P=function(a,b){return"translate("+a+","+b+")"},Q=5,R=17;O.selectAll("text").attr("transform",function(a,b,c){return P(0,c%2==0?Q:R)});var S=d3.selectAll(".nv-x.nv-axis .nv-wrap g g text")[0].length;L.selectAll(".nv-x.nv-axis .nv-axisMaxMin text").attr("transform",function(a,b){return P(0,0===b||S%2!==0?R:Q)})}u&&O.filter(function(a,b){return b%Math.ceil(j[0].values.length/(D/100))!==0}).selectAll("text, line").style("opacity",0),w&&O.selectAll(".tick text").attr("transform","rotate("+w+" 0,0)").style("text-anchor",w>0?"start":"end"),L.select(".nv-x.nv-axis").selectAll("g.nv-axisMaxMin text").style("opacity",1)}s&&(g.scale(d)._ticks(a.utils.calcTicksY(H/36,j)).tickSize(-D,0),L.select(".nv-y.nv-axis").call(g)),h.dispatch.on("stateChange",function(a){for(var c in a)x[c]=a[c];A.stateChange(x),b.update()}),i.dispatch.on("legendClick",function(a){if(a.disabled){switch(M=M.map(function(a){return a.disabled=!0,a}),a.disabled=!1,a.key){case"Grouped":case p.grouped:e.stacked(!1);break;case"Stacked":case p.stacked:e.stacked(!0)}x.stacked=e.stacked(),A.stateChange(x),b.update()}}),A.on("changeState",function(a){"undefined"!=typeof a.disabled&&(j.forEach(function(b,c){b.disabled=a.disabled[c]}),x.disabled=a.disabled),"undefined"!=typeof a.stacked&&(e.stacked(a.stacked),x.stacked=a.stacked,E=a.stacked),b.update()})}),D.renderEnd("multibarchart immediate"),b}var c,d,e=a.models.multiBar(),f=a.models.axis(),g=a.models.axis(),h=a.models.legend(),i=a.models.legend(),j=a.models.tooltip(),k={top:30,right:20,bottom:50,left:60},l=null,m=null,n=a.utils.defaultColor(),o=!0,p={},q=!0,r=!0,s=!0,t=!1,u=!0,v=!1,w=0,x=a.utils.state(),y=null,z=null,A=d3.dispatch("stateChange","changeState","renderEnd"),B=function(){return o?180:0},C=250;x.stacked=!1,e.stacked(!1),f.orient("bottom").tickPadding(7).showMaxMin(!1).tickFormat(function(a){return a}),g.orient(t?"right":"left").tickFormat(d3.format(",.1f")),j.duration(0).valueFormatter(function(a,b){return g.tickFormat()(a,b)}).headerFormatter(function(a,b){return f.tickFormat()(a,b)}),i.updateState(!1);var D=a.utils.renderWatch(A),E=!1,F=function(a){return function(){return{active:a.map(function(a){return!a.disabled}),stacked:E}}},G=function(a){return function(b){void 0!==b.stacked&&(E=b.stacked),void 0!==b.active&&a.forEach(function(a,c){a.disabled=!b.active[c]})}};return e.dispatch.on("elementMouseover.tooltip",function(a){a.value=b.x()(a.data),a.series={key:a.data.key,value:b.y()(a.data),color:a.color},j.data(a).hidden(!1)}),e.dispatch.on("elementMouseout.tooltip",function(){j.hidden(!0)}),e.dispatch.on("elementMousemove.tooltip",function(){j.position({top:d3.event.pageY,left:d3.event.pageX})()}),b.dispatch=A,b.multibar=e,b.legend=h,b.controls=i,b.xAxis=f,b.yAxis=g,b.state=x,b.tooltip=j,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return l},set:function(a){l=a}},height:{get:function(){return m},set:function(a){m=a}},showLegend:{get:function(){return q},set:function(a){q=a}},showControls:{get:function(){return o},set:function(a){o=a}},controlLabels:{get:function(){return p},set:function(a){p=a}},showXAxis:{get:function(){return r},set:function(a){r=a}},showYAxis:{get:function(){return s},set:function(a){s=a}},defaultState:{get:function(){return y},set:function(a){y=a}},noData:{get:function(){return z},set:function(a){z=a}},reduceXTicks:{get:function(){return u},set:function(a){u=a}},rotateLabels:{get:function(){return w},set:function(a){w=a}},staggerLabels:{get:function(){return v},set:function(a){v=a}},tooltips:{get:function(){return j.enabled()},set:function(b){a.deprecated("tooltips","use chart.tooltip.enabled() instead"),j.enabled(!!b)}},tooltipContent:{get:function(){return j.contentGenerator()},set:function(b){a.deprecated("tooltipContent","use chart.tooltip.contentGenerator() instead"),j.contentGenerator(b)}},margin:{get:function(){return k},set:function(a){k.top=void 0!==a.top?a.top:k.top,k.right=void 0!==a.right?a.right:k.right,k.bottom=void 0!==a.bottom?a.bottom:k.bottom,k.left=void 0!==a.left?a.left:k.left}},duration:{get:function(){return C},set:function(a){C=a,e.duration(C),f.duration(C),g.duration(C),D.reset(C)}},color:{get:function(){return n},set:function(b){n=a.utils.getColor(b),h.color(n)}},rightAlignYAxis:{get:function(){return t},set:function(a){t=a,g.orient(t?"right":"left")}},barColor:{get:function(){return e.barColor},set:function(a){e.barColor(a),h.color(function(a,b){return d3.rgb("#ccc").darker(1.5*b).toString()})}}}),a.utils.inheritOptions(b,e),a.utils.initOptions(b),b},a.models.multiBarHorizontal=function(){"use strict";function b(m){return E.reset(),m.each(function(b){var m=k-j.left-j.right,C=l-j.top-j.bottom;n=d3.select(this),a.utils.initSVG(n),w&&(b=d3.layout.stack().offset("zero").values(function(a){return a.values}).y(r)(b)),b.forEach(function(a,b){a.values.forEach(function(c){c.series=b,c.key=a.key})}),w&&b[0].values.map(function(a,c){var d=0,e=0;b.map(function(a){var b=a.values[c];b.size=Math.abs(b.y),b.y<0?(b.y1=e-b.size,e-=b.size):(b.y1=d,d+=b.size)})});var F=d&&e?[]:b.map(function(a){return a.values.map(function(a,b){return{x:q(a,b),y:r(a,b),y0:a.y0,y1:a.y1}})});o.domain(d||d3.merge(F).map(function(a){return a.x})).rangeBands(f||[0,C],A),p.domain(e||d3.extent(d3.merge(F).map(function(a){return w?a.y>0?a.y1+a.y:a.y1:a.y}).concat(t))),p.range(x&&!w?g||[p.domain()[0]<0?z:0,m-(p.domain()[1]>0?z:0)]:g||[0,m]),h=h||o,i=i||d3.scale.linear().domain(p.domain()).range([p(0),p(0)]);{var G=d3.select(this).selectAll("g.nv-wrap.nv-multibarHorizontal").data([b]),H=G.enter().append("g").attr("class","nvd3 nv-wrap nv-multibarHorizontal"),I=(H.append("defs"),H.append("g"));G.select("g")}I.append("g").attr("class","nv-groups"),G.attr("transform","translate("+j.left+","+j.top+")");var J=G.select(".nv-groups").selectAll(".nv-group").data(function(a){return a},function(a,b){return b});J.enter().append("g").style("stroke-opacity",1e-6).style("fill-opacity",1e-6),J.exit().watchTransition(E,"multibarhorizontal: exit groups").style("stroke-opacity",1e-6).style("fill-opacity",1e-6).remove(),J.attr("class",function(a,b){return"nv-group nv-series-"+b}).classed("hover",function(a){return a.hover}).style("fill",function(a,b){return u(a,b)}).style("stroke",function(a,b){return u(a,b)}),J.watchTransition(E,"multibarhorizontal: groups").style("stroke-opacity",1).style("fill-opacity",.75);var K=J.selectAll("g.nv-bar").data(function(a){return a.values});K.exit().remove();var L=K.enter().append("g").attr("transform",function(a,c,d){return"translate("+i(w?a.y0:0)+","+(w?0:d*o.rangeBand()/b.length+o(q(a,c)))+")"});L.append("rect").attr("width",0).attr("height",o.rangeBand()/(w?1:b.length)),K.on("mouseover",function(a,b){d3.select(this).classed("hover",!0),D.elementMouseover({data:a,index:b,color:d3.select(this).style("fill")})}).on("mouseout",function(a,b){d3.select(this).classed("hover",!1),D.elementMouseout({data:a,index:b,color:d3.select(this).style("fill")})}).on("mouseout",function(a,b){D.elementMouseout({data:a,index:b,color:d3.select(this).style("fill")})}).on("mousemove",function(a,b){D.elementMousemove({data:a,index:b,color:d3.select(this).style("fill")})}).on("click",function(a,b){D.elementClick({data:a,index:b,color:d3.select(this).style("fill")}),d3.event.stopPropagation()}).on("dblclick",function(a,b){D.elementDblClick({data:a,index:b,color:d3.select(this).style("fill")}),d3.event.stopPropagation()}),s(b[0],0)&&(L.append("polyline"),K.select("polyline").attr("fill","none").attr("points",function(a,c){var d=s(a,c),e=.8*o.rangeBand()/(2*(w?1:b.length));d=d.length?d:[-Math.abs(d),Math.abs(d)],d=d.map(function(a){return p(a)-p(0)});var f=[[d[0],-e],[d[0],e],[d[0],0],[d[1],0],[d[1],-e],[d[1],e]];return f.map(function(a){return a.join(",")}).join(" ")}).attr("transform",function(a,c){var d=o.rangeBand()/(2*(w?1:b.length));return"translate("+(r(a,c)<0?0:p(r(a,c))-p(0))+", "+d+")"})),L.append("text"),x&&!w?(K.select("text").attr("text-anchor",function(a,b){return r(a,b)<0?"end":"start"}).attr("y",o.rangeBand()/(2*b.length)).attr("dy",".32em").text(function(a,b){var c=B(r(a,b)),d=s(a,b);return void 0===d?c:d.length?c+"+"+B(Math.abs(d[1]))+"-"+B(Math.abs(d[0])):c+"±"+B(Math.abs(d))}),K.watchTransition(E,"multibarhorizontal: bars").select("text").attr("x",function(a,b){return r(a,b)<0?-4:p(r(a,b))-p(0)+4})):K.selectAll("text").text(""),y&&!w?(L.append("text").classed("nv-bar-label",!0),K.select("text.nv-bar-label").attr("text-anchor",function(a,b){return r(a,b)<0?"start":"end"}).attr("y",o.rangeBand()/(2*b.length)).attr("dy",".32em").text(function(a,b){return q(a,b)}),K.watchTransition(E,"multibarhorizontal: bars").select("text.nv-bar-label").attr("x",function(a,b){return r(a,b)<0?p(0)-p(r(a,b))+4:-4})):K.selectAll("text.nv-bar-label").text(""),K.attr("class",function(a,b){return r(a,b)<0?"nv-bar negative":"nv-bar positive"}),v&&(c||(c=b.map(function(){return!0})),K.style("fill",function(a,b,d){return d3.rgb(v(a,b)).darker(c.map(function(a,b){return b}).filter(function(a,b){return!c[b]})[d]).toString()}).style("stroke",function(a,b,d){return d3.rgb(v(a,b)).darker(c.map(function(a,b){return b}).filter(function(a,b){return!c[b]})[d]).toString()})),w?K.watchTransition(E,"multibarhorizontal: bars").attr("transform",function(a,b){return"translate("+p(a.y1)+","+o(q(a,b))+")"}).select("rect").attr("width",function(a,b){return Math.abs(p(r(a,b)+a.y0)-p(a.y0))}).attr("height",o.rangeBand()):K.watchTransition(E,"multibarhorizontal: bars").attr("transform",function(a,c){return"translate("+p(r(a,c)<0?r(a,c):0)+","+(a.series*o.rangeBand()/b.length+o(q(a,c)))+")"}).select("rect").attr("height",o.rangeBand()/b.length).attr("width",function(a,b){return Math.max(Math.abs(p(r(a,b))-p(0)),1)}),h=o.copy(),i=p.copy()}),E.renderEnd("multibarHorizontal immediate"),b}var c,d,e,f,g,h,i,j={top:0,right:0,bottom:0,left:0},k=960,l=500,m=Math.floor(1e4*Math.random()),n=null,o=d3.scale.ordinal(),p=d3.scale.linear(),q=function(a){return a.x},r=function(a){return a.y},s=function(a){return a.yErr},t=[0],u=a.utils.defaultColor(),v=null,w=!1,x=!1,y=!1,z=60,A=.1,B=d3.format(",.2f"),C=250,D=d3.dispatch("chartClick","elementClick","elementDblClick","elementMouseover","elementMouseout","elementMousemove","renderEnd"),E=a.utils.renderWatch(D,C);return b.dispatch=D,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return k},set:function(a){k=a}},height:{get:function(){return l},set:function(a){l=a}},x:{get:function(){return q},set:function(a){q=a}},y:{get:function(){return r},set:function(a){r=a}},yErr:{get:function(){return s},set:function(a){s=a}},xScale:{get:function(){return o},set:function(a){o=a}},yScale:{get:function(){return p},set:function(a){p=a}},xDomain:{get:function(){return d},set:function(a){d=a}},yDomain:{get:function(){return e},set:function(a){e=a}},xRange:{get:function(){return f},set:function(a){f=a}},yRange:{get:function(){return g},set:function(a){g=a}},forceY:{get:function(){return t},set:function(a){t=a}},stacked:{get:function(){return w},set:function(a){w=a}},showValues:{get:function(){return x},set:function(a){x=a}},disabled:{get:function(){return c},set:function(a){c=a}},id:{get:function(){return m},set:function(a){m=a}},valueFormat:{get:function(){return B},set:function(a){B=a}},valuePadding:{get:function(){return z},set:function(a){z=a}},groupSpacing:{get:function(){return A},set:function(a){A=a}},margin:{get:function(){return j},set:function(a){j.top=void 0!==a.top?a.top:j.top,j.right=void 0!==a.right?a.right:j.right,j.bottom=void 0!==a.bottom?a.bottom:j.bottom,j.left=void 0!==a.left?a.left:j.left}},duration:{get:function(){return C},set:function(a){C=a,E.reset(C)}},color:{get:function(){return u},set:function(b){u=a.utils.getColor(b)}},barColor:{get:function(){return v},set:function(b){v=b?a.utils.getColor(b):null}}}),a.utils.initOptions(b),b},a.models.multiBarHorizontalChart=function(){"use strict";function b(j){return C.reset(),C.models(e),r&&C.models(f),s&&C.models(g),j.each(function(j){var w=d3.select(this);a.utils.initSVG(w);var C=a.utils.availableWidth(l,w,k),D=a.utils.availableHeight(m,w,k);if(b.update=function(){w.transition().duration(z).call(b)},b.container=this,t=e.stacked(),u.setter(B(j),b.update).getter(A(j)).update(),u.disabled=j.map(function(a){return!!a.disabled}),!v){var E;v={};for(E in u)v[E]=u[E]instanceof Array?u[E].slice(0):u[E]}if(!(j&&j.length&&j.filter(function(a){return a.values.length}).length))return a.utils.noData(b,w),b;w.selectAll(".nv-noData").remove(),c=e.xScale(),d=e.yScale();var F=w.selectAll("g.nv-wrap.nv-multiBarHorizontalChart").data([j]),G=F.enter().append("g").attr("class","nvd3 nv-wrap nv-multiBarHorizontalChart").append("g"),H=F.select("g");if(G.append("g").attr("class","nv-x nv-axis"),G.append("g").attr("class","nv-y nv-axis").append("g").attr("class","nv-zeroLine").append("line"),G.append("g").attr("class","nv-barsWrap"),G.append("g").attr("class","nv-legendWrap"),G.append("g").attr("class","nv-controlsWrap"),q&&(h.width(C-y()),H.select(".nv-legendWrap").datum(j).call(h),k.top!=h.height()&&(k.top=h.height(),D=a.utils.availableHeight(m,w,k)),H.select(".nv-legendWrap").attr("transform","translate("+y()+","+-k.top+")")),o){var I=[{key:p.grouped||"Grouped",disabled:e.stacked()},{key:p.stacked||"Stacked",disabled:!e.stacked()}];i.width(y()).color(["#444","#444","#444"]),H.select(".nv-controlsWrap").datum(I).attr("transform","translate(0,"+-k.top+")").call(i)}F.attr("transform","translate("+k.left+","+k.top+")"),e.disabled(j.map(function(a){return a.disabled})).width(C).height(D).color(j.map(function(a,b){return a.color||n(a,b)}).filter(function(a,b){return!j[b].disabled}));var J=H.select(".nv-barsWrap").datum(j.filter(function(a){return!a.disabled}));if(J.transition().call(e),r){f.scale(c)._ticks(a.utils.calcTicksY(D/24,j)).tickSize(-C,0),H.select(".nv-x.nv-axis").call(f);var K=H.select(".nv-x.nv-axis").selectAll("g");K.selectAll("line, text")}s&&(g.scale(d)._ticks(a.utils.calcTicksX(C/100,j)).tickSize(-D,0),H.select(".nv-y.nv-axis").attr("transform","translate(0,"+D+")"),H.select(".nv-y.nv-axis").call(g)),H.select(".nv-zeroLine line").attr("x1",d(0)).attr("x2",d(0)).attr("y1",0).attr("y2",-D),h.dispatch.on("stateChange",function(a){for(var c in a)u[c]=a[c];x.stateChange(u),b.update()}),i.dispatch.on("legendClick",function(a){if(a.disabled){switch(I=I.map(function(a){return a.disabled=!0,a}),a.disabled=!1,a.key){case"Grouped":e.stacked(!1);break;case"Stacked":e.stacked(!0)}u.stacked=e.stacked(),x.stateChange(u),t=e.stacked(),b.update()}}),x.on("changeState",function(a){"undefined"!=typeof a.disabled&&(j.forEach(function(b,c){b.disabled=a.disabled[c]}),u.disabled=a.disabled),"undefined"!=typeof a.stacked&&(e.stacked(a.stacked),u.stacked=a.stacked,t=a.stacked),b.update()})}),C.renderEnd("multibar horizontal chart immediate"),b}var c,d,e=a.models.multiBarHorizontal(),f=a.models.axis(),g=a.models.axis(),h=a.models.legend().height(30),i=a.models.legend().height(30),j=a.models.tooltip(),k={top:30,right:20,bottom:50,left:60},l=null,m=null,n=a.utils.defaultColor(),o=!0,p={},q=!0,r=!0,s=!0,t=!1,u=a.utils.state(),v=null,w=null,x=d3.dispatch("stateChange","changeState","renderEnd"),y=function(){return o?180:0},z=250;u.stacked=!1,e.stacked(t),f.orient("left").tickPadding(5).showMaxMin(!1).tickFormat(function(a){return a}),g.orient("bottom").tickFormat(d3.format(",.1f")),j.duration(0).valueFormatter(function(a,b){return g.tickFormat()(a,b)}).headerFormatter(function(a,b){return f.tickFormat()(a,b)}),i.updateState(!1);var A=function(a){return function(){return{active:a.map(function(a){return!a.disabled}),stacked:t}}},B=function(a){return function(b){void 0!==b.stacked&&(t=b.stacked),void 0!==b.active&&a.forEach(function(a,c){a.disabled=!b.active[c]})}},C=a.utils.renderWatch(x,z);return e.dispatch.on("elementMouseover.tooltip",function(a){a.value=b.x()(a.data),a.series={key:a.data.key,value:b.y()(a.data),color:a.color},j.data(a).hidden(!1)}),e.dispatch.on("elementMouseout.tooltip",function(){j.hidden(!0)}),e.dispatch.on("elementMousemove.tooltip",function(){j.position({top:d3.event.pageY,left:d3.event.pageX})()}),b.dispatch=x,b.multibar=e,b.legend=h,b.controls=i,b.xAxis=f,b.yAxis=g,b.state=u,b.tooltip=j,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return l},set:function(a){l=a}},height:{get:function(){return m},set:function(a){m=a}},showLegend:{get:function(){return q},set:function(a){q=a}},showControls:{get:function(){return o},set:function(a){o=a}},controlLabels:{get:function(){return p},set:function(a){p=a}},showXAxis:{get:function(){return r},set:function(a){r=a}},showYAxis:{get:function(){return s},set:function(a){s=a}},defaultState:{get:function(){return v},set:function(a){v=a}},noData:{get:function(){return w},set:function(a){w=a}},tooltips:{get:function(){return j.enabled()},set:function(b){a.deprecated("tooltips","use chart.tooltip.enabled() instead"),j.enabled(!!b)}},tooltipContent:{get:function(){return j.contentGenerator()},set:function(b){a.deprecated("tooltipContent","use chart.tooltip.contentGenerator() instead"),j.contentGenerator(b)}},margin:{get:function(){return k},set:function(a){k.top=void 0!==a.top?a.top:k.top,k.right=void 0!==a.right?a.right:k.right,k.bottom=void 0!==a.bottom?a.bottom:k.bottom,k.left=void 0!==a.left?a.left:k.left}},duration:{get:function(){return z},set:function(a){z=a,C.reset(z),e.duration(z),f.duration(z),g.duration(z)}},color:{get:function(){return n},set:function(b){n=a.utils.getColor(b),h.color(n)}},barColor:{get:function(){return e.barColor},set:function(a){e.barColor(a),h.color(function(a,b){return d3.rgb("#ccc").darker(1.5*b).toString()})}}}),a.utils.inheritOptions(b,e),a.utils.initOptions(b),b},a.models.multiChart=function(){"use strict";function b(j){return j.each(function(j){function k(a){var b=2===j[a.seriesIndex].yAxis?z:y;a.value=a.point.x,a.series={value:a.point.y,color:a.point.color},B.duration(100).valueFormatter(function(a,c){return b.tickFormat()(a,c)}).data(a).position(a.pos).hidden(!1)}function l(a){var b=2===j[a.seriesIndex].yAxis?z:y;a.point.x=v.x()(a.point),a.point.y=v.y()(a.point),B.duration(100).valueFormatter(function(a,c){return b.tickFormat()(a,c)}).data(a).position(a.pos).hidden(!1)}function n(a){var b=2===j[a.data.series].yAxis?z:y;a.value=t.x()(a.data),a.series={value:t.y()(a.data),color:a.color},B.duration(0).valueFormatter(function(a,c){return b.tickFormat()(a,c)}).data(a).hidden(!1)}var C=d3.select(this);a.utils.initSVG(C),b.update=function(){C.transition().call(b)},b.container=this;var D=a.utils.availableWidth(g,C,e),E=a.utils.availableHeight(h,C,e),F=j.filter(function(a){return"line"==a.type&&1==a.yAxis}),G=j.filter(function(a){return"line"==a.type&&2==a.yAxis}),H=j.filter(function(a){return"bar"==a.type&&1==a.yAxis}),I=j.filter(function(a){return"bar"==a.type&&2==a.yAxis}),J=j.filter(function(a){return"area"==a.type&&1==a.yAxis}),K=j.filter(function(a){return"area"==a.type&&2==a.yAxis});if(!(j&&j.length&&j.filter(function(a){return a.values.length}).length))return a.utils.noData(b,C),b;C.selectAll(".nv-noData").remove();var L=j.filter(function(a){return!a.disabled&&1==a.yAxis}).map(function(a){return a.values.map(function(a){return{x:a.x,y:a.y}})}),M=j.filter(function(a){return!a.disabled&&2==a.yAxis}).map(function(a){return a.values.map(function(a){return{x:a.x,y:a.y}})});o.domain(d3.extent(d3.merge(L.concat(M)),function(a){return a.x})).range([0,D]);var N=C.selectAll("g.wrap.multiChart").data([j]),O=N.enter().append("g").attr("class","wrap nvd3 multiChart").append("g");O.append("g").attr("class","nv-x nv-axis"),O.append("g").attr("class","nv-y1 nv-axis"),O.append("g").attr("class","nv-y2 nv-axis"),O.append("g").attr("class","lines1Wrap"),O.append("g").attr("class","lines2Wrap"),O.append("g").attr("class","bars1Wrap"),O.append("g").attr("class","bars2Wrap"),O.append("g").attr("class","stack1Wrap"),O.append("g").attr("class","stack2Wrap"),O.append("g").attr("class","legendWrap");var P=N.select("g"),Q=j.map(function(a,b){return j[b].color||f(a,b)});if(i){var R=A.align()?D/2:D,S=A.align()?R:0;A.width(R),A.color(Q),P.select(".legendWrap").datum(j.map(function(a){return a.originalKey=void 0===a.originalKey?a.key:a.originalKey,a.key=a.originalKey+(1==a.yAxis?"":" (right axis)"),a})).call(A),e.top!=A.height()&&(e.top=A.height(),E=a.utils.availableHeight(h,C,e)),P.select(".legendWrap").attr("transform","translate("+S+","+-e.top+")")}r.width(D).height(E).interpolate(m).color(Q.filter(function(a,b){return!j[b].disabled&&1==j[b].yAxis&&"line"==j[b].type})),s.width(D).height(E).interpolate(m).color(Q.filter(function(a,b){return!j[b].disabled&&2==j[b].yAxis&&"line"==j[b].type})),t.width(D).height(E).color(Q.filter(function(a,b){return!j[b].disabled&&1==j[b].yAxis&&"bar"==j[b].type})),u.width(D).height(E).color(Q.filter(function(a,b){return!j[b].disabled&&2==j[b].yAxis&&"bar"==j[b].type})),v.width(D).height(E).color(Q.filter(function(a,b){return!j[b].disabled&&1==j[b].yAxis&&"area"==j[b].type})),w.width(D).height(E).color(Q.filter(function(a,b){return!j[b].disabled&&2==j[b].yAxis&&"area"==j[b].type})),P.attr("transform","translate("+e.left+","+e.top+")");var T=P.select(".lines1Wrap").datum(F.filter(function(a){return!a.disabled})),U=P.select(".bars1Wrap").datum(H.filter(function(a){return!a.disabled})),V=P.select(".stack1Wrap").datum(J.filter(function(a){return!a.disabled})),W=P.select(".lines2Wrap").datum(G.filter(function(a){return!a.disabled})),X=P.select(".bars2Wrap").datum(I.filter(function(a){return!a.disabled})),Y=P.select(".stack2Wrap").datum(K.filter(function(a){return!a.disabled})),Z=J.length?J.map(function(a){return a.values}).reduce(function(a,b){return a.map(function(a,c){return{x:a.x,y:a.y+b[c].y}})}).concat([{x:0,y:0}]):[],$=K.length?K.map(function(a){return a.values}).reduce(function(a,b){return a.map(function(a,c){return{x:a.x,y:a.y+b[c].y}})}).concat([{x:0,y:0}]):[];p.domain(c||d3.extent(d3.merge(L).concat(Z),function(a){return a.y})).range([0,E]),q.domain(d||d3.extent(d3.merge(M).concat($),function(a){return a.y})).range([0,E]),r.yDomain(p.domain()),t.yDomain(p.domain()),v.yDomain(p.domain()),s.yDomain(q.domain()),u.yDomain(q.domain()),w.yDomain(q.domain()),J.length&&d3.transition(V).call(v),K.length&&d3.transition(Y).call(w),H.length&&d3.transition(U).call(t),I.length&&d3.transition(X).call(u),F.length&&d3.transition(T).call(r),G.length&&d3.transition(W).call(s),x._ticks(a.utils.calcTicksX(D/100,j)).tickSize(-E,0),P.select(".nv-x.nv-axis").attr("transform","translate(0,"+E+")"),d3.transition(P.select(".nv-x.nv-axis")).call(x),y._ticks(a.utils.calcTicksY(E/36,j)).tickSize(-D,0),d3.transition(P.select(".nv-y1.nv-axis")).call(y),z._ticks(a.utils.calcTicksY(E/36,j)).tickSize(-D,0),d3.transition(P.select(".nv-y2.nv-axis")).call(z),P.select(".nv-y1.nv-axis").classed("nv-disabled",L.length?!1:!0).attr("transform","translate("+o.range()[0]+",0)"),P.select(".nv-y2.nv-axis").classed("nv-disabled",M.length?!1:!0).attr("transform","translate("+o.range()[1]+",0)"),A.dispatch.on("stateChange",function(){b.update()}),r.dispatch.on("elementMouseover.tooltip",k),s.dispatch.on("elementMouseover.tooltip",k),r.dispatch.on("elementMouseout.tooltip",function(){B.hidden(!0)}),s.dispatch.on("elementMouseout.tooltip",function(){B.hidden(!0)}),v.dispatch.on("elementMouseover.tooltip",l),w.dispatch.on("elementMouseover.tooltip",l),v.dispatch.on("elementMouseout.tooltip",function(){B.hidden(!0)}),w.dispatch.on("elementMouseout.tooltip",function(){B.hidden(!0)}),t.dispatch.on("elementMouseover.tooltip",n),u.dispatch.on("elementMouseover.tooltip",n),t.dispatch.on("elementMouseout.tooltip",function(){B.hidden(!0)}),u.dispatch.on("elementMouseout.tooltip",function(){B.hidden(!0)}),t.dispatch.on("elementMousemove.tooltip",function(){B.position({top:d3.event.pageY,left:d3.event.pageX})()}),u.dispatch.on("elementMousemove.tooltip",function(){B.position({top:d3.event.pageY,left:d3.event.pageX})()})}),b}var c,d,e={top:30,right:20,bottom:50,left:60},f=a.utils.defaultColor(),g=null,h=null,i=!0,j=null,k=function(a){return a.x},l=function(a){return a.y},m="monotone",n=!0,o=d3.scale.linear(),p=d3.scale.linear(),q=d3.scale.linear(),r=a.models.line().yScale(p),s=a.models.line().yScale(q),t=a.models.multiBar().stacked(!1).yScale(p),u=a.models.multiBar().stacked(!1).yScale(q),v=a.models.stackedArea().yScale(p),w=a.models.stackedArea().yScale(q),x=a.models.axis().scale(o).orient("bottom").tickPadding(5),y=a.models.axis().scale(p).orient("left"),z=a.models.axis().scale(q).orient("right"),A=a.models.legend().height(30),B=a.models.tooltip(),C=d3.dispatch();return b.dispatch=C,b.lines1=r,b.lines2=s,b.bars1=t,b.bars2=u,b.stack1=v,b.stack2=w,b.xAxis=x,b.yAxis1=y,b.yAxis2=z,b.tooltip=B,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return g},set:function(a){g=a}},height:{get:function(){return h},set:function(a){h=a}},showLegend:{get:function(){return i},set:function(a){i=a}},yDomain1:{get:function(){return c},set:function(a){c=a}},yDomain2:{get:function(){return d},set:function(a){d=a}},noData:{get:function(){return j},set:function(a){j=a}},interpolate:{get:function(){return m},set:function(a){m=a}},tooltips:{get:function(){return B.enabled()},set:function(b){a.deprecated("tooltips","use chart.tooltip.enabled() instead"),B.enabled(!!b)}},tooltipContent:{get:function(){return B.contentGenerator()},set:function(b){a.deprecated("tooltipContent","use chart.tooltip.contentGenerator() instead"),B.contentGenerator(b)}},margin:{get:function(){return e},set:function(a){e.top=void 0!==a.top?a.top:e.top,e.right=void 0!==a.right?a.right:e.right,e.bottom=void 0!==a.bottom?a.bottom:e.bottom,e.left=void 0!==a.left?a.left:e.left}},color:{get:function(){return f},set:function(b){f=a.utils.getColor(b)}},x:{get:function(){return k},set:function(a){k=a,r.x(a),s.x(a),t.x(a),u.x(a),v.x(a),w.x(a)}},y:{get:function(){return l},set:function(a){l=a,r.y(a),s.y(a),v.y(a),w.y(a),t.y(a),u.y(a)}},useVoronoi:{get:function(){return n},set:function(a){n=a,r.useVoronoi(a),s.useVoronoi(a),v.useVoronoi(a),w.useVoronoi(a)}}}),a.utils.initOptions(b),b},a.models.ohlcBar=function(){"use strict";function b(y){return y.each(function(b){k=d3.select(this);var y=a.utils.availableWidth(h,k,g),A=a.utils.availableHeight(i,k,g);a.utils.initSVG(k);var B=y/b[0].values.length*.9;l.domain(c||d3.extent(b[0].values.map(n).concat(t))),l.range(v?e||[.5*y/b[0].values.length,y*(b[0].values.length-.5)/b[0].values.length]:e||[5+B/2,y-B/2-5]),m.domain(d||[d3.min(b[0].values.map(s).concat(u)),d3.max(b[0].values.map(r).concat(u))]).range(f||[A,0]),l.domain()[0]===l.domain()[1]&&l.domain(l.domain()[0]?[l.domain()[0]-.01*l.domain()[0],l.domain()[1]+.01*l.domain()[1]]:[-1,1]),m.domain()[0]===m.domain()[1]&&m.domain(m.domain()[0]?[m.domain()[0]+.01*m.domain()[0],m.domain()[1]-.01*m.domain()[1]]:[-1,1]);var C=d3.select(this).selectAll("g.nv-wrap.nv-ohlcBar").data([b[0].values]),D=C.enter().append("g").attr("class","nvd3 nv-wrap nv-ohlcBar"),E=D.append("defs"),F=D.append("g"),G=C.select("g");F.append("g").attr("class","nv-ticks"),C.attr("transform","translate("+g.left+","+g.top+")"),k.on("click",function(a,b){z.chartClick({data:a,index:b,pos:d3.event,id:j})}),E.append("clipPath").attr("id","nv-chart-clip-path-"+j).append("rect"),C.select("#nv-chart-clip-path-"+j+" rect").attr("width",y).attr("height",A),G.attr("clip-path",w?"url(#nv-chart-clip-path-"+j+")":"");var H=C.select(".nv-ticks").selectAll(".nv-tick").data(function(a){return a});H.exit().remove(),H.enter().append("path").attr("class",function(a,b,c){return(p(a,b)>q(a,b)?"nv-tick negative":"nv-tick positive")+" nv-tick-"+c+"-"+b}).attr("d",function(a,b){return"m0,0l0,"+(m(p(a,b))-m(r(a,b)))+"l"+-B/2+",0l"+B/2+",0l0,"+(m(s(a,b))-m(p(a,b)))+"l0,"+(m(q(a,b))-m(s(a,b)))+"l"+B/2+",0l"+-B/2+",0z"}).attr("transform",function(a,b){return"translate("+l(n(a,b))+","+m(r(a,b))+")"}).attr("fill",function(){return x[0]}).attr("stroke",function(){return x[0]}).attr("x",0).attr("y",function(a,b){return m(Math.max(0,o(a,b)))}).attr("height",function(a,b){return Math.abs(m(o(a,b))-m(0))}),H.attr("class",function(a,b,c){return(p(a,b)>q(a,b)?"nv-tick negative":"nv-tick positive")+" nv-tick-"+c+"-"+b}),d3.transition(H).attr("transform",function(a,b){return"translate("+l(n(a,b))+","+m(r(a,b))+")"}).attr("d",function(a,c){var d=y/b[0].values.length*.9;return"m0,0l0,"+(m(p(a,c))-m(r(a,c)))+"l"+-d/2+",0l"+d/2+",0l0,"+(m(s(a,c))-m(p(a,c)))+"l0,"+(m(q(a,c))-m(s(a,c)))+"l"+d/2+",0l"+-d/2+",0z"})}),b}var c,d,e,f,g={top:0,right:0,bottom:0,left:0},h=null,i=null,j=Math.floor(1e4*Math.random()),k=null,l=d3.scale.linear(),m=d3.scale.linear(),n=function(a){return a.x},o=function(a){return a.y},p=function(a){return a.open},q=function(a){return a.close},r=function(a){return a.high},s=function(a){return a.low},t=[],u=[],v=!1,w=!0,x=a.utils.defaultColor(),y=!1,z=d3.dispatch("tooltipShow","tooltipHide","stateChange","changeState","renderEnd","chartClick","elementClick","elementDblClick","elementMouseover","elementMouseout","elementMousemove");return b.highlightPoint=function(a,c){b.clearHighlights(),k.select(".nv-ohlcBar .nv-tick-0-"+a).classed("hover",c)},b.clearHighlights=function(){k.select(".nv-ohlcBar .nv-tick.hover").classed("hover",!1)},b.dispatch=z,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return h},set:function(a){h=a}},height:{get:function(){return i},set:function(a){i=a}},xScale:{get:function(){return l},set:function(a){l=a}},yScale:{get:function(){return m},set:function(a){m=a}},xDomain:{get:function(){return c},set:function(a){c=a}},yDomain:{get:function(){return d},set:function(a){d=a}},xRange:{get:function(){return e},set:function(a){e=a}},yRange:{get:function(){return f},set:function(a){f=a}},forceX:{get:function(){return t},set:function(a){t=a}},forceY:{get:function(){return u},set:function(a){u=a}},padData:{get:function(){return v},set:function(a){v=a}},clipEdge:{get:function(){return w},set:function(a){w=a}},id:{get:function(){return j},set:function(a){j=a}},interactive:{get:function(){return y},set:function(a){y=a}},x:{get:function(){return n},set:function(a){n=a}},y:{get:function(){return o},set:function(a){o=a}},open:{get:function(){return p()},set:function(a){p=a}},close:{get:function(){return q()},set:function(a){q=a}},high:{get:function(){return r},set:function(a){r=a}},low:{get:function(){return s},set:function(a){s=a}},margin:{get:function(){return g},set:function(a){g.top=void 0!=a.top?a.top:g.top,g.right=void 0!=a.right?a.right:g.right,g.bottom=void 0!=a.bottom?a.bottom:g.bottom,g.left=void 0!=a.left?a.left:g.left
  22803. }},color:{get:function(){return x},set:function(b){x=a.utils.getColor(b)}}}),a.utils.initOptions(b),b},a.models.parallelCoordinates=function(){"use strict";function b(p){return p.each(function(b){function p(a){return F(h.map(function(b){if(isNaN(a[b])||isNaN(parseFloat(a[b]))){var c=g[b].domain(),d=g[b].range(),e=c[0]-(c[1]-c[0])/9;if(J.indexOf(b)<0){var h=d3.scale.linear().domain([e,c[1]]).range([x-12,d[1]]);g[b].brush.y(h),J.push(b)}return[f(b),g[b](e)]}return J.length>0?(D.style("display","inline"),E.style("display","inline")):(D.style("display","none"),E.style("display","none")),[f(b),g[b](a[b])]}))}function q(){var a=h.filter(function(a){return!g[a].brush.empty()}),b=a.map(function(a){return g[a].brush.extent()});k=[],a.forEach(function(a,c){k[c]={dimension:a,extent:b[c]}}),l=[],M.style("display",function(c){var d=a.every(function(a,d){return isNaN(c[a])&&b[d][0]==g[a].brush.y().domain()[0]?!0:b[d][0]<=c[a]&&c[a]<=b[d][1]});return d&&l.push(c),d?null:"none"}),o.brush({filters:k,active:l})}function r(a){m[a]=this.parentNode.__origin__=f(a),L.attr("visibility","hidden")}function s(a){m[a]=Math.min(w,Math.max(0,this.parentNode.__origin__+=d3.event.x)),M.attr("d",p),h.sort(function(a,b){return u(a)-u(b)}),f.domain(h),N.attr("transform",function(a){return"translate("+u(a)+")"})}function t(a){delete this.parentNode.__origin__,delete m[a],d3.select(this.parentNode).attr("transform","translate("+f(a)+")"),M.attr("d",p),L.attr("d",p).attr("visibility",null)}function u(a){var b=m[a];return null==b?f(a):b}var v=d3.select(this),w=a.utils.availableWidth(d,v,c),x=a.utils.availableHeight(e,v,c);a.utils.initSVG(v),l=b,f.rangePoints([0,w],1).domain(h);var y={};h.forEach(function(a){var c=d3.extent(b,function(b){return+b[a]});return y[a]=!1,void 0===c[0]&&(y[a]=!0,c[0]=0,c[1]=0),c[0]===c[1]&&(c[0]=c[0]-1,c[1]=c[1]+1),g[a]=d3.scale.linear().domain(c).range([.9*(x-12),0]),g[a].brush=d3.svg.brush().y(g[a]).on("brush",q),"name"!=a});var z=v.selectAll("g.nv-wrap.nv-parallelCoordinates").data([b]),A=z.enter().append("g").attr("class","nvd3 nv-wrap nv-parallelCoordinates"),B=A.append("g"),C=z.select("g");B.append("g").attr("class","nv-parallelCoordinates background"),B.append("g").attr("class","nv-parallelCoordinates foreground"),B.append("g").attr("class","nv-parallelCoordinates missingValuesline"),z.attr("transform","translate("+c.left+","+c.top+")");var D,E,F=d3.svg.line().interpolate("cardinal").tension(n),G=d3.svg.axis().orient("left"),H=d3.behavior.drag().on("dragstart",r).on("drag",s).on("dragend",t),I=f.range()[1]-f.range()[0],J=[],K=[0+I/2,x-12,w-I/2,x-12];D=z.select(".missingValuesline").selectAll("line").data([K]),D.enter().append("line"),D.exit().remove(),D.attr("x1",function(a){return a[0]}).attr("y1",function(a){return a[1]}).attr("x2",function(a){return a[2]}).attr("y2",function(a){return a[3]}),E=z.select(".missingValuesline").selectAll("text").data(["undefined values"]),E.append("text").data(["undefined values"]),E.enter().append("text"),E.exit().remove(),E.attr("y",x).attr("x",w-92-I/2).text(function(a){return a});var L=z.select(".background").selectAll("path").data(b);L.enter().append("path"),L.exit().remove(),L.attr("d",p);var M=z.select(".foreground").selectAll("path").data(b);M.enter().append("path"),M.exit().remove(),M.attr("d",p).attr("stroke",j),M.on("mouseover",function(a,b){d3.select(this).classed("hover",!0),o.elementMouseover({label:a.name,data:a.data,index:b,pos:[d3.mouse(this.parentNode)[0],d3.mouse(this.parentNode)[1]]})}),M.on("mouseout",function(a,b){d3.select(this).classed("hover",!1),o.elementMouseout({label:a.name,data:a.data,index:b})});var N=C.selectAll(".dimension").data(h),O=N.enter().append("g").attr("class","nv-parallelCoordinates dimension");O.append("g").attr("class","nv-parallelCoordinates nv-axis"),O.append("g").attr("class","nv-parallelCoordinates-brush"),O.append("text").attr("class","nv-parallelCoordinates nv-label"),N.attr("transform",function(a){return"translate("+f(a)+",0)"}),N.exit().remove(),N.select(".nv-label").style("cursor","move").attr("dy","-1em").attr("text-anchor","middle").text(String).on("mouseover",function(a){o.elementMouseover({dim:a,pos:[d3.mouse(this.parentNode.parentNode)[0],d3.mouse(this.parentNode.parentNode)[1]]})}).on("mouseout",function(a){o.elementMouseout({dim:a})}).call(H),N.select(".nv-axis").each(function(a,b){d3.select(this).call(G.scale(g[a]).tickFormat(d3.format(i[b])))}),N.select(".nv-parallelCoordinates-brush").each(function(a){d3.select(this).call(g[a].brush)}).selectAll("rect").attr("x",-8).attr("width",16)}),b}var c={top:30,right:0,bottom:10,left:0},d=null,e=null,f=d3.scale.ordinal(),g={},h=[],i=[],j=a.utils.defaultColor(),k=[],l=[],m=[],n=1,o=d3.dispatch("brush","elementMouseover","elementMouseout");return b.dispatch=o,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return d},set:function(a){d=a}},height:{get:function(){return e},set:function(a){e=a}},dimensionNames:{get:function(){return h},set:function(a){h=a}},dimensionFormats:{get:function(){return i},set:function(a){i=a}},lineTension:{get:function(){return n},set:function(a){n=a}},dimensions:{get:function(){return h},set:function(b){a.deprecated("dimensions","use dimensionNames instead"),h=b}},margin:{get:function(){return c},set:function(a){c.top=void 0!==a.top?a.top:c.top,c.right=void 0!==a.right?a.right:c.right,c.bottom=void 0!==a.bottom?a.bottom:c.bottom,c.left=void 0!==a.left?a.left:c.left}},color:{get:function(){return j},set:function(b){j=a.utils.getColor(b)}}}),a.utils.initOptions(b),b},a.models.pie=function(){"use strict";function b(E){return D.reset(),E.each(function(b){function E(a,b){a.endAngle=isNaN(a.endAngle)?0:a.endAngle,a.startAngle=isNaN(a.startAngle)?0:a.startAngle,p||(a.innerRadius=0);var c=d3.interpolate(this._current,a);return this._current=c(0),function(a){return B[b](c(a))}}var F=d-c.left-c.right,G=e-c.top-c.bottom,H=Math.min(F,G)/2,I=[],J=[];if(i=d3.select(this),0===z.length)for(var K=H-H/5,L=y*H,M=0;M<b[0].length;M++)I.push(K),J.push(L);else I=z.map(function(a){return(a.outer-a.outer/5)*H}),J=z.map(function(a){return(a.inner-a.inner/5)*H}),y=d3.min(z.map(function(a){return a.inner-a.inner/5}));a.utils.initSVG(i);var N=i.selectAll(".nv-wrap.nv-pie").data(b),O=N.enter().append("g").attr("class","nvd3 nv-wrap nv-pie nv-chart-"+h),P=O.append("g"),Q=N.select("g"),R=P.append("g").attr("class","nv-pie");P.append("g").attr("class","nv-pieLabels"),N.attr("transform","translate("+c.left+","+c.top+")"),Q.select(".nv-pie").attr("transform","translate("+F/2+","+G/2+")"),Q.select(".nv-pieLabels").attr("transform","translate("+F/2+","+G/2+")"),i.on("click",function(a,b){A.chartClick({data:a,index:b,pos:d3.event,id:h})}),B=[],C=[];for(var M=0;M<b[0].length;M++){var S=d3.svg.arc().outerRadius(I[M]),T=d3.svg.arc().outerRadius(I[M]+5);u!==!1&&(S.startAngle(u),T.startAngle(u)),w!==!1&&(S.endAngle(w),T.endAngle(w)),p&&(S.innerRadius(J[M]),T.innerRadius(J[M])),S.cornerRadius&&x&&(S.cornerRadius(x),T.cornerRadius(x)),B.push(S),C.push(T)}var U=d3.layout.pie().sort(null).value(function(a){return a.disabled?0:g(a)});U.padAngle&&v&&U.padAngle(v),p&&q&&(R.append("text").attr("class","nv-pie-title"),N.select(".nv-pie-title").style("text-anchor","middle").text(function(){return q}).style("font-size",Math.min(F,G)*y*2/(q.length+2)+"px").attr("dy","0.35em").attr("transform",function(){return"translate(0, "+s+")"}));var V=N.select(".nv-pie").selectAll(".nv-slice").data(U),W=N.select(".nv-pieLabels").selectAll(".nv-label").data(U);V.exit().remove(),W.exit().remove();var X=V.enter().append("g");X.attr("class","nv-slice"),X.on("mouseover",function(a,b){d3.select(this).classed("hover",!0),r&&d3.select(this).select("path").transition().duration(70).attr("d",C[b]),A.elementMouseover({data:a.data,index:b,color:d3.select(this).style("fill")})}),X.on("mouseout",function(a,b){d3.select(this).classed("hover",!1),r&&d3.select(this).select("path").transition().duration(50).attr("d",B[b]),A.elementMouseout({data:a.data,index:b})}),X.on("mousemove",function(a,b){A.elementMousemove({data:a.data,index:b})}),X.on("click",function(a,b){A.elementClick({data:a.data,index:b,color:d3.select(this).style("fill")})}),X.on("dblclick",function(a,b){A.elementDblClick({data:a.data,index:b,color:d3.select(this).style("fill")})}),V.attr("fill",function(a,b){return j(a.data,b)}),V.attr("stroke",function(a,b){return j(a.data,b)});X.append("path").each(function(a){this._current=a});if(V.select("path").transition().attr("d",function(a,b){return B[b](a)}).attrTween("d",E),l){for(var Y=[],M=0;M<b[0].length;M++)Y.push(B[M]),m?p&&(Y[M]=d3.svg.arc().outerRadius(B[M].outerRadius()),u!==!1&&Y[M].startAngle(u),w!==!1&&Y[M].endAngle(w)):p||Y[M].innerRadius(0);W.enter().append("g").classed("nv-label",!0).each(function(a){var b=d3.select(this);b.attr("transform",function(a,b){if(t){a.outerRadius=I[b]+10,a.innerRadius=I[b]+15;var c=(a.startAngle+a.endAngle)/2*(180/Math.PI);return(a.startAngle+a.endAngle)/2<Math.PI?c-=90:c+=90,"translate("+Y[b].centroid(a)+") rotate("+c+")"}return a.outerRadius=H+10,a.innerRadius=H+15,"translate("+Y[b].centroid(a)+")"}),b.append("rect").style("stroke","#fff").style("fill","#fff").attr("rx",3).attr("ry",3),b.append("text").style("text-anchor",t?(a.startAngle+a.endAngle)/2<Math.PI?"start":"end":"middle").style("fill","#000")});var Z={},$=14,_=140,ab=function(a){return Math.floor(a[0]/_)*_+","+Math.floor(a[1]/$)*$};W.watchTransition(D,"pie labels").attr("transform",function(a,b){if(t){a.outerRadius=I[b]+10,a.innerRadius=I[b]+15;var c=(a.startAngle+a.endAngle)/2*(180/Math.PI);return(a.startAngle+a.endAngle)/2<Math.PI?c-=90:c+=90,"translate("+Y[b].centroid(a)+") rotate("+c+")"}a.outerRadius=H+10,a.innerRadius=H+15;var d=Y[b].centroid(a);if(a.value){var e=ab(d);Z[e]&&(d[1]-=$),Z[ab(d)]=!0}return"translate("+d+")"}),W.select(".nv-label text").style("text-anchor",function(a){return t?(a.startAngle+a.endAngle)/2<Math.PI?"start":"end":"middle"}).text(function(a,b){var c=(a.endAngle-a.startAngle)/(2*Math.PI),d="";if(!a.value||o>c)return"";if("function"==typeof n)d=n(a,b,{key:f(a.data),value:g(a.data),percent:k(c)});else switch(n){case"key":d=f(a.data);break;case"value":d=k(g(a.data));break;case"percent":d=d3.format("%")(c)}return d})}}),D.renderEnd("pie immediate"),b}var c={top:0,right:0,bottom:0,left:0},d=500,e=500,f=function(a){return a.x},g=function(a){return a.y},h=Math.floor(1e4*Math.random()),i=null,j=a.utils.defaultColor(),k=d3.format(",.2f"),l=!0,m=!1,n="key",o=.02,p=!1,q=!1,r=!0,s=0,t=!1,u=!1,v=!1,w=!1,x=0,y=.5,z=[],A=d3.dispatch("chartClick","elementClick","elementDblClick","elementMouseover","elementMouseout","elementMousemove","renderEnd"),B=[],C=[],D=a.utils.renderWatch(A);return b.dispatch=A,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{arcsRadius:{get:function(){return z},set:function(a){z=a}},width:{get:function(){return d},set:function(a){d=a}},height:{get:function(){return e},set:function(a){e=a}},showLabels:{get:function(){return l},set:function(a){l=a}},title:{get:function(){return q},set:function(a){q=a}},titleOffset:{get:function(){return s},set:function(a){s=a}},labelThreshold:{get:function(){return o},set:function(a){o=a}},valueFormat:{get:function(){return k},set:function(a){k=a}},x:{get:function(){return f},set:function(a){f=a}},id:{get:function(){return h},set:function(a){h=a}},endAngle:{get:function(){return w},set:function(a){w=a}},startAngle:{get:function(){return u},set:function(a){u=a}},padAngle:{get:function(){return v},set:function(a){v=a}},cornerRadius:{get:function(){return x},set:function(a){x=a}},donutRatio:{get:function(){return y},set:function(a){y=a}},labelsOutside:{get:function(){return m},set:function(a){m=a}},labelSunbeamLayout:{get:function(){return t},set:function(a){t=a}},donut:{get:function(){return p},set:function(a){p=a}},growOnHover:{get:function(){return r},set:function(a){r=a}},pieLabelsOutside:{get:function(){return m},set:function(b){m=b,a.deprecated("pieLabelsOutside","use labelsOutside instead")}},donutLabelsOutside:{get:function(){return m},set:function(b){m=b,a.deprecated("donutLabelsOutside","use labelsOutside instead")}},labelFormat:{get:function(){return k},set:function(b){k=b,a.deprecated("labelFormat","use valueFormat instead")}},margin:{get:function(){return c},set:function(a){c.top="undefined"!=typeof a.top?a.top:c.top,c.right="undefined"!=typeof a.right?a.right:c.right,c.bottom="undefined"!=typeof a.bottom?a.bottom:c.bottom,c.left="undefined"!=typeof a.left?a.left:c.left}},y:{get:function(){return g},set:function(a){g=d3.functor(a)}},color:{get:function(){return j},set:function(b){j=a.utils.getColor(b)}},labelType:{get:function(){return n},set:function(a){n=a||"key"}}}),a.utils.initOptions(b),b},a.models.pieChart=function(){"use strict";function b(e){return q.reset(),q.models(c),e.each(function(e){var k=d3.select(this);a.utils.initSVG(k);var n=a.utils.availableWidth(g,k,f),o=a.utils.availableHeight(h,k,f);if(b.update=function(){k.transition().call(b)},b.container=this,l.setter(s(e),b.update).getter(r(e)).update(),l.disabled=e.map(function(a){return!!a.disabled}),!m){var q;m={};for(q in l)m[q]=l[q]instanceof Array?l[q].slice(0):l[q]}if(!e||!e.length)return a.utils.noData(b,k),b;k.selectAll(".nv-noData").remove();var t=k.selectAll("g.nv-wrap.nv-pieChart").data([e]),u=t.enter().append("g").attr("class","nvd3 nv-wrap nv-pieChart").append("g"),v=t.select("g");if(u.append("g").attr("class","nv-pieWrap"),u.append("g").attr("class","nv-legendWrap"),i)if("top"===j)d.width(n).key(c.x()),t.select(".nv-legendWrap").datum(e).call(d),f.top!=d.height()&&(f.top=d.height(),o=a.utils.availableHeight(h,k,f)),t.select(".nv-legendWrap").attr("transform","translate(0,"+-f.top+")");else if("right"===j){var w=a.models.legend().width();w>n/2&&(w=n/2),d.height(o).key(c.x()),d.width(w),n-=d.width(),t.select(".nv-legendWrap").datum(e).call(d).attr("transform","translate("+n+",0)")}t.attr("transform","translate("+f.left+","+f.top+")"),c.width(n).height(o);var x=v.select(".nv-pieWrap").datum([e]);d3.transition(x).call(c),d.dispatch.on("stateChange",function(a){for(var c in a)l[c]=a[c];p.stateChange(l),b.update()}),p.on("changeState",function(a){"undefined"!=typeof a.disabled&&(e.forEach(function(b,c){b.disabled=a.disabled[c]}),l.disabled=a.disabled),b.update()})}),q.renderEnd("pieChart immediate"),b}var c=a.models.pie(),d=a.models.legend(),e=a.models.tooltip(),f={top:30,right:20,bottom:20,left:20},g=null,h=null,i=!0,j="top",k=a.utils.defaultColor(),l=a.utils.state(),m=null,n=null,o=250,p=d3.dispatch("tooltipShow","tooltipHide","stateChange","changeState","renderEnd");e.headerEnabled(!1).duration(0).valueFormatter(function(a,b){return c.valueFormat()(a,b)});var q=a.utils.renderWatch(p),r=function(a){return function(){return{active:a.map(function(a){return!a.disabled})}}},s=function(a){return function(b){void 0!==b.active&&a.forEach(function(a,c){a.disabled=!b.active[c]})}};return c.dispatch.on("elementMouseover.tooltip",function(a){a.series={key:b.x()(a.data),value:b.y()(a.data),color:a.color},e.data(a).hidden(!1)}),c.dispatch.on("elementMouseout.tooltip",function(){e.hidden(!0)}),c.dispatch.on("elementMousemove.tooltip",function(){e.position({top:d3.event.pageY,left:d3.event.pageX})()}),b.legend=d,b.dispatch=p,b.pie=c,b.tooltip=e,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{noData:{get:function(){return n},set:function(a){n=a}},showLegend:{get:function(){return i},set:function(a){i=a}},legendPosition:{get:function(){return j},set:function(a){j=a}},defaultState:{get:function(){return m},set:function(a){m=a}},tooltips:{get:function(){return e.enabled()},set:function(b){a.deprecated("tooltips","use chart.tooltip.enabled() instead"),e.enabled(!!b)}},tooltipContent:{get:function(){return e.contentGenerator()},set:function(b){a.deprecated("tooltipContent","use chart.tooltip.contentGenerator() instead"),e.contentGenerator(b)}},color:{get:function(){return k},set:function(a){k=a,d.color(k),c.color(k)}},duration:{get:function(){return o},set:function(a){o=a,q.reset(o)}},margin:{get:function(){return f},set:function(a){f.top=void 0!==a.top?a.top:f.top,f.right=void 0!==a.right?a.right:f.right,f.bottom=void 0!==a.bottom?a.bottom:f.bottom,f.left=void 0!==a.left?a.left:f.left}}}),a.utils.inheritOptions(b,c),a.utils.initOptions(b),b},a.models.scatter=function(){"use strict";function b(N){return P.reset(),N.each(function(b){function N(){if(O=!1,!w)return!1;if(M===!0){var a=d3.merge(b.map(function(a,b){return a.values.map(function(a,c){var d=p(a,c),e=q(a,c);return[m(d)+1e-4*Math.random(),n(e)+1e-4*Math.random(),b,c,a]}).filter(function(a,b){return x(a[4],b)})}));if(0==a.length)return!1;a.length<3&&(a.push([m.range()[0]-20,n.range()[0]-20,null,null]),a.push([m.range()[1]+20,n.range()[1]+20,null,null]),a.push([m.range()[0]-20,n.range()[0]+20,null,null]),a.push([m.range()[1]+20,n.range()[1]-20,null,null]));var c=d3.geom.polygon([[-10,-10],[-10,i+10],[h+10,i+10],[h+10,-10]]),d=d3.geom.voronoi(a).map(function(b,d){return{data:c.clip(b),series:a[d][2],point:a[d][3]}});U.select(".nv-point-paths").selectAll("path").remove();var e=U.select(".nv-point-paths").selectAll("path").data(d),f=e.enter().append("svg:path").attr("d",function(a){return a&&a.data&&0!==a.data.length?"M"+a.data.join(",")+"Z":"M 0 0"}).attr("id",function(a,b){return"nv-path-"+b}).attr("clip-path",function(a,b){return"url(#nv-clip-"+b+")"});C&&f.style("fill",d3.rgb(230,230,230)).style("fill-opacity",.4).style("stroke-opacity",1).style("stroke",d3.rgb(200,200,200)),B&&(U.select(".nv-point-clips").selectAll("clipPath").remove(),U.select(".nv-point-clips").selectAll("clipPath").data(a).enter().append("svg:clipPath").attr("id",function(a,b){return"nv-clip-"+b}).append("svg:circle").attr("cx",function(a){return a[0]}).attr("cy",function(a){return a[1]}).attr("r",D));var k=function(a,c){if(O)return 0;var d=b[a.series];if(void 0!==d){var e=d.values[a.point];e.color=j(d,a.series),e.x=p(e),e.y=q(e);var f=l.node().getBoundingClientRect(),h=window.pageYOffset||document.documentElement.scrollTop,i=window.pageXOffset||document.documentElement.scrollLeft,k={left:m(p(e,a.point))+f.left+i+g.left+10,top:n(q(e,a.point))+f.top+h+g.top+10};c({point:e,series:d,pos:k,seriesIndex:a.series,pointIndex:a.point})}};e.on("click",function(a){k(a,L.elementClick)}).on("dblclick",function(a){k(a,L.elementDblClick)}).on("mouseover",function(a){k(a,L.elementMouseover)}).on("mouseout",function(a){k(a,L.elementMouseout)})}else U.select(".nv-groups").selectAll(".nv-group").selectAll(".nv-point").on("click",function(a,c){if(O||!b[a.series])return 0;var d=b[a.series],e=d.values[c];L.elementClick({point:e,series:d,pos:[m(p(e,c))+g.left,n(q(e,c))+g.top],seriesIndex:a.series,pointIndex:c})}).on("dblclick",function(a,c){if(O||!b[a.series])return 0;var d=b[a.series],e=d.values[c];L.elementDblClick({point:e,series:d,pos:[m(p(e,c))+g.left,n(q(e,c))+g.top],seriesIndex:a.series,pointIndex:c})}).on("mouseover",function(a,c){if(O||!b[a.series])return 0;var d=b[a.series],e=d.values[c];L.elementMouseover({point:e,series:d,pos:[m(p(e,c))+g.left,n(q(e,c))+g.top],seriesIndex:a.series,pointIndex:c,color:j(a,c)})}).on("mouseout",function(a,c){if(O||!b[a.series])return 0;var d=b[a.series],e=d.values[c];L.elementMouseout({point:e,series:d,seriesIndex:a.series,pointIndex:c,color:j(a,c)})})}l=d3.select(this);var R=a.utils.availableWidth(h,l,g),S=a.utils.availableHeight(i,l,g);a.utils.initSVG(l),b.forEach(function(a,b){a.values.forEach(function(a){a.series=b})});var T=E&&F&&I?[]:d3.merge(b.map(function(a){return a.values.map(function(a,b){return{x:p(a,b),y:q(a,b),size:r(a,b)}})}));m.domain(E||d3.extent(T.map(function(a){return a.x}).concat(t))),m.range(y&&b[0]?G||[(R*z+R)/(2*b[0].values.length),R-R*(1+z)/(2*b[0].values.length)]:G||[0,R]),n.domain(F||d3.extent(T.map(function(a){return a.y}).concat(u))).range(H||[S,0]),o.domain(I||d3.extent(T.map(function(a){return a.size}).concat(v))).range(J||Q),K=m.domain()[0]===m.domain()[1]||n.domain()[0]===n.domain()[1],m.domain()[0]===m.domain()[1]&&m.domain(m.domain()[0]?[m.domain()[0]-.01*m.domain()[0],m.domain()[1]+.01*m.domain()[1]]:[-1,1]),n.domain()[0]===n.domain()[1]&&n.domain(n.domain()[0]?[n.domain()[0]-.01*n.domain()[0],n.domain()[1]+.01*n.domain()[1]]:[-1,1]),isNaN(m.domain()[0])&&m.domain([-1,1]),isNaN(n.domain()[0])&&n.domain([-1,1]),c=c||m,d=d||n,e=e||o;var U=l.selectAll("g.nv-wrap.nv-scatter").data([b]),V=U.enter().append("g").attr("class","nvd3 nv-wrap nv-scatter nv-chart-"+k),W=V.append("defs"),X=V.append("g"),Y=U.select("g");U.classed("nv-single-point",K),X.append("g").attr("class","nv-groups"),X.append("g").attr("class","nv-point-paths"),V.append("g").attr("class","nv-point-clips"),U.attr("transform","translate("+g.left+","+g.top+")"),W.append("clipPath").attr("id","nv-edge-clip-"+k).append("rect"),U.select("#nv-edge-clip-"+k+" rect").attr("width",R).attr("height",S>0?S:0),Y.attr("clip-path",A?"url(#nv-edge-clip-"+k+")":""),O=!0;var Z=U.select(".nv-groups").selectAll(".nv-group").data(function(a){return a},function(a){return a.key});Z.enter().append("g").style("stroke-opacity",1e-6).style("fill-opacity",1e-6),Z.exit().remove(),Z.attr("class",function(a,b){return"nv-group nv-series-"+b}).classed("hover",function(a){return a.hover}),Z.watchTransition(P,"scatter: groups").style("fill",function(a,b){return j(a,b)}).style("stroke",function(a,b){return j(a,b)}).style("stroke-opacity",1).style("fill-opacity",.5);var $=Z.selectAll("path.nv-point").data(function(a){return a.values.map(function(a,b){return[a,b]}).filter(function(a,b){return x(a[0],b)})});$.enter().append("path").style("fill",function(a){return a.color}).style("stroke",function(a){return a.color}).attr("transform",function(a){return"translate("+c(p(a[0],a[1]))+","+d(q(a[0],a[1]))+")"}).attr("d",a.utils.symbol().type(function(a){return s(a[0])}).size(function(a){return o(r(a[0],a[1]))})),$.exit().remove(),Z.exit().selectAll("path.nv-point").watchTransition(P,"scatter exit").attr("transform",function(a){return"translate("+m(p(a[0],a[1]))+","+n(q(a[0],a[1]))+")"}).remove(),$.each(function(a){d3.select(this).classed("nv-point",!0).classed("nv-point-"+a[1],!0).classed("nv-noninteractive",!w).classed("hover",!1)}),$.watchTransition(P,"scatter points").attr("transform",function(a){return"translate("+m(p(a[0],a[1]))+","+n(q(a[0],a[1]))+")"}).attr("d",a.utils.symbol().type(function(a){return s(a[0])}).size(function(a){return o(r(a[0],a[1]))})),clearTimeout(f),f=setTimeout(N,300),c=m.copy(),d=n.copy(),e=o.copy()}),P.renderEnd("scatter immediate"),b}var c,d,e,f,g={top:0,right:0,bottom:0,left:0},h=null,i=null,j=a.utils.defaultColor(),k=Math.floor(1e5*Math.random()),l=null,m=d3.scale.linear(),n=d3.scale.linear(),o=d3.scale.linear(),p=function(a){return a.x},q=function(a){return a.y},r=function(a){return a.size||1},s=function(a){return a.shape||"circle"},t=[],u=[],v=[],w=!0,x=function(a){return!a.notActive},y=!1,z=.1,A=!1,B=!0,C=!1,D=function(){return 25},E=null,F=null,G=null,H=null,I=null,J=null,K=!1,L=d3.dispatch("elementClick","elementDblClick","elementMouseover","elementMouseout","renderEnd"),M=!0,N=250,O=!1,P=a.utils.renderWatch(L,N),Q=[16,256];return b.dispatch=L,b.options=a.utils.optionsFunc.bind(b),b._calls=new function(){this.clearHighlights=function(){return a.dom.write(function(){l.selectAll(".nv-point.hover").classed("hover",!1)}),null},this.highlightPoint=function(b,c,d){a.dom.write(function(){l.select(" .nv-series-"+b+" .nv-point-"+c).classed("hover",d)})}},L.on("elementMouseover.point",function(a){w&&b._calls.highlightPoint(a.seriesIndex,a.pointIndex,!0)}),L.on("elementMouseout.point",function(a){w&&b._calls.highlightPoint(a.seriesIndex,a.pointIndex,!1)}),b._options=Object.create({},{width:{get:function(){return h},set:function(a){h=a}},height:{get:function(){return i},set:function(a){i=a}},xScale:{get:function(){return m},set:function(a){m=a}},yScale:{get:function(){return n},set:function(a){n=a}},pointScale:{get:function(){return o},set:function(a){o=a}},xDomain:{get:function(){return E},set:function(a){E=a}},yDomain:{get:function(){return F},set:function(a){F=a}},pointDomain:{get:function(){return I},set:function(a){I=a}},xRange:{get:function(){return G},set:function(a){G=a}},yRange:{get:function(){return H},set:function(a){H=a}},pointRange:{get:function(){return J},set:function(a){J=a}},forceX:{get:function(){return t},set:function(a){t=a}},forceY:{get:function(){return u},set:function(a){u=a}},forcePoint:{get:function(){return v},set:function(a){v=a}},interactive:{get:function(){return w},set:function(a){w=a}},pointActive:{get:function(){return x},set:function(a){x=a}},padDataOuter:{get:function(){return z},set:function(a){z=a}},padData:{get:function(){return y},set:function(a){y=a}},clipEdge:{get:function(){return A},set:function(a){A=a}},clipVoronoi:{get:function(){return B},set:function(a){B=a}},clipRadius:{get:function(){return D},set:function(a){D=a}},showVoronoi:{get:function(){return C},set:function(a){C=a}},id:{get:function(){return k},set:function(a){k=a}},x:{get:function(){return p},set:function(a){p=d3.functor(a)}},y:{get:function(){return q},set:function(a){q=d3.functor(a)}},pointSize:{get:function(){return r},set:function(a){r=d3.functor(a)}},pointShape:{get:function(){return s},set:function(a){s=d3.functor(a)}},margin:{get:function(){return g},set:function(a){g.top=void 0!==a.top?a.top:g.top,g.right=void 0!==a.right?a.right:g.right,g.bottom=void 0!==a.bottom?a.bottom:g.bottom,g.left=void 0!==a.left?a.left:g.left}},duration:{get:function(){return N},set:function(a){N=a,P.reset(N)}},color:{get:function(){return j},set:function(b){j=a.utils.getColor(b)}},useVoronoi:{get:function(){return M},set:function(a){M=a,M===!1&&(B=!1)}}}),a.utils.initOptions(b),b},a.models.scatterChart=function(){"use strict";function b(z){return D.reset(),D.models(c),t&&D.models(d),u&&D.models(e),q&&D.models(g),r&&D.models(h),z.each(function(z){m=d3.select(this),a.utils.initSVG(m);var G=a.utils.availableWidth(k,m,j),H=a.utils.availableHeight(l,m,j);if(b.update=function(){0===A?m.call(b):m.transition().duration(A).call(b)},b.container=this,w.setter(F(z),b.update).getter(E(z)).update(),w.disabled=z.map(function(a){return!!a.disabled}),!x){var I;x={};for(I in w)x[I]=w[I]instanceof Array?w[I].slice(0):w[I]}if(!(z&&z.length&&z.filter(function(a){return a.values.length}).length))return a.utils.noData(b,m),D.renderEnd("scatter immediate"),b;m.selectAll(".nv-noData").remove(),o=c.xScale(),p=c.yScale();var J=m.selectAll("g.nv-wrap.nv-scatterChart").data([z]),K=J.enter().append("g").attr("class","nvd3 nv-wrap nv-scatterChart nv-chart-"+c.id()),L=K.append("g"),M=J.select("g");if(L.append("rect").attr("class","nvd3 nv-background").style("pointer-events","none"),L.append("g").attr("class","nv-x nv-axis"),L.append("g").attr("class","nv-y nv-axis"),L.append("g").attr("class","nv-scatterWrap"),L.append("g").attr("class","nv-regressionLinesWrap"),L.append("g").attr("class","nv-distWrap"),L.append("g").attr("class","nv-legendWrap"),v&&M.select(".nv-y.nv-axis").attr("transform","translate("+G+",0)"),s){var N=G;f.width(N),J.select(".nv-legendWrap").datum(z).call(f),j.top!=f.height()&&(j.top=f.height(),H=a.utils.availableHeight(l,m,j)),J.select(".nv-legendWrap").attr("transform","translate(0,"+-j.top+")")}J.attr("transform","translate("+j.left+","+j.top+")"),c.width(G).height(H).color(z.map(function(a,b){return a.color=a.color||n(a,b),a.color}).filter(function(a,b){return!z[b].disabled})),J.select(".nv-scatterWrap").datum(z.filter(function(a){return!a.disabled})).call(c),J.select(".nv-regressionLinesWrap").attr("clip-path","url(#nv-edge-clip-"+c.id()+")");var O=J.select(".nv-regressionLinesWrap").selectAll(".nv-regLines").data(function(a){return a});O.enter().append("g").attr("class","nv-regLines");var P=O.selectAll(".nv-regLine").data(function(a){return[a]});P.enter().append("line").attr("class","nv-regLine").style("stroke-opacity",0),P.filter(function(a){return a.intercept&&a.slope}).watchTransition(D,"scatterPlusLineChart: regline").attr("x1",o.range()[0]).attr("x2",o.range()[1]).attr("y1",function(a){return p(o.domain()[0]*a.slope+a.intercept)}).attr("y2",function(a){return p(o.domain()[1]*a.slope+a.intercept)}).style("stroke",function(a,b,c){return n(a,c)}).style("stroke-opacity",function(a){return a.disabled||"undefined"==typeof a.slope||"undefined"==typeof a.intercept?0:1}),t&&(d.scale(o)._ticks(a.utils.calcTicksX(G/100,z)).tickSize(-H,0),M.select(".nv-x.nv-axis").attr("transform","translate(0,"+p.range()[0]+")").call(d)),u&&(e.scale(p)._ticks(a.utils.calcTicksY(H/36,z)).tickSize(-G,0),M.select(".nv-y.nv-axis").call(e)),q&&(g.getData(c.x()).scale(o).width(G).color(z.map(function(a,b){return a.color||n(a,b)}).filter(function(a,b){return!z[b].disabled})),L.select(".nv-distWrap").append("g").attr("class","nv-distributionX"),M.select(".nv-distributionX").attr("transform","translate(0,"+p.range()[0]+")").datum(z.filter(function(a){return!a.disabled})).call(g)),r&&(h.getData(c.y()).scale(p).width(H).color(z.map(function(a,b){return a.color||n(a,b)}).filter(function(a,b){return!z[b].disabled})),L.select(".nv-distWrap").append("g").attr("class","nv-distributionY"),M.select(".nv-distributionY").attr("transform","translate("+(v?G:-h.size())+",0)").datum(z.filter(function(a){return!a.disabled})).call(h)),f.dispatch.on("stateChange",function(a){for(var c in a)w[c]=a[c];y.stateChange(w),b.update()}),y.on("changeState",function(a){"undefined"!=typeof a.disabled&&(z.forEach(function(b,c){b.disabled=a.disabled[c]}),w.disabled=a.disabled),b.update()}),c.dispatch.on("elementMouseout.tooltip",function(a){i.hidden(!0),m.select(".nv-chart-"+c.id()+" .nv-series-"+a.seriesIndex+" .nv-distx-"+a.pointIndex).attr("y1",0),m.select(".nv-chart-"+c.id()+" .nv-series-"+a.seriesIndex+" .nv-disty-"+a.pointIndex).attr("x2",h.size())}),c.dispatch.on("elementMouseover.tooltip",function(a){m.select(".nv-series-"+a.seriesIndex+" .nv-distx-"+a.pointIndex).attr("y1",a.pos.top-H-j.top),m.select(".nv-series-"+a.seriesIndex+" .nv-disty-"+a.pointIndex).attr("x2",a.pos.left+g.size()-j.left),i.position(a.pos).data(a).hidden(!1)}),B=o.copy(),C=p.copy()}),D.renderEnd("scatter with line immediate"),b}var c=a.models.scatter(),d=a.models.axis(),e=a.models.axis(),f=a.models.legend(),g=a.models.distribution(),h=a.models.distribution(),i=a.models.tooltip(),j={top:30,right:20,bottom:50,left:75},k=null,l=null,m=null,n=a.utils.defaultColor(),o=c.xScale(),p=c.yScale(),q=!1,r=!1,s=!0,t=!0,u=!0,v=!1,w=a.utils.state(),x=null,y=d3.dispatch("stateChange","changeState","renderEnd"),z=null,A=250;c.xScale(o).yScale(p),d.orient("bottom").tickPadding(10),e.orient(v?"right":"left").tickPadding(10),g.axis("x"),h.axis("y"),i.headerFormatter(function(a,b){return d.tickFormat()(a,b)}).valueFormatter(function(a,b){return e.tickFormat()(a,b)});var B,C,D=a.utils.renderWatch(y,A),E=function(a){return function(){return{active:a.map(function(a){return!a.disabled})}}},F=function(a){return function(b){void 0!==b.active&&a.forEach(function(a,c){a.disabled=!b.active[c]})}};return b.dispatch=y,b.scatter=c,b.legend=f,b.xAxis=d,b.yAxis=e,b.distX=g,b.distY=h,b.tooltip=i,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return k},set:function(a){k=a}},height:{get:function(){return l},set:function(a){l=a}},container:{get:function(){return m},set:function(a){m=a}},showDistX:{get:function(){return q},set:function(a){q=a}},showDistY:{get:function(){return r},set:function(a){r=a}},showLegend:{get:function(){return s},set:function(a){s=a}},showXAxis:{get:function(){return t},set:function(a){t=a}},showYAxis:{get:function(){return u},set:function(a){u=a}},defaultState:{get:function(){return x},set:function(a){x=a}},noData:{get:function(){return z},set:function(a){z=a}},duration:{get:function(){return A},set:function(a){A=a}},tooltips:{get:function(){return i.enabled()},set:function(b){a.deprecated("tooltips","use chart.tooltip.enabled() instead"),i.enabled(!!b)
  22804. }},tooltipContent:{get:function(){return i.contentGenerator()},set:function(b){a.deprecated("tooltipContent","use chart.tooltip.contentGenerator() instead"),i.contentGenerator(b)}},tooltipXContent:{get:function(){return i.contentGenerator()},set:function(){a.deprecated("tooltipContent","This option is removed, put values into main tooltip.")}},tooltipYContent:{get:function(){return i.contentGenerator()},set:function(){a.deprecated("tooltipContent","This option is removed, put values into main tooltip.")}},margin:{get:function(){return j},set:function(a){j.top=void 0!==a.top?a.top:j.top,j.right=void 0!==a.right?a.right:j.right,j.bottom=void 0!==a.bottom?a.bottom:j.bottom,j.left=void 0!==a.left?a.left:j.left}},rightAlignYAxis:{get:function(){return v},set:function(a){v=a,e.orient(a?"right":"left")}},color:{get:function(){return n},set:function(b){n=a.utils.getColor(b),f.color(n),g.color(n),h.color(n)}}}),a.utils.inheritOptions(b,c),a.utils.initOptions(b),b},a.models.sparkline=function(){"use strict";function b(k){return k.each(function(b){var k=h-g.left-g.right,q=i-g.top-g.bottom;j=d3.select(this),a.utils.initSVG(j),l.domain(c||d3.extent(b,n)).range(e||[0,k]),m.domain(d||d3.extent(b,o)).range(f||[q,0]);{var r=j.selectAll("g.nv-wrap.nv-sparkline").data([b]),s=r.enter().append("g").attr("class","nvd3 nv-wrap nv-sparkline");s.append("g"),r.select("g")}r.attr("transform","translate("+g.left+","+g.top+")");var t=r.selectAll("path").data(function(a){return[a]});t.enter().append("path"),t.exit().remove(),t.style("stroke",function(a,b){return a.color||p(a,b)}).attr("d",d3.svg.line().x(function(a,b){return l(n(a,b))}).y(function(a,b){return m(o(a,b))}));var u=r.selectAll("circle.nv-point").data(function(a){function b(b){if(-1!=b){var c=a[b];return c.pointIndex=b,c}return null}var c=a.map(function(a,b){return o(a,b)}),d=b(c.lastIndexOf(m.domain()[1])),e=b(c.indexOf(m.domain()[0])),f=b(c.length-1);return[e,d,f].filter(function(a){return null!=a})});u.enter().append("circle"),u.exit().remove(),u.attr("cx",function(a){return l(n(a,a.pointIndex))}).attr("cy",function(a){return m(o(a,a.pointIndex))}).attr("r",2).attr("class",function(a){return n(a,a.pointIndex)==l.domain()[1]?"nv-point nv-currentValue":o(a,a.pointIndex)==m.domain()[0]?"nv-point nv-minValue":"nv-point nv-maxValue"})}),b}var c,d,e,f,g={top:2,right:0,bottom:2,left:0},h=400,i=32,j=null,k=!0,l=d3.scale.linear(),m=d3.scale.linear(),n=function(a){return a.x},o=function(a){return a.y},p=a.utils.getColor(["#000"]);return b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return h},set:function(a){h=a}},height:{get:function(){return i},set:function(a){i=a}},xDomain:{get:function(){return c},set:function(a){c=a}},yDomain:{get:function(){return d},set:function(a){d=a}},xRange:{get:function(){return e},set:function(a){e=a}},yRange:{get:function(){return f},set:function(a){f=a}},xScale:{get:function(){return l},set:function(a){l=a}},yScale:{get:function(){return m},set:function(a){m=a}},animate:{get:function(){return k},set:function(a){k=a}},x:{get:function(){return n},set:function(a){n=d3.functor(a)}},y:{get:function(){return o},set:function(a){o=d3.functor(a)}},margin:{get:function(){return g},set:function(a){g.top=void 0!==a.top?a.top:g.top,g.right=void 0!==a.right?a.right:g.right,g.bottom=void 0!==a.bottom?a.bottom:g.bottom,g.left=void 0!==a.left?a.left:g.left}},color:{get:function(){return p},set:function(b){p=a.utils.getColor(b)}}}),a.utils.initOptions(b),b},a.models.sparklinePlus=function(){"use strict";function b(p){return p.each(function(p){function q(){if(!j){var a=z.selectAll(".nv-hoverValue").data(i),b=a.enter().append("g").attr("class","nv-hoverValue").style("stroke-opacity",0).style("fill-opacity",0);a.exit().transition().duration(250).style("stroke-opacity",0).style("fill-opacity",0).remove(),a.attr("transform",function(a){return"translate("+c(e.x()(p[a],a))+",0)"}).transition().duration(250).style("stroke-opacity",1).style("fill-opacity",1),i.length&&(b.append("line").attr("x1",0).attr("y1",-f.top).attr("x2",0).attr("y2",u),b.append("text").attr("class","nv-xValue").attr("x",-6).attr("y",-f.top).attr("text-anchor","end").attr("dy",".9em"),z.select(".nv-hoverValue .nv-xValue").text(k(e.x()(p[i[0]],i[0]))),b.append("text").attr("class","nv-yValue").attr("x",6).attr("y",-f.top).attr("text-anchor","start").attr("dy",".9em"),z.select(".nv-hoverValue .nv-yValue").text(l(e.y()(p[i[0]],i[0]))))}}function r(){function a(a,b){for(var c=Math.abs(e.x()(a[0],0)-b),d=0,f=0;f<a.length;f++)Math.abs(e.x()(a[f],f)-b)<c&&(c=Math.abs(e.x()(a[f],f)-b),d=f);return d}if(!j){var b=d3.mouse(this)[0]-f.left;i=[a(p,Math.round(c.invert(b)))],q()}}var s=d3.select(this);a.utils.initSVG(s);var t=a.utils.availableWidth(g,s,f),u=a.utils.availableHeight(h,s,f);if(b.update=function(){s.call(b)},b.container=this,!p||!p.length)return a.utils.noData(b,s),b;s.selectAll(".nv-noData").remove();var v=e.y()(p[p.length-1],p.length-1);c=e.xScale(),d=e.yScale();var w=s.selectAll("g.nv-wrap.nv-sparklineplus").data([p]),x=w.enter().append("g").attr("class","nvd3 nv-wrap nv-sparklineplus"),y=x.append("g"),z=w.select("g");y.append("g").attr("class","nv-sparklineWrap"),y.append("g").attr("class","nv-valueWrap"),y.append("g").attr("class","nv-hoverArea"),w.attr("transform","translate("+f.left+","+f.top+")");var A=z.select(".nv-sparklineWrap");if(e.width(t).height(u),A.call(e),m){var B=z.select(".nv-valueWrap"),C=B.selectAll(".nv-currentValue").data([v]);C.enter().append("text").attr("class","nv-currentValue").attr("dx",o?-8:8).attr("dy",".9em").style("text-anchor",o?"end":"start"),C.attr("x",t+(o?f.right:0)).attr("y",n?function(a){return d(a)}:0).style("fill",e.color()(p[p.length-1],p.length-1)).text(l(v))}y.select(".nv-hoverArea").append("rect").on("mousemove",r).on("click",function(){j=!j}).on("mouseout",function(){i=[],q()}),z.select(".nv-hoverArea rect").attr("transform",function(){return"translate("+-f.left+","+-f.top+")"}).attr("width",t+f.left+f.right).attr("height",u+f.top)}),b}var c,d,e=a.models.sparkline(),f={top:15,right:100,bottom:10,left:50},g=null,h=null,i=[],j=!1,k=d3.format(",r"),l=d3.format(",.2f"),m=!0,n=!0,o=!1,p=null;return b.sparkline=e,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return g},set:function(a){g=a}},height:{get:function(){return h},set:function(a){h=a}},xTickFormat:{get:function(){return k},set:function(a){k=a}},yTickFormat:{get:function(){return l},set:function(a){l=a}},showLastValue:{get:function(){return m},set:function(a){m=a}},alignValue:{get:function(){return n},set:function(a){n=a}},rightAlignValue:{get:function(){return o},set:function(a){o=a}},noData:{get:function(){return p},set:function(a){p=a}},margin:{get:function(){return f},set:function(a){f.top=void 0!==a.top?a.top:f.top,f.right=void 0!==a.right?a.right:f.right,f.bottom=void 0!==a.bottom?a.bottom:f.bottom,f.left=void 0!==a.left?a.left:f.left}}}),a.utils.inheritOptions(b,e),a.utils.initOptions(b),b},a.models.stackedArea=function(){"use strict";function b(m){return u.reset(),u.models(r),m.each(function(m){var s=f-e.left-e.right,v=g-e.top-e.bottom;j=d3.select(this),a.utils.initSVG(j),c=r.xScale(),d=r.yScale();var w=m;m.forEach(function(a,b){a.seriesIndex=b,a.values=a.values.map(function(a,c){return a.index=c,a.seriesIndex=b,a})});var x=m.filter(function(a){return!a.disabled});m=d3.layout.stack().order(o).offset(n).values(function(a){return a.values}).x(k).y(l).out(function(a,b,c){a.display={y:c,y0:b}})(x);var y=j.selectAll("g.nv-wrap.nv-stackedarea").data([m]),z=y.enter().append("g").attr("class","nvd3 nv-wrap nv-stackedarea"),A=z.append("defs"),B=z.append("g"),C=y.select("g");B.append("g").attr("class","nv-areaWrap"),B.append("g").attr("class","nv-scatterWrap"),y.attr("transform","translate("+e.left+","+e.top+")"),0==r.forceY().length&&r.forceY().push(0),r.width(s).height(v).x(k).y(function(a){return a.display.y+a.display.y0}).forceY([0]).color(m.map(function(a){return a.color||h(a,a.seriesIndex)}));var D=C.select(".nv-scatterWrap").datum(m);D.call(r),A.append("clipPath").attr("id","nv-edge-clip-"+i).append("rect"),y.select("#nv-edge-clip-"+i+" rect").attr("width",s).attr("height",v),C.attr("clip-path",q?"url(#nv-edge-clip-"+i+")":"");var E=d3.svg.area().x(function(a,b){return c(k(a,b))}).y0(function(a){return d(a.display.y0)}).y1(function(a){return d(a.display.y+a.display.y0)}).interpolate(p),F=d3.svg.area().x(function(a,b){return c(k(a,b))}).y0(function(a){return d(a.display.y0)}).y1(function(a){return d(a.display.y0)}),G=C.select(".nv-areaWrap").selectAll("path.nv-area").data(function(a){return a});G.enter().append("path").attr("class",function(a,b){return"nv-area nv-area-"+b}).attr("d",function(a){return F(a.values,a.seriesIndex)}).on("mouseover",function(a){d3.select(this).classed("hover",!0),t.areaMouseover({point:a,series:a.key,pos:[d3.event.pageX,d3.event.pageY],seriesIndex:a.seriesIndex})}).on("mouseout",function(a){d3.select(this).classed("hover",!1),t.areaMouseout({point:a,series:a.key,pos:[d3.event.pageX,d3.event.pageY],seriesIndex:a.seriesIndex})}).on("click",function(a){d3.select(this).classed("hover",!1),t.areaClick({point:a,series:a.key,pos:[d3.event.pageX,d3.event.pageY],seriesIndex:a.seriesIndex})}),G.exit().remove(),G.style("fill",function(a){return a.color||h(a,a.seriesIndex)}).style("stroke",function(a){return a.color||h(a,a.seriesIndex)}),G.watchTransition(u,"stackedArea path").attr("d",function(a,b){return E(a.values,b)}),r.dispatch.on("elementMouseover.area",function(a){C.select(".nv-chart-"+i+" .nv-area-"+a.seriesIndex).classed("hover",!0)}),r.dispatch.on("elementMouseout.area",function(a){C.select(".nv-chart-"+i+" .nv-area-"+a.seriesIndex).classed("hover",!1)}),b.d3_stackedOffset_stackPercent=function(a){var b,c,d,e=a.length,f=a[0].length,g=[];for(c=0;f>c;++c){for(b=0,d=0;b<w.length;b++)d+=l(w[b].values[c]);if(d)for(b=0;e>b;b++)a[b][c][1]/=d;else for(b=0;e>b;b++)a[b][c][1]=0}for(c=0;f>c;++c)g[c]=0;return g}}),u.renderEnd("stackedArea immediate"),b}var c,d,e={top:0,right:0,bottom:0,left:0},f=960,g=500,h=a.utils.defaultColor(),i=Math.floor(1e5*Math.random()),j=null,k=function(a){return a.x},l=function(a){return a.y},m="stack",n="zero",o="default",p="linear",q=!1,r=a.models.scatter(),s=250,t=d3.dispatch("areaClick","areaMouseover","areaMouseout","renderEnd","elementClick","elementMouseover","elementMouseout");r.pointSize(2.2).pointDomain([2.2,2.2]);var u=a.utils.renderWatch(t,s);return b.dispatch=t,b.scatter=r,r.dispatch.on("elementClick",function(){t.elementClick.apply(this,arguments)}),r.dispatch.on("elementMouseover",function(){t.elementMouseover.apply(this,arguments)}),r.dispatch.on("elementMouseout",function(){t.elementMouseout.apply(this,arguments)}),b.interpolate=function(a){return arguments.length?(p=a,b):p},b.duration=function(a){return arguments.length?(s=a,u.reset(s),r.duration(s),b):s},b.dispatch=t,b.scatter=r,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return f},set:function(a){f=a}},height:{get:function(){return g},set:function(a){g=a}},clipEdge:{get:function(){return q},set:function(a){q=a}},offset:{get:function(){return n},set:function(a){n=a}},order:{get:function(){return o},set:function(a){o=a}},interpolate:{get:function(){return p},set:function(a){p=a}},x:{get:function(){return k},set:function(a){k=d3.functor(a)}},y:{get:function(){return l},set:function(a){l=d3.functor(a)}},margin:{get:function(){return e},set:function(a){e.top=void 0!==a.top?a.top:e.top,e.right=void 0!==a.right?a.right:e.right,e.bottom=void 0!==a.bottom?a.bottom:e.bottom,e.left=void 0!==a.left?a.left:e.left}},color:{get:function(){return h},set:function(b){h=a.utils.getColor(b)}},style:{get:function(){return m},set:function(a){switch(m=a){case"stack":b.offset("zero"),b.order("default");break;case"stream":b.offset("wiggle"),b.order("inside-out");break;case"stream-center":b.offset("silhouette"),b.order("inside-out");break;case"expand":b.offset("expand"),b.order("default");break;case"stack_percent":b.offset(b.d3_stackedOffset_stackPercent),b.order("default")}}},duration:{get:function(){return s},set:function(a){s=a,u.reset(s),r.duration(s)}}}),a.utils.inheritOptions(b,r),a.utils.initOptions(b),b},a.models.stackedAreaChart=function(){"use strict";function b(k){return F.reset(),F.models(e),r&&F.models(f),s&&F.models(g),k.each(function(k){var x=d3.select(this),F=this;a.utils.initSVG(x);var K=a.utils.availableWidth(m,x,l),L=a.utils.availableHeight(n,x,l);if(b.update=function(){x.transition().duration(C).call(b)},b.container=this,v.setter(I(k),b.update).getter(H(k)).update(),v.disabled=k.map(function(a){return!!a.disabled}),!w){var M;w={};for(M in v)w[M]=v[M]instanceof Array?v[M].slice(0):v[M]}if(!(k&&k.length&&k.filter(function(a){return a.values.length}).length))return a.utils.noData(b,x),b;x.selectAll(".nv-noData").remove(),c=e.xScale(),d=e.yScale();var N=x.selectAll("g.nv-wrap.nv-stackedAreaChart").data([k]),O=N.enter().append("g").attr("class","nvd3 nv-wrap nv-stackedAreaChart").append("g"),P=N.select("g");if(O.append("rect").style("opacity",0),O.append("g").attr("class","nv-x nv-axis"),O.append("g").attr("class","nv-y nv-axis"),O.append("g").attr("class","nv-stackedWrap"),O.append("g").attr("class","nv-legendWrap"),O.append("g").attr("class","nv-controlsWrap"),O.append("g").attr("class","nv-interactive"),P.select("rect").attr("width",K).attr("height",L),q){var Q=p?K-z:K;h.width(Q),P.select(".nv-legendWrap").datum(k).call(h),l.top!=h.height()&&(l.top=h.height(),L=a.utils.availableHeight(n,x,l)),P.select(".nv-legendWrap").attr("transform","translate("+(K-Q)+","+-l.top+")")}if(p){var R=[{key:B.stacked||"Stacked",metaKey:"Stacked",disabled:"stack"!=e.style(),style:"stack"},{key:B.stream||"Stream",metaKey:"Stream",disabled:"stream"!=e.style(),style:"stream"},{key:B.expanded||"Expanded",metaKey:"Expanded",disabled:"expand"!=e.style(),style:"expand"},{key:B.stack_percent||"Stack %",metaKey:"Stack_Percent",disabled:"stack_percent"!=e.style(),style:"stack_percent"}];z=A.length/3*260,R=R.filter(function(a){return-1!==A.indexOf(a.metaKey)}),i.width(z).color(["#444","#444","#444"]),P.select(".nv-controlsWrap").datum(R).call(i),l.top!=Math.max(i.height(),h.height())&&(l.top=Math.max(i.height(),h.height()),L=a.utils.availableHeight(n,x,l)),P.select(".nv-controlsWrap").attr("transform","translate(0,"+-l.top+")")}N.attr("transform","translate("+l.left+","+l.top+")"),t&&P.select(".nv-y.nv-axis").attr("transform","translate("+K+",0)"),u&&(j.width(K).height(L).margin({left:l.left,top:l.top}).svgContainer(x).xScale(c),N.select(".nv-interactive").call(j)),e.width(K).height(L);var S=P.select(".nv-stackedWrap").datum(k);if(S.transition().call(e),r&&(f.scale(c)._ticks(a.utils.calcTicksX(K/100,k)).tickSize(-L,0),P.select(".nv-x.nv-axis").attr("transform","translate(0,"+L+")"),P.select(".nv-x.nv-axis").transition().duration(0).call(f)),s){var T;if(T="wiggle"===e.offset()?0:a.utils.calcTicksY(L/36,k),g.scale(d)._ticks(T).tickSize(-K,0),"expand"===e.style()||"stack_percent"===e.style()){var U=g.tickFormat();D&&U===J||(D=U),g.tickFormat(J)}else D&&(g.tickFormat(D),D=null);P.select(".nv-y.nv-axis").transition().duration(0).call(g)}e.dispatch.on("areaClick.toggle",function(a){k.forEach(1===k.filter(function(a){return!a.disabled}).length?function(a){a.disabled=!1}:function(b,c){b.disabled=c!=a.seriesIndex}),v.disabled=k.map(function(a){return!!a.disabled}),y.stateChange(v),b.update()}),h.dispatch.on("stateChange",function(a){for(var c in a)v[c]=a[c];y.stateChange(v),b.update()}),i.dispatch.on("legendClick",function(a){a.disabled&&(R=R.map(function(a){return a.disabled=!0,a}),a.disabled=!1,e.style(a.style),v.style=e.style(),y.stateChange(v),b.update())}),j.dispatch.on("elementMousemove",function(c){e.clearHighlights();var d,g,h,i=[];if(k.filter(function(a,b){return a.seriesIndex=b,!a.disabled}).forEach(function(f,j){g=a.interactiveBisect(f.values,c.pointXValue,b.x());var k=f.values[g],l=b.y()(k,g);if(null!=l&&e.highlightPoint(j,g,!0),"undefined"!=typeof k){"undefined"==typeof d&&(d=k),"undefined"==typeof h&&(h=b.xScale()(b.x()(k,g)));var m="expand"==e.style()?k.display.y:b.y()(k,g);i.push({key:f.key,value:m,color:o(f,f.seriesIndex),stackedValue:k.display})}}),i.reverse(),i.length>2){var m=b.yScale().invert(c.mouseY),n=null;i.forEach(function(a,b){m=Math.abs(m);var c=Math.abs(a.stackedValue.y0),d=Math.abs(a.stackedValue.y);return m>=c&&d+c>=m?void(n=b):void 0}),null!=n&&(i[n].highlight=!0)}var p=f.tickFormat()(b.x()(d,g)),q=j.tooltip.valueFormatter();"expand"===e.style()||"stack_percent"===e.style()?(E||(E=q),q=d3.format(".1%")):E&&(q=E,E=null),j.tooltip.position({left:h+l.left,top:c.mouseY+l.top}).chartContainer(F.parentNode).valueFormatter(q).data({value:p,series:i})(),j.renderGuideLine(h)}),j.dispatch.on("elementMouseout",function(){e.clearHighlights()}),y.on("changeState",function(a){"undefined"!=typeof a.disabled&&k.length===a.disabled.length&&(k.forEach(function(b,c){b.disabled=a.disabled[c]}),v.disabled=a.disabled),"undefined"!=typeof a.style&&(e.style(a.style),G=a.style),b.update()})}),F.renderEnd("stacked Area chart immediate"),b}var c,d,e=a.models.stackedArea(),f=a.models.axis(),g=a.models.axis(),h=a.models.legend(),i=a.models.legend(),j=a.interactiveGuideline(),k=a.models.tooltip(),l={top:30,right:25,bottom:50,left:60},m=null,n=null,o=a.utils.defaultColor(),p=!0,q=!0,r=!0,s=!0,t=!1,u=!1,v=a.utils.state(),w=null,x=null,y=d3.dispatch("stateChange","changeState","renderEnd"),z=250,A=["Stacked","Stream","Expanded"],B={},C=250;v.style=e.style(),f.orient("bottom").tickPadding(7),g.orient(t?"right":"left"),k.headerFormatter(function(a,b){return f.tickFormat()(a,b)}).valueFormatter(function(a,b){return g.tickFormat()(a,b)}),j.tooltip.headerFormatter(function(a,b){return f.tickFormat()(a,b)}).valueFormatter(function(a,b){return g.tickFormat()(a,b)});var D=null,E=null;i.updateState(!1);var F=a.utils.renderWatch(y),G=e.style(),H=function(a){return function(){return{active:a.map(function(a){return!a.disabled}),style:e.style()}}},I=function(a){return function(b){void 0!==b.style&&(G=b.style),void 0!==b.active&&a.forEach(function(a,c){a.disabled=!b.active[c]})}},J=d3.format("%");return e.dispatch.on("elementMouseover.tooltip",function(a){a.point.x=e.x()(a.point),a.point.y=e.y()(a.point),k.data(a).position(a.pos).hidden(!1)}),e.dispatch.on("elementMouseout.tooltip",function(){k.hidden(!0)}),b.dispatch=y,b.stacked=e,b.legend=h,b.controls=i,b.xAxis=f,b.yAxis=g,b.interactiveLayer=j,b.tooltip=k,b.dispatch=y,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return m},set:function(a){m=a}},height:{get:function(){return n},set:function(a){n=a}},showLegend:{get:function(){return q},set:function(a){q=a}},showXAxis:{get:function(){return r},set:function(a){r=a}},showYAxis:{get:function(){return s},set:function(a){s=a}},defaultState:{get:function(){return w},set:function(a){w=a}},noData:{get:function(){return x},set:function(a){x=a}},showControls:{get:function(){return p},set:function(a){p=a}},controlLabels:{get:function(){return B},set:function(a){B=a}},controlOptions:{get:function(){return A},set:function(a){A=a}},tooltips:{get:function(){return k.enabled()},set:function(b){a.deprecated("tooltips","use chart.tooltip.enabled() instead"),k.enabled(!!b)}},tooltipContent:{get:function(){return k.contentGenerator()},set:function(b){a.deprecated("tooltipContent","use chart.tooltip.contentGenerator() instead"),k.contentGenerator(b)}},margin:{get:function(){return l},set:function(a){l.top=void 0!==a.top?a.top:l.top,l.right=void 0!==a.right?a.right:l.right,l.bottom=void 0!==a.bottom?a.bottom:l.bottom,l.left=void 0!==a.left?a.left:l.left}},duration:{get:function(){return C},set:function(a){C=a,F.reset(C),e.duration(C),f.duration(C),g.duration(C)}},color:{get:function(){return o},set:function(b){o=a.utils.getColor(b),h.color(o),e.color(o)}},rightAlignYAxis:{get:function(){return t},set:function(a){t=a,g.orient(t?"right":"left")}},useInteractiveGuideline:{get:function(){return u},set:function(a){u=!!a,b.interactive(!a),b.useVoronoi(!a),e.scatter.interactive(!a)}}}),a.utils.inheritOptions(b,e),a.utils.initOptions(b),b},a.models.sunburst=function(){"use strict";function b(u){return t.reset(),u.each(function(b){function t(a){a.x0=a.x,a.dx0=a.dx}function u(a){var b=d3.interpolate(p.domain(),[a.x,a.x+a.dx]),c=d3.interpolate(q.domain(),[a.y,1]),d=d3.interpolate(q.range(),[a.y?20:0,y]);return function(a,e){return e?function(){return s(a)}:function(e){return p.domain(b(e)),q.domain(c(e)).range(d(e)),s(a)}}}l=d3.select(this);var v,w=a.utils.availableWidth(g,l,f),x=a.utils.availableHeight(h,l,f),y=Math.min(w,x)/2;a.utils.initSVG(l);var z=l.selectAll(".nv-wrap.nv-sunburst").data(b),A=z.enter().append("g").attr("class","nvd3 nv-wrap nv-sunburst nv-chart-"+k),B=A.selectAll("nv-sunburst");z.attr("transform","translate("+w/2+","+x/2+")"),l.on("click",function(a,b){o.chartClick({data:a,index:b,pos:d3.event,id:k})}),q.range([0,y]),c=c||b,e=b[0],r.value(j[i]||j.count),v=B.data(r.nodes).enter().append("path").attr("d",s).style("fill",function(a){return m((a.children?a:a.parent).name)}).style("stroke","#FFF").on("click",function(a){d!==c&&c!==a&&(d=c),c=a,v.transition().duration(n).attrTween("d",u(a))}).each(t).on("dblclick",function(a){d.parent==a&&v.transition().duration(n).attrTween("d",u(e))}).each(t).on("mouseover",function(a){d3.select(this).classed("hover",!0).style("opacity",.8),o.elementMouseover({data:a,color:d3.select(this).style("fill")})}).on("mouseout",function(a){d3.select(this).classed("hover",!1).style("opacity",1),o.elementMouseout({data:a})}).on("mousemove",function(a){o.elementMousemove({data:a})})}),t.renderEnd("sunburst immediate"),b}var c,d,e,f={top:0,right:0,bottom:0,left:0},g=null,h=null,i="count",j={count:function(){return 1},size:function(a){return a.size}},k=Math.floor(1e4*Math.random()),l=null,m=a.utils.defaultColor(),n=500,o=d3.dispatch("chartClick","elementClick","elementDblClick","elementMousemove","elementMouseover","elementMouseout","renderEnd"),p=d3.scale.linear().range([0,2*Math.PI]),q=d3.scale.sqrt(),r=d3.layout.partition().sort(null).value(function(){return 1}),s=d3.svg.arc().startAngle(function(a){return Math.max(0,Math.min(2*Math.PI,p(a.x)))}).endAngle(function(a){return Math.max(0,Math.min(2*Math.PI,p(a.x+a.dx)))}).innerRadius(function(a){return Math.max(0,q(a.y))}).outerRadius(function(a){return Math.max(0,q(a.y+a.dy))}),t=a.utils.renderWatch(o);return b.dispatch=o,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return g},set:function(a){g=a}},height:{get:function(){return h},set:function(a){h=a}},mode:{get:function(){return i},set:function(a){i=a}},id:{get:function(){return k},set:function(a){k=a}},duration:{get:function(){return n},set:function(a){n=a}},margin:{get:function(){return f},set:function(a){f.top=void 0!=a.top?a.top:f.top,f.right=void 0!=a.right?a.right:f.right,f.bottom=void 0!=a.bottom?a.bottom:f.bottom,f.left=void 0!=a.left?a.left:f.left}},color:{get:function(){return m},set:function(b){m=a.utils.getColor(b)}}}),a.utils.initOptions(b),b},a.models.sunburstChart=function(){"use strict";function b(d){return m.reset(),m.models(c),d.each(function(d){var h=d3.select(this);a.utils.initSVG(h);var i=a.utils.availableWidth(f,h,e),j=a.utils.availableHeight(g,h,e);if(b.update=function(){0===k?h.call(b):h.transition().duration(k).call(b)},b.container=this,!d||!d.length)return a.utils.noData(b,h),b;h.selectAll(".nv-noData").remove();var l=h.selectAll("g.nv-wrap.nv-sunburstChart").data(d),m=l.enter().append("g").attr("class","nvd3 nv-wrap nv-sunburstChart").append("g"),n=l.select("g");m.append("g").attr("class","nv-sunburstWrap"),l.attr("transform","translate("+e.left+","+e.top+")"),c.width(i).height(j);var o=n.select(".nv-sunburstWrap").datum(d);d3.transition(o).call(c)}),m.renderEnd("sunburstChart immediate"),b}var c=a.models.sunburst(),d=a.models.tooltip(),e={top:30,right:20,bottom:20,left:20},f=null,g=null,h=a.utils.defaultColor(),i=(Math.round(1e5*Math.random()),null),j=null,k=250,l=d3.dispatch("tooltipShow","tooltipHide","stateChange","changeState","renderEnd"),m=a.utils.renderWatch(l);return d.headerEnabled(!1).duration(0).valueFormatter(function(a){return a}),c.dispatch.on("elementMouseover.tooltip",function(a){a.series={key:a.data.name,value:a.data.size,color:a.color},d.data(a).hidden(!1)}),c.dispatch.on("elementMouseout.tooltip",function(){d.hidden(!0)}),c.dispatch.on("elementMousemove.tooltip",function(){d.position({top:d3.event.pageY,left:d3.event.pageX})()}),b.dispatch=l,b.sunburst=c,b.tooltip=d,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{noData:{get:function(){return j},set:function(a){j=a}},defaultState:{get:function(){return i},set:function(a){i=a}},color:{get:function(){return h},set:function(a){h=a,c.color(h)}},duration:{get:function(){return k},set:function(a){k=a,m.reset(k),c.duration(k)}},margin:{get:function(){return e},set:function(a){e.top=void 0!==a.top?a.top:e.top,e.right=void 0!==a.right?a.right:e.right,e.bottom=void 0!==a.bottom?a.bottom:e.bottom,e.left=void 0!==a.left?a.left:e.left}}}),a.utils.inheritOptions(b,c),a.utils.initOptions(b),b},a.version="1.8.1"}(); $(function() {
  22805. var $window = $(window)
  22806. , $top_link = $('#toplink')
  22807. , $body = $('body, html')
  22808. , offset = $('#code').offset().top
  22809. , hidePopover = function ($target) {
  22810. $target.data('popover-hover', false);
  22811. setTimeout(function () {
  22812. if (!$target.data('popover-hover')) {
  22813. $target.popover('hide');
  22814. }
  22815. }, 300);
  22816. };
  22817. $top_link.hide().click(function(event) {
  22818. event.preventDefault();
  22819. $body.animate({scrollTop:0}, 800);
  22820. });
  22821. $window.scroll(function() {
  22822. if($window.scrollTop() > offset) {
  22823. $top_link.fadeIn();
  22824. } else {
  22825. $top_link.fadeOut();
  22826. }
  22827. }).scroll();
  22828. $('.popin')
  22829. .popover({trigger: 'manual'})
  22830. .on({
  22831. 'mouseenter.popover': function () {
  22832. var $target = $(this);
  22833. var $container = $target.children().first();
  22834. $target.data('popover-hover', true);
  22835. // popover already displayed
  22836. if ($target.next('.popover').length) {
  22837. return;
  22838. }
  22839. // show the popover
  22840. $container.popover('show');
  22841. // register mouse events on the popover
  22842. $target.next('.popover:not(.popover-initialized)')
  22843. .on({
  22844. 'mouseenter': function () {
  22845. $target.data('popover-hover', true);
  22846. },
  22847. 'mouseleave': function () {
  22848. hidePopover($container);
  22849. }
  22850. })
  22851. .addClass('popover-initialized');
  22852. },
  22853. 'mouseleave.popover': function () {
  22854. hidePopover($(this).children().first());
  22855. }
  22856. });
  22857. });
  22858. !function(){function n(n){return n&&(n.ownerDocument||n.document||n).documentElement}function t(n){return n&&(n.ownerDocument&&n.ownerDocument.defaultView||n.document&&n||n.defaultView)}function e(n,t){return t>n?-1:n>t?1:n>=t?0:NaN}function r(n){return null===n?NaN:+n}function i(n){return!isNaN(n)}function u(n){return{left:function(t,e,r,i){for(arguments.length<3&&(r=0),arguments.length<4&&(i=t.length);i>r;){var u=r+i>>>1;n(t[u],e)<0?r=u+1:i=u}return r},right:function(t,e,r,i){for(arguments.length<3&&(r=0),arguments.length<4&&(i=t.length);i>r;){var u=r+i>>>1;n(t[u],e)>0?i=u:r=u+1}return r}}}function o(n){return n.length}function a(n){for(var t=1;n*t%1;)t*=10;return t}function l(n,t){for(var e in t)Object.defineProperty(n.prototype,e,{value:t[e],enumerable:!1})}function c(){this._=Object.create(null)}function f(n){return(n+="")===bo||n[0]===_o?_o+n:n}function s(n){return(n+="")[0]===_o?n.slice(1):n}function h(n){return f(n)in this._}function p(n){return(n=f(n))in this._&&delete this._[n]}function g(){var n=[];for(var t in this._)n.push(s(t));return n}function v(){var n=0;for(var t in this._)++n;return n}function d(){for(var n in this._)return!1;return!0}function y(){this._=Object.create(null)}function m(n){return n}function M(n,t,e){return function(){var r=e.apply(t,arguments);return r===t?n:r}}function x(n,t){if(t in n)return t;t=t.charAt(0).toUpperCase()+t.slice(1);for(var e=0,r=wo.length;r>e;++e){var i=wo[e]+t;if(i in n)return i}}function b(){}function _(){}function w(n){function t(){for(var t,r=e,i=-1,u=r.length;++i<u;)(t=r[i].on)&&t.apply(this,arguments);return n}var e=[],r=new c;return t.on=function(t,i){var u,o=r.get(t);return arguments.length<2?o&&o.on:(o&&(o.on=null,e=e.slice(0,u=e.indexOf(o)).concat(e.slice(u+1)),r.remove(t)),i&&e.push(r.set(t,{on:i})),n)},t}function S(){ao.event.preventDefault()}function k(){for(var n,t=ao.event;n=t.sourceEvent;)t=n;return t}function N(n){for(var t=new _,e=0,r=arguments.length;++e<r;)t[arguments[e]]=w(t);return t.of=function(e,r){return function(i){try{var u=i.sourceEvent=ao.event;i.target=n,ao.event=i,t[i.type].apply(e,r)}finally{ao.event=u}}},t}function E(n){return ko(n,Co),n}function A(n){return"function"==typeof n?n:function(){return No(n,this)}}function C(n){return"function"==typeof n?n:function(){return Eo(n,this)}}function z(n,t){function e(){this.removeAttribute(n)}function r(){this.removeAttributeNS(n.space,n.local)}function i(){this.setAttribute(n,t)}function u(){this.setAttributeNS(n.space,n.local,t)}function o(){var e=t.apply(this,arguments);null==e?this.removeAttribute(n):this.setAttribute(n,e)}function a(){var e=t.apply(this,arguments);null==e?this.removeAttributeNS(n.space,n.local):this.setAttributeNS(n.space,n.local,e)}return n=ao.ns.qualify(n),null==t?n.local?r:e:"function"==typeof t?n.local?a:o:n.local?u:i}function L(n){return n.trim().replace(/\s+/g," ")}function q(n){return new RegExp("(?:^|\\s+)"+ao.requote(n)+"(?:\\s+|$)","g")}function T(n){return(n+"").trim().split(/^|\s+/)}function R(n,t){function e(){for(var e=-1;++e<i;)n[e](this,t)}function r(){for(var e=-1,r=t.apply(this,arguments);++e<i;)n[e](this,r)}n=T(n).map(D);var i=n.length;return"function"==typeof t?r:e}function D(n){var t=q(n);return function(e,r){if(i=e.classList)return r?i.add(n):i.remove(n);var i=e.getAttribute("class")||"";r?(t.lastIndex=0,t.test(i)||e.setAttribute("class",L(i+" "+n))):e.setAttribute("class",L(i.replace(t," ")))}}function P(n,t,e){function r(){this.style.removeProperty(n)}function i(){this.style.setProperty(n,t,e)}function u(){var r=t.apply(this,arguments);null==r?this.style.removeProperty(n):this.style.setProperty(n,r,e)}return null==t?r:"function"==typeof t?u:i}function U(n,t){function e(){delete this[n]}function r(){this[n]=t}function i(){var e=t.apply(this,arguments);null==e?delete this[n]:this[n]=e}return null==t?e:"function"==typeof t?i:r}function j(n){function t(){var t=this.ownerDocument,e=this.namespaceURI;return e===zo&&t.documentElement.namespaceURI===zo?t.createElement(n):t.createElementNS(e,n)}function e(){return this.ownerDocument.createElementNS(n.space,n.local)}return"function"==typeof n?n:(n=ao.ns.qualify(n)).local?e:t}function F(){var n=this.parentNode;n&&n.removeChild(this)}function H(n){return{__data__:n}}function O(n){return function(){return Ao(this,n)}}function I(n){return arguments.length||(n=e),function(t,e){return t&&e?n(t.__data__,e.__data__):!t-!e}}function Y(n,t){for(var e=0,r=n.length;r>e;e++)for(var i,u=n[e],o=0,a=u.length;a>o;o++)(i=u[o])&&t(i,o,e);return n}function Z(n){return ko(n,qo),n}function V(n){var t,e;return function(r,i,u){var o,a=n[u].update,l=a.length;for(u!=e&&(e=u,t=0),i>=t&&(t=i+1);!(o=a[t])&&++t<l;);return o}}function X(n,t,e){function r(){var t=this[o];t&&(this.removeEventListener(n,t,t.$),delete this[o])}function i(){var i=l(t,co(arguments));r.call(this),this.addEventListener(n,this[o]=i,i.$=e),i._=t}function u(){var t,e=new RegExp("^__on([^.]+)"+ao.requote(n)+"$");for(var r in this)if(t=r.match(e)){var i=this[r];this.removeEventListener(t[1],i,i.$),delete this[r]}}var o="__on"+n,a=n.indexOf("."),l=$;a>0&&(n=n.slice(0,a));var c=To.get(n);return c&&(n=c,l=B),a?t?i:r:t?b:u}function $(n,t){return function(e){var r=ao.event;ao.event=e,t[0]=this.__data__;try{n.apply(this,t)}finally{ao.event=r}}}function B(n,t){var e=$(n,t);return function(n){var t=this,r=n.relatedTarget;r&&(r===t||8&r.compareDocumentPosition(t))||e.call(t,n)}}function W(e){var r=".dragsuppress-"+ ++Do,i="click"+r,u=ao.select(t(e)).on("touchmove"+r,S).on("dragstart"+r,S).on("selectstart"+r,S);if(null==Ro&&(Ro="onselectstart"in e?!1:x(e.style,"userSelect")),Ro){var o=n(e).style,a=o[Ro];o[Ro]="none"}return function(n){if(u.on(r,null),Ro&&(o[Ro]=a),n){var t=function(){u.on(i,null)};u.on(i,function(){S(),t()},!0),setTimeout(t,0)}}}function J(n,e){e.changedTouches&&(e=e.changedTouches[0]);var r=n.ownerSVGElement||n;if(r.createSVGPoint){var i=r.createSVGPoint();if(0>Po){var u=t(n);if(u.scrollX||u.scrollY){r=ao.select("body").append("svg").style({position:"absolute",top:0,left:0,margin:0,padding:0,border:"none"},"important");var o=r[0][0].getScreenCTM();Po=!(o.f||o.e),r.remove()}}return Po?(i.x=e.pageX,i.y=e.pageY):(i.x=e.clientX,i.y=e.clientY),i=i.matrixTransform(n.getScreenCTM().inverse()),[i.x,i.y]}var a=n.getBoundingClientRect();return[e.clientX-a.left-n.clientLeft,e.clientY-a.top-n.clientTop]}function G(){return ao.event.changedTouches[0].identifier}function K(n){return n>0?1:0>n?-1:0}function Q(n,t,e){return(t[0]-n[0])*(e[1]-n[1])-(t[1]-n[1])*(e[0]-n[0])}function nn(n){return n>1?0:-1>n?Fo:Math.acos(n)}function tn(n){return n>1?Io:-1>n?-Io:Math.asin(n)}function en(n){return((n=Math.exp(n))-1/n)/2}function rn(n){return((n=Math.exp(n))+1/n)/2}function un(n){return((n=Math.exp(2*n))-1)/(n+1)}function on(n){return(n=Math.sin(n/2))*n}function an(){}function ln(n,t,e){return this instanceof ln?(this.h=+n,this.s=+t,void(this.l=+e)):arguments.length<2?n instanceof ln?new ln(n.h,n.s,n.l):_n(""+n,wn,ln):new ln(n,t,e)}function cn(n,t,e){function r(n){return n>360?n-=360:0>n&&(n+=360),60>n?u+(o-u)*n/60:180>n?o:240>n?u+(o-u)*(240-n)/60:u}function i(n){return Math.round(255*r(n))}var u,o;return n=isNaN(n)?0:(n%=360)<0?n+360:n,t=isNaN(t)?0:0>t?0:t>1?1:t,e=0>e?0:e>1?1:e,o=.5>=e?e*(1+t):e+t-e*t,u=2*e-o,new mn(i(n+120),i(n),i(n-120))}function fn(n,t,e){return this instanceof fn?(this.h=+n,this.c=+t,void(this.l=+e)):arguments.length<2?n instanceof fn?new fn(n.h,n.c,n.l):n instanceof hn?gn(n.l,n.a,n.b):gn((n=Sn((n=ao.rgb(n)).r,n.g,n.b)).l,n.a,n.b):new fn(n,t,e)}function sn(n,t,e){return isNaN(n)&&(n=0),isNaN(t)&&(t=0),new hn(e,Math.cos(n*=Yo)*t,Math.sin(n)*t)}function hn(n,t,e){return this instanceof hn?(this.l=+n,this.a=+t,void(this.b=+e)):arguments.length<2?n instanceof hn?new hn(n.l,n.a,n.b):n instanceof fn?sn(n.h,n.c,n.l):Sn((n=mn(n)).r,n.g,n.b):new hn(n,t,e)}function pn(n,t,e){var r=(n+16)/116,i=r+t/500,u=r-e/200;return i=vn(i)*na,r=vn(r)*ta,u=vn(u)*ea,new mn(yn(3.2404542*i-1.5371385*r-.4985314*u),yn(-.969266*i+1.8760108*r+.041556*u),yn(.0556434*i-.2040259*r+1.0572252*u))}function gn(n,t,e){return n>0?new fn(Math.atan2(e,t)*Zo,Math.sqrt(t*t+e*e),n):new fn(NaN,NaN,n)}function vn(n){return n>.206893034?n*n*n:(n-4/29)/7.787037}function dn(n){return n>.008856?Math.pow(n,1/3):7.787037*n+4/29}function yn(n){return Math.round(255*(.00304>=n?12.92*n:1.055*Math.pow(n,1/2.4)-.055))}function mn(n,t,e){return this instanceof mn?(this.r=~~n,this.g=~~t,void(this.b=~~e)):arguments.length<2?n instanceof mn?new mn(n.r,n.g,n.b):_n(""+n,mn,cn):new mn(n,t,e)}function Mn(n){return new mn(n>>16,n>>8&255,255&n)}function xn(n){return Mn(n)+""}function bn(n){return 16>n?"0"+Math.max(0,n).toString(16):Math.min(255,n).toString(16)}function _n(n,t,e){var r,i,u,o=0,a=0,l=0;if(r=/([a-z]+)\((.*)\)/.exec(n=n.toLowerCase()))switch(i=r[2].split(","),r[1]){case"hsl":return e(parseFloat(i[0]),parseFloat(i[1])/100,parseFloat(i[2])/100);case"rgb":return t(Nn(i[0]),Nn(i[1]),Nn(i[2]))}return(u=ua.get(n))?t(u.r,u.g,u.b):(null==n||"#"!==n.charAt(0)||isNaN(u=parseInt(n.slice(1),16))||(4===n.length?(o=(3840&u)>>4,o=o>>4|o,a=240&u,a=a>>4|a,l=15&u,l=l<<4|l):7===n.length&&(o=(16711680&u)>>16,a=(65280&u)>>8,l=255&u)),t(o,a,l))}function wn(n,t,e){var r,i,u=Math.min(n/=255,t/=255,e/=255),o=Math.max(n,t,e),a=o-u,l=(o+u)/2;return a?(i=.5>l?a/(o+u):a/(2-o-u),r=n==o?(t-e)/a+(e>t?6:0):t==o?(e-n)/a+2:(n-t)/a+4,r*=60):(r=NaN,i=l>0&&1>l?0:r),new ln(r,i,l)}function Sn(n,t,e){n=kn(n),t=kn(t),e=kn(e);var r=dn((.4124564*n+.3575761*t+.1804375*e)/na),i=dn((.2126729*n+.7151522*t+.072175*e)/ta),u=dn((.0193339*n+.119192*t+.9503041*e)/ea);return hn(116*i-16,500*(r-i),200*(i-u))}function kn(n){return(n/=255)<=.04045?n/12.92:Math.pow((n+.055)/1.055,2.4)}function Nn(n){var t=parseFloat(n);return"%"===n.charAt(n.length-1)?Math.round(2.55*t):t}function En(n){return"function"==typeof n?n:function(){return n}}function An(n){return function(t,e,r){return 2===arguments.length&&"function"==typeof e&&(r=e,e=null),Cn(t,e,n,r)}}function Cn(n,t,e,r){function i(){var n,t=l.status;if(!t&&Ln(l)||t>=200&&300>t||304===t){try{n=e.call(u,l)}catch(r){return void o.error.call(u,r)}o.load.call(u,n)}else o.error.call(u,l)}var u={},o=ao.dispatch("beforesend","progress","load","error"),a={},l=new XMLHttpRequest,c=null;return!this.XDomainRequest||"withCredentials"in l||!/^(http(s)?:)?\/\//.test(n)||(l=new XDomainRequest),"onload"in l?l.onload=l.onerror=i:l.onreadystatechange=function(){l.readyState>3&&i()},l.onprogress=function(n){var t=ao.event;ao.event=n;try{o.progress.call(u,l)}finally{ao.event=t}},u.header=function(n,t){return n=(n+"").toLowerCase(),arguments.length<2?a[n]:(null==t?delete a[n]:a[n]=t+"",u)},u.mimeType=function(n){return arguments.length?(t=null==n?null:n+"",u):t},u.responseType=function(n){return arguments.length?(c=n,u):c},u.response=function(n){return e=n,u},["get","post"].forEach(function(n){u[n]=function(){return u.send.apply(u,[n].concat(co(arguments)))}}),u.send=function(e,r,i){if(2===arguments.length&&"function"==typeof r&&(i=r,r=null),l.open(e,n,!0),null==t||"accept"in a||(a.accept=t+",*/*"),l.setRequestHeader)for(var f in a)l.setRequestHeader(f,a[f]);return null!=t&&l.overrideMimeType&&l.overrideMimeType(t),null!=c&&(l.responseType=c),null!=i&&u.on("error",i).on("load",function(n){i(null,n)}),o.beforesend.call(u,l),l.send(null==r?null:r),u},u.abort=function(){return l.abort(),u},ao.rebind(u,o,"on"),null==r?u:u.get(zn(r))}function zn(n){return 1===n.length?function(t,e){n(null==t?e:null)}:n}function Ln(n){var t=n.responseType;return t&&"text"!==t?n.response:n.responseText}function qn(n,t,e){var r=arguments.length;2>r&&(t=0),3>r&&(e=Date.now());var i=e+t,u={c:n,t:i,n:null};return aa?aa.n=u:oa=u,aa=u,la||(ca=clearTimeout(ca),la=1,fa(Tn)),u}function Tn(){var n=Rn(),t=Dn()-n;t>24?(isFinite(t)&&(clearTimeout(ca),ca=setTimeout(Tn,t)),la=0):(la=1,fa(Tn))}function Rn(){for(var n=Date.now(),t=oa;t;)n>=t.t&&t.c(n-t.t)&&(t.c=null),t=t.n;return n}function Dn(){for(var n,t=oa,e=1/0;t;)t.c?(t.t<e&&(e=t.t),t=(n=t).n):t=n?n.n=t.n:oa=t.n;return aa=n,e}function Pn(n,t){return t-(n?Math.ceil(Math.log(n)/Math.LN10):1)}function Un(n,t){var e=Math.pow(10,3*xo(8-t));return{scale:t>8?function(n){return n/e}:function(n){return n*e},symbol:n}}function jn(n){var t=n.decimal,e=n.thousands,r=n.grouping,i=n.currency,u=r&&e?function(n,t){for(var i=n.length,u=[],o=0,a=r[0],l=0;i>0&&a>0&&(l+a+1>t&&(a=Math.max(1,t-l)),u.push(n.substring(i-=a,i+a)),!((l+=a+1)>t));)a=r[o=(o+1)%r.length];return u.reverse().join(e)}:m;return function(n){var e=ha.exec(n),r=e[1]||" ",o=e[2]||">",a=e[3]||"-",l=e[4]||"",c=e[5],f=+e[6],s=e[7],h=e[8],p=e[9],g=1,v="",d="",y=!1,m=!0;switch(h&&(h=+h.substring(1)),(c||"0"===r&&"="===o)&&(c=r="0",o="="),p){case"n":s=!0,p="g";break;case"%":g=100,d="%",p="f";break;case"p":g=100,d="%",p="r";break;case"b":case"o":case"x":case"X":"#"===l&&(v="0"+p.toLowerCase());case"c":m=!1;case"d":y=!0,h=0;break;case"s":g=-1,p="r"}"$"===l&&(v=i[0],d=i[1]),"r"!=p||h||(p="g"),null!=h&&("g"==p?h=Math.max(1,Math.min(21,h)):"e"!=p&&"f"!=p||(h=Math.max(0,Math.min(20,h)))),p=pa.get(p)||Fn;var M=c&&s;return function(n){var e=d;if(y&&n%1)return"";var i=0>n||0===n&&0>1/n?(n=-n,"-"):"-"===a?"":a;if(0>g){var l=ao.formatPrefix(n,h);n=l.scale(n),e=l.symbol+d}else n*=g;n=p(n,h);var x,b,_=n.lastIndexOf(".");if(0>_){var w=m?n.lastIndexOf("e"):-1;0>w?(x=n,b=""):(x=n.substring(0,w),b=n.substring(w))}else x=n.substring(0,_),b=t+n.substring(_+1);!c&&s&&(x=u(x,1/0));var S=v.length+x.length+b.length+(M?0:i.length),k=f>S?new Array(S=f-S+1).join(r):"";return M&&(x=u(k+x,k.length?f-b.length:1/0)),i+=v,n=x+b,("<"===o?i+n+k:">"===o?k+i+n:"^"===o?k.substring(0,S>>=1)+i+n+k.substring(S):i+(M?n:k+n))+e}}}function Fn(n){return n+""}function Hn(){this._=new Date(arguments.length>1?Date.UTC.apply(this,arguments):arguments[0])}function On(n,t,e){function r(t){var e=n(t),r=u(e,1);return r-t>t-e?e:r}function i(e){return t(e=n(new va(e-1)),1),e}function u(n,e){return t(n=new va(+n),e),n}function o(n,r,u){var o=i(n),a=[];if(u>1)for(;r>o;)e(o)%u||a.push(new Date(+o)),t(o,1);else for(;r>o;)a.push(new Date(+o)),t(o,1);return a}function a(n,t,e){try{va=Hn;var r=new Hn;return r._=n,o(r,t,e)}finally{va=Date}}n.floor=n,n.round=r,n.ceil=i,n.offset=u,n.range=o;var l=n.utc=In(n);return l.floor=l,l.round=In(r),l.ceil=In(i),l.offset=In(u),l.range=a,n}function In(n){return function(t,e){try{va=Hn;var r=new Hn;return r._=t,n(r,e)._}finally{va=Date}}}function Yn(n){function t(n){function t(t){for(var e,i,u,o=[],a=-1,l=0;++a<r;)37===n.charCodeAt(a)&&(o.push(n.slice(l,a)),null!=(i=ya[e=n.charAt(++a)])&&(e=n.charAt(++a)),(u=A[e])&&(e=u(t,null==i?"e"===e?" ":"0":i)),o.push(e),l=a+1);return o.push(n.slice(l,a)),o.join("")}var r=n.length;return t.parse=function(t){var r={y:1900,m:0,d:1,H:0,M:0,S:0,L:0,Z:null},i=e(r,n,t,0);if(i!=t.length)return null;"p"in r&&(r.H=r.H%12+12*r.p);var u=null!=r.Z&&va!==Hn,o=new(u?Hn:va);return"j"in r?o.setFullYear(r.y,0,r.j):"W"in r||"U"in r?("w"in r||(r.w="W"in r?1:0),o.setFullYear(r.y,0,1),o.setFullYear(r.y,0,"W"in r?(r.w+6)%7+7*r.W-(o.getDay()+5)%7:r.w+7*r.U-(o.getDay()+6)%7)):o.setFullYear(r.y,r.m,r.d),o.setHours(r.H+(r.Z/100|0),r.M+r.Z%100,r.S,r.L),u?o._:o},t.toString=function(){return n},t}function e(n,t,e,r){for(var i,u,o,a=0,l=t.length,c=e.length;l>a;){if(r>=c)return-1;if(i=t.charCodeAt(a++),37===i){if(o=t.charAt(a++),u=C[o in ya?t.charAt(a++):o],!u||(r=u(n,e,r))<0)return-1}else if(i!=e.charCodeAt(r++))return-1}return r}function r(n,t,e){_.lastIndex=0;var r=_.exec(t.slice(e));return r?(n.w=w.get(r[0].toLowerCase()),e+r[0].length):-1}function i(n,t,e){x.lastIndex=0;var r=x.exec(t.slice(e));return r?(n.w=b.get(r[0].toLowerCase()),e+r[0].length):-1}function u(n,t,e){N.lastIndex=0;var r=N.exec(t.slice(e));return r?(n.m=E.get(r[0].toLowerCase()),e+r[0].length):-1}function o(n,t,e){S.lastIndex=0;var r=S.exec(t.slice(e));return r?(n.m=k.get(r[0].toLowerCase()),e+r[0].length):-1}function a(n,t,r){return e(n,A.c.toString(),t,r)}function l(n,t,r){return e(n,A.x.toString(),t,r)}function c(n,t,r){return e(n,A.X.toString(),t,r)}function f(n,t,e){var r=M.get(t.slice(e,e+=2).toLowerCase());return null==r?-1:(n.p=r,e)}var s=n.dateTime,h=n.date,p=n.time,g=n.periods,v=n.days,d=n.shortDays,y=n.months,m=n.shortMonths;t.utc=function(n){function e(n){try{va=Hn;var t=new va;return t._=n,r(t)}finally{va=Date}}var r=t(n);return e.parse=function(n){try{va=Hn;var t=r.parse(n);return t&&t._}finally{va=Date}},e.toString=r.toString,e},t.multi=t.utc.multi=ct;var M=ao.map(),x=Vn(v),b=Xn(v),_=Vn(d),w=Xn(d),S=Vn(y),k=Xn(y),N=Vn(m),E=Xn(m);g.forEach(function(n,t){M.set(n.toLowerCase(),t)});var A={a:function(n){return d[n.getDay()]},A:function(n){return v[n.getDay()]},b:function(n){return m[n.getMonth()]},B:function(n){return y[n.getMonth()]},c:t(s),d:function(n,t){return Zn(n.getDate(),t,2)},e:function(n,t){return Zn(n.getDate(),t,2)},H:function(n,t){return Zn(n.getHours(),t,2)},I:function(n,t){return Zn(n.getHours()%12||12,t,2)},j:function(n,t){return Zn(1+ga.dayOfYear(n),t,3)},L:function(n,t){return Zn(n.getMilliseconds(),t,3)},m:function(n,t){return Zn(n.getMonth()+1,t,2)},M:function(n,t){return Zn(n.getMinutes(),t,2)},p:function(n){return g[+(n.getHours()>=12)]},S:function(n,t){return Zn(n.getSeconds(),t,2)},U:function(n,t){return Zn(ga.sundayOfYear(n),t,2)},w:function(n){return n.getDay()},W:function(n,t){return Zn(ga.mondayOfYear(n),t,2)},x:t(h),X:t(p),y:function(n,t){return Zn(n.getFullYear()%100,t,2)},Y:function(n,t){return Zn(n.getFullYear()%1e4,t,4)},Z:at,"%":function(){return"%"}},C={a:r,A:i,b:u,B:o,c:a,d:tt,e:tt,H:rt,I:rt,j:et,L:ot,m:nt,M:it,p:f,S:ut,U:Bn,w:$n,W:Wn,x:l,X:c,y:Gn,Y:Jn,Z:Kn,"%":lt};return t}function Zn(n,t,e){var r=0>n?"-":"",i=(r?-n:n)+"",u=i.length;return r+(e>u?new Array(e-u+1).join(t)+i:i)}function Vn(n){return new RegExp("^(?:"+n.map(ao.requote).join("|")+")","i")}function Xn(n){for(var t=new c,e=-1,r=n.length;++e<r;)t.set(n[e].toLowerCase(),e);return t}function $n(n,t,e){ma.lastIndex=0;var r=ma.exec(t.slice(e,e+1));return r?(n.w=+r[0],e+r[0].length):-1}function Bn(n,t,e){ma.lastIndex=0;var r=ma.exec(t.slice(e));return r?(n.U=+r[0],e+r[0].length):-1}function Wn(n,t,e){ma.lastIndex=0;var r=ma.exec(t.slice(e));return r?(n.W=+r[0],e+r[0].length):-1}function Jn(n,t,e){ma.lastIndex=0;var r=ma.exec(t.slice(e,e+4));return r?(n.y=+r[0],e+r[0].length):-1}function Gn(n,t,e){ma.lastIndex=0;var r=ma.exec(t.slice(e,e+2));return r?(n.y=Qn(+r[0]),e+r[0].length):-1}function Kn(n,t,e){return/^[+-]\d{4}$/.test(t=t.slice(e,e+5))?(n.Z=-t,e+5):-1}function Qn(n){return n+(n>68?1900:2e3)}function nt(n,t,e){ma.lastIndex=0;var r=ma.exec(t.slice(e,e+2));return r?(n.m=r[0]-1,e+r[0].length):-1}function tt(n,t,e){ma.lastIndex=0;var r=ma.exec(t.slice(e,e+2));return r?(n.d=+r[0],e+r[0].length):-1}function et(n,t,e){ma.lastIndex=0;var r=ma.exec(t.slice(e,e+3));return r?(n.j=+r[0],e+r[0].length):-1}function rt(n,t,e){ma.lastIndex=0;var r=ma.exec(t.slice(e,e+2));return r?(n.H=+r[0],e+r[0].length):-1}function it(n,t,e){ma.lastIndex=0;var r=ma.exec(t.slice(e,e+2));return r?(n.M=+r[0],e+r[0].length):-1}function ut(n,t,e){ma.lastIndex=0;var r=ma.exec(t.slice(e,e+2));return r?(n.S=+r[0],e+r[0].length):-1}function ot(n,t,e){ma.lastIndex=0;var r=ma.exec(t.slice(e,e+3));return r?(n.L=+r[0],e+r[0].length):-1}function at(n){var t=n.getTimezoneOffset(),e=t>0?"-":"+",r=xo(t)/60|0,i=xo(t)%60;return e+Zn(r,"0",2)+Zn(i,"0",2)}function lt(n,t,e){Ma.lastIndex=0;var r=Ma.exec(t.slice(e,e+1));return r?e+r[0].length:-1}function ct(n){for(var t=n.length,e=-1;++e<t;)n[e][0]=this(n[e][0]);return function(t){for(var e=0,r=n[e];!r[1](t);)r=n[++e];return r[0](t)}}function ft(){}function st(n,t,e){var r=e.s=n+t,i=r-n,u=r-i;e.t=n-u+(t-i)}function ht(n,t){n&&wa.hasOwnProperty(n.type)&&wa[n.type](n,t)}function pt(n,t,e){var r,i=-1,u=n.length-e;for(t.lineStart();++i<u;)r=n[i],t.point(r[0],r[1],r[2]);t.lineEnd()}function gt(n,t){var e=-1,r=n.length;for(t.polygonStart();++e<r;)pt(n[e],t,1);t.polygonEnd()}function vt(){function n(n,t){n*=Yo,t=t*Yo/2+Fo/4;var e=n-r,o=e>=0?1:-1,a=o*e,l=Math.cos(t),c=Math.sin(t),f=u*c,s=i*l+f*Math.cos(a),h=f*o*Math.sin(a);ka.add(Math.atan2(h,s)),r=n,i=l,u=c}var t,e,r,i,u;Na.point=function(o,a){Na.point=n,r=(t=o)*Yo,i=Math.cos(a=(e=a)*Yo/2+Fo/4),u=Math.sin(a)},Na.lineEnd=function(){n(t,e)}}function dt(n){var t=n[0],e=n[1],r=Math.cos(e);return[r*Math.cos(t),r*Math.sin(t),Math.sin(e)]}function yt(n,t){return n[0]*t[0]+n[1]*t[1]+n[2]*t[2]}function mt(n,t){return[n[1]*t[2]-n[2]*t[1],n[2]*t[0]-n[0]*t[2],n[0]*t[1]-n[1]*t[0]]}function Mt(n,t){n[0]+=t[0],n[1]+=t[1],n[2]+=t[2]}function xt(n,t){return[n[0]*t,n[1]*t,n[2]*t]}function bt(n){var t=Math.sqrt(n[0]*n[0]+n[1]*n[1]+n[2]*n[2]);n[0]/=t,n[1]/=t,n[2]/=t}function _t(n){return[Math.atan2(n[1],n[0]),tn(n[2])]}function wt(n,t){return xo(n[0]-t[0])<Uo&&xo(n[1]-t[1])<Uo}function St(n,t){n*=Yo;var e=Math.cos(t*=Yo);kt(e*Math.cos(n),e*Math.sin(n),Math.sin(t))}function kt(n,t,e){++Ea,Ca+=(n-Ca)/Ea,za+=(t-za)/Ea,La+=(e-La)/Ea}function Nt(){function n(n,i){n*=Yo;var u=Math.cos(i*=Yo),o=u*Math.cos(n),a=u*Math.sin(n),l=Math.sin(i),c=Math.atan2(Math.sqrt((c=e*l-r*a)*c+(c=r*o-t*l)*c+(c=t*a-e*o)*c),t*o+e*a+r*l);Aa+=c,qa+=c*(t+(t=o)),Ta+=c*(e+(e=a)),Ra+=c*(r+(r=l)),kt(t,e,r)}var t,e,r;ja.point=function(i,u){i*=Yo;var o=Math.cos(u*=Yo);t=o*Math.cos(i),e=o*Math.sin(i),r=Math.sin(u),ja.point=n,kt(t,e,r)}}function Et(){ja.point=St}function At(){function n(n,t){n*=Yo;var e=Math.cos(t*=Yo),o=e*Math.cos(n),a=e*Math.sin(n),l=Math.sin(t),c=i*l-u*a,f=u*o-r*l,s=r*a-i*o,h=Math.sqrt(c*c+f*f+s*s),p=r*o+i*a+u*l,g=h&&-nn(p)/h,v=Math.atan2(h,p);Da+=g*c,Pa+=g*f,Ua+=g*s,Aa+=v,qa+=v*(r+(r=o)),Ta+=v*(i+(i=a)),Ra+=v*(u+(u=l)),kt(r,i,u)}var t,e,r,i,u;ja.point=function(o,a){t=o,e=a,ja.point=n,o*=Yo;var l=Math.cos(a*=Yo);r=l*Math.cos(o),i=l*Math.sin(o),u=Math.sin(a),kt(r,i,u)},ja.lineEnd=function(){n(t,e),ja.lineEnd=Et,ja.point=St}}function Ct(n,t){function e(e,r){return e=n(e,r),t(e[0],e[1])}return n.invert&&t.invert&&(e.invert=function(e,r){return e=t.invert(e,r),e&&n.invert(e[0],e[1])}),e}function zt(){return!0}function Lt(n,t,e,r,i){var u=[],o=[];if(n.forEach(function(n){if(!((t=n.length-1)<=0)){var t,e=n[0],r=n[t];if(wt(e,r)){i.lineStart();for(var a=0;t>a;++a)i.point((e=n[a])[0],e[1]);return void i.lineEnd()}var l=new Tt(e,n,null,!0),c=new Tt(e,null,l,!1);l.o=c,u.push(l),o.push(c),l=new Tt(r,n,null,!1),c=new Tt(r,null,l,!0),l.o=c,u.push(l),o.push(c)}}),o.sort(t),qt(u),qt(o),u.length){for(var a=0,l=e,c=o.length;c>a;++a)o[a].e=l=!l;for(var f,s,h=u[0];;){for(var p=h,g=!0;p.v;)if((p=p.n)===h)return;f=p.z,i.lineStart();do{if(p.v=p.o.v=!0,p.e){if(g)for(var a=0,c=f.length;c>a;++a)i.point((s=f[a])[0],s[1]);else r(p.x,p.n.x,1,i);p=p.n}else{if(g){f=p.p.z;for(var a=f.length-1;a>=0;--a)i.point((s=f[a])[0],s[1])}else r(p.x,p.p.x,-1,i);p=p.p}p=p.o,f=p.z,g=!g}while(!p.v);i.lineEnd()}}}function qt(n){if(t=n.length){for(var t,e,r=0,i=n[0];++r<t;)i.n=e=n[r],e.p=i,i=e;i.n=e=n[0],e.p=i}}function Tt(n,t,e,r){this.x=n,this.z=t,this.o=e,this.e=r,this.v=!1,this.n=this.p=null}function Rt(n,t,e,r){return function(i,u){function o(t,e){var r=i(t,e);n(t=r[0],e=r[1])&&u.point(t,e)}function a(n,t){var e=i(n,t);d.point(e[0],e[1])}function l(){m.point=a,d.lineStart()}function c(){m.point=o,d.lineEnd()}function f(n,t){v.push([n,t]);var e=i(n,t);x.point(e[0],e[1])}function s(){x.lineStart(),v=[]}function h(){f(v[0][0],v[0][1]),x.lineEnd();var n,t=x.clean(),e=M.buffer(),r=e.length;if(v.pop(),g.push(v),v=null,r)if(1&t){n=e[0];var i,r=n.length-1,o=-1;if(r>0){for(b||(u.polygonStart(),b=!0),u.lineStart();++o<r;)u.point((i=n[o])[0],i[1]);u.lineEnd()}}else r>1&&2&t&&e.push(e.pop().concat(e.shift())),p.push(e.filter(Dt))}var p,g,v,d=t(u),y=i.invert(r[0],r[1]),m={point:o,lineStart:l,lineEnd:c,polygonStart:function(){m.point=f,m.lineStart=s,m.lineEnd=h,p=[],g=[]},polygonEnd:function(){m.point=o,m.lineStart=l,m.lineEnd=c,p=ao.merge(p);var n=Ot(y,g);p.length?(b||(u.polygonStart(),b=!0),Lt(p,Ut,n,e,u)):n&&(b||(u.polygonStart(),b=!0),u.lineStart(),e(null,null,1,u),u.lineEnd()),b&&(u.polygonEnd(),b=!1),p=g=null},sphere:function(){u.polygonStart(),u.lineStart(),e(null,null,1,u),u.lineEnd(),u.polygonEnd()}},M=Pt(),x=t(M),b=!1;return m}}function Dt(n){return n.length>1}function Pt(){var n,t=[];return{lineStart:function(){t.push(n=[])},point:function(t,e){n.push([t,e])},lineEnd:b,buffer:function(){var e=t;return t=[],n=null,e},rejoin:function(){t.length>1&&t.push(t.pop().concat(t.shift()))}}}function Ut(n,t){return((n=n.x)[0]<0?n[1]-Io-Uo:Io-n[1])-((t=t.x)[0]<0?t[1]-Io-Uo:Io-t[1])}function jt(n){var t,e=NaN,r=NaN,i=NaN;return{lineStart:function(){n.lineStart(),t=1},point:function(u,o){var a=u>0?Fo:-Fo,l=xo(u-e);xo(l-Fo)<Uo?(n.point(e,r=(r+o)/2>0?Io:-Io),n.point(i,r),n.lineEnd(),n.lineStart(),n.point(a,r),n.point(u,r),t=0):i!==a&&l>=Fo&&(xo(e-i)<Uo&&(e-=i*Uo),xo(u-a)<Uo&&(u-=a*Uo),r=Ft(e,r,u,o),n.point(i,r),n.lineEnd(),n.lineStart(),n.point(a,r),t=0),n.point(e=u,r=o),i=a},lineEnd:function(){n.lineEnd(),e=r=NaN},clean:function(){return 2-t}}}function Ft(n,t,e,r){var i,u,o=Math.sin(n-e);return xo(o)>Uo?Math.atan((Math.sin(t)*(u=Math.cos(r))*Math.sin(e)-Math.sin(r)*(i=Math.cos(t))*Math.sin(n))/(i*u*o)):(t+r)/2}function Ht(n,t,e,r){var i;if(null==n)i=e*Io,r.point(-Fo,i),r.point(0,i),r.point(Fo,i),r.point(Fo,0),r.point(Fo,-i),r.point(0,-i),r.point(-Fo,-i),r.point(-Fo,0),r.point(-Fo,i);else if(xo(n[0]-t[0])>Uo){var u=n[0]<t[0]?Fo:-Fo;i=e*u/2,r.point(-u,i),r.point(0,i),r.point(u,i)}else r.point(t[0],t[1])}function Ot(n,t){var e=n[0],r=n[1],i=[Math.sin(e),-Math.cos(e),0],u=0,o=0;ka.reset();for(var a=0,l=t.length;l>a;++a){var c=t[a],f=c.length;if(f)for(var s=c[0],h=s[0],p=s[1]/2+Fo/4,g=Math.sin(p),v=Math.cos(p),d=1;;){d===f&&(d=0),n=c[d];var y=n[0],m=n[1]/2+Fo/4,M=Math.sin(m),x=Math.cos(m),b=y-h,_=b>=0?1:-1,w=_*b,S=w>Fo,k=g*M;if(ka.add(Math.atan2(k*_*Math.sin(w),v*x+k*Math.cos(w))),u+=S?b+_*Ho:b,S^h>=e^y>=e){var N=mt(dt(s),dt(n));bt(N);var E=mt(i,N);bt(E);var A=(S^b>=0?-1:1)*tn(E[2]);(r>A||r===A&&(N[0]||N[1]))&&(o+=S^b>=0?1:-1)}if(!d++)break;h=y,g=M,v=x,s=n}}return(-Uo>u||Uo>u&&-Uo>ka)^1&o}function It(n){function t(n,t){return Math.cos(n)*Math.cos(t)>u}function e(n){var e,u,l,c,f;return{lineStart:function(){c=l=!1,f=1},point:function(s,h){var p,g=[s,h],v=t(s,h),d=o?v?0:i(s,h):v?i(s+(0>s?Fo:-Fo),h):0;if(!e&&(c=l=v)&&n.lineStart(),v!==l&&(p=r(e,g),(wt(e,p)||wt(g,p))&&(g[0]+=Uo,g[1]+=Uo,v=t(g[0],g[1]))),v!==l)f=0,v?(n.lineStart(),p=r(g,e),n.point(p[0],p[1])):(p=r(e,g),n.point(p[0],p[1]),n.lineEnd()),e=p;else if(a&&e&&o^v){var y;d&u||!(y=r(g,e,!0))||(f=0,o?(n.lineStart(),n.point(y[0][0],y[0][1]),n.point(y[1][0],y[1][1]),n.lineEnd()):(n.point(y[1][0],y[1][1]),n.lineEnd(),n.lineStart(),n.point(y[0][0],y[0][1])))}!v||e&&wt(e,g)||n.point(g[0],g[1]),e=g,l=v,u=d},lineEnd:function(){l&&n.lineEnd(),e=null},clean:function(){return f|(c&&l)<<1}}}function r(n,t,e){var r=dt(n),i=dt(t),o=[1,0,0],a=mt(r,i),l=yt(a,a),c=a[0],f=l-c*c;if(!f)return!e&&n;var s=u*l/f,h=-u*c/f,p=mt(o,a),g=xt(o,s),v=xt(a,h);Mt(g,v);var d=p,y=yt(g,d),m=yt(d,d),M=y*y-m*(yt(g,g)-1);if(!(0>M)){var x=Math.sqrt(M),b=xt(d,(-y-x)/m);if(Mt(b,g),b=_t(b),!e)return b;var _,w=n[0],S=t[0],k=n[1],N=t[1];w>S&&(_=w,w=S,S=_);var E=S-w,A=xo(E-Fo)<Uo,C=A||Uo>E;if(!A&&k>N&&(_=k,k=N,N=_),C?A?k+N>0^b[1]<(xo(b[0]-w)<Uo?k:N):k<=b[1]&&b[1]<=N:E>Fo^(w<=b[0]&&b[0]<=S)){var z=xt(d,(-y+x)/m);return Mt(z,g),[b,_t(z)]}}}function i(t,e){var r=o?n:Fo-n,i=0;return-r>t?i|=1:t>r&&(i|=2),-r>e?i|=4:e>r&&(i|=8),i}var u=Math.cos(n),o=u>0,a=xo(u)>Uo,l=ve(n,6*Yo);return Rt(t,e,l,o?[0,-n]:[-Fo,n-Fo])}function Yt(n,t,e,r){return function(i){var u,o=i.a,a=i.b,l=o.x,c=o.y,f=a.x,s=a.y,h=0,p=1,g=f-l,v=s-c;if(u=n-l,g||!(u>0)){if(u/=g,0>g){if(h>u)return;p>u&&(p=u)}else if(g>0){if(u>p)return;u>h&&(h=u)}if(u=e-l,g||!(0>u)){if(u/=g,0>g){if(u>p)return;u>h&&(h=u)}else if(g>0){if(h>u)return;p>u&&(p=u)}if(u=t-c,v||!(u>0)){if(u/=v,0>v){if(h>u)return;p>u&&(p=u)}else if(v>0){if(u>p)return;u>h&&(h=u)}if(u=r-c,v||!(0>u)){if(u/=v,0>v){if(u>p)return;u>h&&(h=u)}else if(v>0){if(h>u)return;p>u&&(p=u)}return h>0&&(i.a={x:l+h*g,y:c+h*v}),1>p&&(i.b={x:l+p*g,y:c+p*v}),i}}}}}}function Zt(n,t,e,r){function i(r,i){return xo(r[0]-n)<Uo?i>0?0:3:xo(r[0]-e)<Uo?i>0?2:1:xo(r[1]-t)<Uo?i>0?1:0:i>0?3:2}function u(n,t){return o(n.x,t.x)}function o(n,t){var e=i(n,1),r=i(t,1);return e!==r?e-r:0===e?t[1]-n[1]:1===e?n[0]-t[0]:2===e?n[1]-t[1]:t[0]-n[0]}return function(a){function l(n){for(var t=0,e=d.length,r=n[1],i=0;e>i;++i)for(var u,o=1,a=d[i],l=a.length,c=a[0];l>o;++o)u=a[o],c[1]<=r?u[1]>r&&Q(c,u,n)>0&&++t:u[1]<=r&&Q(c,u,n)<0&&--t,c=u;return 0!==t}function c(u,a,l,c){var f=0,s=0;if(null==u||(f=i(u,l))!==(s=i(a,l))||o(u,a)<0^l>0){do c.point(0===f||3===f?n:e,f>1?r:t);while((f=(f+l+4)%4)!==s)}else c.point(a[0],a[1])}function f(i,u){return i>=n&&e>=i&&u>=t&&r>=u}function s(n,t){f(n,t)&&a.point(n,t)}function h(){C.point=g,d&&d.push(y=[]),S=!0,w=!1,b=_=NaN}function p(){v&&(g(m,M),x&&w&&E.rejoin(),v.push(E.buffer())),C.point=s,w&&a.lineEnd()}function g(n,t){n=Math.max(-Ha,Math.min(Ha,n)),t=Math.max(-Ha,Math.min(Ha,t));var e=f(n,t);if(d&&y.push([n,t]),S)m=n,M=t,x=e,S=!1,e&&(a.lineStart(),a.point(n,t));else if(e&&w)a.point(n,t);else{var r={a:{x:b,y:_},b:{x:n,y:t}};A(r)?(w||(a.lineStart(),a.point(r.a.x,r.a.y)),a.point(r.b.x,r.b.y),e||a.lineEnd(),k=!1):e&&(a.lineStart(),a.point(n,t),k=!1)}b=n,_=t,w=e}var v,d,y,m,M,x,b,_,w,S,k,N=a,E=Pt(),A=Yt(n,t,e,r),C={point:s,lineStart:h,lineEnd:p,polygonStart:function(){a=E,v=[],d=[],k=!0},polygonEnd:function(){a=N,v=ao.merge(v);var t=l([n,r]),e=k&&t,i=v.length;(e||i)&&(a.polygonStart(),e&&(a.lineStart(),c(null,null,1,a),a.lineEnd()),i&&Lt(v,u,t,c,a),a.polygonEnd()),v=d=y=null}};return C}}function Vt(n){var t=0,e=Fo/3,r=ae(n),i=r(t,e);return i.parallels=function(n){return arguments.length?r(t=n[0]*Fo/180,e=n[1]*Fo/180):[t/Fo*180,e/Fo*180]},i}function Xt(n,t){function e(n,t){var e=Math.sqrt(u-2*i*Math.sin(t))/i;return[e*Math.sin(n*=i),o-e*Math.cos(n)]}var r=Math.sin(n),i=(r+Math.sin(t))/2,u=1+r*(2*i-r),o=Math.sqrt(u)/i;return e.invert=function(n,t){var e=o-t;return[Math.atan2(n,e)/i,tn((u-(n*n+e*e)*i*i)/(2*i))]},e}function $t(){function n(n,t){Ia+=i*n-r*t,r=n,i=t}var t,e,r,i;$a.point=function(u,o){$a.point=n,t=r=u,e=i=o},$a.lineEnd=function(){n(t,e)}}function Bt(n,t){Ya>n&&(Ya=n),n>Va&&(Va=n),Za>t&&(Za=t),t>Xa&&(Xa=t)}function Wt(){function n(n,t){o.push("M",n,",",t,u)}function t(n,t){o.push("M",n,",",t),a.point=e}function e(n,t){o.push("L",n,",",t)}function r(){a.point=n}function i(){o.push("Z")}var u=Jt(4.5),o=[],a={point:n,lineStart:function(){a.point=t},lineEnd:r,polygonStart:function(){a.lineEnd=i},polygonEnd:function(){a.lineEnd=r,a.point=n},pointRadius:function(n){return u=Jt(n),a},result:function(){if(o.length){var n=o.join("");return o=[],n}}};return a}function Jt(n){return"m0,"+n+"a"+n+","+n+" 0 1,1 0,"+-2*n+"a"+n+","+n+" 0 1,1 0,"+2*n+"z"}function Gt(n,t){Ca+=n,za+=t,++La}function Kt(){function n(n,r){var i=n-t,u=r-e,o=Math.sqrt(i*i+u*u);qa+=o*(t+n)/2,Ta+=o*(e+r)/2,Ra+=o,Gt(t=n,e=r)}var t,e;Wa.point=function(r,i){Wa.point=n,Gt(t=r,e=i)}}function Qt(){Wa.point=Gt}function ne(){function n(n,t){var e=n-r,u=t-i,o=Math.sqrt(e*e+u*u);qa+=o*(r+n)/2,Ta+=o*(i+t)/2,Ra+=o,o=i*n-r*t,Da+=o*(r+n),Pa+=o*(i+t),Ua+=3*o,Gt(r=n,i=t)}var t,e,r,i;Wa.point=function(u,o){Wa.point=n,Gt(t=r=u,e=i=o)},Wa.lineEnd=function(){n(t,e)}}function te(n){function t(t,e){n.moveTo(t+o,e),n.arc(t,e,o,0,Ho)}function e(t,e){n.moveTo(t,e),a.point=r}function r(t,e){n.lineTo(t,e)}function i(){a.point=t}function u(){n.closePath()}var o=4.5,a={point:t,lineStart:function(){a.point=e},lineEnd:i,polygonStart:function(){a.lineEnd=u},polygonEnd:function(){a.lineEnd=i,a.point=t},pointRadius:function(n){return o=n,a},result:b};return a}function ee(n){function t(n){return(a?r:e)(n)}function e(t){return ue(t,function(e,r){e=n(e,r),t.point(e[0],e[1])})}function r(t){function e(e,r){e=n(e,r),t.point(e[0],e[1])}function r(){M=NaN,S.point=u,t.lineStart()}function u(e,r){var u=dt([e,r]),o=n(e,r);i(M,x,m,b,_,w,M=o[0],x=o[1],m=e,b=u[0],_=u[1],w=u[2],a,t),t.point(M,x)}function o(){S.point=e,t.lineEnd()}function l(){
  22859. r(),S.point=c,S.lineEnd=f}function c(n,t){u(s=n,h=t),p=M,g=x,v=b,d=_,y=w,S.point=u}function f(){i(M,x,m,b,_,w,p,g,s,v,d,y,a,t),S.lineEnd=o,o()}var s,h,p,g,v,d,y,m,M,x,b,_,w,S={point:e,lineStart:r,lineEnd:o,polygonStart:function(){t.polygonStart(),S.lineStart=l},polygonEnd:function(){t.polygonEnd(),S.lineStart=r}};return S}function i(t,e,r,a,l,c,f,s,h,p,g,v,d,y){var m=f-t,M=s-e,x=m*m+M*M;if(x>4*u&&d--){var b=a+p,_=l+g,w=c+v,S=Math.sqrt(b*b+_*_+w*w),k=Math.asin(w/=S),N=xo(xo(w)-1)<Uo||xo(r-h)<Uo?(r+h)/2:Math.atan2(_,b),E=n(N,k),A=E[0],C=E[1],z=A-t,L=C-e,q=M*z-m*L;(q*q/x>u||xo((m*z+M*L)/x-.5)>.3||o>a*p+l*g+c*v)&&(i(t,e,r,a,l,c,A,C,N,b/=S,_/=S,w,d,y),y.point(A,C),i(A,C,N,b,_,w,f,s,h,p,g,v,d,y))}}var u=.5,o=Math.cos(30*Yo),a=16;return t.precision=function(n){return arguments.length?(a=(u=n*n)>0&&16,t):Math.sqrt(u)},t}function re(n){var t=ee(function(t,e){return n([t*Zo,e*Zo])});return function(n){return le(t(n))}}function ie(n){this.stream=n}function ue(n,t){return{point:t,sphere:function(){n.sphere()},lineStart:function(){n.lineStart()},lineEnd:function(){n.lineEnd()},polygonStart:function(){n.polygonStart()},polygonEnd:function(){n.polygonEnd()}}}function oe(n){return ae(function(){return n})()}function ae(n){function t(n){return n=a(n[0]*Yo,n[1]*Yo),[n[0]*h+l,c-n[1]*h]}function e(n){return n=a.invert((n[0]-l)/h,(c-n[1])/h),n&&[n[0]*Zo,n[1]*Zo]}function r(){a=Ct(o=se(y,M,x),u);var n=u(v,d);return l=p-n[0]*h,c=g+n[1]*h,i()}function i(){return f&&(f.valid=!1,f=null),t}var u,o,a,l,c,f,s=ee(function(n,t){return n=u(n,t),[n[0]*h+l,c-n[1]*h]}),h=150,p=480,g=250,v=0,d=0,y=0,M=0,x=0,b=Fa,_=m,w=null,S=null;return t.stream=function(n){return f&&(f.valid=!1),f=le(b(o,s(_(n)))),f.valid=!0,f},t.clipAngle=function(n){return arguments.length?(b=null==n?(w=n,Fa):It((w=+n)*Yo),i()):w},t.clipExtent=function(n){return arguments.length?(S=n,_=n?Zt(n[0][0],n[0][1],n[1][0],n[1][1]):m,i()):S},t.scale=function(n){return arguments.length?(h=+n,r()):h},t.translate=function(n){return arguments.length?(p=+n[0],g=+n[1],r()):[p,g]},t.center=function(n){return arguments.length?(v=n[0]%360*Yo,d=n[1]%360*Yo,r()):[v*Zo,d*Zo]},t.rotate=function(n){return arguments.length?(y=n[0]%360*Yo,M=n[1]%360*Yo,x=n.length>2?n[2]%360*Yo:0,r()):[y*Zo,M*Zo,x*Zo]},ao.rebind(t,s,"precision"),function(){return u=n.apply(this,arguments),t.invert=u.invert&&e,r()}}function le(n){return ue(n,function(t,e){n.point(t*Yo,e*Yo)})}function ce(n,t){return[n,t]}function fe(n,t){return[n>Fo?n-Ho:-Fo>n?n+Ho:n,t]}function se(n,t,e){return n?t||e?Ct(pe(n),ge(t,e)):pe(n):t||e?ge(t,e):fe}function he(n){return function(t,e){return t+=n,[t>Fo?t-Ho:-Fo>t?t+Ho:t,e]}}function pe(n){var t=he(n);return t.invert=he(-n),t}function ge(n,t){function e(n,t){var e=Math.cos(t),a=Math.cos(n)*e,l=Math.sin(n)*e,c=Math.sin(t),f=c*r+a*i;return[Math.atan2(l*u-f*o,a*r-c*i),tn(f*u+l*o)]}var r=Math.cos(n),i=Math.sin(n),u=Math.cos(t),o=Math.sin(t);return e.invert=function(n,t){var e=Math.cos(t),a=Math.cos(n)*e,l=Math.sin(n)*e,c=Math.sin(t),f=c*u-l*o;return[Math.atan2(l*u+c*o,a*r+f*i),tn(f*r-a*i)]},e}function ve(n,t){var e=Math.cos(n),r=Math.sin(n);return function(i,u,o,a){var l=o*t;null!=i?(i=de(e,i),u=de(e,u),(o>0?u>i:i>u)&&(i+=o*Ho)):(i=n+o*Ho,u=n-.5*l);for(var c,f=i;o>0?f>u:u>f;f-=l)a.point((c=_t([e,-r*Math.cos(f),-r*Math.sin(f)]))[0],c[1])}}function de(n,t){var e=dt(t);e[0]-=n,bt(e);var r=nn(-e[1]);return((-e[2]<0?-r:r)+2*Math.PI-Uo)%(2*Math.PI)}function ye(n,t,e){var r=ao.range(n,t-Uo,e).concat(t);return function(n){return r.map(function(t){return[n,t]})}}function me(n,t,e){var r=ao.range(n,t-Uo,e).concat(t);return function(n){return r.map(function(t){return[t,n]})}}function Me(n){return n.source}function xe(n){return n.target}function be(n,t,e,r){var i=Math.cos(t),u=Math.sin(t),o=Math.cos(r),a=Math.sin(r),l=i*Math.cos(n),c=i*Math.sin(n),f=o*Math.cos(e),s=o*Math.sin(e),h=2*Math.asin(Math.sqrt(on(r-t)+i*o*on(e-n))),p=1/Math.sin(h),g=h?function(n){var t=Math.sin(n*=h)*p,e=Math.sin(h-n)*p,r=e*l+t*f,i=e*c+t*s,o=e*u+t*a;return[Math.atan2(i,r)*Zo,Math.atan2(o,Math.sqrt(r*r+i*i))*Zo]}:function(){return[n*Zo,t*Zo]};return g.distance=h,g}function _e(){function n(n,i){var u=Math.sin(i*=Yo),o=Math.cos(i),a=xo((n*=Yo)-t),l=Math.cos(a);Ja+=Math.atan2(Math.sqrt((a=o*Math.sin(a))*a+(a=r*u-e*o*l)*a),e*u+r*o*l),t=n,e=u,r=o}var t,e,r;Ga.point=function(i,u){t=i*Yo,e=Math.sin(u*=Yo),r=Math.cos(u),Ga.point=n},Ga.lineEnd=function(){Ga.point=Ga.lineEnd=b}}function we(n,t){function e(t,e){var r=Math.cos(t),i=Math.cos(e),u=n(r*i);return[u*i*Math.sin(t),u*Math.sin(e)]}return e.invert=function(n,e){var r=Math.sqrt(n*n+e*e),i=t(r),u=Math.sin(i),o=Math.cos(i);return[Math.atan2(n*u,r*o),Math.asin(r&&e*u/r)]},e}function Se(n,t){function e(n,t){o>0?-Io+Uo>t&&(t=-Io+Uo):t>Io-Uo&&(t=Io-Uo);var e=o/Math.pow(i(t),u);return[e*Math.sin(u*n),o-e*Math.cos(u*n)]}var r=Math.cos(n),i=function(n){return Math.tan(Fo/4+n/2)},u=n===t?Math.sin(n):Math.log(r/Math.cos(t))/Math.log(i(t)/i(n)),o=r*Math.pow(i(n),u)/u;return u?(e.invert=function(n,t){var e=o-t,r=K(u)*Math.sqrt(n*n+e*e);return[Math.atan2(n,e)/u,2*Math.atan(Math.pow(o/r,1/u))-Io]},e):Ne}function ke(n,t){function e(n,t){var e=u-t;return[e*Math.sin(i*n),u-e*Math.cos(i*n)]}var r=Math.cos(n),i=n===t?Math.sin(n):(r-Math.cos(t))/(t-n),u=r/i+n;return xo(i)<Uo?ce:(e.invert=function(n,t){var e=u-t;return[Math.atan2(n,e)/i,u-K(i)*Math.sqrt(n*n+e*e)]},e)}function Ne(n,t){return[n,Math.log(Math.tan(Fo/4+t/2))]}function Ee(n){var t,e=oe(n),r=e.scale,i=e.translate,u=e.clipExtent;return e.scale=function(){var n=r.apply(e,arguments);return n===e?t?e.clipExtent(null):e:n},e.translate=function(){var n=i.apply(e,arguments);return n===e?t?e.clipExtent(null):e:n},e.clipExtent=function(n){var o=u.apply(e,arguments);if(o===e){if(t=null==n){var a=Fo*r(),l=i();u([[l[0]-a,l[1]-a],[l[0]+a,l[1]+a]])}}else t&&(o=null);return o},e.clipExtent(null)}function Ae(n,t){return[Math.log(Math.tan(Fo/4+t/2)),-n]}function Ce(n){return n[0]}function ze(n){return n[1]}function Le(n){for(var t=n.length,e=[0,1],r=2,i=2;t>i;i++){for(;r>1&&Q(n[e[r-2]],n[e[r-1]],n[i])<=0;)--r;e[r++]=i}return e.slice(0,r)}function qe(n,t){return n[0]-t[0]||n[1]-t[1]}function Te(n,t,e){return(e[0]-t[0])*(n[1]-t[1])<(e[1]-t[1])*(n[0]-t[0])}function Re(n,t,e,r){var i=n[0],u=e[0],o=t[0]-i,a=r[0]-u,l=n[1],c=e[1],f=t[1]-l,s=r[1]-c,h=(a*(l-c)-s*(i-u))/(s*o-a*f);return[i+h*o,l+h*f]}function De(n){var t=n[0],e=n[n.length-1];return!(t[0]-e[0]||t[1]-e[1])}function Pe(){rr(this),this.edge=this.site=this.circle=null}function Ue(n){var t=cl.pop()||new Pe;return t.site=n,t}function je(n){Be(n),ol.remove(n),cl.push(n),rr(n)}function Fe(n){var t=n.circle,e=t.x,r=t.cy,i={x:e,y:r},u=n.P,o=n.N,a=[n];je(n);for(var l=u;l.circle&&xo(e-l.circle.x)<Uo&&xo(r-l.circle.cy)<Uo;)u=l.P,a.unshift(l),je(l),l=u;a.unshift(l),Be(l);for(var c=o;c.circle&&xo(e-c.circle.x)<Uo&&xo(r-c.circle.cy)<Uo;)o=c.N,a.push(c),je(c),c=o;a.push(c),Be(c);var f,s=a.length;for(f=1;s>f;++f)c=a[f],l=a[f-1],nr(c.edge,l.site,c.site,i);l=a[0],c=a[s-1],c.edge=Ke(l.site,c.site,null,i),$e(l),$e(c)}function He(n){for(var t,e,r,i,u=n.x,o=n.y,a=ol._;a;)if(r=Oe(a,o)-u,r>Uo)a=a.L;else{if(i=u-Ie(a,o),!(i>Uo)){r>-Uo?(t=a.P,e=a):i>-Uo?(t=a,e=a.N):t=e=a;break}if(!a.R){t=a;break}a=a.R}var l=Ue(n);if(ol.insert(t,l),t||e){if(t===e)return Be(t),e=Ue(t.site),ol.insert(l,e),l.edge=e.edge=Ke(t.site,l.site),$e(t),void $e(e);if(!e)return void(l.edge=Ke(t.site,l.site));Be(t),Be(e);var c=t.site,f=c.x,s=c.y,h=n.x-f,p=n.y-s,g=e.site,v=g.x-f,d=g.y-s,y=2*(h*d-p*v),m=h*h+p*p,M=v*v+d*d,x={x:(d*m-p*M)/y+f,y:(h*M-v*m)/y+s};nr(e.edge,c,g,x),l.edge=Ke(c,n,null,x),e.edge=Ke(n,g,null,x),$e(t),$e(e)}}function Oe(n,t){var e=n.site,r=e.x,i=e.y,u=i-t;if(!u)return r;var o=n.P;if(!o)return-(1/0);e=o.site;var a=e.x,l=e.y,c=l-t;if(!c)return a;var f=a-r,s=1/u-1/c,h=f/c;return s?(-h+Math.sqrt(h*h-2*s*(f*f/(-2*c)-l+c/2+i-u/2)))/s+r:(r+a)/2}function Ie(n,t){var e=n.N;if(e)return Oe(e,t);var r=n.site;return r.y===t?r.x:1/0}function Ye(n){this.site=n,this.edges=[]}function Ze(n){for(var t,e,r,i,u,o,a,l,c,f,s=n[0][0],h=n[1][0],p=n[0][1],g=n[1][1],v=ul,d=v.length;d--;)if(u=v[d],u&&u.prepare())for(a=u.edges,l=a.length,o=0;l>o;)f=a[o].end(),r=f.x,i=f.y,c=a[++o%l].start(),t=c.x,e=c.y,(xo(r-t)>Uo||xo(i-e)>Uo)&&(a.splice(o,0,new tr(Qe(u.site,f,xo(r-s)<Uo&&g-i>Uo?{x:s,y:xo(t-s)<Uo?e:g}:xo(i-g)<Uo&&h-r>Uo?{x:xo(e-g)<Uo?t:h,y:g}:xo(r-h)<Uo&&i-p>Uo?{x:h,y:xo(t-h)<Uo?e:p}:xo(i-p)<Uo&&r-s>Uo?{x:xo(e-p)<Uo?t:s,y:p}:null),u.site,null)),++l)}function Ve(n,t){return t.angle-n.angle}function Xe(){rr(this),this.x=this.y=this.arc=this.site=this.cy=null}function $e(n){var t=n.P,e=n.N;if(t&&e){var r=t.site,i=n.site,u=e.site;if(r!==u){var o=i.x,a=i.y,l=r.x-o,c=r.y-a,f=u.x-o,s=u.y-a,h=2*(l*s-c*f);if(!(h>=-jo)){var p=l*l+c*c,g=f*f+s*s,v=(s*p-c*g)/h,d=(l*g-f*p)/h,s=d+a,y=fl.pop()||new Xe;y.arc=n,y.site=i,y.x=v+o,y.y=s+Math.sqrt(v*v+d*d),y.cy=s,n.circle=y;for(var m=null,M=ll._;M;)if(y.y<M.y||y.y===M.y&&y.x<=M.x){if(!M.L){m=M.P;break}M=M.L}else{if(!M.R){m=M;break}M=M.R}ll.insert(m,y),m||(al=y)}}}}function Be(n){var t=n.circle;t&&(t.P||(al=t.N),ll.remove(t),fl.push(t),rr(t),n.circle=null)}function We(n){for(var t,e=il,r=Yt(n[0][0],n[0][1],n[1][0],n[1][1]),i=e.length;i--;)t=e[i],(!Je(t,n)||!r(t)||xo(t.a.x-t.b.x)<Uo&&xo(t.a.y-t.b.y)<Uo)&&(t.a=t.b=null,e.splice(i,1))}function Je(n,t){var e=n.b;if(e)return!0;var r,i,u=n.a,o=t[0][0],a=t[1][0],l=t[0][1],c=t[1][1],f=n.l,s=n.r,h=f.x,p=f.y,g=s.x,v=s.y,d=(h+g)/2,y=(p+v)/2;if(v===p){if(o>d||d>=a)return;if(h>g){if(u){if(u.y>=c)return}else u={x:d,y:l};e={x:d,y:c}}else{if(u){if(u.y<l)return}else u={x:d,y:c};e={x:d,y:l}}}else if(r=(h-g)/(v-p),i=y-r*d,-1>r||r>1)if(h>g){if(u){if(u.y>=c)return}else u={x:(l-i)/r,y:l};e={x:(c-i)/r,y:c}}else{if(u){if(u.y<l)return}else u={x:(c-i)/r,y:c};e={x:(l-i)/r,y:l}}else if(v>p){if(u){if(u.x>=a)return}else u={x:o,y:r*o+i};e={x:a,y:r*a+i}}else{if(u){if(u.x<o)return}else u={x:a,y:r*a+i};e={x:o,y:r*o+i}}return n.a=u,n.b=e,!0}function Ge(n,t){this.l=n,this.r=t,this.a=this.b=null}function Ke(n,t,e,r){var i=new Ge(n,t);return il.push(i),e&&nr(i,n,t,e),r&&nr(i,t,n,r),ul[n.i].edges.push(new tr(i,n,t)),ul[t.i].edges.push(new tr(i,t,n)),i}function Qe(n,t,e){var r=new Ge(n,null);return r.a=t,r.b=e,il.push(r),r}function nr(n,t,e,r){n.a||n.b?n.l===e?n.b=r:n.a=r:(n.a=r,n.l=t,n.r=e)}function tr(n,t,e){var r=n.a,i=n.b;this.edge=n,this.site=t,this.angle=e?Math.atan2(e.y-t.y,e.x-t.x):n.l===t?Math.atan2(i.x-r.x,r.y-i.y):Math.atan2(r.x-i.x,i.y-r.y)}function er(){this._=null}function rr(n){n.U=n.C=n.L=n.R=n.P=n.N=null}function ir(n,t){var e=t,r=t.R,i=e.U;i?i.L===e?i.L=r:i.R=r:n._=r,r.U=i,e.U=r,e.R=r.L,e.R&&(e.R.U=e),r.L=e}function ur(n,t){var e=t,r=t.L,i=e.U;i?i.L===e?i.L=r:i.R=r:n._=r,r.U=i,e.U=r,e.L=r.R,e.L&&(e.L.U=e),r.R=e}function or(n){for(;n.L;)n=n.L;return n}function ar(n,t){var e,r,i,u=n.sort(lr).pop();for(il=[],ul=new Array(n.length),ol=new er,ll=new er;;)if(i=al,u&&(!i||u.y<i.y||u.y===i.y&&u.x<i.x))u.x===e&&u.y===r||(ul[u.i]=new Ye(u),He(u),e=u.x,r=u.y),u=n.pop();else{if(!i)break;Fe(i.arc)}t&&(We(t),Ze(t));var o={cells:ul,edges:il};return ol=ll=il=ul=null,o}function lr(n,t){return t.y-n.y||t.x-n.x}function cr(n,t,e){return(n.x-e.x)*(t.y-n.y)-(n.x-t.x)*(e.y-n.y)}function fr(n){return n.x}function sr(n){return n.y}function hr(){return{leaf:!0,nodes:[],point:null,x:null,y:null}}function pr(n,t,e,r,i,u){if(!n(t,e,r,i,u)){var o=.5*(e+i),a=.5*(r+u),l=t.nodes;l[0]&&pr(n,l[0],e,r,o,a),l[1]&&pr(n,l[1],o,r,i,a),l[2]&&pr(n,l[2],e,a,o,u),l[3]&&pr(n,l[3],o,a,i,u)}}function gr(n,t,e,r,i,u,o){var a,l=1/0;return function c(n,f,s,h,p){if(!(f>u||s>o||r>h||i>p)){if(g=n.point){var g,v=t-n.x,d=e-n.y,y=v*v+d*d;if(l>y){var m=Math.sqrt(l=y);r=t-m,i=e-m,u=t+m,o=e+m,a=g}}for(var M=n.nodes,x=.5*(f+h),b=.5*(s+p),_=t>=x,w=e>=b,S=w<<1|_,k=S+4;k>S;++S)if(n=M[3&S])switch(3&S){case 0:c(n,f,s,x,b);break;case 1:c(n,x,s,h,b);break;case 2:c(n,f,b,x,p);break;case 3:c(n,x,b,h,p)}}}(n,r,i,u,o),a}function vr(n,t){n=ao.rgb(n),t=ao.rgb(t);var e=n.r,r=n.g,i=n.b,u=t.r-e,o=t.g-r,a=t.b-i;return function(n){return"#"+bn(Math.round(e+u*n))+bn(Math.round(r+o*n))+bn(Math.round(i+a*n))}}function dr(n,t){var e,r={},i={};for(e in n)e in t?r[e]=Mr(n[e],t[e]):i[e]=n[e];for(e in t)e in n||(i[e]=t[e]);return function(n){for(e in r)i[e]=r[e](n);return i}}function yr(n,t){return n=+n,t=+t,function(e){return n*(1-e)+t*e}}function mr(n,t){var e,r,i,u=hl.lastIndex=pl.lastIndex=0,o=-1,a=[],l=[];for(n+="",t+="";(e=hl.exec(n))&&(r=pl.exec(t));)(i=r.index)>u&&(i=t.slice(u,i),a[o]?a[o]+=i:a[++o]=i),(e=e[0])===(r=r[0])?a[o]?a[o]+=r:a[++o]=r:(a[++o]=null,l.push({i:o,x:yr(e,r)})),u=pl.lastIndex;return u<t.length&&(i=t.slice(u),a[o]?a[o]+=i:a[++o]=i),a.length<2?l[0]?(t=l[0].x,function(n){return t(n)+""}):function(){return t}:(t=l.length,function(n){for(var e,r=0;t>r;++r)a[(e=l[r]).i]=e.x(n);return a.join("")})}function Mr(n,t){for(var e,r=ao.interpolators.length;--r>=0&&!(e=ao.interpolators[r](n,t)););return e}function xr(n,t){var e,r=[],i=[],u=n.length,o=t.length,a=Math.min(n.length,t.length);for(e=0;a>e;++e)r.push(Mr(n[e],t[e]));for(;u>e;++e)i[e]=n[e];for(;o>e;++e)i[e]=t[e];return function(n){for(e=0;a>e;++e)i[e]=r[e](n);return i}}function br(n){return function(t){return 0>=t?0:t>=1?1:n(t)}}function _r(n){return function(t){return 1-n(1-t)}}function wr(n){return function(t){return.5*(.5>t?n(2*t):2-n(2-2*t))}}function Sr(n){return n*n}function kr(n){return n*n*n}function Nr(n){if(0>=n)return 0;if(n>=1)return 1;var t=n*n,e=t*n;return 4*(.5>n?e:3*(n-t)+e-.75)}function Er(n){return function(t){return Math.pow(t,n)}}function Ar(n){return 1-Math.cos(n*Io)}function Cr(n){return Math.pow(2,10*(n-1))}function zr(n){return 1-Math.sqrt(1-n*n)}function Lr(n,t){var e;return arguments.length<2&&(t=.45),arguments.length?e=t/Ho*Math.asin(1/n):(n=1,e=t/4),function(r){return 1+n*Math.pow(2,-10*r)*Math.sin((r-e)*Ho/t)}}function qr(n){return n||(n=1.70158),function(t){return t*t*((n+1)*t-n)}}function Tr(n){return 1/2.75>n?7.5625*n*n:2/2.75>n?7.5625*(n-=1.5/2.75)*n+.75:2.5/2.75>n?7.5625*(n-=2.25/2.75)*n+.9375:7.5625*(n-=2.625/2.75)*n+.984375}function Rr(n,t){n=ao.hcl(n),t=ao.hcl(t);var e=n.h,r=n.c,i=n.l,u=t.h-e,o=t.c-r,a=t.l-i;return isNaN(o)&&(o=0,r=isNaN(r)?t.c:r),isNaN(u)?(u=0,e=isNaN(e)?t.h:e):u>180?u-=360:-180>u&&(u+=360),function(n){return sn(e+u*n,r+o*n,i+a*n)+""}}function Dr(n,t){n=ao.hsl(n),t=ao.hsl(t);var e=n.h,r=n.s,i=n.l,u=t.h-e,o=t.s-r,a=t.l-i;return isNaN(o)&&(o=0,r=isNaN(r)?t.s:r),isNaN(u)?(u=0,e=isNaN(e)?t.h:e):u>180?u-=360:-180>u&&(u+=360),function(n){return cn(e+u*n,r+o*n,i+a*n)+""}}function Pr(n,t){n=ao.lab(n),t=ao.lab(t);var e=n.l,r=n.a,i=n.b,u=t.l-e,o=t.a-r,a=t.b-i;return function(n){return pn(e+u*n,r+o*n,i+a*n)+""}}function Ur(n,t){return t-=n,function(e){return Math.round(n+t*e)}}function jr(n){var t=[n.a,n.b],e=[n.c,n.d],r=Hr(t),i=Fr(t,e),u=Hr(Or(e,t,-i))||0;t[0]*e[1]<e[0]*t[1]&&(t[0]*=-1,t[1]*=-1,r*=-1,i*=-1),this.rotate=(r?Math.atan2(t[1],t[0]):Math.atan2(-e[0],e[1]))*Zo,this.translate=[n.e,n.f],this.scale=[r,u],this.skew=u?Math.atan2(i,u)*Zo:0}function Fr(n,t){return n[0]*t[0]+n[1]*t[1]}function Hr(n){var t=Math.sqrt(Fr(n,n));return t&&(n[0]/=t,n[1]/=t),t}function Or(n,t,e){return n[0]+=e*t[0],n[1]+=e*t[1],n}function Ir(n){return n.length?n.pop()+",":""}function Yr(n,t,e,r){if(n[0]!==t[0]||n[1]!==t[1]){var i=e.push("translate(",null,",",null,")");r.push({i:i-4,x:yr(n[0],t[0])},{i:i-2,x:yr(n[1],t[1])})}else(t[0]||t[1])&&e.push("translate("+t+")")}function Zr(n,t,e,r){n!==t?(n-t>180?t+=360:t-n>180&&(n+=360),r.push({i:e.push(Ir(e)+"rotate(",null,")")-2,x:yr(n,t)})):t&&e.push(Ir(e)+"rotate("+t+")")}function Vr(n,t,e,r){n!==t?r.push({i:e.push(Ir(e)+"skewX(",null,")")-2,x:yr(n,t)}):t&&e.push(Ir(e)+"skewX("+t+")")}function Xr(n,t,e,r){if(n[0]!==t[0]||n[1]!==t[1]){var i=e.push(Ir(e)+"scale(",null,",",null,")");r.push({i:i-4,x:yr(n[0],t[0])},{i:i-2,x:yr(n[1],t[1])})}else 1===t[0]&&1===t[1]||e.push(Ir(e)+"scale("+t+")")}function $r(n,t){var e=[],r=[];return n=ao.transform(n),t=ao.transform(t),Yr(n.translate,t.translate,e,r),Zr(n.rotate,t.rotate,e,r),Vr(n.skew,t.skew,e,r),Xr(n.scale,t.scale,e,r),n=t=null,function(n){for(var t,i=-1,u=r.length;++i<u;)e[(t=r[i]).i]=t.x(n);return e.join("")}}function Br(n,t){return t=(t-=n=+n)||1/t,function(e){return(e-n)/t}}function Wr(n,t){return t=(t-=n=+n)||1/t,function(e){return Math.max(0,Math.min(1,(e-n)/t))}}function Jr(n){for(var t=n.source,e=n.target,r=Kr(t,e),i=[t];t!==r;)t=t.parent,i.push(t);for(var u=i.length;e!==r;)i.splice(u,0,e),e=e.parent;return i}function Gr(n){for(var t=[],e=n.parent;null!=e;)t.push(n),n=e,e=e.parent;return t.push(n),t}function Kr(n,t){if(n===t)return n;for(var e=Gr(n),r=Gr(t),i=e.pop(),u=r.pop(),o=null;i===u;)o=i,i=e.pop(),u=r.pop();return o}function Qr(n){n.fixed|=2}function ni(n){n.fixed&=-7}function ti(n){n.fixed|=4,n.px=n.x,n.py=n.y}function ei(n){n.fixed&=-5}function ri(n,t,e){var r=0,i=0;if(n.charge=0,!n.leaf)for(var u,o=n.nodes,a=o.length,l=-1;++l<a;)u=o[l],null!=u&&(ri(u,t,e),n.charge+=u.charge,r+=u.charge*u.cx,i+=u.charge*u.cy);if(n.point){n.leaf||(n.point.x+=Math.random()-.5,n.point.y+=Math.random()-.5);var c=t*e[n.point.index];n.charge+=n.pointCharge=c,r+=c*n.point.x,i+=c*n.point.y}n.cx=r/n.charge,n.cy=i/n.charge}function ii(n,t){return ao.rebind(n,t,"sort","children","value"),n.nodes=n,n.links=fi,n}function ui(n,t){for(var e=[n];null!=(n=e.pop());)if(t(n),(i=n.children)&&(r=i.length))for(var r,i;--r>=0;)e.push(i[r])}function oi(n,t){for(var e=[n],r=[];null!=(n=e.pop());)if(r.push(n),(u=n.children)&&(i=u.length))for(var i,u,o=-1;++o<i;)e.push(u[o]);for(;null!=(n=r.pop());)t(n)}function ai(n){return n.children}function li(n){return n.value}function ci(n,t){return t.value-n.value}function fi(n){return ao.merge(n.map(function(n){return(n.children||[]).map(function(t){return{source:n,target:t}})}))}function si(n){return n.x}function hi(n){return n.y}function pi(n,t,e){n.y0=t,n.y=e}function gi(n){return ao.range(n.length)}function vi(n){for(var t=-1,e=n[0].length,r=[];++t<e;)r[t]=0;return r}function di(n){for(var t,e=1,r=0,i=n[0][1],u=n.length;u>e;++e)(t=n[e][1])>i&&(r=e,i=t);return r}function yi(n){return n.reduce(mi,0)}function mi(n,t){return n+t[1]}function Mi(n,t){return xi(n,Math.ceil(Math.log(t.length)/Math.LN2+1))}function xi(n,t){for(var e=-1,r=+n[0],i=(n[1]-r)/t,u=[];++e<=t;)u[e]=i*e+r;return u}function bi(n){return[ao.min(n),ao.max(n)]}function _i(n,t){return n.value-t.value}function wi(n,t){var e=n._pack_next;n._pack_next=t,t._pack_prev=n,t._pack_next=e,e._pack_prev=t}function Si(n,t){n._pack_next=t,t._pack_prev=n}function ki(n,t){var e=t.x-n.x,r=t.y-n.y,i=n.r+t.r;return.999*i*i>e*e+r*r}function Ni(n){function t(n){f=Math.min(n.x-n.r,f),s=Math.max(n.x+n.r,s),h=Math.min(n.y-n.r,h),p=Math.max(n.y+n.r,p)}if((e=n.children)&&(c=e.length)){var e,r,i,u,o,a,l,c,f=1/0,s=-(1/0),h=1/0,p=-(1/0);if(e.forEach(Ei),r=e[0],r.x=-r.r,r.y=0,t(r),c>1&&(i=e[1],i.x=i.r,i.y=0,t(i),c>2))for(u=e[2],zi(r,i,u),t(u),wi(r,u),r._pack_prev=u,wi(u,i),i=r._pack_next,o=3;c>o;o++){zi(r,i,u=e[o]);var g=0,v=1,d=1;for(a=i._pack_next;a!==i;a=a._pack_next,v++)if(ki(a,u)){g=1;break}if(1==g)for(l=r._pack_prev;l!==a._pack_prev&&!ki(l,u);l=l._pack_prev,d++);g?(d>v||v==d&&i.r<r.r?Si(r,i=a):Si(r=l,i),o--):(wi(r,u),i=u,t(u))}var y=(f+s)/2,m=(h+p)/2,M=0;for(o=0;c>o;o++)u=e[o],u.x-=y,u.y-=m,M=Math.max(M,u.r+Math.sqrt(u.x*u.x+u.y*u.y));n.r=M,e.forEach(Ai)}}function Ei(n){n._pack_next=n._pack_prev=n}function Ai(n){delete n._pack_next,delete n._pack_prev}function Ci(n,t,e,r){var i=n.children;if(n.x=t+=r*n.x,n.y=e+=r*n.y,n.r*=r,i)for(var u=-1,o=i.length;++u<o;)Ci(i[u],t,e,r)}function zi(n,t,e){var r=n.r+e.r,i=t.x-n.x,u=t.y-n.y;if(r&&(i||u)){var o=t.r+e.r,a=i*i+u*u;o*=o,r*=r;var l=.5+(r-o)/(2*a),c=Math.sqrt(Math.max(0,2*o*(r+a)-(r-=a)*r-o*o))/(2*a);e.x=n.x+l*i+c*u,e.y=n.y+l*u-c*i}else e.x=n.x+r,e.y=n.y}function Li(n,t){return n.parent==t.parent?1:2}function qi(n){var t=n.children;return t.length?t[0]:n.t}function Ti(n){var t,e=n.children;return(t=e.length)?e[t-1]:n.t}function Ri(n,t,e){var r=e/(t.i-n.i);t.c-=r,t.s+=e,n.c+=r,t.z+=e,t.m+=e}function Di(n){for(var t,e=0,r=0,i=n.children,u=i.length;--u>=0;)t=i[u],t.z+=e,t.m+=e,e+=t.s+(r+=t.c)}function Pi(n,t,e){return n.a.parent===t.parent?n.a:e}function Ui(n){return 1+ao.max(n,function(n){return n.y})}function ji(n){return n.reduce(function(n,t){return n+t.x},0)/n.length}function Fi(n){var t=n.children;return t&&t.length?Fi(t[0]):n}function Hi(n){var t,e=n.children;return e&&(t=e.length)?Hi(e[t-1]):n}function Oi(n){return{x:n.x,y:n.y,dx:n.dx,dy:n.dy}}function Ii(n,t){var e=n.x+t[3],r=n.y+t[0],i=n.dx-t[1]-t[3],u=n.dy-t[0]-t[2];return 0>i&&(e+=i/2,i=0),0>u&&(r+=u/2,u=0),{x:e,y:r,dx:i,dy:u}}function Yi(n){var t=n[0],e=n[n.length-1];return e>t?[t,e]:[e,t]}function Zi(n){return n.rangeExtent?n.rangeExtent():Yi(n.range())}function Vi(n,t,e,r){var i=e(n[0],n[1]),u=r(t[0],t[1]);return function(n){return u(i(n))}}function Xi(n,t){var e,r=0,i=n.length-1,u=n[r],o=n[i];return u>o&&(e=r,r=i,i=e,e=u,u=o,o=e),n[r]=t.floor(u),n[i]=t.ceil(o),n}function $i(n){return n?{floor:function(t){return Math.floor(t/n)*n},ceil:function(t){return Math.ceil(t/n)*n}}:Sl}function Bi(n,t,e,r){var i=[],u=[],o=0,a=Math.min(n.length,t.length)-1;for(n[a]<n[0]&&(n=n.slice().reverse(),t=t.slice().reverse());++o<=a;)i.push(e(n[o-1],n[o])),u.push(r(t[o-1],t[o]));return function(t){var e=ao.bisect(n,t,1,a)-1;return u[e](i[e](t))}}function Wi(n,t,e,r){function i(){var i=Math.min(n.length,t.length)>2?Bi:Vi,l=r?Wr:Br;return o=i(n,t,l,e),a=i(t,n,l,Mr),u}function u(n){return o(n)}var o,a;return u.invert=function(n){return a(n)},u.domain=function(t){return arguments.length?(n=t.map(Number),i()):n},u.range=function(n){return arguments.length?(t=n,i()):t},u.rangeRound=function(n){return u.range(n).interpolate(Ur)},u.clamp=function(n){return arguments.length?(r=n,i()):r},u.interpolate=function(n){return arguments.length?(e=n,i()):e},u.ticks=function(t){return Qi(n,t)},u.tickFormat=function(t,e){return nu(n,t,e)},u.nice=function(t){return Gi(n,t),i()},u.copy=function(){return Wi(n,t,e,r)},i()}function Ji(n,t){return ao.rebind(n,t,"range","rangeRound","interpolate","clamp")}function Gi(n,t){return Xi(n,$i(Ki(n,t)[2])),Xi(n,$i(Ki(n,t)[2])),n}function Ki(n,t){null==t&&(t=10);var e=Yi(n),r=e[1]-e[0],i=Math.pow(10,Math.floor(Math.log(r/t)/Math.LN10)),u=t/r*i;return.15>=u?i*=10:.35>=u?i*=5:.75>=u&&(i*=2),e[0]=Math.ceil(e[0]/i)*i,e[1]=Math.floor(e[1]/i)*i+.5*i,e[2]=i,e}function Qi(n,t){return ao.range.apply(ao,Ki(n,t))}function nu(n,t,e){var r=Ki(n,t);if(e){var i=ha.exec(e);if(i.shift(),"s"===i[8]){var u=ao.formatPrefix(Math.max(xo(r[0]),xo(r[1])));return i[7]||(i[7]="."+tu(u.scale(r[2]))),i[8]="f",e=ao.format(i.join("")),function(n){return e(u.scale(n))+u.symbol}}i[7]||(i[7]="."+eu(i[8],r)),e=i.join("")}else e=",."+tu(r[2])+"f";return ao.format(e)}function tu(n){return-Math.floor(Math.log(n)/Math.LN10+.01)}function eu(n,t){var e=tu(t[2]);return n in kl?Math.abs(e-tu(Math.max(xo(t[0]),xo(t[1]))))+ +("e"!==n):e-2*("%"===n)}function ru(n,t,e,r){function i(n){return(e?Math.log(0>n?0:n):-Math.log(n>0?0:-n))/Math.log(t)}function u(n){return e?Math.pow(t,n):-Math.pow(t,-n)}function o(t){return n(i(t))}return o.invert=function(t){return u(n.invert(t))},o.domain=function(t){return arguments.length?(e=t[0]>=0,n.domain((r=t.map(Number)).map(i)),o):r},o.base=function(e){return arguments.length?(t=+e,n.domain(r.map(i)),o):t},o.nice=function(){var t=Xi(r.map(i),e?Math:El);return n.domain(t),r=t.map(u),o},o.ticks=function(){var n=Yi(r),o=[],a=n[0],l=n[1],c=Math.floor(i(a)),f=Math.ceil(i(l)),s=t%1?2:t;if(isFinite(f-c)){if(e){for(;f>c;c++)for(var h=1;s>h;h++)o.push(u(c)*h);o.push(u(c))}else for(o.push(u(c));c++<f;)for(var h=s-1;h>0;h--)o.push(u(c)*h);for(c=0;o[c]<a;c++);for(f=o.length;o[f-1]>l;f--);o=o.slice(c,f)}return o},o.tickFormat=function(n,e){if(!arguments.length)return Nl;arguments.length<2?e=Nl:"function"!=typeof e&&(e=ao.format(e));var r=Math.max(1,t*n/o.ticks().length);return function(n){var o=n/u(Math.round(i(n)));return t-.5>o*t&&(o*=t),r>=o?e(n):""}},o.copy=function(){return ru(n.copy(),t,e,r)},Ji(o,n)}function iu(n,t,e){function r(t){return n(i(t))}var i=uu(t),u=uu(1/t);return r.invert=function(t){return u(n.invert(t))},r.domain=function(t){return arguments.length?(n.domain((e=t.map(Number)).map(i)),r):e},r.ticks=function(n){return Qi(e,n)},r.tickFormat=function(n,t){return nu(e,n,t)},r.nice=function(n){return r.domain(Gi(e,n))},r.exponent=function(o){return arguments.length?(i=uu(t=o),u=uu(1/t),n.domain(e.map(i)),r):t},r.copy=function(){return iu(n.copy(),t,e)},Ji(r,n)}function uu(n){return function(t){return 0>t?-Math.pow(-t,n):Math.pow(t,n)}}function ou(n,t){function e(e){return u[((i.get(e)||("range"===t.t?i.set(e,n.push(e)):NaN))-1)%u.length]}function r(t,e){return ao.range(n.length).map(function(n){return t+e*n})}var i,u,o;return e.domain=function(r){if(!arguments.length)return n;n=[],i=new c;for(var u,o=-1,a=r.length;++o<a;)i.has(u=r[o])||i.set(u,n.push(u));return e[t.t].apply(e,t.a)},e.range=function(n){return arguments.length?(u=n,o=0,t={t:"range",a:arguments},e):u},e.rangePoints=function(i,a){arguments.length<2&&(a=0);var l=i[0],c=i[1],f=n.length<2?(l=(l+c)/2,0):(c-l)/(n.length-1+a);return u=r(l+f*a/2,f),o=0,t={t:"rangePoints",a:arguments},e},e.rangeRoundPoints=function(i,a){arguments.length<2&&(a=0);var l=i[0],c=i[1],f=n.length<2?(l=c=Math.round((l+c)/2),0):(c-l)/(n.length-1+a)|0;return u=r(l+Math.round(f*a/2+(c-l-(n.length-1+a)*f)/2),f),o=0,t={t:"rangeRoundPoints",a:arguments},e},e.rangeBands=function(i,a,l){arguments.length<2&&(a=0),arguments.length<3&&(l=a);var c=i[1]<i[0],f=i[c-0],s=i[1-c],h=(s-f)/(n.length-a+2*l);return u=r(f+h*l,h),c&&u.reverse(),o=h*(1-a),t={t:"rangeBands",a:arguments},e},e.rangeRoundBands=function(i,a,l){arguments.length<2&&(a=0),arguments.length<3&&(l=a);var c=i[1]<i[0],f=i[c-0],s=i[1-c],h=Math.floor((s-f)/(n.length-a+2*l));return u=r(f+Math.round((s-f-(n.length-a)*h)/2),h),c&&u.reverse(),o=Math.round(h*(1-a)),t={t:"rangeRoundBands",a:arguments},e},e.rangeBand=function(){return o},e.rangeExtent=function(){return Yi(t.a[0])},e.copy=function(){return ou(n,t)},e.domain(n)}function au(n,t){function u(){var e=0,r=t.length;for(a=[];++e<r;)a[e-1]=ao.quantile(n,e/r);return o}function o(n){return isNaN(n=+n)?void 0:t[ao.bisect(a,n)]}var a;return o.domain=function(t){return arguments.length?(n=t.map(r).filter(i).sort(e),u()):n},o.range=function(n){return arguments.length?(t=n,u()):t},o.quantiles=function(){return a},o.invertExtent=function(e){return e=t.indexOf(e),0>e?[NaN,NaN]:[e>0?a[e-1]:n[0],e<a.length?a[e]:n[n.length-1]]},o.copy=function(){return au(n,t)},u()}function lu(n,t,e){function r(t){return e[Math.max(0,Math.min(o,Math.floor(u*(t-n))))]}function i(){return u=e.length/(t-n),o=e.length-1,r}var u,o;return r.domain=function(e){return arguments.length?(n=+e[0],t=+e[e.length-1],i()):[n,t]},r.range=function(n){return arguments.length?(e=n,i()):e},r.invertExtent=function(t){return t=e.indexOf(t),t=0>t?NaN:t/u+n,[t,t+1/u]},r.copy=function(){return lu(n,t,e)},i()}function cu(n,t){function e(e){return e>=e?t[ao.bisect(n,e)]:void 0}return e.domain=function(t){return arguments.length?(n=t,e):n},e.range=function(n){return arguments.length?(t=n,e):t},e.invertExtent=function(e){return e=t.indexOf(e),[n[e-1],n[e]]},e.copy=function(){return cu(n,t)},e}function fu(n){function t(n){return+n}return t.invert=t,t.domain=t.range=function(e){return arguments.length?(n=e.map(t),t):n},t.ticks=function(t){return Qi(n,t)},t.tickFormat=function(t,e){return nu(n,t,e)},t.copy=function(){return fu(n)},t}function su(){return 0}function hu(n){return n.innerRadius}function pu(n){return n.outerRadius}function gu(n){return n.startAngle}function vu(n){return n.endAngle}function du(n){return n&&n.padAngle}function yu(n,t,e,r){return(n-e)*t-(t-r)*n>0?0:1}function mu(n,t,e,r,i){var u=n[0]-t[0],o=n[1]-t[1],a=(i?r:-r)/Math.sqrt(u*u+o*o),l=a*o,c=-a*u,f=n[0]+l,s=n[1]+c,h=t[0]+l,p=t[1]+c,g=(f+h)/2,v=(s+p)/2,d=h-f,y=p-s,m=d*d+y*y,M=e-r,x=f*p-h*s,b=(0>y?-1:1)*Math.sqrt(Math.max(0,M*M*m-x*x)),_=(x*y-d*b)/m,w=(-x*d-y*b)/m,S=(x*y+d*b)/m,k=(-x*d+y*b)/m,N=_-g,E=w-v,A=S-g,C=k-v;return N*N+E*E>A*A+C*C&&(_=S,w=k),[[_-l,w-c],[_*e/M,w*e/M]]}function Mu(n){function t(t){function o(){c.push("M",u(n(f),a))}for(var l,c=[],f=[],s=-1,h=t.length,p=En(e),g=En(r);++s<h;)i.call(this,l=t[s],s)?f.push([+p.call(this,l,s),+g.call(this,l,s)]):f.length&&(o(),f=[]);return f.length&&o(),c.length?c.join(""):null}var e=Ce,r=ze,i=zt,u=xu,o=u.key,a=.7;return t.x=function(n){return arguments.length?(e=n,t):e},t.y=function(n){return arguments.length?(r=n,t):r},t.defined=function(n){return arguments.length?(i=n,t):i},t.interpolate=function(n){return arguments.length?(o="function"==typeof n?u=n:(u=Tl.get(n)||xu).key,t):o},t.tension=function(n){return arguments.length?(a=n,t):a},t}function xu(n){return n.length>1?n.join("L"):n+"Z"}function bu(n){return n.join("L")+"Z"}function _u(n){for(var t=0,e=n.length,r=n[0],i=[r[0],",",r[1]];++t<e;)i.push("H",(r[0]+(r=n[t])[0])/2,"V",r[1]);return e>1&&i.push("H",r[0]),i.join("")}function wu(n){for(var t=0,e=n.length,r=n[0],i=[r[0],",",r[1]];++t<e;)i.push("V",(r=n[t])[1],"H",r[0]);return i.join("")}function Su(n){for(var t=0,e=n.length,r=n[0],i=[r[0],",",r[1]];++t<e;)i.push("H",(r=n[t])[0],"V",r[1]);return i.join("")}function ku(n,t){return n.length<4?xu(n):n[1]+Au(n.slice(1,-1),Cu(n,t))}function Nu(n,t){return n.length<3?bu(n):n[0]+Au((n.push(n[0]),n),Cu([n[n.length-2]].concat(n,[n[1]]),t))}function Eu(n,t){return n.length<3?xu(n):n[0]+Au(n,Cu(n,t))}function Au(n,t){if(t.length<1||n.length!=t.length&&n.length!=t.length+2)return xu(n);var e=n.length!=t.length,r="",i=n[0],u=n[1],o=t[0],a=o,l=1;if(e&&(r+="Q"+(u[0]-2*o[0]/3)+","+(u[1]-2*o[1]/3)+","+u[0]+","+u[1],i=n[1],l=2),t.length>1){a=t[1],u=n[l],l++,r+="C"+(i[0]+o[0])+","+(i[1]+o[1])+","+(u[0]-a[0])+","+(u[1]-a[1])+","+u[0]+","+u[1];for(var c=2;c<t.length;c++,l++)u=n[l],a=t[c],r+="S"+(u[0]-a[0])+","+(u[1]-a[1])+","+u[0]+","+u[1]}if(e){var f=n[l];r+="Q"+(u[0]+2*a[0]/3)+","+(u[1]+2*a[1]/3)+","+f[0]+","+f[1]}return r}function Cu(n,t){for(var e,r=[],i=(1-t)/2,u=n[0],o=n[1],a=1,l=n.length;++a<l;)e=u,u=o,o=n[a],r.push([i*(o[0]-e[0]),i*(o[1]-e[1])]);return r}function zu(n){if(n.length<3)return xu(n);var t=1,e=n.length,r=n[0],i=r[0],u=r[1],o=[i,i,i,(r=n[1])[0]],a=[u,u,u,r[1]],l=[i,",",u,"L",Ru(Pl,o),",",Ru(Pl,a)];for(n.push(n[e-1]);++t<=e;)r=n[t],o.shift(),o.push(r[0]),a.shift(),a.push(r[1]),Du(l,o,a);return n.pop(),l.push("L",r),l.join("")}function Lu(n){if(n.length<4)return xu(n);for(var t,e=[],r=-1,i=n.length,u=[0],o=[0];++r<3;)t=n[r],u.push(t[0]),o.push(t[1]);for(e.push(Ru(Pl,u)+","+Ru(Pl,o)),--r;++r<i;)t=n[r],u.shift(),u.push(t[0]),o.shift(),o.push(t[1]),Du(e,u,o);return e.join("")}function qu(n){for(var t,e,r=-1,i=n.length,u=i+4,o=[],a=[];++r<4;)e=n[r%i],o.push(e[0]),a.push(e[1]);for(t=[Ru(Pl,o),",",Ru(Pl,a)],--r;++r<u;)e=n[r%i],o.shift(),o.push(e[0]),a.shift(),a.push(e[1]),Du(t,o,a);return t.join("")}function Tu(n,t){var e=n.length-1;if(e)for(var r,i,u=n[0][0],o=n[0][1],a=n[e][0]-u,l=n[e][1]-o,c=-1;++c<=e;)r=n[c],i=c/e,r[0]=t*r[0]+(1-t)*(u+i*a),r[1]=t*r[1]+(1-t)*(o+i*l);return zu(n)}function Ru(n,t){return n[0]*t[0]+n[1]*t[1]+n[2]*t[2]+n[3]*t[3]}function Du(n,t,e){n.push("C",Ru(Rl,t),",",Ru(Rl,e),",",Ru(Dl,t),",",Ru(Dl,e),",",Ru(Pl,t),",",Ru(Pl,e))}function Pu(n,t){return(t[1]-n[1])/(t[0]-n[0])}function Uu(n){for(var t=0,e=n.length-1,r=[],i=n[0],u=n[1],o=r[0]=Pu(i,u);++t<e;)r[t]=(o+(o=Pu(i=u,u=n[t+1])))/2;return r[t]=o,r}function ju(n){for(var t,e,r,i,u=[],o=Uu(n),a=-1,l=n.length-1;++a<l;)t=Pu(n[a],n[a+1]),xo(t)<Uo?o[a]=o[a+1]=0:(e=o[a]/t,r=o[a+1]/t,i=e*e+r*r,i>9&&(i=3*t/Math.sqrt(i),o[a]=i*e,o[a+1]=i*r));for(a=-1;++a<=l;)i=(n[Math.min(l,a+1)][0]-n[Math.max(0,a-1)][0])/(6*(1+o[a]*o[a])),u.push([i||0,o[a]*i||0]);return u}function Fu(n){return n.length<3?xu(n):n[0]+Au(n,ju(n))}function Hu(n){for(var t,e,r,i=-1,u=n.length;++i<u;)t=n[i],e=t[0],r=t[1]-Io,t[0]=e*Math.cos(r),t[1]=e*Math.sin(r);return n}function Ou(n){function t(t){function l(){v.push("M",a(n(y),s),f,c(n(d.reverse()),s),"Z")}for(var h,p,g,v=[],d=[],y=[],m=-1,M=t.length,x=En(e),b=En(i),_=e===r?function(){
  22860. return p}:En(r),w=i===u?function(){return g}:En(u);++m<M;)o.call(this,h=t[m],m)?(d.push([p=+x.call(this,h,m),g=+b.call(this,h,m)]),y.push([+_.call(this,h,m),+w.call(this,h,m)])):d.length&&(l(),d=[],y=[]);return d.length&&l(),v.length?v.join(""):null}var e=Ce,r=Ce,i=0,u=ze,o=zt,a=xu,l=a.key,c=a,f="L",s=.7;return t.x=function(n){return arguments.length?(e=r=n,t):r},t.x0=function(n){return arguments.length?(e=n,t):e},t.x1=function(n){return arguments.length?(r=n,t):r},t.y=function(n){return arguments.length?(i=u=n,t):u},t.y0=function(n){return arguments.length?(i=n,t):i},t.y1=function(n){return arguments.length?(u=n,t):u},t.defined=function(n){return arguments.length?(o=n,t):o},t.interpolate=function(n){return arguments.length?(l="function"==typeof n?a=n:(a=Tl.get(n)||xu).key,c=a.reverse||a,f=a.closed?"M":"L",t):l},t.tension=function(n){return arguments.length?(s=n,t):s},t}function Iu(n){return n.radius}function Yu(n){return[n.x,n.y]}function Zu(n){return function(){var t=n.apply(this,arguments),e=t[0],r=t[1]-Io;return[e*Math.cos(r),e*Math.sin(r)]}}function Vu(){return 64}function Xu(){return"circle"}function $u(n){var t=Math.sqrt(n/Fo);return"M0,"+t+"A"+t+","+t+" 0 1,1 0,"+-t+"A"+t+","+t+" 0 1,1 0,"+t+"Z"}function Bu(n){return function(){var t,e,r;(t=this[n])&&(r=t[e=t.active])&&(r.timer.c=null,r.timer.t=NaN,--t.count?delete t[e]:delete this[n],t.active+=.5,r.event&&r.event.interrupt.call(this,this.__data__,r.index))}}function Wu(n,t,e){return ko(n,Yl),n.namespace=t,n.id=e,n}function Ju(n,t,e,r){var i=n.id,u=n.namespace;return Y(n,"function"==typeof e?function(n,o,a){n[u][i].tween.set(t,r(e.call(n,n.__data__,o,a)))}:(e=r(e),function(n){n[u][i].tween.set(t,e)}))}function Gu(n){return null==n&&(n=""),function(){this.textContent=n}}function Ku(n){return null==n?"__transition__":"__transition_"+n+"__"}function Qu(n,t,e,r,i){function u(n){var t=v.delay;return f.t=t+l,n>=t?o(n-t):void(f.c=o)}function o(e){var i=g.active,u=g[i];u&&(u.timer.c=null,u.timer.t=NaN,--g.count,delete g[i],u.event&&u.event.interrupt.call(n,n.__data__,u.index));for(var o in g)if(r>+o){var c=g[o];c.timer.c=null,c.timer.t=NaN,--g.count,delete g[o]}f.c=a,qn(function(){return f.c&&a(e||1)&&(f.c=null,f.t=NaN),1},0,l),g.active=r,v.event&&v.event.start.call(n,n.__data__,t),p=[],v.tween.forEach(function(e,r){(r=r.call(n,n.__data__,t))&&p.push(r)}),h=v.ease,s=v.duration}function a(i){for(var u=i/s,o=h(u),a=p.length;a>0;)p[--a].call(n,o);return u>=1?(v.event&&v.event.end.call(n,n.__data__,t),--g.count?delete g[r]:delete n[e],1):void 0}var l,f,s,h,p,g=n[e]||(n[e]={active:0,count:0}),v=g[r];v||(l=i.time,f=qn(u,0,l),v=g[r]={tween:new c,time:l,timer:f,delay:i.delay,duration:i.duration,ease:i.ease,index:t},i=null,++g.count)}function no(n,t,e){n.attr("transform",function(n){var r=t(n);return"translate("+(isFinite(r)?r:e(n))+",0)"})}function to(n,t,e){n.attr("transform",function(n){var r=t(n);return"translate(0,"+(isFinite(r)?r:e(n))+")"})}function eo(n){return n.toISOString()}function ro(n,t,e){function r(t){return n(t)}function i(n,e){var r=n[1]-n[0],i=r/e,u=ao.bisect(Kl,i);return u==Kl.length?[t.year,Ki(n.map(function(n){return n/31536e6}),e)[2]]:u?t[i/Kl[u-1]<Kl[u]/i?u-1:u]:[tc,Ki(n,e)[2]]}return r.invert=function(t){return io(n.invert(t))},r.domain=function(t){return arguments.length?(n.domain(t),r):n.domain().map(io)},r.nice=function(n,t){function e(e){return!isNaN(e)&&!n.range(e,io(+e+1),t).length}var u=r.domain(),o=Yi(u),a=null==n?i(o,10):"number"==typeof n&&i(o,n);return a&&(n=a[0],t=a[1]),r.domain(Xi(u,t>1?{floor:function(t){for(;e(t=n.floor(t));)t=io(t-1);return t},ceil:function(t){for(;e(t=n.ceil(t));)t=io(+t+1);return t}}:n))},r.ticks=function(n,t){var e=Yi(r.domain()),u=null==n?i(e,10):"number"==typeof n?i(e,n):!n.range&&[{range:n},t];return u&&(n=u[0],t=u[1]),n.range(e[0],io(+e[1]+1),1>t?1:t)},r.tickFormat=function(){return e},r.copy=function(){return ro(n.copy(),t,e)},Ji(r,n)}function io(n){return new Date(n)}function uo(n){return JSON.parse(n.responseText)}function oo(n){var t=fo.createRange();return t.selectNode(fo.body),t.createContextualFragment(n.responseText)}var ao={version:"3.5.17"},lo=[].slice,co=function(n){return lo.call(n)},fo=this.document;if(fo)try{co(fo.documentElement.childNodes)[0].nodeType}catch(so){co=function(n){for(var t=n.length,e=new Array(t);t--;)e[t]=n[t];return e}}if(Date.now||(Date.now=function(){return+new Date}),fo)try{fo.createElement("DIV").style.setProperty("opacity",0,"")}catch(ho){var po=this.Element.prototype,go=po.setAttribute,vo=po.setAttributeNS,yo=this.CSSStyleDeclaration.prototype,mo=yo.setProperty;po.setAttribute=function(n,t){go.call(this,n,t+"")},po.setAttributeNS=function(n,t,e){vo.call(this,n,t,e+"")},yo.setProperty=function(n,t,e){mo.call(this,n,t+"",e)}}ao.ascending=e,ao.descending=function(n,t){return n>t?-1:t>n?1:t>=n?0:NaN},ao.min=function(n,t){var e,r,i=-1,u=n.length;if(1===arguments.length){for(;++i<u;)if(null!=(r=n[i])&&r>=r){e=r;break}for(;++i<u;)null!=(r=n[i])&&e>r&&(e=r)}else{for(;++i<u;)if(null!=(r=t.call(n,n[i],i))&&r>=r){e=r;break}for(;++i<u;)null!=(r=t.call(n,n[i],i))&&e>r&&(e=r)}return e},ao.max=function(n,t){var e,r,i=-1,u=n.length;if(1===arguments.length){for(;++i<u;)if(null!=(r=n[i])&&r>=r){e=r;break}for(;++i<u;)null!=(r=n[i])&&r>e&&(e=r)}else{for(;++i<u;)if(null!=(r=t.call(n,n[i],i))&&r>=r){e=r;break}for(;++i<u;)null!=(r=t.call(n,n[i],i))&&r>e&&(e=r)}return e},ao.extent=function(n,t){var e,r,i,u=-1,o=n.length;if(1===arguments.length){for(;++u<o;)if(null!=(r=n[u])&&r>=r){e=i=r;break}for(;++u<o;)null!=(r=n[u])&&(e>r&&(e=r),r>i&&(i=r))}else{for(;++u<o;)if(null!=(r=t.call(n,n[u],u))&&r>=r){e=i=r;break}for(;++u<o;)null!=(r=t.call(n,n[u],u))&&(e>r&&(e=r),r>i&&(i=r))}return[e,i]},ao.sum=function(n,t){var e,r=0,u=n.length,o=-1;if(1===arguments.length)for(;++o<u;)i(e=+n[o])&&(r+=e);else for(;++o<u;)i(e=+t.call(n,n[o],o))&&(r+=e);return r},ao.mean=function(n,t){var e,u=0,o=n.length,a=-1,l=o;if(1===arguments.length)for(;++a<o;)i(e=r(n[a]))?u+=e:--l;else for(;++a<o;)i(e=r(t.call(n,n[a],a)))?u+=e:--l;return l?u/l:void 0},ao.quantile=function(n,t){var e=(n.length-1)*t+1,r=Math.floor(e),i=+n[r-1],u=e-r;return u?i+u*(n[r]-i):i},ao.median=function(n,t){var u,o=[],a=n.length,l=-1;if(1===arguments.length)for(;++l<a;)i(u=r(n[l]))&&o.push(u);else for(;++l<a;)i(u=r(t.call(n,n[l],l)))&&o.push(u);return o.length?ao.quantile(o.sort(e),.5):void 0},ao.variance=function(n,t){var e,u,o=n.length,a=0,l=0,c=-1,f=0;if(1===arguments.length)for(;++c<o;)i(e=r(n[c]))&&(u=e-a,a+=u/++f,l+=u*(e-a));else for(;++c<o;)i(e=r(t.call(n,n[c],c)))&&(u=e-a,a+=u/++f,l+=u*(e-a));return f>1?l/(f-1):void 0},ao.deviation=function(){var n=ao.variance.apply(this,arguments);return n?Math.sqrt(n):n};var Mo=u(e);ao.bisectLeft=Mo.left,ao.bisect=ao.bisectRight=Mo.right,ao.bisector=function(n){return u(1===n.length?function(t,r){return e(n(t),r)}:n)},ao.shuffle=function(n,t,e){(u=arguments.length)<3&&(e=n.length,2>u&&(t=0));for(var r,i,u=e-t;u;)i=Math.random()*u--|0,r=n[u+t],n[u+t]=n[i+t],n[i+t]=r;return n},ao.permute=function(n,t){for(var e=t.length,r=new Array(e);e--;)r[e]=n[t[e]];return r},ao.pairs=function(n){for(var t,e=0,r=n.length-1,i=n[0],u=new Array(0>r?0:r);r>e;)u[e]=[t=i,i=n[++e]];return u},ao.transpose=function(n){if(!(i=n.length))return[];for(var t=-1,e=ao.min(n,o),r=new Array(e);++t<e;)for(var i,u=-1,a=r[t]=new Array(i);++u<i;)a[u]=n[u][t];return r},ao.zip=function(){return ao.transpose(arguments)},ao.keys=function(n){var t=[];for(var e in n)t.push(e);return t},ao.values=function(n){var t=[];for(var e in n)t.push(n[e]);return t},ao.entries=function(n){var t=[];for(var e in n)t.push({key:e,value:n[e]});return t},ao.merge=function(n){for(var t,e,r,i=n.length,u=-1,o=0;++u<i;)o+=n[u].length;for(e=new Array(o);--i>=0;)for(r=n[i],t=r.length;--t>=0;)e[--o]=r[t];return e};var xo=Math.abs;ao.range=function(n,t,e){if(arguments.length<3&&(e=1,arguments.length<2&&(t=n,n=0)),(t-n)/e===1/0)throw new Error("infinite range");var r,i=[],u=a(xo(e)),o=-1;if(n*=u,t*=u,e*=u,0>e)for(;(r=n+e*++o)>t;)i.push(r/u);else for(;(r=n+e*++o)<t;)i.push(r/u);return i},ao.map=function(n,t){var e=new c;if(n instanceof c)n.forEach(function(n,t){e.set(n,t)});else if(Array.isArray(n)){var r,i=-1,u=n.length;if(1===arguments.length)for(;++i<u;)e.set(i,n[i]);else for(;++i<u;)e.set(t.call(n,r=n[i],i),r)}else for(var o in n)e.set(o,n[o]);return e};var bo="__proto__",_o="\x00";l(c,{has:h,get:function(n){return this._[f(n)]},set:function(n,t){return this._[f(n)]=t},remove:p,keys:g,values:function(){var n=[];for(var t in this._)n.push(this._[t]);return n},entries:function(){var n=[];for(var t in this._)n.push({key:s(t),value:this._[t]});return n},size:v,empty:d,forEach:function(n){for(var t in this._)n.call(this,s(t),this._[t])}}),ao.nest=function(){function n(t,o,a){if(a>=u.length)return r?r.call(i,o):e?o.sort(e):o;for(var l,f,s,h,p=-1,g=o.length,v=u[a++],d=new c;++p<g;)(h=d.get(l=v(f=o[p])))?h.push(f):d.set(l,[f]);return t?(f=t(),s=function(e,r){f.set(e,n(t,r,a))}):(f={},s=function(e,r){f[e]=n(t,r,a)}),d.forEach(s),f}function t(n,e){if(e>=u.length)return n;var r=[],i=o[e++];return n.forEach(function(n,i){r.push({key:n,values:t(i,e)})}),i?r.sort(function(n,t){return i(n.key,t.key)}):r}var e,r,i={},u=[],o=[];return i.map=function(t,e){return n(e,t,0)},i.entries=function(e){return t(n(ao.map,e,0),0)},i.key=function(n){return u.push(n),i},i.sortKeys=function(n){return o[u.length-1]=n,i},i.sortValues=function(n){return e=n,i},i.rollup=function(n){return r=n,i},i},ao.set=function(n){var t=new y;if(n)for(var e=0,r=n.length;r>e;++e)t.add(n[e]);return t},l(y,{has:h,add:function(n){return this._[f(n+="")]=!0,n},remove:p,values:g,size:v,empty:d,forEach:function(n){for(var t in this._)n.call(this,s(t))}}),ao.behavior={},ao.rebind=function(n,t){for(var e,r=1,i=arguments.length;++r<i;)n[e=arguments[r]]=M(n,t,t[e]);return n};var wo=["webkit","ms","moz","Moz","o","O"];ao.dispatch=function(){for(var n=new _,t=-1,e=arguments.length;++t<e;)n[arguments[t]]=w(n);return n},_.prototype.on=function(n,t){var e=n.indexOf("."),r="";if(e>=0&&(r=n.slice(e+1),n=n.slice(0,e)),n)return arguments.length<2?this[n].on(r):this[n].on(r,t);if(2===arguments.length){if(null==t)for(n in this)this.hasOwnProperty(n)&&this[n].on(r,null);return this}},ao.event=null,ao.requote=function(n){return n.replace(So,"\\$&")};var So=/[\\\^\$\*\+\?\|\[\]\(\)\.\{\}]/g,ko={}.__proto__?function(n,t){n.__proto__=t}:function(n,t){for(var e in t)n[e]=t[e]},No=function(n,t){return t.querySelector(n)},Eo=function(n,t){return t.querySelectorAll(n)},Ao=function(n,t){var e=n.matches||n[x(n,"matchesSelector")];return(Ao=function(n,t){return e.call(n,t)})(n,t)};"function"==typeof Sizzle&&(No=function(n,t){return Sizzle(n,t)[0]||null},Eo=Sizzle,Ao=Sizzle.matchesSelector),ao.selection=function(){return ao.select(fo.documentElement)};var Co=ao.selection.prototype=[];Co.select=function(n){var t,e,r,i,u=[];n=A(n);for(var o=-1,a=this.length;++o<a;){u.push(t=[]),t.parentNode=(r=this[o]).parentNode;for(var l=-1,c=r.length;++l<c;)(i=r[l])?(t.push(e=n.call(i,i.__data__,l,o)),e&&"__data__"in i&&(e.__data__=i.__data__)):t.push(null)}return E(u)},Co.selectAll=function(n){var t,e,r=[];n=C(n);for(var i=-1,u=this.length;++i<u;)for(var o=this[i],a=-1,l=o.length;++a<l;)(e=o[a])&&(r.push(t=co(n.call(e,e.__data__,a,i))),t.parentNode=e);return E(r)};var zo="http://www.w3.org/1999/xhtml",Lo={svg:"http://www.w3.org/2000/svg",xhtml:zo,xlink:"http://www.w3.org/1999/xlink",xml:"http://www.w3.org/XML/1998/namespace",xmlns:"http://www.w3.org/2000/xmlns/"};ao.ns={prefix:Lo,qualify:function(n){var t=n.indexOf(":"),e=n;return t>=0&&"xmlns"!==(e=n.slice(0,t))&&(n=n.slice(t+1)),Lo.hasOwnProperty(e)?{space:Lo[e],local:n}:n}},Co.attr=function(n,t){if(arguments.length<2){if("string"==typeof n){var e=this.node();return n=ao.ns.qualify(n),n.local?e.getAttributeNS(n.space,n.local):e.getAttribute(n)}for(t in n)this.each(z(t,n[t]));return this}return this.each(z(n,t))},Co.classed=function(n,t){if(arguments.length<2){if("string"==typeof n){var e=this.node(),r=(n=T(n)).length,i=-1;if(t=e.classList){for(;++i<r;)if(!t.contains(n[i]))return!1}else for(t=e.getAttribute("class");++i<r;)if(!q(n[i]).test(t))return!1;return!0}for(t in n)this.each(R(t,n[t]));return this}return this.each(R(n,t))},Co.style=function(n,e,r){var i=arguments.length;if(3>i){if("string"!=typeof n){2>i&&(e="");for(r in n)this.each(P(r,n[r],e));return this}if(2>i){var u=this.node();return t(u).getComputedStyle(u,null).getPropertyValue(n)}r=""}return this.each(P(n,e,r))},Co.property=function(n,t){if(arguments.length<2){if("string"==typeof n)return this.node()[n];for(t in n)this.each(U(t,n[t]));return this}return this.each(U(n,t))},Co.text=function(n){return arguments.length?this.each("function"==typeof n?function(){var t=n.apply(this,arguments);this.textContent=null==t?"":t}:null==n?function(){this.textContent=""}:function(){this.textContent=n}):this.node().textContent},Co.html=function(n){return arguments.length?this.each("function"==typeof n?function(){var t=n.apply(this,arguments);this.innerHTML=null==t?"":t}:null==n?function(){this.innerHTML=""}:function(){this.innerHTML=n}):this.node().innerHTML},Co.append=function(n){return n=j(n),this.select(function(){return this.appendChild(n.apply(this,arguments))})},Co.insert=function(n,t){return n=j(n),t=A(t),this.select(function(){return this.insertBefore(n.apply(this,arguments),t.apply(this,arguments)||null)})},Co.remove=function(){return this.each(F)},Co.data=function(n,t){function e(n,e){var r,i,u,o=n.length,s=e.length,h=Math.min(o,s),p=new Array(s),g=new Array(s),v=new Array(o);if(t){var d,y=new c,m=new Array(o);for(r=-1;++r<o;)(i=n[r])&&(y.has(d=t.call(i,i.__data__,r))?v[r]=i:y.set(d,i),m[r]=d);for(r=-1;++r<s;)(i=y.get(d=t.call(e,u=e[r],r)))?i!==!0&&(p[r]=i,i.__data__=u):g[r]=H(u),y.set(d,!0);for(r=-1;++r<o;)r in m&&y.get(m[r])!==!0&&(v[r]=n[r])}else{for(r=-1;++r<h;)i=n[r],u=e[r],i?(i.__data__=u,p[r]=i):g[r]=H(u);for(;s>r;++r)g[r]=H(e[r]);for(;o>r;++r)v[r]=n[r]}g.update=p,g.parentNode=p.parentNode=v.parentNode=n.parentNode,a.push(g),l.push(p),f.push(v)}var r,i,u=-1,o=this.length;if(!arguments.length){for(n=new Array(o=(r=this[0]).length);++u<o;)(i=r[u])&&(n[u]=i.__data__);return n}var a=Z([]),l=E([]),f=E([]);if("function"==typeof n)for(;++u<o;)e(r=this[u],n.call(r,r.parentNode.__data__,u));else for(;++u<o;)e(r=this[u],n);return l.enter=function(){return a},l.exit=function(){return f},l},Co.datum=function(n){return arguments.length?this.property("__data__",n):this.property("__data__")},Co.filter=function(n){var t,e,r,i=[];"function"!=typeof n&&(n=O(n));for(var u=0,o=this.length;o>u;u++){i.push(t=[]),t.parentNode=(e=this[u]).parentNode;for(var a=0,l=e.length;l>a;a++)(r=e[a])&&n.call(r,r.__data__,a,u)&&t.push(r)}return E(i)},Co.order=function(){for(var n=-1,t=this.length;++n<t;)for(var e,r=this[n],i=r.length-1,u=r[i];--i>=0;)(e=r[i])&&(u&&u!==e.nextSibling&&u.parentNode.insertBefore(e,u),u=e);return this},Co.sort=function(n){n=I.apply(this,arguments);for(var t=-1,e=this.length;++t<e;)this[t].sort(n);return this.order()},Co.each=function(n){return Y(this,function(t,e,r){n.call(t,t.__data__,e,r)})},Co.call=function(n){var t=co(arguments);return n.apply(t[0]=this,t),this},Co.empty=function(){return!this.node()},Co.node=function(){for(var n=0,t=this.length;t>n;n++)for(var e=this[n],r=0,i=e.length;i>r;r++){var u=e[r];if(u)return u}return null},Co.size=function(){var n=0;return Y(this,function(){++n}),n};var qo=[];ao.selection.enter=Z,ao.selection.enter.prototype=qo,qo.append=Co.append,qo.empty=Co.empty,qo.node=Co.node,qo.call=Co.call,qo.size=Co.size,qo.select=function(n){for(var t,e,r,i,u,o=[],a=-1,l=this.length;++a<l;){r=(i=this[a]).update,o.push(t=[]),t.parentNode=i.parentNode;for(var c=-1,f=i.length;++c<f;)(u=i[c])?(t.push(r[c]=e=n.call(i.parentNode,u.__data__,c,a)),e.__data__=u.__data__):t.push(null)}return E(o)},qo.insert=function(n,t){return arguments.length<2&&(t=V(this)),Co.insert.call(this,n,t)},ao.select=function(t){var e;return"string"==typeof t?(e=[No(t,fo)],e.parentNode=fo.documentElement):(e=[t],e.parentNode=n(t)),E([e])},ao.selectAll=function(n){var t;return"string"==typeof n?(t=co(Eo(n,fo)),t.parentNode=fo.documentElement):(t=co(n),t.parentNode=null),E([t])},Co.on=function(n,t,e){var r=arguments.length;if(3>r){if("string"!=typeof n){2>r&&(t=!1);for(e in n)this.each(X(e,n[e],t));return this}if(2>r)return(r=this.node()["__on"+n])&&r._;e=!1}return this.each(X(n,t,e))};var To=ao.map({mouseenter:"mouseover",mouseleave:"mouseout"});fo&&To.forEach(function(n){"on"+n in fo&&To.remove(n)});var Ro,Do=0;ao.mouse=function(n){return J(n,k())};var Po=this.navigator&&/WebKit/.test(this.navigator.userAgent)?-1:0;ao.touch=function(n,t,e){if(arguments.length<3&&(e=t,t=k().changedTouches),t)for(var r,i=0,u=t.length;u>i;++i)if((r=t[i]).identifier===e)return J(n,r)},ao.behavior.drag=function(){function n(){this.on("mousedown.drag",u).on("touchstart.drag",o)}function e(n,t,e,u,o){return function(){function a(){var n,e,r=t(h,v);r&&(n=r[0]-M[0],e=r[1]-M[1],g|=n|e,M=r,p({type:"drag",x:r[0]+c[0],y:r[1]+c[1],dx:n,dy:e}))}function l(){t(h,v)&&(y.on(u+d,null).on(o+d,null),m(g),p({type:"dragend"}))}var c,f=this,s=ao.event.target.correspondingElement||ao.event.target,h=f.parentNode,p=r.of(f,arguments),g=0,v=n(),d=".drag"+(null==v?"":"-"+v),y=ao.select(e(s)).on(u+d,a).on(o+d,l),m=W(s),M=t(h,v);i?(c=i.apply(f,arguments),c=[c.x-M[0],c.y-M[1]]):c=[0,0],p({type:"dragstart"})}}var r=N(n,"drag","dragstart","dragend"),i=null,u=e(b,ao.mouse,t,"mousemove","mouseup"),o=e(G,ao.touch,m,"touchmove","touchend");return n.origin=function(t){return arguments.length?(i=t,n):i},ao.rebind(n,r,"on")},ao.touches=function(n,t){return arguments.length<2&&(t=k().touches),t?co(t).map(function(t){var e=J(n,t);return e.identifier=t.identifier,e}):[]};var Uo=1e-6,jo=Uo*Uo,Fo=Math.PI,Ho=2*Fo,Oo=Ho-Uo,Io=Fo/2,Yo=Fo/180,Zo=180/Fo,Vo=Math.SQRT2,Xo=2,$o=4;ao.interpolateZoom=function(n,t){var e,r,i=n[0],u=n[1],o=n[2],a=t[0],l=t[1],c=t[2],f=a-i,s=l-u,h=f*f+s*s;if(jo>h)r=Math.log(c/o)/Vo,e=function(n){return[i+n*f,u+n*s,o*Math.exp(Vo*n*r)]};else{var p=Math.sqrt(h),g=(c*c-o*o+$o*h)/(2*o*Xo*p),v=(c*c-o*o-$o*h)/(2*c*Xo*p),d=Math.log(Math.sqrt(g*g+1)-g),y=Math.log(Math.sqrt(v*v+1)-v);r=(y-d)/Vo,e=function(n){var t=n*r,e=rn(d),a=o/(Xo*p)*(e*un(Vo*t+d)-en(d));return[i+a*f,u+a*s,o*e/rn(Vo*t+d)]}}return e.duration=1e3*r,e},ao.behavior.zoom=function(){function n(n){n.on(L,s).on(Wo+".zoom",p).on("dblclick.zoom",g).on(R,h)}function e(n){return[(n[0]-k.x)/k.k,(n[1]-k.y)/k.k]}function r(n){return[n[0]*k.k+k.x,n[1]*k.k+k.y]}function i(n){k.k=Math.max(A[0],Math.min(A[1],n))}function u(n,t){t=r(t),k.x+=n[0]-t[0],k.y+=n[1]-t[1]}function o(t,e,r,o){t.__chart__={x:k.x,y:k.y,k:k.k},i(Math.pow(2,o)),u(d=e,r),t=ao.select(t),C>0&&(t=t.transition().duration(C)),t.call(n.event)}function a(){b&&b.domain(x.range().map(function(n){return(n-k.x)/k.k}).map(x.invert)),w&&w.domain(_.range().map(function(n){return(n-k.y)/k.k}).map(_.invert))}function l(n){z++||n({type:"zoomstart"})}function c(n){a(),n({type:"zoom",scale:k.k,translate:[k.x,k.y]})}function f(n){--z||(n({type:"zoomend"}),d=null)}function s(){function n(){a=1,u(ao.mouse(i),h),c(o)}function r(){s.on(q,null).on(T,null),p(a),f(o)}var i=this,o=D.of(i,arguments),a=0,s=ao.select(t(i)).on(q,n).on(T,r),h=e(ao.mouse(i)),p=W(i);Il.call(i),l(o)}function h(){function n(){var n=ao.touches(g);return p=k.k,n.forEach(function(n){n.identifier in d&&(d[n.identifier]=e(n))}),n}function t(){var t=ao.event.target;ao.select(t).on(x,r).on(b,a),_.push(t);for(var e=ao.event.changedTouches,i=0,u=e.length;u>i;++i)d[e[i].identifier]=null;var l=n(),c=Date.now();if(1===l.length){if(500>c-M){var f=l[0];o(g,f,d[f.identifier],Math.floor(Math.log(k.k)/Math.LN2)+1),S()}M=c}else if(l.length>1){var f=l[0],s=l[1],h=f[0]-s[0],p=f[1]-s[1];y=h*h+p*p}}function r(){var n,t,e,r,o=ao.touches(g);Il.call(g);for(var a=0,l=o.length;l>a;++a,r=null)if(e=o[a],r=d[e.identifier]){if(t)break;n=e,t=r}if(r){var f=(f=e[0]-n[0])*f+(f=e[1]-n[1])*f,s=y&&Math.sqrt(f/y);n=[(n[0]+e[0])/2,(n[1]+e[1])/2],t=[(t[0]+r[0])/2,(t[1]+r[1])/2],i(s*p)}M=null,u(n,t),c(v)}function a(){if(ao.event.touches.length){for(var t=ao.event.changedTouches,e=0,r=t.length;r>e;++e)delete d[t[e].identifier];for(var i in d)return void n()}ao.selectAll(_).on(m,null),w.on(L,s).on(R,h),N(),f(v)}var p,g=this,v=D.of(g,arguments),d={},y=0,m=".zoom-"+ao.event.changedTouches[0].identifier,x="touchmove"+m,b="touchend"+m,_=[],w=ao.select(g),N=W(g);t(),l(v),w.on(L,null).on(R,t)}function p(){var n=D.of(this,arguments);m?clearTimeout(m):(Il.call(this),v=e(d=y||ao.mouse(this)),l(n)),m=setTimeout(function(){m=null,f(n)},50),S(),i(Math.pow(2,.002*Bo())*k.k),u(d,v),c(n)}function g(){var n=ao.mouse(this),t=Math.log(k.k)/Math.LN2;o(this,n,e(n),ao.event.shiftKey?Math.ceil(t)-1:Math.floor(t)+1)}var v,d,y,m,M,x,b,_,w,k={x:0,y:0,k:1},E=[960,500],A=Jo,C=250,z=0,L="mousedown.zoom",q="mousemove.zoom",T="mouseup.zoom",R="touchstart.zoom",D=N(n,"zoomstart","zoom","zoomend");return Wo||(Wo="onwheel"in fo?(Bo=function(){return-ao.event.deltaY*(ao.event.deltaMode?120:1)},"wheel"):"onmousewheel"in fo?(Bo=function(){return ao.event.wheelDelta},"mousewheel"):(Bo=function(){return-ao.event.detail},"MozMousePixelScroll")),n.event=function(n){n.each(function(){var n=D.of(this,arguments),t=k;Hl?ao.select(this).transition().each("start.zoom",function(){k=this.__chart__||{x:0,y:0,k:1},l(n)}).tween("zoom:zoom",function(){var e=E[0],r=E[1],i=d?d[0]:e/2,u=d?d[1]:r/2,o=ao.interpolateZoom([(i-k.x)/k.k,(u-k.y)/k.k,e/k.k],[(i-t.x)/t.k,(u-t.y)/t.k,e/t.k]);return function(t){var r=o(t),a=e/r[2];this.__chart__=k={x:i-r[0]*a,y:u-r[1]*a,k:a},c(n)}}).each("interrupt.zoom",function(){f(n)}).each("end.zoom",function(){f(n)}):(this.__chart__=k,l(n),c(n),f(n))})},n.translate=function(t){return arguments.length?(k={x:+t[0],y:+t[1],k:k.k},a(),n):[k.x,k.y]},n.scale=function(t){return arguments.length?(k={x:k.x,y:k.y,k:null},i(+t),a(),n):k.k},n.scaleExtent=function(t){return arguments.length?(A=null==t?Jo:[+t[0],+t[1]],n):A},n.center=function(t){return arguments.length?(y=t&&[+t[0],+t[1]],n):y},n.size=function(t){return arguments.length?(E=t&&[+t[0],+t[1]],n):E},n.duration=function(t){return arguments.length?(C=+t,n):C},n.x=function(t){return arguments.length?(b=t,x=t.copy(),k={x:0,y:0,k:1},n):b},n.y=function(t){return arguments.length?(w=t,_=t.copy(),k={x:0,y:0,k:1},n):w},ao.rebind(n,D,"on")};var Bo,Wo,Jo=[0,1/0];ao.color=an,an.prototype.toString=function(){return this.rgb()+""},ao.hsl=ln;var Go=ln.prototype=new an;Go.brighter=function(n){return n=Math.pow(.7,arguments.length?n:1),new ln(this.h,this.s,this.l/n)},Go.darker=function(n){return n=Math.pow(.7,arguments.length?n:1),new ln(this.h,this.s,n*this.l)},Go.rgb=function(){return cn(this.h,this.s,this.l)},ao.hcl=fn;var Ko=fn.prototype=new an;Ko.brighter=function(n){return new fn(this.h,this.c,Math.min(100,this.l+Qo*(arguments.length?n:1)))},Ko.darker=function(n){return new fn(this.h,this.c,Math.max(0,this.l-Qo*(arguments.length?n:1)))},Ko.rgb=function(){return sn(this.h,this.c,this.l).rgb()},ao.lab=hn;var Qo=18,na=.95047,ta=1,ea=1.08883,ra=hn.prototype=new an;ra.brighter=function(n){return new hn(Math.min(100,this.l+Qo*(arguments.length?n:1)),this.a,this.b)},ra.darker=function(n){return new hn(Math.max(0,this.l-Qo*(arguments.length?n:1)),this.a,this.b)},ra.rgb=function(){return pn(this.l,this.a,this.b)},ao.rgb=mn;var ia=mn.prototype=new an;ia.brighter=function(n){n=Math.pow(.7,arguments.length?n:1);var t=this.r,e=this.g,r=this.b,i=30;return t||e||r?(t&&i>t&&(t=i),e&&i>e&&(e=i),r&&i>r&&(r=i),new mn(Math.min(255,t/n),Math.min(255,e/n),Math.min(255,r/n))):new mn(i,i,i)},ia.darker=function(n){return n=Math.pow(.7,arguments.length?n:1),new mn(n*this.r,n*this.g,n*this.b)},ia.hsl=function(){return wn(this.r,this.g,this.b)},ia.toString=function(){return"#"+bn(this.r)+bn(this.g)+bn(this.b)};var ua=ao.map({aliceblue:15792383,antiquewhite:16444375,aqua:65535,aquamarine:8388564,azure:15794175,beige:16119260,bisque:16770244,black:0,blanchedalmond:16772045,blue:255,blueviolet:9055202,brown:10824234,burlywood:14596231,cadetblue:6266528,chartreuse:8388352,chocolate:13789470,coral:16744272,cornflowerblue:6591981,cornsilk:16775388,crimson:14423100,cyan:65535,darkblue:139,darkcyan:35723,darkgoldenrod:12092939,darkgray:11119017,darkgreen:25600,darkgrey:11119017,darkkhaki:12433259,darkmagenta:9109643,darkolivegreen:5597999,darkorange:16747520,darkorchid:10040012,darkred:9109504,darksalmon:15308410,darkseagreen:9419919,darkslateblue:4734347,darkslategray:3100495,darkslategrey:3100495,darkturquoise:52945,darkviolet:9699539,deeppink:16716947,deepskyblue:49151,dimgray:6908265,dimgrey:6908265,dodgerblue:2003199,firebrick:11674146,floralwhite:16775920,forestgreen:2263842,fuchsia:16711935,gainsboro:14474460,ghostwhite:16316671,gold:16766720,goldenrod:14329120,gray:8421504,green:32768,greenyellow:11403055,grey:8421504,honeydew:15794160,hotpink:16738740,indianred:13458524,indigo:4915330,ivory:16777200,khaki:15787660,lavender:15132410,lavenderblush:16773365,lawngreen:8190976,lemonchiffon:16775885,lightblue:11393254,lightcoral:15761536,lightcyan:14745599,lightgoldenrodyellow:16448210,lightgray:13882323,lightgreen:9498256,lightgrey:13882323,lightpink:16758465,lightsalmon:16752762,lightseagreen:2142890,lightskyblue:8900346,lightslategray:7833753,lightslategrey:7833753,lightsteelblue:11584734,lightyellow:16777184,lime:65280,limegreen:3329330,linen:16445670,magenta:16711935,maroon:8388608,mediumaquamarine:6737322,mediumblue:205,mediumorchid:12211667,mediumpurple:9662683,mediumseagreen:3978097,mediumslateblue:8087790,mediumspringgreen:64154,mediumturquoise:4772300,mediumvioletred:13047173,midnightblue:1644912,mintcream:16121850,mistyrose:16770273,moccasin:16770229,navajowhite:16768685,navy:128,oldlace:16643558,olive:8421376,olivedrab:7048739,orange:16753920,orangered:16729344,orchid:14315734,palegoldenrod:15657130,palegreen:10025880,paleturquoise:11529966,palevioletred:14381203,papayawhip:16773077,peachpuff:16767673,peru:13468991,pink:16761035,plum:14524637,powderblue:11591910,purple:8388736,rebeccapurple:6697881,red:16711680,rosybrown:12357519,royalblue:4286945,saddlebrown:9127187,salmon:16416882,sandybrown:16032864,seagreen:3050327,seashell:16774638,sienna:10506797,silver:12632256,skyblue:8900331,slateblue:6970061,slategray:7372944,slategrey:7372944,snow:16775930,springgreen:65407,steelblue:4620980,tan:13808780,teal:32896,thistle:14204888,tomato:16737095,turquoise:4251856,violet:15631086,wheat:16113331,white:16777215,whitesmoke:16119285,yellow:16776960,yellowgreen:10145074});ua.forEach(function(n,t){ua.set(n,Mn(t))}),ao.functor=En,ao.xhr=An(m),ao.dsv=function(n,t){function e(n,e,u){arguments.length<3&&(u=e,e=null);var o=Cn(n,t,null==e?r:i(e),u);return o.row=function(n){return arguments.length?o.response(null==(e=n)?r:i(n)):e},o}function r(n){return e.parse(n.responseText)}function i(n){return function(t){return e.parse(t.responseText,n)}}function u(t){return t.map(o).join(n)}function o(n){return a.test(n)?'"'+n.replace(/\"/g,'""')+'"':n}var a=new RegExp('["'+n+"\n]"),l=n.charCodeAt(0);return e.parse=function(n,t){var r;return e.parseRows(n,function(n,e){if(r)return r(n,e-1);var i=new Function("d","return {"+n.map(function(n,t){return JSON.stringify(n)+": d["+t+"]"}).join(",")+"}");r=t?function(n,e){return t(i(n),e)}:i})},e.parseRows=function(n,t){function e(){if(f>=c)return o;if(i)return i=!1,u;var t=f;if(34===n.charCodeAt(t)){for(var e=t;e++<c;)if(34===n.charCodeAt(e)){if(34!==n.charCodeAt(e+1))break;++e}f=e+2;var r=n.charCodeAt(e+1);return 13===r?(i=!0,10===n.charCodeAt(e+2)&&++f):10===r&&(i=!0),n.slice(t+1,e).replace(/""/g,'"')}for(;c>f;){var r=n.charCodeAt(f++),a=1;if(10===r)i=!0;else if(13===r)i=!0,10===n.charCodeAt(f)&&(++f,++a);else if(r!==l)continue;return n.slice(t,f-a)}return n.slice(t)}for(var r,i,u={},o={},a=[],c=n.length,f=0,s=0;(r=e())!==o;){for(var h=[];r!==u&&r!==o;)h.push(r),r=e();t&&null==(h=t(h,s++))||a.push(h)}return a},e.format=function(t){if(Array.isArray(t[0]))return e.formatRows(t);var r=new y,i=[];return t.forEach(function(n){for(var t in n)r.has(t)||i.push(r.add(t))}),[i.map(o).join(n)].concat(t.map(function(t){return i.map(function(n){return o(t[n])}).join(n)})).join("\n")},e.formatRows=function(n){return n.map(u).join("\n")},e},ao.csv=ao.dsv(",","text/csv"),ao.tsv=ao.dsv(" ","text/tab-separated-values");var oa,aa,la,ca,fa=this[x(this,"requestAnimationFrame")]||function(n){setTimeout(n,17)};ao.timer=function(){qn.apply(this,arguments)},ao.timer.flush=function(){Rn(),Dn()},ao.round=function(n,t){return t?Math.round(n*(t=Math.pow(10,t)))/t:Math.round(n)};var sa=["y","z","a","f","p","n","\xb5","m","","k","M","G","T","P","E","Z","Y"].map(Un);ao.formatPrefix=function(n,t){var e=0;return(n=+n)&&(0>n&&(n*=-1),t&&(n=ao.round(n,Pn(n,t))),e=1+Math.floor(1e-12+Math.log(n)/Math.LN10),e=Math.max(-24,Math.min(24,3*Math.floor((e-1)/3)))),sa[8+e/3]};var ha=/(?:([^{])?([<>=^]))?([+\- ])?([$#])?(0)?(\d+)?(,)?(\.-?\d+)?([a-z%])?/i,pa=ao.map({b:function(n){return n.toString(2)},c:function(n){return String.fromCharCode(n)},o:function(n){return n.toString(8)},x:function(n){return n.toString(16)},X:function(n){return n.toString(16).toUpperCase()},g:function(n,t){return n.toPrecision(t)},e:function(n,t){return n.toExponential(t)},f:function(n,t){return n.toFixed(t)},r:function(n,t){return(n=ao.round(n,Pn(n,t))).toFixed(Math.max(0,Math.min(20,Pn(n*(1+1e-15),t))))}}),ga=ao.time={},va=Date;Hn.prototype={getDate:function(){return this._.getUTCDate()},getDay:function(){return this._.getUTCDay()},getFullYear:function(){return this._.getUTCFullYear()},getHours:function(){return this._.getUTCHours()},getMilliseconds:function(){return this._.getUTCMilliseconds()},getMinutes:function(){return this._.getUTCMinutes()},getMonth:function(){return this._.getUTCMonth()},getSeconds:function(){return this._.getUTCSeconds()},getTime:function(){return this._.getTime()},getTimezoneOffset:function(){return 0},valueOf:function(){return this._.valueOf()},setDate:function(){da.setUTCDate.apply(this._,arguments)},setDay:function(){da.setUTCDay.apply(this._,arguments)},setFullYear:function(){da.setUTCFullYear.apply(this._,arguments)},setHours:function(){da.setUTCHours.apply(this._,arguments)},setMilliseconds:function(){da.setUTCMilliseconds.apply(this._,arguments)},setMinutes:function(){da.setUTCMinutes.apply(this._,arguments)},setMonth:function(){da.setUTCMonth.apply(this._,arguments)},setSeconds:function(){da.setUTCSeconds.apply(this._,arguments)},setTime:function(){da.setTime.apply(this._,arguments)}};var da=Date.prototype;ga.year=On(function(n){return n=ga.day(n),n.setMonth(0,1),n},function(n,t){n.setFullYear(n.getFullYear()+t)},function(n){return n.getFullYear()}),ga.years=ga.year.range,ga.years.utc=ga.year.utc.range,ga.day=On(function(n){var t=new va(2e3,0);return t.setFullYear(n.getFullYear(),n.getMonth(),n.getDate()),t},function(n,t){n.setDate(n.getDate()+t)},function(n){return n.getDate()-1}),ga.days=ga.day.range,ga.days.utc=ga.day.utc.range,ga.dayOfYear=function(n){var t=ga.year(n);return Math.floor((n-t-6e4*(n.getTimezoneOffset()-t.getTimezoneOffset()))/864e5)},["sunday","monday","tuesday","wednesday","thursday","friday","saturday"].forEach(function(n,t){t=7-t;var e=ga[n]=On(function(n){return(n=ga.day(n)).setDate(n.getDate()-(n.getDay()+t)%7),n},function(n,t){n.setDate(n.getDate()+7*Math.floor(t))},function(n){var e=ga.year(n).getDay();return Math.floor((ga.dayOfYear(n)+(e+t)%7)/7)-(e!==t)});ga[n+"s"]=e.range,ga[n+"s"].utc=e.utc.range,ga[n+"OfYear"]=function(n){var e=ga.year(n).getDay();return Math.floor((ga.dayOfYear(n)+(e+t)%7)/7)}}),ga.week=ga.sunday,ga.weeks=ga.sunday.range,ga.weeks.utc=ga.sunday.utc.range,ga.weekOfYear=ga.sundayOfYear;var ya={"-":"",_:" ",0:"0"},ma=/^\s*\d+/,Ma=/^%/;ao.locale=function(n){return{numberFormat:jn(n),timeFormat:Yn(n)}};var xa=ao.locale({decimal:".",thousands:",",grouping:[3],currency:["$",""],dateTime:"%a %b %e %X %Y",date:"%m/%d/%Y",time:"%H:%M:%S",periods:["AM","PM"],days:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],
  22861. shortDays:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],months:["January","February","March","April","May","June","July","August","September","October","November","December"],shortMonths:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"]});ao.format=xa.numberFormat,ao.geo={},ft.prototype={s:0,t:0,add:function(n){st(n,this.t,ba),st(ba.s,this.s,this),this.s?this.t+=ba.t:this.s=ba.t},reset:function(){this.s=this.t=0},valueOf:function(){return this.s}};var ba=new ft;ao.geo.stream=function(n,t){n&&_a.hasOwnProperty(n.type)?_a[n.type](n,t):ht(n,t)};var _a={Feature:function(n,t){ht(n.geometry,t)},FeatureCollection:function(n,t){for(var e=n.features,r=-1,i=e.length;++r<i;)ht(e[r].geometry,t)}},wa={Sphere:function(n,t){t.sphere()},Point:function(n,t){n=n.coordinates,t.point(n[0],n[1],n[2])},MultiPoint:function(n,t){for(var e=n.coordinates,r=-1,i=e.length;++r<i;)n=e[r],t.point(n[0],n[1],n[2])},LineString:function(n,t){pt(n.coordinates,t,0)},MultiLineString:function(n,t){for(var e=n.coordinates,r=-1,i=e.length;++r<i;)pt(e[r],t,0)},Polygon:function(n,t){gt(n.coordinates,t)},MultiPolygon:function(n,t){for(var e=n.coordinates,r=-1,i=e.length;++r<i;)gt(e[r],t)},GeometryCollection:function(n,t){for(var e=n.geometries,r=-1,i=e.length;++r<i;)ht(e[r],t)}};ao.geo.area=function(n){return Sa=0,ao.geo.stream(n,Na),Sa};var Sa,ka=new ft,Na={sphere:function(){Sa+=4*Fo},point:b,lineStart:b,lineEnd:b,polygonStart:function(){ka.reset(),Na.lineStart=vt},polygonEnd:function(){var n=2*ka;Sa+=0>n?4*Fo+n:n,Na.lineStart=Na.lineEnd=Na.point=b}};ao.geo.bounds=function(){function n(n,t){M.push(x=[f=n,h=n]),s>t&&(s=t),t>p&&(p=t)}function t(t,e){var r=dt([t*Yo,e*Yo]);if(y){var i=mt(y,r),u=[i[1],-i[0],0],o=mt(u,i);bt(o),o=_t(o);var l=t-g,c=l>0?1:-1,v=o[0]*Zo*c,d=xo(l)>180;if(d^(v>c*g&&c*t>v)){var m=o[1]*Zo;m>p&&(p=m)}else if(v=(v+360)%360-180,d^(v>c*g&&c*t>v)){var m=-o[1]*Zo;s>m&&(s=m)}else s>e&&(s=e),e>p&&(p=e);d?g>t?a(f,t)>a(f,h)&&(h=t):a(t,h)>a(f,h)&&(f=t):h>=f?(f>t&&(f=t),t>h&&(h=t)):t>g?a(f,t)>a(f,h)&&(h=t):a(t,h)>a(f,h)&&(f=t)}else n(t,e);y=r,g=t}function e(){b.point=t}function r(){x[0]=f,x[1]=h,b.point=n,y=null}function i(n,e){if(y){var r=n-g;m+=xo(r)>180?r+(r>0?360:-360):r}else v=n,d=e;Na.point(n,e),t(n,e)}function u(){Na.lineStart()}function o(){i(v,d),Na.lineEnd(),xo(m)>Uo&&(f=-(h=180)),x[0]=f,x[1]=h,y=null}function a(n,t){return(t-=n)<0?t+360:t}function l(n,t){return n[0]-t[0]}function c(n,t){return t[0]<=t[1]?t[0]<=n&&n<=t[1]:n<t[0]||t[1]<n}var f,s,h,p,g,v,d,y,m,M,x,b={point:n,lineStart:e,lineEnd:r,polygonStart:function(){b.point=i,b.lineStart=u,b.lineEnd=o,m=0,Na.polygonStart()},polygonEnd:function(){Na.polygonEnd(),b.point=n,b.lineStart=e,b.lineEnd=r,0>ka?(f=-(h=180),s=-(p=90)):m>Uo?p=90:-Uo>m&&(s=-90),x[0]=f,x[1]=h}};return function(n){p=h=-(f=s=1/0),M=[],ao.geo.stream(n,b);var t=M.length;if(t){M.sort(l);for(var e,r=1,i=M[0],u=[i];t>r;++r)e=M[r],c(e[0],i)||c(e[1],i)?(a(i[0],e[1])>a(i[0],i[1])&&(i[1]=e[1]),a(e[0],i[1])>a(i[0],i[1])&&(i[0]=e[0])):u.push(i=e);for(var o,e,g=-(1/0),t=u.length-1,r=0,i=u[t];t>=r;i=e,++r)e=u[r],(o=a(i[1],e[0]))>g&&(g=o,f=e[0],h=i[1])}return M=x=null,f===1/0||s===1/0?[[NaN,NaN],[NaN,NaN]]:[[f,s],[h,p]]}}(),ao.geo.centroid=function(n){Ea=Aa=Ca=za=La=qa=Ta=Ra=Da=Pa=Ua=0,ao.geo.stream(n,ja);var t=Da,e=Pa,r=Ua,i=t*t+e*e+r*r;return jo>i&&(t=qa,e=Ta,r=Ra,Uo>Aa&&(t=Ca,e=za,r=La),i=t*t+e*e+r*r,jo>i)?[NaN,NaN]:[Math.atan2(e,t)*Zo,tn(r/Math.sqrt(i))*Zo]};var Ea,Aa,Ca,za,La,qa,Ta,Ra,Da,Pa,Ua,ja={sphere:b,point:St,lineStart:Nt,lineEnd:Et,polygonStart:function(){ja.lineStart=At},polygonEnd:function(){ja.lineStart=Nt}},Fa=Rt(zt,jt,Ht,[-Fo,-Fo/2]),Ha=1e9;ao.geo.clipExtent=function(){var n,t,e,r,i,u,o={stream:function(n){return i&&(i.valid=!1),i=u(n),i.valid=!0,i},extent:function(a){return arguments.length?(u=Zt(n=+a[0][0],t=+a[0][1],e=+a[1][0],r=+a[1][1]),i&&(i.valid=!1,i=null),o):[[n,t],[e,r]]}};return o.extent([[0,0],[960,500]])},(ao.geo.conicEqualArea=function(){return Vt(Xt)}).raw=Xt,ao.geo.albers=function(){return ao.geo.conicEqualArea().rotate([96,0]).center([-.6,38.7]).parallels([29.5,45.5]).scale(1070)},ao.geo.albersUsa=function(){function n(n){var u=n[0],o=n[1];return t=null,e(u,o),t||(r(u,o),t)||i(u,o),t}var t,e,r,i,u=ao.geo.albers(),o=ao.geo.conicEqualArea().rotate([154,0]).center([-2,58.5]).parallels([55,65]),a=ao.geo.conicEqualArea().rotate([157,0]).center([-3,19.9]).parallels([8,18]),l={point:function(n,e){t=[n,e]}};return n.invert=function(n){var t=u.scale(),e=u.translate(),r=(n[0]-e[0])/t,i=(n[1]-e[1])/t;return(i>=.12&&.234>i&&r>=-.425&&-.214>r?o:i>=.166&&.234>i&&r>=-.214&&-.115>r?a:u).invert(n)},n.stream=function(n){var t=u.stream(n),e=o.stream(n),r=a.stream(n);return{point:function(n,i){t.point(n,i),e.point(n,i),r.point(n,i)},sphere:function(){t.sphere(),e.sphere(),r.sphere()},lineStart:function(){t.lineStart(),e.lineStart(),r.lineStart()},lineEnd:function(){t.lineEnd(),e.lineEnd(),r.lineEnd()},polygonStart:function(){t.polygonStart(),e.polygonStart(),r.polygonStart()},polygonEnd:function(){t.polygonEnd(),e.polygonEnd(),r.polygonEnd()}}},n.precision=function(t){return arguments.length?(u.precision(t),o.precision(t),a.precision(t),n):u.precision()},n.scale=function(t){return arguments.length?(u.scale(t),o.scale(.35*t),a.scale(t),n.translate(u.translate())):u.scale()},n.translate=function(t){if(!arguments.length)return u.translate();var c=u.scale(),f=+t[0],s=+t[1];return e=u.translate(t).clipExtent([[f-.455*c,s-.238*c],[f+.455*c,s+.238*c]]).stream(l).point,r=o.translate([f-.307*c,s+.201*c]).clipExtent([[f-.425*c+Uo,s+.12*c+Uo],[f-.214*c-Uo,s+.234*c-Uo]]).stream(l).point,i=a.translate([f-.205*c,s+.212*c]).clipExtent([[f-.214*c+Uo,s+.166*c+Uo],[f-.115*c-Uo,s+.234*c-Uo]]).stream(l).point,n},n.scale(1070)};var Oa,Ia,Ya,Za,Va,Xa,$a={point:b,lineStart:b,lineEnd:b,polygonStart:function(){Ia=0,$a.lineStart=$t},polygonEnd:function(){$a.lineStart=$a.lineEnd=$a.point=b,Oa+=xo(Ia/2)}},Ba={point:Bt,lineStart:b,lineEnd:b,polygonStart:b,polygonEnd:b},Wa={point:Gt,lineStart:Kt,lineEnd:Qt,polygonStart:function(){Wa.lineStart=ne},polygonEnd:function(){Wa.point=Gt,Wa.lineStart=Kt,Wa.lineEnd=Qt}};ao.geo.path=function(){function n(n){return n&&("function"==typeof a&&u.pointRadius(+a.apply(this,arguments)),o&&o.valid||(o=i(u)),ao.geo.stream(n,o)),u.result()}function t(){return o=null,n}var e,r,i,u,o,a=4.5;return n.area=function(n){return Oa=0,ao.geo.stream(n,i($a)),Oa},n.centroid=function(n){return Ca=za=La=qa=Ta=Ra=Da=Pa=Ua=0,ao.geo.stream(n,i(Wa)),Ua?[Da/Ua,Pa/Ua]:Ra?[qa/Ra,Ta/Ra]:La?[Ca/La,za/La]:[NaN,NaN]},n.bounds=function(n){return Va=Xa=-(Ya=Za=1/0),ao.geo.stream(n,i(Ba)),[[Ya,Za],[Va,Xa]]},n.projection=function(n){return arguments.length?(i=(e=n)?n.stream||re(n):m,t()):e},n.context=function(n){return arguments.length?(u=null==(r=n)?new Wt:new te(n),"function"!=typeof a&&u.pointRadius(a),t()):r},n.pointRadius=function(t){return arguments.length?(a="function"==typeof t?t:(u.pointRadius(+t),+t),n):a},n.projection(ao.geo.albersUsa()).context(null)},ao.geo.transform=function(n){return{stream:function(t){var e=new ie(t);for(var r in n)e[r]=n[r];return e}}},ie.prototype={point:function(n,t){this.stream.point(n,t)},sphere:function(){this.stream.sphere()},lineStart:function(){this.stream.lineStart()},lineEnd:function(){this.stream.lineEnd()},polygonStart:function(){this.stream.polygonStart()},polygonEnd:function(){this.stream.polygonEnd()}},ao.geo.projection=oe,ao.geo.projectionMutator=ae,(ao.geo.equirectangular=function(){return oe(ce)}).raw=ce.invert=ce,ao.geo.rotation=function(n){function t(t){return t=n(t[0]*Yo,t[1]*Yo),t[0]*=Zo,t[1]*=Zo,t}return n=se(n[0]%360*Yo,n[1]*Yo,n.length>2?n[2]*Yo:0),t.invert=function(t){return t=n.invert(t[0]*Yo,t[1]*Yo),t[0]*=Zo,t[1]*=Zo,t},t},fe.invert=ce,ao.geo.circle=function(){function n(){var n="function"==typeof r?r.apply(this,arguments):r,t=se(-n[0]*Yo,-n[1]*Yo,0).invert,i=[];return e(null,null,1,{point:function(n,e){i.push(n=t(n,e)),n[0]*=Zo,n[1]*=Zo}}),{type:"Polygon",coordinates:[i]}}var t,e,r=[0,0],i=6;return n.origin=function(t){return arguments.length?(r=t,n):r},n.angle=function(r){return arguments.length?(e=ve((t=+r)*Yo,i*Yo),n):t},n.precision=function(r){return arguments.length?(e=ve(t*Yo,(i=+r)*Yo),n):i},n.angle(90)},ao.geo.distance=function(n,t){var e,r=(t[0]-n[0])*Yo,i=n[1]*Yo,u=t[1]*Yo,o=Math.sin(r),a=Math.cos(r),l=Math.sin(i),c=Math.cos(i),f=Math.sin(u),s=Math.cos(u);return Math.atan2(Math.sqrt((e=s*o)*e+(e=c*f-l*s*a)*e),l*f+c*s*a)},ao.geo.graticule=function(){function n(){return{type:"MultiLineString",coordinates:t()}}function t(){return ao.range(Math.ceil(u/d)*d,i,d).map(h).concat(ao.range(Math.ceil(c/y)*y,l,y).map(p)).concat(ao.range(Math.ceil(r/g)*g,e,g).filter(function(n){return xo(n%d)>Uo}).map(f)).concat(ao.range(Math.ceil(a/v)*v,o,v).filter(function(n){return xo(n%y)>Uo}).map(s))}var e,r,i,u,o,a,l,c,f,s,h,p,g=10,v=g,d=90,y=360,m=2.5;return n.lines=function(){return t().map(function(n){return{type:"LineString",coordinates:n}})},n.outline=function(){return{type:"Polygon",coordinates:[h(u).concat(p(l).slice(1),h(i).reverse().slice(1),p(c).reverse().slice(1))]}},n.extent=function(t){return arguments.length?n.majorExtent(t).minorExtent(t):n.minorExtent()},n.majorExtent=function(t){return arguments.length?(u=+t[0][0],i=+t[1][0],c=+t[0][1],l=+t[1][1],u>i&&(t=u,u=i,i=t),c>l&&(t=c,c=l,l=t),n.precision(m)):[[u,c],[i,l]]},n.minorExtent=function(t){return arguments.length?(r=+t[0][0],e=+t[1][0],a=+t[0][1],o=+t[1][1],r>e&&(t=r,r=e,e=t),a>o&&(t=a,a=o,o=t),n.precision(m)):[[r,a],[e,o]]},n.step=function(t){return arguments.length?n.majorStep(t).minorStep(t):n.minorStep()},n.majorStep=function(t){return arguments.length?(d=+t[0],y=+t[1],n):[d,y]},n.minorStep=function(t){return arguments.length?(g=+t[0],v=+t[1],n):[g,v]},n.precision=function(t){return arguments.length?(m=+t,f=ye(a,o,90),s=me(r,e,m),h=ye(c,l,90),p=me(u,i,m),n):m},n.majorExtent([[-180,-90+Uo],[180,90-Uo]]).minorExtent([[-180,-80-Uo],[180,80+Uo]])},ao.geo.greatArc=function(){function n(){return{type:"LineString",coordinates:[t||r.apply(this,arguments),e||i.apply(this,arguments)]}}var t,e,r=Me,i=xe;return n.distance=function(){return ao.geo.distance(t||r.apply(this,arguments),e||i.apply(this,arguments))},n.source=function(e){return arguments.length?(r=e,t="function"==typeof e?null:e,n):r},n.target=function(t){return arguments.length?(i=t,e="function"==typeof t?null:t,n):i},n.precision=function(){return arguments.length?n:0},n},ao.geo.interpolate=function(n,t){return be(n[0]*Yo,n[1]*Yo,t[0]*Yo,t[1]*Yo)},ao.geo.length=function(n){return Ja=0,ao.geo.stream(n,Ga),Ja};var Ja,Ga={sphere:b,point:b,lineStart:_e,lineEnd:b,polygonStart:b,polygonEnd:b},Ka=we(function(n){return Math.sqrt(2/(1+n))},function(n){return 2*Math.asin(n/2)});(ao.geo.azimuthalEqualArea=function(){return oe(Ka)}).raw=Ka;var Qa=we(function(n){var t=Math.acos(n);return t&&t/Math.sin(t)},m);(ao.geo.azimuthalEquidistant=function(){return oe(Qa)}).raw=Qa,(ao.geo.conicConformal=function(){return Vt(Se)}).raw=Se,(ao.geo.conicEquidistant=function(){return Vt(ke)}).raw=ke;var nl=we(function(n){return 1/n},Math.atan);(ao.geo.gnomonic=function(){return oe(nl)}).raw=nl,Ne.invert=function(n,t){return[n,2*Math.atan(Math.exp(t))-Io]},(ao.geo.mercator=function(){return Ee(Ne)}).raw=Ne;var tl=we(function(){return 1},Math.asin);(ao.geo.orthographic=function(){return oe(tl)}).raw=tl;var el=we(function(n){return 1/(1+n)},function(n){return 2*Math.atan(n)});(ao.geo.stereographic=function(){return oe(el)}).raw=el,Ae.invert=function(n,t){return[-t,2*Math.atan(Math.exp(n))-Io]},(ao.geo.transverseMercator=function(){var n=Ee(Ae),t=n.center,e=n.rotate;return n.center=function(n){return n?t([-n[1],n[0]]):(n=t(),[n[1],-n[0]])},n.rotate=function(n){return n?e([n[0],n[1],n.length>2?n[2]+90:90]):(n=e(),[n[0],n[1],n[2]-90])},e([0,0,90])}).raw=Ae,ao.geom={},ao.geom.hull=function(n){function t(n){if(n.length<3)return[];var t,i=En(e),u=En(r),o=n.length,a=[],l=[];for(t=0;o>t;t++)a.push([+i.call(this,n[t],t),+u.call(this,n[t],t),t]);for(a.sort(qe),t=0;o>t;t++)l.push([a[t][0],-a[t][1]]);var c=Le(a),f=Le(l),s=f[0]===c[0],h=f[f.length-1]===c[c.length-1],p=[];for(t=c.length-1;t>=0;--t)p.push(n[a[c[t]][2]]);for(t=+s;t<f.length-h;++t)p.push(n[a[f[t]][2]]);return p}var e=Ce,r=ze;return arguments.length?t(n):(t.x=function(n){return arguments.length?(e=n,t):e},t.y=function(n){return arguments.length?(r=n,t):r},t)},ao.geom.polygon=function(n){return ko(n,rl),n};var rl=ao.geom.polygon.prototype=[];rl.area=function(){for(var n,t=-1,e=this.length,r=this[e-1],i=0;++t<e;)n=r,r=this[t],i+=n[1]*r[0]-n[0]*r[1];return.5*i},rl.centroid=function(n){var t,e,r=-1,i=this.length,u=0,o=0,a=this[i-1];for(arguments.length||(n=-1/(6*this.area()));++r<i;)t=a,a=this[r],e=t[0]*a[1]-a[0]*t[1],u+=(t[0]+a[0])*e,o+=(t[1]+a[1])*e;return[u*n,o*n]},rl.clip=function(n){for(var t,e,r,i,u,o,a=De(n),l=-1,c=this.length-De(this),f=this[c-1];++l<c;){for(t=n.slice(),n.length=0,i=this[l],u=t[(r=t.length-a)-1],e=-1;++e<r;)o=t[e],Te(o,f,i)?(Te(u,f,i)||n.push(Re(u,o,f,i)),n.push(o)):Te(u,f,i)&&n.push(Re(u,o,f,i)),u=o;a&&n.push(n[0]),f=i}return n};var il,ul,ol,al,ll,cl=[],fl=[];Ye.prototype.prepare=function(){for(var n,t=this.edges,e=t.length;e--;)n=t[e].edge,n.b&&n.a||t.splice(e,1);return t.sort(Ve),t.length},tr.prototype={start:function(){return this.edge.l===this.site?this.edge.a:this.edge.b},end:function(){return this.edge.l===this.site?this.edge.b:this.edge.a}},er.prototype={insert:function(n,t){var e,r,i;if(n){if(t.P=n,t.N=n.N,n.N&&(n.N.P=t),n.N=t,n.R){for(n=n.R;n.L;)n=n.L;n.L=t}else n.R=t;e=n}else this._?(n=or(this._),t.P=null,t.N=n,n.P=n.L=t,e=n):(t.P=t.N=null,this._=t,e=null);for(t.L=t.R=null,t.U=e,t.C=!0,n=t;e&&e.C;)r=e.U,e===r.L?(i=r.R,i&&i.C?(e.C=i.C=!1,r.C=!0,n=r):(n===e.R&&(ir(this,e),n=e,e=n.U),e.C=!1,r.C=!0,ur(this,r))):(i=r.L,i&&i.C?(e.C=i.C=!1,r.C=!0,n=r):(n===e.L&&(ur(this,e),n=e,e=n.U),e.C=!1,r.C=!0,ir(this,r))),e=n.U;this._.C=!1},remove:function(n){n.N&&(n.N.P=n.P),n.P&&(n.P.N=n.N),n.N=n.P=null;var t,e,r,i=n.U,u=n.L,o=n.R;if(e=u?o?or(o):u:o,i?i.L===n?i.L=e:i.R=e:this._=e,u&&o?(r=e.C,e.C=n.C,e.L=u,u.U=e,e!==o?(i=e.U,e.U=n.U,n=e.R,i.L=n,e.R=o,o.U=e):(e.U=i,i=e,n=e.R)):(r=n.C,n=e),n&&(n.U=i),!r){if(n&&n.C)return void(n.C=!1);do{if(n===this._)break;if(n===i.L){if(t=i.R,t.C&&(t.C=!1,i.C=!0,ir(this,i),t=i.R),t.L&&t.L.C||t.R&&t.R.C){t.R&&t.R.C||(t.L.C=!1,t.C=!0,ur(this,t),t=i.R),t.C=i.C,i.C=t.R.C=!1,ir(this,i),n=this._;break}}else if(t=i.L,t.C&&(t.C=!1,i.C=!0,ur(this,i),t=i.L),t.L&&t.L.C||t.R&&t.R.C){t.L&&t.L.C||(t.R.C=!1,t.C=!0,ir(this,t),t=i.L),t.C=i.C,i.C=t.L.C=!1,ur(this,i),n=this._;break}t.C=!0,n=i,i=i.U}while(!n.C);n&&(n.C=!1)}}},ao.geom.voronoi=function(n){function t(n){var t=new Array(n.length),r=a[0][0],i=a[0][1],u=a[1][0],o=a[1][1];return ar(e(n),a).cells.forEach(function(e,a){var l=e.edges,c=e.site,f=t[a]=l.length?l.map(function(n){var t=n.start();return[t.x,t.y]}):c.x>=r&&c.x<=u&&c.y>=i&&c.y<=o?[[r,o],[u,o],[u,i],[r,i]]:[];f.point=n[a]}),t}function e(n){return n.map(function(n,t){return{x:Math.round(u(n,t)/Uo)*Uo,y:Math.round(o(n,t)/Uo)*Uo,i:t}})}var r=Ce,i=ze,u=r,o=i,a=sl;return n?t(n):(t.links=function(n){return ar(e(n)).edges.filter(function(n){return n.l&&n.r}).map(function(t){return{source:n[t.l.i],target:n[t.r.i]}})},t.triangles=function(n){var t=[];return ar(e(n)).cells.forEach(function(e,r){for(var i,u,o=e.site,a=e.edges.sort(Ve),l=-1,c=a.length,f=a[c-1].edge,s=f.l===o?f.r:f.l;++l<c;)i=f,u=s,f=a[l].edge,s=f.l===o?f.r:f.l,r<u.i&&r<s.i&&cr(o,u,s)<0&&t.push([n[r],n[u.i],n[s.i]])}),t},t.x=function(n){return arguments.length?(u=En(r=n),t):r},t.y=function(n){return arguments.length?(o=En(i=n),t):i},t.clipExtent=function(n){return arguments.length?(a=null==n?sl:n,t):a===sl?null:a},t.size=function(n){return arguments.length?t.clipExtent(n&&[[0,0],n]):a===sl?null:a&&a[1]},t)};var sl=[[-1e6,-1e6],[1e6,1e6]];ao.geom.delaunay=function(n){return ao.geom.voronoi().triangles(n)},ao.geom.quadtree=function(n,t,e,r,i){function u(n){function u(n,t,e,r,i,u,o,a){if(!isNaN(e)&&!isNaN(r))if(n.leaf){var l=n.x,f=n.y;if(null!=l)if(xo(l-e)+xo(f-r)<.01)c(n,t,e,r,i,u,o,a);else{var s=n.point;n.x=n.y=n.point=null,c(n,s,l,f,i,u,o,a),c(n,t,e,r,i,u,o,a)}else n.x=e,n.y=r,n.point=t}else c(n,t,e,r,i,u,o,a)}function c(n,t,e,r,i,o,a,l){var c=.5*(i+a),f=.5*(o+l),s=e>=c,h=r>=f,p=h<<1|s;n.leaf=!1,n=n.nodes[p]||(n.nodes[p]=hr()),s?i=c:a=c,h?o=f:l=f,u(n,t,e,r,i,o,a,l)}var f,s,h,p,g,v,d,y,m,M=En(a),x=En(l);if(null!=t)v=t,d=e,y=r,m=i;else if(y=m=-(v=d=1/0),s=[],h=[],g=n.length,o)for(p=0;g>p;++p)f=n[p],f.x<v&&(v=f.x),f.y<d&&(d=f.y),f.x>y&&(y=f.x),f.y>m&&(m=f.y),s.push(f.x),h.push(f.y);else for(p=0;g>p;++p){var b=+M(f=n[p],p),_=+x(f,p);v>b&&(v=b),d>_&&(d=_),b>y&&(y=b),_>m&&(m=_),s.push(b),h.push(_)}var w=y-v,S=m-d;w>S?m=d+w:y=v+S;var k=hr();if(k.add=function(n){u(k,n,+M(n,++p),+x(n,p),v,d,y,m)},k.visit=function(n){pr(n,k,v,d,y,m)},k.find=function(n){return gr(k,n[0],n[1],v,d,y,m)},p=-1,null==t){for(;++p<g;)u(k,n[p],s[p],h[p],v,d,y,m);--p}else n.forEach(k.add);return s=h=n=f=null,k}var o,a=Ce,l=ze;return(o=arguments.length)?(a=fr,l=sr,3===o&&(i=e,r=t,e=t=0),u(n)):(u.x=function(n){return arguments.length?(a=n,u):a},u.y=function(n){return arguments.length?(l=n,u):l},u.extent=function(n){return arguments.length?(null==n?t=e=r=i=null:(t=+n[0][0],e=+n[0][1],r=+n[1][0],i=+n[1][1]),u):null==t?null:[[t,e],[r,i]]},u.size=function(n){return arguments.length?(null==n?t=e=r=i=null:(t=e=0,r=+n[0],i=+n[1]),u):null==t?null:[r-t,i-e]},u)},ao.interpolateRgb=vr,ao.interpolateObject=dr,ao.interpolateNumber=yr,ao.interpolateString=mr;var hl=/[-+]?(?:\d+\.?\d*|\.?\d+)(?:[eE][-+]?\d+)?/g,pl=new RegExp(hl.source,"g");ao.interpolate=Mr,ao.interpolators=[function(n,t){var e=typeof t;return("string"===e?ua.has(t.toLowerCase())||/^(#|rgb\(|hsl\()/i.test(t)?vr:mr:t instanceof an?vr:Array.isArray(t)?xr:"object"===e&&isNaN(t)?dr:yr)(n,t)}],ao.interpolateArray=xr;var gl=function(){return m},vl=ao.map({linear:gl,poly:Er,quad:function(){return Sr},cubic:function(){return kr},sin:function(){return Ar},exp:function(){return Cr},circle:function(){return zr},elastic:Lr,back:qr,bounce:function(){return Tr}}),dl=ao.map({"in":m,out:_r,"in-out":wr,"out-in":function(n){return wr(_r(n))}});ao.ease=function(n){var t=n.indexOf("-"),e=t>=0?n.slice(0,t):n,r=t>=0?n.slice(t+1):"in";return e=vl.get(e)||gl,r=dl.get(r)||m,br(r(e.apply(null,lo.call(arguments,1))))},ao.interpolateHcl=Rr,ao.interpolateHsl=Dr,ao.interpolateLab=Pr,ao.interpolateRound=Ur,ao.transform=function(n){var t=fo.createElementNS(ao.ns.prefix.svg,"g");return(ao.transform=function(n){if(null!=n){t.setAttribute("transform",n);var e=t.transform.baseVal.consolidate()}return new jr(e?e.matrix:yl)})(n)},jr.prototype.toString=function(){return"translate("+this.translate+")rotate("+this.rotate+")skewX("+this.skew+")scale("+this.scale+")"};var yl={a:1,b:0,c:0,d:1,e:0,f:0};ao.interpolateTransform=$r,ao.layout={},ao.layout.bundle=function(){return function(n){for(var t=[],e=-1,r=n.length;++e<r;)t.push(Jr(n[e]));return t}},ao.layout.chord=function(){function n(){var n,c,s,h,p,g={},v=[],d=ao.range(u),y=[];for(e=[],r=[],n=0,h=-1;++h<u;){for(c=0,p=-1;++p<u;)c+=i[h][p];v.push(c),y.push(ao.range(u)),n+=c}for(o&&d.sort(function(n,t){return o(v[n],v[t])}),a&&y.forEach(function(n,t){n.sort(function(n,e){return a(i[t][n],i[t][e])})}),n=(Ho-f*u)/n,c=0,h=-1;++h<u;){for(s=c,p=-1;++p<u;){var m=d[h],M=y[m][p],x=i[m][M],b=c,_=c+=x*n;g[m+"-"+M]={index:m,subindex:M,startAngle:b,endAngle:_,value:x}}r[m]={index:m,startAngle:s,endAngle:c,value:v[m]},c+=f}for(h=-1;++h<u;)for(p=h-1;++p<u;){var w=g[h+"-"+p],S=g[p+"-"+h];(w.value||S.value)&&e.push(w.value<S.value?{source:S,target:w}:{source:w,target:S})}l&&t()}function t(){e.sort(function(n,t){return l((n.source.value+n.target.value)/2,(t.source.value+t.target.value)/2)})}var e,r,i,u,o,a,l,c={},f=0;return c.matrix=function(n){return arguments.length?(u=(i=n)&&i.length,e=r=null,c):i},c.padding=function(n){return arguments.length?(f=n,e=r=null,c):f},c.sortGroups=function(n){return arguments.length?(o=n,e=r=null,c):o},c.sortSubgroups=function(n){return arguments.length?(a=n,e=null,c):a},c.sortChords=function(n){return arguments.length?(l=n,e&&t(),c):l},c.chords=function(){return e||n(),e},c.groups=function(){return r||n(),r},c},ao.layout.force=function(){function n(n){return function(t,e,r,i){if(t.point!==n){var u=t.cx-n.x,o=t.cy-n.y,a=i-e,l=u*u+o*o;if(l>a*a/y){if(v>l){var c=t.charge/l;n.px-=u*c,n.py-=o*c}return!0}if(t.point&&l&&v>l){var c=t.pointCharge/l;n.px-=u*c,n.py-=o*c}}return!t.charge}}function t(n){n.px=ao.event.x,n.py=ao.event.y,l.resume()}var e,r,i,u,o,a,l={},c=ao.dispatch("start","tick","end"),f=[1,1],s=.9,h=ml,p=Ml,g=-30,v=xl,d=.1,y=.64,M=[],x=[];return l.tick=function(){if((i*=.99)<.005)return e=null,c.end({type:"end",alpha:i=0}),!0;var t,r,l,h,p,v,y,m,b,_=M.length,w=x.length;for(r=0;w>r;++r)l=x[r],h=l.source,p=l.target,m=p.x-h.x,b=p.y-h.y,(v=m*m+b*b)&&(v=i*o[r]*((v=Math.sqrt(v))-u[r])/v,m*=v,b*=v,p.x-=m*(y=h.weight+p.weight?h.weight/(h.weight+p.weight):.5),p.y-=b*y,h.x+=m*(y=1-y),h.y+=b*y);if((y=i*d)&&(m=f[0]/2,b=f[1]/2,r=-1,y))for(;++r<_;)l=M[r],l.x+=(m-l.x)*y,l.y+=(b-l.y)*y;if(g)for(ri(t=ao.geom.quadtree(M),i,a),r=-1;++r<_;)(l=M[r]).fixed||t.visit(n(l));for(r=-1;++r<_;)l=M[r],l.fixed?(l.x=l.px,l.y=l.py):(l.x-=(l.px-(l.px=l.x))*s,l.y-=(l.py-(l.py=l.y))*s);c.tick({type:"tick",alpha:i})},l.nodes=function(n){return arguments.length?(M=n,l):M},l.links=function(n){return arguments.length?(x=n,l):x},l.size=function(n){return arguments.length?(f=n,l):f},l.linkDistance=function(n){return arguments.length?(h="function"==typeof n?n:+n,l):h},l.distance=l.linkDistance,l.linkStrength=function(n){return arguments.length?(p="function"==typeof n?n:+n,l):p},l.friction=function(n){return arguments.length?(s=+n,l):s},l.charge=function(n){return arguments.length?(g="function"==typeof n?n:+n,l):g},l.chargeDistance=function(n){return arguments.length?(v=n*n,l):Math.sqrt(v)},l.gravity=function(n){return arguments.length?(d=+n,l):d},l.theta=function(n){return arguments.length?(y=n*n,l):Math.sqrt(y)},l.alpha=function(n){return arguments.length?(n=+n,i?n>0?i=n:(e.c=null,e.t=NaN,e=null,c.end({type:"end",alpha:i=0})):n>0&&(c.start({type:"start",alpha:i=n}),e=qn(l.tick)),l):i},l.start=function(){function n(n,r){if(!e){for(e=new Array(i),l=0;i>l;++l)e[l]=[];for(l=0;c>l;++l){var u=x[l];e[u.source.index].push(u.target),e[u.target.index].push(u.source)}}for(var o,a=e[t],l=-1,f=a.length;++l<f;)if(!isNaN(o=a[l][n]))return o;return Math.random()*r}var t,e,r,i=M.length,c=x.length,s=f[0],v=f[1];for(t=0;i>t;++t)(r=M[t]).index=t,r.weight=0;for(t=0;c>t;++t)r=x[t],"number"==typeof r.source&&(r.source=M[r.source]),"number"==typeof r.target&&(r.target=M[r.target]),++r.source.weight,++r.target.weight;for(t=0;i>t;++t)r=M[t],isNaN(r.x)&&(r.x=n("x",s)),isNaN(r.y)&&(r.y=n("y",v)),isNaN(r.px)&&(r.px=r.x),isNaN(r.py)&&(r.py=r.y);if(u=[],"function"==typeof h)for(t=0;c>t;++t)u[t]=+h.call(this,x[t],t);else for(t=0;c>t;++t)u[t]=h;if(o=[],"function"==typeof p)for(t=0;c>t;++t)o[t]=+p.call(this,x[t],t);else for(t=0;c>t;++t)o[t]=p;if(a=[],"function"==typeof g)for(t=0;i>t;++t)a[t]=+g.call(this,M[t],t);else for(t=0;i>t;++t)a[t]=g;return l.resume()},l.resume=function(){return l.alpha(.1)},l.stop=function(){return l.alpha(0)},l.drag=function(){return r||(r=ao.behavior.drag().origin(m).on("dragstart.force",Qr).on("drag.force",t).on("dragend.force",ni)),arguments.length?void this.on("mouseover.force",ti).on("mouseout.force",ei).call(r):r},ao.rebind(l,c,"on")};var ml=20,Ml=1,xl=1/0;ao.layout.hierarchy=function(){function n(i){var u,o=[i],a=[];for(i.depth=0;null!=(u=o.pop());)if(a.push(u),(c=e.call(n,u,u.depth))&&(l=c.length)){for(var l,c,f;--l>=0;)o.push(f=c[l]),f.parent=u,f.depth=u.depth+1;r&&(u.value=0),u.children=c}else r&&(u.value=+r.call(n,u,u.depth)||0),delete u.children;return oi(i,function(n){var e,i;t&&(e=n.children)&&e.sort(t),r&&(i=n.parent)&&(i.value+=n.value)}),a}var t=ci,e=ai,r=li;return n.sort=function(e){return arguments.length?(t=e,n):t},n.children=function(t){return arguments.length?(e=t,n):e},n.value=function(t){return arguments.length?(r=t,n):r},n.revalue=function(t){return r&&(ui(t,function(n){n.children&&(n.value=0)}),oi(t,function(t){var e;t.children||(t.value=+r.call(n,t,t.depth)||0),(e=t.parent)&&(e.value+=t.value)})),t},n},ao.layout.partition=function(){function n(t,e,r,i){var u=t.children;if(t.x=e,t.y=t.depth*i,t.dx=r,t.dy=i,u&&(o=u.length)){var o,a,l,c=-1;for(r=t.value?r/t.value:0;++c<o;)n(a=u[c],e,l=a.value*r,i),e+=l}}function t(n){var e=n.children,r=0;if(e&&(i=e.length))for(var i,u=-1;++u<i;)r=Math.max(r,t(e[u]));return 1+r}function e(e,u){var o=r.call(this,e,u);return n(o[0],0,i[0],i[1]/t(o[0])),o}var r=ao.layout.hierarchy(),i=[1,1];return e.size=function(n){return arguments.length?(i=n,e):i},ii(e,r)},ao.layout.pie=function(){function n(o){var a,l=o.length,c=o.map(function(e,r){return+t.call(n,e,r)}),f=+("function"==typeof r?r.apply(this,arguments):r),s=("function"==typeof i?i.apply(this,arguments):i)-f,h=Math.min(Math.abs(s)/l,+("function"==typeof u?u.apply(this,arguments):u)),p=h*(0>s?-1:1),g=ao.sum(c),v=g?(s-l*p)/g:0,d=ao.range(l),y=[];return null!=e&&d.sort(e===bl?function(n,t){return c[t]-c[n]}:function(n,t){return e(o[n],o[t])}),d.forEach(function(n){y[n]={data:o[n],value:a=c[n],startAngle:f,endAngle:f+=a*v+p,padAngle:h}}),y}var t=Number,e=bl,r=0,i=Ho,u=0;return n.value=function(e){return arguments.length?(t=e,n):t},n.sort=function(t){return arguments.length?(e=t,n):e},n.startAngle=function(t){return arguments.length?(r=t,n):r},n.endAngle=function(t){return arguments.length?(i=t,n):i},n.padAngle=function(t){return arguments.length?(u=t,n):u},n};var bl={};ao.layout.stack=function(){function n(a,l){if(!(h=a.length))return a;var c=a.map(function(e,r){return t.call(n,e,r)}),f=c.map(function(t){return t.map(function(t,e){return[u.call(n,t,e),o.call(n,t,e)]})}),s=e.call(n,f,l);c=ao.permute(c,s),f=ao.permute(f,s);var h,p,g,v,d=r.call(n,f,l),y=c[0].length;for(g=0;y>g;++g)for(i.call(n,c[0][g],v=d[g],f[0][g][1]),p=1;h>p;++p)i.call(n,c[p][g],v+=f[p-1][g][1],f[p][g][1]);return a}var t=m,e=gi,r=vi,i=pi,u=si,o=hi;return n.values=function(e){return arguments.length?(t=e,n):t},n.order=function(t){return arguments.length?(e="function"==typeof t?t:_l.get(t)||gi,n):e},n.offset=function(t){return arguments.length?(r="function"==typeof t?t:wl.get(t)||vi,n):r},n.x=function(t){return arguments.length?(u=t,n):u},n.y=function(t){return arguments.length?(o=t,n):o},n.out=function(t){return arguments.length?(i=t,n):i},n};var _l=ao.map({"inside-out":function(n){var t,e,r=n.length,i=n.map(di),u=n.map(yi),o=ao.range(r).sort(function(n,t){return i[n]-i[t]}),a=0,l=0,c=[],f=[];for(t=0;r>t;++t)e=o[t],l>a?(a+=u[e],c.push(e)):(l+=u[e],f.push(e));return f.reverse().concat(c)},reverse:function(n){return ao.range(n.length).reverse()},"default":gi}),wl=ao.map({silhouette:function(n){var t,e,r,i=n.length,u=n[0].length,o=[],a=0,l=[];for(e=0;u>e;++e){for(t=0,r=0;i>t;t++)r+=n[t][e][1];r>a&&(a=r),o.push(r)}for(e=0;u>e;++e)l[e]=(a-o[e])/2;return l},wiggle:function(n){var t,e,r,i,u,o,a,l,c,f=n.length,s=n[0],h=s.length,p=[];for(p[0]=l=c=0,e=1;h>e;++e){for(t=0,i=0;f>t;++t)i+=n[t][e][1];for(t=0,u=0,a=s[e][0]-s[e-1][0];f>t;++t){for(r=0,o=(n[t][e][1]-n[t][e-1][1])/(2*a);t>r;++r)o+=(n[r][e][1]-n[r][e-1][1])/a;u+=o*n[t][e][1]}p[e]=l-=i?u/i*a:0,c>l&&(c=l)}for(e=0;h>e;++e)p[e]-=c;return p},expand:function(n){var t,e,r,i=n.length,u=n[0].length,o=1/i,a=[];for(e=0;u>e;++e){for(t=0,r=0;i>t;t++)r+=n[t][e][1];if(r)for(t=0;i>t;t++)n[t][e][1]/=r;else for(t=0;i>t;t++)n[t][e][1]=o}for(e=0;u>e;++e)a[e]=0;return a},zero:vi});ao.layout.histogram=function(){function n(n,u){for(var o,a,l=[],c=n.map(e,this),f=r.call(this,c,u),s=i.call(this,f,c,u),u=-1,h=c.length,p=s.length-1,g=t?1:1/h;++u<p;)o=l[u]=[],o.dx=s[u+1]-(o.x=s[u]),o.y=0;if(p>0)for(u=-1;++u<h;)a=c[u],a>=f[0]&&a<=f[1]&&(o=l[ao.bisect(s,a,1,p)-1],o.y+=g,o.push(n[u]));return l}var t=!0,e=Number,r=bi,i=Mi;return n.value=function(t){return arguments.length?(e=t,n):e},n.range=function(t){return arguments.length?(r=En(t),n):r},n.bins=function(t){return arguments.length?(i="number"==typeof t?function(n){return xi(n,t)}:En(t),n):i},n.frequency=function(e){return arguments.length?(t=!!e,n):t},n},ao.layout.pack=function(){function n(n,u){var o=e.call(this,n,u),a=o[0],l=i[0],c=i[1],f=null==t?Math.sqrt:"function"==typeof t?t:function(){return t};if(a.x=a.y=0,oi(a,function(n){n.r=+f(n.value)}),oi(a,Ni),r){var s=r*(t?1:Math.max(2*a.r/l,2*a.r/c))/2;oi(a,function(n){n.r+=s}),oi(a,Ni),oi(a,function(n){n.r-=s})}return Ci(a,l/2,c/2,t?1:1/Math.max(2*a.r/l,2*a.r/c)),o}var t,e=ao.layout.hierarchy().sort(_i),r=0,i=[1,1];return n.size=function(t){return arguments.length?(i=t,n):i},n.radius=function(e){return arguments.length?(t=null==e||"function"==typeof e?e:+e,n):t},n.padding=function(t){return arguments.length?(r=+t,n):r},ii(n,e)},ao.layout.tree=function(){function n(n,i){var f=o.call(this,n,i),s=f[0],h=t(s);if(oi(h,e),h.parent.m=-h.z,ui(h,r),c)ui(s,u);else{var p=s,g=s,v=s;ui(s,function(n){n.x<p.x&&(p=n),n.x>g.x&&(g=n),n.depth>v.depth&&(v=n)});var d=a(p,g)/2-p.x,y=l[0]/(g.x+a(g,p)/2+d),m=l[1]/(v.depth||1);ui(s,function(n){n.x=(n.x+d)*y,n.y=n.depth*m})}return f}function t(n){for(var t,e={A:null,children:[n]},r=[e];null!=(t=r.pop());)for(var i,u=t.children,o=0,a=u.length;a>o;++o)r.push((u[o]=i={_:u[o],parent:t,children:(i=u[o].children)&&i.slice()||[],A:null,a:null,z:0,m:0,c:0,s:0,t:null,i:o}).a=i);return e.children[0]}function e(n){var t=n.children,e=n.parent.children,r=n.i?e[n.i-1]:null;if(t.length){Di(n);var u=(t[0].z+t[t.length-1].z)/2;r?(n.z=r.z+a(n._,r._),n.m=n.z-u):n.z=u}else r&&(n.z=r.z+a(n._,r._));n.parent.A=i(n,r,n.parent.A||e[0])}function r(n){n._.x=n.z+n.parent.m,n.m+=n.parent.m}function i(n,t,e){if(t){for(var r,i=n,u=n,o=t,l=i.parent.children[0],c=i.m,f=u.m,s=o.m,h=l.m;o=Ti(o),i=qi(i),o&&i;)l=qi(l),u=Ti(u),u.a=n,r=o.z+s-i.z-c+a(o._,i._),r>0&&(Ri(Pi(o,n,e),n,r),c+=r,f+=r),s+=o.m,c+=i.m,h+=l.m,f+=u.m;o&&!Ti(u)&&(u.t=o,u.m+=s-f),i&&!qi(l)&&(l.t=i,l.m+=c-h,e=n)}return e}function u(n){n.x*=l[0],n.y=n.depth*l[1]}var o=ao.layout.hierarchy().sort(null).value(null),a=Li,l=[1,1],c=null;return n.separation=function(t){return arguments.length?(a=t,n):a},n.size=function(t){return arguments.length?(c=null==(l=t)?u:null,n):c?null:l},n.nodeSize=function(t){return arguments.length?(c=null==(l=t)?null:u,n):c?l:null},ii(n,o)},ao.layout.cluster=function(){function n(n,u){var o,a=t.call(this,n,u),l=a[0],c=0;oi(l,function(n){var t=n.children;t&&t.length?(n.x=ji(t),n.y=Ui(t)):(n.x=o?c+=e(n,o):0,n.y=0,o=n)});var f=Fi(l),s=Hi(l),h=f.x-e(f,s)/2,p=s.x+e(s,f)/2;return oi(l,i?function(n){n.x=(n.x-l.x)*r[0],n.y=(l.y-n.y)*r[1]}:function(n){n.x=(n.x-h)/(p-h)*r[0],n.y=(1-(l.y?n.y/l.y:1))*r[1]}),a}var t=ao.layout.hierarchy().sort(null).value(null),e=Li,r=[1,1],i=!1;return n.separation=function(t){return arguments.length?(e=t,n):e},n.size=function(t){return arguments.length?(i=null==(r=t),n):i?null:r},n.nodeSize=function(t){return arguments.length?(i=null!=(r=t),n):i?r:null},ii(n,t)},ao.layout.treemap=function(){function n(n,t){for(var e,r,i=-1,u=n.length;++i<u;)r=(e=n[i]).value*(0>t?0:t),e.area=isNaN(r)||0>=r?0:r}function t(e){var u=e.children;if(u&&u.length){var o,a,l,c=s(e),f=[],h=u.slice(),g=1/0,v="slice"===p?c.dx:"dice"===p?c.dy:"slice-dice"===p?1&e.depth?c.dy:c.dx:Math.min(c.dx,c.dy);for(n(h,c.dx*c.dy/e.value),f.area=0;(l=h.length)>0;)f.push(o=h[l-1]),f.area+=o.area,"squarify"!==p||(a=r(f,v))<=g?(h.pop(),g=a):(f.area-=f.pop().area,i(f,v,c,!1),v=Math.min(c.dx,c.dy),f.length=f.area=0,g=1/0);f.length&&(i(f,v,c,!0),f.length=f.area=0),u.forEach(t)}}function e(t){var r=t.children;if(r&&r.length){var u,o=s(t),a=r.slice(),l=[];for(n(a,o.dx*o.dy/t.value),l.area=0;u=a.pop();)l.push(u),l.area+=u.area,null!=u.z&&(i(l,u.z?o.dx:o.dy,o,!a.length),l.length=l.area=0);r.forEach(e)}}function r(n,t){for(var e,r=n.area,i=0,u=1/0,o=-1,a=n.length;++o<a;)(e=n[o].area)&&(u>e&&(u=e),e>i&&(i=e));return r*=r,t*=t,r?Math.max(t*i*g/r,r/(t*u*g)):1/0}function i(n,t,e,r){var i,u=-1,o=n.length,a=e.x,c=e.y,f=t?l(n.area/t):0;
  22862. if(t==e.dx){for((r||f>e.dy)&&(f=e.dy);++u<o;)i=n[u],i.x=a,i.y=c,i.dy=f,a+=i.dx=Math.min(e.x+e.dx-a,f?l(i.area/f):0);i.z=!0,i.dx+=e.x+e.dx-a,e.y+=f,e.dy-=f}else{for((r||f>e.dx)&&(f=e.dx);++u<o;)i=n[u],i.x=a,i.y=c,i.dx=f,c+=i.dy=Math.min(e.y+e.dy-c,f?l(i.area/f):0);i.z=!1,i.dy+=e.y+e.dy-c,e.x+=f,e.dx-=f}}function u(r){var i=o||a(r),u=i[0];return u.x=u.y=0,u.value?(u.dx=c[0],u.dy=c[1]):u.dx=u.dy=0,o&&a.revalue(u),n([u],u.dx*u.dy/u.value),(o?e:t)(u),h&&(o=i),i}var o,a=ao.layout.hierarchy(),l=Math.round,c=[1,1],f=null,s=Oi,h=!1,p="squarify",g=.5*(1+Math.sqrt(5));return u.size=function(n){return arguments.length?(c=n,u):c},u.padding=function(n){function t(t){var e=n.call(u,t,t.depth);return null==e?Oi(t):Ii(t,"number"==typeof e?[e,e,e,e]:e)}function e(t){return Ii(t,n)}if(!arguments.length)return f;var r;return s=null==(f=n)?Oi:"function"==(r=typeof n)?t:"number"===r?(n=[n,n,n,n],e):e,u},u.round=function(n){return arguments.length?(l=n?Math.round:Number,u):l!=Number},u.sticky=function(n){return arguments.length?(h=n,o=null,u):h},u.ratio=function(n){return arguments.length?(g=n,u):g},u.mode=function(n){return arguments.length?(p=n+"",u):p},ii(u,a)},ao.random={normal:function(n,t){var e=arguments.length;return 2>e&&(t=1),1>e&&(n=0),function(){var e,r,i;do e=2*Math.random()-1,r=2*Math.random()-1,i=e*e+r*r;while(!i||i>1);return n+t*e*Math.sqrt(-2*Math.log(i)/i)}},logNormal:function(){var n=ao.random.normal.apply(ao,arguments);return function(){return Math.exp(n())}},bates:function(n){var t=ao.random.irwinHall(n);return function(){return t()/n}},irwinHall:function(n){return function(){for(var t=0,e=0;n>e;e++)t+=Math.random();return t}}},ao.scale={};var Sl={floor:m,ceil:m};ao.scale.linear=function(){return Wi([0,1],[0,1],Mr,!1)};var kl={s:1,g:1,p:1,r:1,e:1};ao.scale.log=function(){return ru(ao.scale.linear().domain([0,1]),10,!0,[1,10])};var Nl=ao.format(".0e"),El={floor:function(n){return-Math.ceil(-n)},ceil:function(n){return-Math.floor(-n)}};ao.scale.pow=function(){return iu(ao.scale.linear(),1,[0,1])},ao.scale.sqrt=function(){return ao.scale.pow().exponent(.5)},ao.scale.ordinal=function(){return ou([],{t:"range",a:[[]]})},ao.scale.category10=function(){return ao.scale.ordinal().range(Al)},ao.scale.category20=function(){return ao.scale.ordinal().range(Cl)},ao.scale.category20b=function(){return ao.scale.ordinal().range(zl)},ao.scale.category20c=function(){return ao.scale.ordinal().range(Ll)};var Al=[2062260,16744206,2924588,14034728,9725885,9197131,14907330,8355711,12369186,1556175].map(xn),Cl=[2062260,11454440,16744206,16759672,2924588,10018698,14034728,16750742,9725885,12955861,9197131,12885140,14907330,16234194,8355711,13092807,12369186,14408589,1556175,10410725].map(xn),zl=[3750777,5395619,7040719,10264286,6519097,9216594,11915115,13556636,9202993,12426809,15186514,15190932,8666169,11356490,14049643,15177372,8077683,10834324,13528509,14589654].map(xn),Ll=[3244733,7057110,10406625,13032431,15095053,16616764,16625259,16634018,3253076,7652470,10607003,13101504,7695281,10394312,12369372,14342891,6513507,9868950,12434877,14277081].map(xn);ao.scale.quantile=function(){return au([],[])},ao.scale.quantize=function(){return lu(0,1,[0,1])},ao.scale.threshold=function(){return cu([.5],[0,1])},ao.scale.identity=function(){return fu([0,1])},ao.svg={},ao.svg.arc=function(){function n(){var n=Math.max(0,+e.apply(this,arguments)),c=Math.max(0,+r.apply(this,arguments)),f=o.apply(this,arguments)-Io,s=a.apply(this,arguments)-Io,h=Math.abs(s-f),p=f>s?0:1;if(n>c&&(g=c,c=n,n=g),h>=Oo)return t(c,p)+(n?t(n,1-p):"")+"Z";var g,v,d,y,m,M,x,b,_,w,S,k,N=0,E=0,A=[];if((y=(+l.apply(this,arguments)||0)/2)&&(d=u===ql?Math.sqrt(n*n+c*c):+u.apply(this,arguments),p||(E*=-1),c&&(E=tn(d/c*Math.sin(y))),n&&(N=tn(d/n*Math.sin(y)))),c){m=c*Math.cos(f+E),M=c*Math.sin(f+E),x=c*Math.cos(s-E),b=c*Math.sin(s-E);var C=Math.abs(s-f-2*E)<=Fo?0:1;if(E&&yu(m,M,x,b)===p^C){var z=(f+s)/2;m=c*Math.cos(z),M=c*Math.sin(z),x=b=null}}else m=M=0;if(n){_=n*Math.cos(s-N),w=n*Math.sin(s-N),S=n*Math.cos(f+N),k=n*Math.sin(f+N);var L=Math.abs(f-s+2*N)<=Fo?0:1;if(N&&yu(_,w,S,k)===1-p^L){var q=(f+s)/2;_=n*Math.cos(q),w=n*Math.sin(q),S=k=null}}else _=w=0;if(h>Uo&&(g=Math.min(Math.abs(c-n)/2,+i.apply(this,arguments)))>.001){v=c>n^p?0:1;var T=g,R=g;if(Fo>h){var D=null==S?[_,w]:null==x?[m,M]:Re([m,M],[S,k],[x,b],[_,w]),P=m-D[0],U=M-D[1],j=x-D[0],F=b-D[1],H=1/Math.sin(Math.acos((P*j+U*F)/(Math.sqrt(P*P+U*U)*Math.sqrt(j*j+F*F)))/2),O=Math.sqrt(D[0]*D[0]+D[1]*D[1]);R=Math.min(g,(n-O)/(H-1)),T=Math.min(g,(c-O)/(H+1))}if(null!=x){var I=mu(null==S?[_,w]:[S,k],[m,M],c,T,p),Y=mu([x,b],[_,w],c,T,p);g===T?A.push("M",I[0],"A",T,",",T," 0 0,",v," ",I[1],"A",c,",",c," 0 ",1-p^yu(I[1][0],I[1][1],Y[1][0],Y[1][1]),",",p," ",Y[1],"A",T,",",T," 0 0,",v," ",Y[0]):A.push("M",I[0],"A",T,",",T," 0 1,",v," ",Y[0])}else A.push("M",m,",",M);if(null!=S){var Z=mu([m,M],[S,k],n,-R,p),V=mu([_,w],null==x?[m,M]:[x,b],n,-R,p);g===R?A.push("L",V[0],"A",R,",",R," 0 0,",v," ",V[1],"A",n,",",n," 0 ",p^yu(V[1][0],V[1][1],Z[1][0],Z[1][1]),",",1-p," ",Z[1],"A",R,",",R," 0 0,",v," ",Z[0]):A.push("L",V[0],"A",R,",",R," 0 0,",v," ",Z[0])}else A.push("L",_,",",w)}else A.push("M",m,",",M),null!=x&&A.push("A",c,",",c," 0 ",C,",",p," ",x,",",b),A.push("L",_,",",w),null!=S&&A.push("A",n,",",n," 0 ",L,",",1-p," ",S,",",k);return A.push("Z"),A.join("")}function t(n,t){return"M0,"+n+"A"+n+","+n+" 0 1,"+t+" 0,"+-n+"A"+n+","+n+" 0 1,"+t+" 0,"+n}var e=hu,r=pu,i=su,u=ql,o=gu,a=vu,l=du;return n.innerRadius=function(t){return arguments.length?(e=En(t),n):e},n.outerRadius=function(t){return arguments.length?(r=En(t),n):r},n.cornerRadius=function(t){return arguments.length?(i=En(t),n):i},n.padRadius=function(t){return arguments.length?(u=t==ql?ql:En(t),n):u},n.startAngle=function(t){return arguments.length?(o=En(t),n):o},n.endAngle=function(t){return arguments.length?(a=En(t),n):a},n.padAngle=function(t){return arguments.length?(l=En(t),n):l},n.centroid=function(){var n=(+e.apply(this,arguments)+ +r.apply(this,arguments))/2,t=(+o.apply(this,arguments)+ +a.apply(this,arguments))/2-Io;return[Math.cos(t)*n,Math.sin(t)*n]},n};var ql="auto";ao.svg.line=function(){return Mu(m)};var Tl=ao.map({linear:xu,"linear-closed":bu,step:_u,"step-before":wu,"step-after":Su,basis:zu,"basis-open":Lu,"basis-closed":qu,bundle:Tu,cardinal:Eu,"cardinal-open":ku,"cardinal-closed":Nu,monotone:Fu});Tl.forEach(function(n,t){t.key=n,t.closed=/-closed$/.test(n)});var Rl=[0,2/3,1/3,0],Dl=[0,1/3,2/3,0],Pl=[0,1/6,2/3,1/6];ao.svg.line.radial=function(){var n=Mu(Hu);return n.radius=n.x,delete n.x,n.angle=n.y,delete n.y,n},wu.reverse=Su,Su.reverse=wu,ao.svg.area=function(){return Ou(m)},ao.svg.area.radial=function(){var n=Ou(Hu);return n.radius=n.x,delete n.x,n.innerRadius=n.x0,delete n.x0,n.outerRadius=n.x1,delete n.x1,n.angle=n.y,delete n.y,n.startAngle=n.y0,delete n.y0,n.endAngle=n.y1,delete n.y1,n},ao.svg.chord=function(){function n(n,a){var l=t(this,u,n,a),c=t(this,o,n,a);return"M"+l.p0+r(l.r,l.p1,l.a1-l.a0)+(e(l,c)?i(l.r,l.p1,l.r,l.p0):i(l.r,l.p1,c.r,c.p0)+r(c.r,c.p1,c.a1-c.a0)+i(c.r,c.p1,l.r,l.p0))+"Z"}function t(n,t,e,r){var i=t.call(n,e,r),u=a.call(n,i,r),o=l.call(n,i,r)-Io,f=c.call(n,i,r)-Io;return{r:u,a0:o,a1:f,p0:[u*Math.cos(o),u*Math.sin(o)],p1:[u*Math.cos(f),u*Math.sin(f)]}}function e(n,t){return n.a0==t.a0&&n.a1==t.a1}function r(n,t,e){return"A"+n+","+n+" 0 "+ +(e>Fo)+",1 "+t}function i(n,t,e,r){return"Q 0,0 "+r}var u=Me,o=xe,a=Iu,l=gu,c=vu;return n.radius=function(t){return arguments.length?(a=En(t),n):a},n.source=function(t){return arguments.length?(u=En(t),n):u},n.target=function(t){return arguments.length?(o=En(t),n):o},n.startAngle=function(t){return arguments.length?(l=En(t),n):l},n.endAngle=function(t){return arguments.length?(c=En(t),n):c},n},ao.svg.diagonal=function(){function n(n,i){var u=t.call(this,n,i),o=e.call(this,n,i),a=(u.y+o.y)/2,l=[u,{x:u.x,y:a},{x:o.x,y:a},o];return l=l.map(r),"M"+l[0]+"C"+l[1]+" "+l[2]+" "+l[3]}var t=Me,e=xe,r=Yu;return n.source=function(e){return arguments.length?(t=En(e),n):t},n.target=function(t){return arguments.length?(e=En(t),n):e},n.projection=function(t){return arguments.length?(r=t,n):r},n},ao.svg.diagonal.radial=function(){var n=ao.svg.diagonal(),t=Yu,e=n.projection;return n.projection=function(n){return arguments.length?e(Zu(t=n)):t},n},ao.svg.symbol=function(){function n(n,r){return(Ul.get(t.call(this,n,r))||$u)(e.call(this,n,r))}var t=Xu,e=Vu;return n.type=function(e){return arguments.length?(t=En(e),n):t},n.size=function(t){return arguments.length?(e=En(t),n):e},n};var Ul=ao.map({circle:$u,cross:function(n){var t=Math.sqrt(n/5)/2;return"M"+-3*t+","+-t+"H"+-t+"V"+-3*t+"H"+t+"V"+-t+"H"+3*t+"V"+t+"H"+t+"V"+3*t+"H"+-t+"V"+t+"H"+-3*t+"Z"},diamond:function(n){var t=Math.sqrt(n/(2*Fl)),e=t*Fl;return"M0,"+-t+"L"+e+",0 0,"+t+" "+-e+",0Z"},square:function(n){var t=Math.sqrt(n)/2;return"M"+-t+","+-t+"L"+t+","+-t+" "+t+","+t+" "+-t+","+t+"Z"},"triangle-down":function(n){var t=Math.sqrt(n/jl),e=t*jl/2;return"M0,"+e+"L"+t+","+-e+" "+-t+","+-e+"Z"},"triangle-up":function(n){var t=Math.sqrt(n/jl),e=t*jl/2;return"M0,"+-e+"L"+t+","+e+" "+-t+","+e+"Z"}});ao.svg.symbolTypes=Ul.keys();var jl=Math.sqrt(3),Fl=Math.tan(30*Yo);Co.transition=function(n){for(var t,e,r=Hl||++Zl,i=Ku(n),u=[],o=Ol||{time:Date.now(),ease:Nr,delay:0,duration:250},a=-1,l=this.length;++a<l;){u.push(t=[]);for(var c=this[a],f=-1,s=c.length;++f<s;)(e=c[f])&&Qu(e,f,i,r,o),t.push(e)}return Wu(u,i,r)},Co.interrupt=function(n){return this.each(null==n?Il:Bu(Ku(n)))};var Hl,Ol,Il=Bu(Ku()),Yl=[],Zl=0;Yl.call=Co.call,Yl.empty=Co.empty,Yl.node=Co.node,Yl.size=Co.size,ao.transition=function(n,t){return n&&n.transition?Hl?n.transition(t):n:ao.selection().transition(n)},ao.transition.prototype=Yl,Yl.select=function(n){var t,e,r,i=this.id,u=this.namespace,o=[];n=A(n);for(var a=-1,l=this.length;++a<l;){o.push(t=[]);for(var c=this[a],f=-1,s=c.length;++f<s;)(r=c[f])&&(e=n.call(r,r.__data__,f,a))?("__data__"in r&&(e.__data__=r.__data__),Qu(e,f,u,i,r[u][i]),t.push(e)):t.push(null)}return Wu(o,u,i)},Yl.selectAll=function(n){var t,e,r,i,u,o=this.id,a=this.namespace,l=[];n=C(n);for(var c=-1,f=this.length;++c<f;)for(var s=this[c],h=-1,p=s.length;++h<p;)if(r=s[h]){u=r[a][o],e=n.call(r,r.__data__,h,c),l.push(t=[]);for(var g=-1,v=e.length;++g<v;)(i=e[g])&&Qu(i,g,a,o,u),t.push(i)}return Wu(l,a,o)},Yl.filter=function(n){var t,e,r,i=[];"function"!=typeof n&&(n=O(n));for(var u=0,o=this.length;o>u;u++){i.push(t=[]);for(var e=this[u],a=0,l=e.length;l>a;a++)(r=e[a])&&n.call(r,r.__data__,a,u)&&t.push(r)}return Wu(i,this.namespace,this.id)},Yl.tween=function(n,t){var e=this.id,r=this.namespace;return arguments.length<2?this.node()[r][e].tween.get(n):Y(this,null==t?function(t){t[r][e].tween.remove(n)}:function(i){i[r][e].tween.set(n,t)})},Yl.attr=function(n,t){function e(){this.removeAttribute(a)}function r(){this.removeAttributeNS(a.space,a.local)}function i(n){return null==n?e:(n+="",function(){var t,e=this.getAttribute(a);return e!==n&&(t=o(e,n),function(n){this.setAttribute(a,t(n))})})}function u(n){return null==n?r:(n+="",function(){var t,e=this.getAttributeNS(a.space,a.local);return e!==n&&(t=o(e,n),function(n){this.setAttributeNS(a.space,a.local,t(n))})})}if(arguments.length<2){for(t in n)this.attr(t,n[t]);return this}var o="transform"==n?$r:Mr,a=ao.ns.qualify(n);return Ju(this,"attr."+n,t,a.local?u:i)},Yl.attrTween=function(n,t){function e(n,e){var r=t.call(this,n,e,this.getAttribute(i));return r&&function(n){this.setAttribute(i,r(n))}}function r(n,e){var r=t.call(this,n,e,this.getAttributeNS(i.space,i.local));return r&&function(n){this.setAttributeNS(i.space,i.local,r(n))}}var i=ao.ns.qualify(n);return this.tween("attr."+n,i.local?r:e)},Yl.style=function(n,e,r){function i(){this.style.removeProperty(n)}function u(e){return null==e?i:(e+="",function(){var i,u=t(this).getComputedStyle(this,null).getPropertyValue(n);return u!==e&&(i=Mr(u,e),function(t){this.style.setProperty(n,i(t),r)})})}var o=arguments.length;if(3>o){if("string"!=typeof n){2>o&&(e="");for(r in n)this.style(r,n[r],e);return this}r=""}return Ju(this,"style."+n,e,u)},Yl.styleTween=function(n,e,r){function i(i,u){var o=e.call(this,i,u,t(this).getComputedStyle(this,null).getPropertyValue(n));return o&&function(t){this.style.setProperty(n,o(t),r)}}return arguments.length<3&&(r=""),this.tween("style."+n,i)},Yl.text=function(n){return Ju(this,"text",n,Gu)},Yl.remove=function(){var n=this.namespace;return this.each("end.transition",function(){var t;this[n].count<2&&(t=this.parentNode)&&t.removeChild(this)})},Yl.ease=function(n){var t=this.id,e=this.namespace;return arguments.length<1?this.node()[e][t].ease:("function"!=typeof n&&(n=ao.ease.apply(ao,arguments)),Y(this,function(r){r[e][t].ease=n}))},Yl.delay=function(n){var t=this.id,e=this.namespace;return arguments.length<1?this.node()[e][t].delay:Y(this,"function"==typeof n?function(r,i,u){r[e][t].delay=+n.call(r,r.__data__,i,u)}:(n=+n,function(r){r[e][t].delay=n}))},Yl.duration=function(n){var t=this.id,e=this.namespace;return arguments.length<1?this.node()[e][t].duration:Y(this,"function"==typeof n?function(r,i,u){r[e][t].duration=Math.max(1,n.call(r,r.__data__,i,u))}:(n=Math.max(1,n),function(r){r[e][t].duration=n}))},Yl.each=function(n,t){var e=this.id,r=this.namespace;if(arguments.length<2){var i=Ol,u=Hl;try{Hl=e,Y(this,function(t,i,u){Ol=t[r][e],n.call(t,t.__data__,i,u)})}finally{Ol=i,Hl=u}}else Y(this,function(i){var u=i[r][e];(u.event||(u.event=ao.dispatch("start","end","interrupt"))).on(n,t)});return this},Yl.transition=function(){for(var n,t,e,r,i=this.id,u=++Zl,o=this.namespace,a=[],l=0,c=this.length;c>l;l++){a.push(n=[]);for(var t=this[l],f=0,s=t.length;s>f;f++)(e=t[f])&&(r=e[o][i],Qu(e,f,o,u,{time:r.time,ease:r.ease,delay:r.delay+r.duration,duration:r.duration})),n.push(e)}return Wu(a,o,u)},ao.svg.axis=function(){function n(n){n.each(function(){var n,c=ao.select(this),f=this.__chart__||e,s=this.__chart__=e.copy(),h=null==l?s.ticks?s.ticks.apply(s,a):s.domain():l,p=null==t?s.tickFormat?s.tickFormat.apply(s,a):m:t,g=c.selectAll(".tick").data(h,s),v=g.enter().insert("g",".domain").attr("class","tick").style("opacity",Uo),d=ao.transition(g.exit()).style("opacity",Uo).remove(),y=ao.transition(g.order()).style("opacity",1),M=Math.max(i,0)+o,x=Zi(s),b=c.selectAll(".domain").data([0]),_=(b.enter().append("path").attr("class","domain"),ao.transition(b));v.append("line"),v.append("text");var w,S,k,N,E=v.select("line"),A=y.select("line"),C=g.select("text").text(p),z=v.select("text"),L=y.select("text"),q="top"===r||"left"===r?-1:1;if("bottom"===r||"top"===r?(n=no,w="x",k="y",S="x2",N="y2",C.attr("dy",0>q?"0em":".71em").style("text-anchor","middle"),_.attr("d","M"+x[0]+","+q*u+"V0H"+x[1]+"V"+q*u)):(n=to,w="y",k="x",S="y2",N="x2",C.attr("dy",".32em").style("text-anchor",0>q?"end":"start"),_.attr("d","M"+q*u+","+x[0]+"H0V"+x[1]+"H"+q*u)),E.attr(N,q*i),z.attr(k,q*M),A.attr(S,0).attr(N,q*i),L.attr(w,0).attr(k,q*M),s.rangeBand){var T=s,R=T.rangeBand()/2;f=s=function(n){return T(n)+R}}else f.rangeBand?f=s:d.call(n,s,f);v.call(n,f,s),y.call(n,s,s)})}var t,e=ao.scale.linear(),r=Vl,i=6,u=6,o=3,a=[10],l=null;return n.scale=function(t){return arguments.length?(e=t,n):e},n.orient=function(t){return arguments.length?(r=t in Xl?t+"":Vl,n):r},n.ticks=function(){return arguments.length?(a=co(arguments),n):a},n.tickValues=function(t){return arguments.length?(l=t,n):l},n.tickFormat=function(e){return arguments.length?(t=e,n):t},n.tickSize=function(t){var e=arguments.length;return e?(i=+t,u=+arguments[e-1],n):i},n.innerTickSize=function(t){return arguments.length?(i=+t,n):i},n.outerTickSize=function(t){return arguments.length?(u=+t,n):u},n.tickPadding=function(t){return arguments.length?(o=+t,n):o},n.tickSubdivide=function(){return arguments.length&&n},n};var Vl="bottom",Xl={top:1,right:1,bottom:1,left:1};ao.svg.brush=function(){function n(t){t.each(function(){var t=ao.select(this).style("pointer-events","all").style("-webkit-tap-highlight-color","rgba(0,0,0,0)").on("mousedown.brush",u).on("touchstart.brush",u),o=t.selectAll(".background").data([0]);o.enter().append("rect").attr("class","background").style("visibility","hidden").style("cursor","crosshair"),t.selectAll(".extent").data([0]).enter().append("rect").attr("class","extent").style("cursor","move");var a=t.selectAll(".resize").data(v,m);a.exit().remove(),a.enter().append("g").attr("class",function(n){return"resize "+n}).style("cursor",function(n){return $l[n]}).append("rect").attr("x",function(n){return/[ew]$/.test(n)?-3:null}).attr("y",function(n){return/^[ns]/.test(n)?-3:null}).attr("width",6).attr("height",6).style("visibility","hidden"),a.style("display",n.empty()?"none":null);var l,s=ao.transition(t),h=ao.transition(o);c&&(l=Zi(c),h.attr("x",l[0]).attr("width",l[1]-l[0]),r(s)),f&&(l=Zi(f),h.attr("y",l[0]).attr("height",l[1]-l[0]),i(s)),e(s)})}function e(n){n.selectAll(".resize").attr("transform",function(n){return"translate("+s[+/e$/.test(n)]+","+h[+/^s/.test(n)]+")"})}function r(n){n.select(".extent").attr("x",s[0]),n.selectAll(".extent,.n>rect,.s>rect").attr("width",s[1]-s[0])}function i(n){n.select(".extent").attr("y",h[0]),n.selectAll(".extent,.e>rect,.w>rect").attr("height",h[1]-h[0])}function u(){function u(){32==ao.event.keyCode&&(C||(M=null,L[0]-=s[1],L[1]-=h[1],C=2),S())}function v(){32==ao.event.keyCode&&2==C&&(L[0]+=s[1],L[1]+=h[1],C=0,S())}function d(){var n=ao.mouse(b),t=!1;x&&(n[0]+=x[0],n[1]+=x[1]),C||(ao.event.altKey?(M||(M=[(s[0]+s[1])/2,(h[0]+h[1])/2]),L[0]=s[+(n[0]<M[0])],L[1]=h[+(n[1]<M[1])]):M=null),E&&y(n,c,0)&&(r(k),t=!0),A&&y(n,f,1)&&(i(k),t=!0),t&&(e(k),w({type:"brush",mode:C?"move":"resize"}))}function y(n,t,e){var r,i,u=Zi(t),l=u[0],c=u[1],f=L[e],v=e?h:s,d=v[1]-v[0];return C&&(l-=f,c-=d+f),r=(e?g:p)?Math.max(l,Math.min(c,n[e])):n[e],C?i=(r+=f)+d:(M&&(f=Math.max(l,Math.min(c,2*M[e]-r))),r>f?(i=r,r=f):i=f),v[0]!=r||v[1]!=i?(e?a=null:o=null,v[0]=r,v[1]=i,!0):void 0}function m(){d(),k.style("pointer-events","all").selectAll(".resize").style("display",n.empty()?"none":null),ao.select("body").style("cursor",null),q.on("mousemove.brush",null).on("mouseup.brush",null).on("touchmove.brush",null).on("touchend.brush",null).on("keydown.brush",null).on("keyup.brush",null),z(),w({type:"brushend"})}var M,x,b=this,_=ao.select(ao.event.target),w=l.of(b,arguments),k=ao.select(b),N=_.datum(),E=!/^(n|s)$/.test(N)&&c,A=!/^(e|w)$/.test(N)&&f,C=_.classed("extent"),z=W(b),L=ao.mouse(b),q=ao.select(t(b)).on("keydown.brush",u).on("keyup.brush",v);if(ao.event.changedTouches?q.on("touchmove.brush",d).on("touchend.brush",m):q.on("mousemove.brush",d).on("mouseup.brush",m),k.interrupt().selectAll("*").interrupt(),C)L[0]=s[0]-L[0],L[1]=h[0]-L[1];else if(N){var T=+/w$/.test(N),R=+/^n/.test(N);x=[s[1-T]-L[0],h[1-R]-L[1]],L[0]=s[T],L[1]=h[R]}else ao.event.altKey&&(M=L.slice());k.style("pointer-events","none").selectAll(".resize").style("display",null),ao.select("body").style("cursor",_.style("cursor")),w({type:"brushstart"}),d()}var o,a,l=N(n,"brushstart","brush","brushend"),c=null,f=null,s=[0,0],h=[0,0],p=!0,g=!0,v=Bl[0];return n.event=function(n){n.each(function(){var n=l.of(this,arguments),t={x:s,y:h,i:o,j:a},e=this.__chart__||t;this.__chart__=t,Hl?ao.select(this).transition().each("start.brush",function(){o=e.i,a=e.j,s=e.x,h=e.y,n({type:"brushstart"})}).tween("brush:brush",function(){var e=xr(s,t.x),r=xr(h,t.y);return o=a=null,function(i){s=t.x=e(i),h=t.y=r(i),n({type:"brush",mode:"resize"})}}).each("end.brush",function(){o=t.i,a=t.j,n({type:"brush",mode:"resize"}),n({type:"brushend"})}):(n({type:"brushstart"}),n({type:"brush",mode:"resize"}),n({type:"brushend"}))})},n.x=function(t){return arguments.length?(c=t,v=Bl[!c<<1|!f],n):c},n.y=function(t){return arguments.length?(f=t,v=Bl[!c<<1|!f],n):f},n.clamp=function(t){return arguments.length?(c&&f?(p=!!t[0],g=!!t[1]):c?p=!!t:f&&(g=!!t),n):c&&f?[p,g]:c?p:f?g:null},n.extent=function(t){var e,r,i,u,l;return arguments.length?(c&&(e=t[0],r=t[1],f&&(e=e[0],r=r[0]),o=[e,r],c.invert&&(e=c(e),r=c(r)),e>r&&(l=e,e=r,r=l),e==s[0]&&r==s[1]||(s=[e,r])),f&&(i=t[0],u=t[1],c&&(i=i[1],u=u[1]),a=[i,u],f.invert&&(i=f(i),u=f(u)),i>u&&(l=i,i=u,u=l),i==h[0]&&u==h[1]||(h=[i,u])),n):(c&&(o?(e=o[0],r=o[1]):(e=s[0],r=s[1],c.invert&&(e=c.invert(e),r=c.invert(r)),e>r&&(l=e,e=r,r=l))),f&&(a?(i=a[0],u=a[1]):(i=h[0],u=h[1],f.invert&&(i=f.invert(i),u=f.invert(u)),i>u&&(l=i,i=u,u=l))),c&&f?[[e,i],[r,u]]:c?[e,r]:f&&[i,u])},n.clear=function(){return n.empty()||(s=[0,0],h=[0,0],o=a=null),n},n.empty=function(){return!!c&&s[0]==s[1]||!!f&&h[0]==h[1]},ao.rebind(n,l,"on")};var $l={n:"ns-resize",e:"ew-resize",s:"ns-resize",w:"ew-resize",nw:"nwse-resize",ne:"nesw-resize",se:"nwse-resize",sw:"nesw-resize"},Bl=[["n","e","s","w","nw","ne","se","sw"],["e","w"],["n","s"],[]],Wl=ga.format=xa.timeFormat,Jl=Wl.utc,Gl=Jl("%Y-%m-%dT%H:%M:%S.%LZ");Wl.iso=Date.prototype.toISOString&&+new Date("2000-01-01T00:00:00.000Z")?eo:Gl,eo.parse=function(n){var t=new Date(n);return isNaN(t)?null:t},eo.toString=Gl.toString,ga.second=On(function(n){return new va(1e3*Math.floor(n/1e3))},function(n,t){n.setTime(n.getTime()+1e3*Math.floor(t))},function(n){return n.getSeconds()}),ga.seconds=ga.second.range,ga.seconds.utc=ga.second.utc.range,ga.minute=On(function(n){return new va(6e4*Math.floor(n/6e4))},function(n,t){n.setTime(n.getTime()+6e4*Math.floor(t))},function(n){return n.getMinutes()}),ga.minutes=ga.minute.range,ga.minutes.utc=ga.minute.utc.range,ga.hour=On(function(n){var t=n.getTimezoneOffset()/60;return new va(36e5*(Math.floor(n/36e5-t)+t))},function(n,t){n.setTime(n.getTime()+36e5*Math.floor(t))},function(n){return n.getHours()}),ga.hours=ga.hour.range,ga.hours.utc=ga.hour.utc.range,ga.month=On(function(n){return n=ga.day(n),n.setDate(1),n},function(n,t){n.setMonth(n.getMonth()+t)},function(n){return n.getMonth()}),ga.months=ga.month.range,ga.months.utc=ga.month.utc.range;var Kl=[1e3,5e3,15e3,3e4,6e4,3e5,9e5,18e5,36e5,108e5,216e5,432e5,864e5,1728e5,6048e5,2592e6,7776e6,31536e6],Ql=[[ga.second,1],[ga.second,5],[ga.second,15],[ga.second,30],[ga.minute,1],[ga.minute,5],[ga.minute,15],[ga.minute,30],[ga.hour,1],[ga.hour,3],[ga.hour,6],[ga.hour,12],[ga.day,1],[ga.day,2],[ga.week,1],[ga.month,1],[ga.month,3],[ga.year,1]],nc=Wl.multi([[".%L",function(n){return n.getMilliseconds()}],[":%S",function(n){return n.getSeconds()}],["%I:%M",function(n){return n.getMinutes()}],["%I %p",function(n){return n.getHours()}],["%a %d",function(n){return n.getDay()&&1!=n.getDate()}],["%b %d",function(n){return 1!=n.getDate()}],["%B",function(n){return n.getMonth()}],["%Y",zt]]),tc={range:function(n,t,e){return ao.range(Math.ceil(n/e)*e,+t,e).map(io)},floor:m,ceil:m};Ql.year=ga.year,ga.scale=function(){return ro(ao.scale.linear(),Ql,nc)};var ec=Ql.map(function(n){return[n[0].utc,n[1]]}),rc=Jl.multi([[".%L",function(n){return n.getUTCMilliseconds()}],[":%S",function(n){return n.getUTCSeconds()}],["%I:%M",function(n){return n.getUTCMinutes()}],["%I %p",function(n){return n.getUTCHours()}],["%a %d",function(n){return n.getUTCDay()&&1!=n.getUTCDate()}],["%b %d",function(n){return 1!=n.getUTCDate()}],["%B",function(n){return n.getUTCMonth()}],["%Y",zt]]);ec.year=ga.year.utc,ga.scale.utc=function(){return ro(ao.scale.linear(),ec,rc)},ao.text=An(function(n){return n.responseText}),ao.json=function(n,t){return Cn(n,"application/json",uo,t)},ao.html=function(n,t){return Cn(n,"text/html",oo,t)},ao.xml=An(function(n){return n.responseXML}),"function"==typeof define&&define.amd?(this.d3=ao,define(ao)):"object"==typeof module&&module.exports?module.exports=ao:this.d3=ao}();/*
  22863. Copyright (C) Federico Zivolo 2019
  22864. Distributed under the MIT License (license terms are at http://opensource.org/licenses/MIT).
  22865. */(function(e,t){'object'==typeof exports&&'undefined'!=typeof module?module.exports=t():'function'==typeof define&&define.amd?define(t):e.Popper=t()})(this,function(){'use strict';function e(e){return e&&'[object Function]'==={}.toString.call(e)}function t(e,t){if(1!==e.nodeType)return[];var o=e.ownerDocument.defaultView,n=o.getComputedStyle(e,null);return t?n[t]:n}function o(e){return'HTML'===e.nodeName?e:e.parentNode||e.host}function n(e){if(!e)return document.body;switch(e.nodeName){case'HTML':case'BODY':return e.ownerDocument.body;case'#document':return e.body;}var i=t(e),r=i.overflow,p=i.overflowX,s=i.overflowY;return /(auto|scroll|overlay)/.test(r+s+p)?e:n(o(e))}function r(e){return 11===e?pe:10===e?se:pe||se}function p(e){if(!e)return document.documentElement;for(var o=r(10)?document.body:null,n=e.offsetParent||null;n===o&&e.nextElementSibling;)n=(e=e.nextElementSibling).offsetParent;var i=n&&n.nodeName;return i&&'BODY'!==i&&'HTML'!==i?-1!==['TH','TD','TABLE'].indexOf(n.nodeName)&&'static'===t(n,'position')?p(n):n:e?e.ownerDocument.documentElement:document.documentElement}function s(e){var t=e.nodeName;return'BODY'!==t&&('HTML'===t||p(e.firstElementChild)===e)}function d(e){return null===e.parentNode?e:d(e.parentNode)}function a(e,t){if(!e||!e.nodeType||!t||!t.nodeType)return document.documentElement;var o=e.compareDocumentPosition(t)&Node.DOCUMENT_POSITION_FOLLOWING,n=o?e:t,i=o?t:e,r=document.createRange();r.setStart(n,0),r.setEnd(i,0);var l=r.commonAncestorContainer;if(e!==l&&t!==l||n.contains(i))return s(l)?l:p(l);var f=d(e);return f.host?a(f.host,t):a(e,d(t).host)}function l(e){var t=1<arguments.length&&void 0!==arguments[1]?arguments[1]:'top',o='top'===t?'scrollTop':'scrollLeft',n=e.nodeName;if('BODY'===n||'HTML'===n){var i=e.ownerDocument.documentElement,r=e.ownerDocument.scrollingElement||i;return r[o]}return e[o]}function f(e,t){var o=2<arguments.length&&void 0!==arguments[2]&&arguments[2],n=l(t,'top'),i=l(t,'left'),r=o?-1:1;return e.top+=n*r,e.bottom+=n*r,e.left+=i*r,e.right+=i*r,e}function m(e,t){var o='x'===t?'Left':'Top',n='Left'==o?'Right':'Bottom';return parseFloat(e['border'+o+'Width'],10)+parseFloat(e['border'+n+'Width'],10)}function h(e,t,o,n){return ee(t['offset'+e],t['scroll'+e],o['client'+e],o['offset'+e],o['scroll'+e],r(10)?parseInt(o['offset'+e])+parseInt(n['margin'+('Height'===e?'Top':'Left')])+parseInt(n['margin'+('Height'===e?'Bottom':'Right')]):0)}function c(e){var t=e.body,o=e.documentElement,n=r(10)&&getComputedStyle(o);return{height:h('Height',t,o,n),width:h('Width',t,o,n)}}function g(e){return fe({},e,{right:e.left+e.width,bottom:e.top+e.height})}function u(e){var o={};try{if(r(10)){o=e.getBoundingClientRect();var n=l(e,'top'),i=l(e,'left');o.top+=n,o.left+=i,o.bottom+=n,o.right+=i}else o=e.getBoundingClientRect()}catch(t){}var p={left:o.left,top:o.top,width:o.right-o.left,height:o.bottom-o.top},s='HTML'===e.nodeName?c(e.ownerDocument):{},d=s.width||e.clientWidth||p.right-p.left,a=s.height||e.clientHeight||p.bottom-p.top,f=e.offsetWidth-d,h=e.offsetHeight-a;if(f||h){var u=t(e);f-=m(u,'x'),h-=m(u,'y'),p.width-=f,p.height-=h}return g(p)}function b(e,o){var i=2<arguments.length&&void 0!==arguments[2]&&arguments[2],p=r(10),s='HTML'===o.nodeName,d=u(e),a=u(o),l=n(e),m=t(o),h=parseFloat(m.borderTopWidth,10),c=parseFloat(m.borderLeftWidth,10);i&&s&&(a.top=ee(a.top,0),a.left=ee(a.left,0));var b=g({top:d.top-a.top-h,left:d.left-a.left-c,width:d.width,height:d.height});if(b.marginTop=0,b.marginLeft=0,!p&&s){var w=parseFloat(m.marginTop,10),y=parseFloat(m.marginLeft,10);b.top-=h-w,b.bottom-=h-w,b.left-=c-y,b.right-=c-y,b.marginTop=w,b.marginLeft=y}return(p&&!i?o.contains(l):o===l&&'BODY'!==l.nodeName)&&(b=f(b,o)),b}function w(e){var t=1<arguments.length&&void 0!==arguments[1]&&arguments[1],o=e.ownerDocument.documentElement,n=b(e,o),i=ee(o.clientWidth,window.innerWidth||0),r=ee(o.clientHeight,window.innerHeight||0),p=t?0:l(o),s=t?0:l(o,'left'),d={top:p-n.top+n.marginTop,left:s-n.left+n.marginLeft,width:i,height:r};return g(d)}function y(e){var n=e.nodeName;if('BODY'===n||'HTML'===n)return!1;if('fixed'===t(e,'position'))return!0;var i=o(e);return!!i&&y(i)}function E(e){if(!e||!e.parentElement||r())return document.documentElement;for(var o=e.parentElement;o&&'none'===t(o,'transform');)o=o.parentElement;return o||document.documentElement}function v(e,t,i,r){var p=4<arguments.length&&void 0!==arguments[4]&&arguments[4],s={top:0,left:0},d=p?E(e):a(e,t);if('viewport'===r)s=w(d,p);else{var l;'scrollParent'===r?(l=n(o(t)),'BODY'===l.nodeName&&(l=e.ownerDocument.documentElement)):'window'===r?l=e.ownerDocument.documentElement:l=r;var f=b(l,d,p);if('HTML'===l.nodeName&&!y(d)){var m=c(e.ownerDocument),h=m.height,g=m.width;s.top+=f.top-f.marginTop,s.bottom=h+f.top,s.left+=f.left-f.marginLeft,s.right=g+f.left}else s=f}i=i||0;var u='number'==typeof i;return s.left+=u?i:i.left||0,s.top+=u?i:i.top||0,s.right-=u?i:i.right||0,s.bottom-=u?i:i.bottom||0,s}function x(e){var t=e.width,o=e.height;return t*o}function O(e,t,o,n,i){var r=5<arguments.length&&void 0!==arguments[5]?arguments[5]:0;if(-1===e.indexOf('auto'))return e;var p=v(o,n,r,i),s={top:{width:p.width,height:t.top-p.top},right:{width:p.right-t.right,height:p.height},bottom:{width:p.width,height:p.bottom-t.bottom},left:{width:t.left-p.left,height:p.height}},d=Object.keys(s).map(function(e){return fe({key:e},s[e],{area:x(s[e])})}).sort(function(e,t){return t.area-e.area}),a=d.filter(function(e){var t=e.width,n=e.height;return t>=o.clientWidth&&n>=o.clientHeight}),l=0<a.length?a[0].key:d[0].key,f=e.split('-')[1];return l+(f?'-'+f:'')}function L(e,t,o){var n=3<arguments.length&&void 0!==arguments[3]?arguments[3]:null,i=n?E(t):a(t,o);return b(o,i,n)}function S(e){var t=e.ownerDocument.defaultView,o=t.getComputedStyle(e),n=parseFloat(o.marginTop||0)+parseFloat(o.marginBottom||0),i=parseFloat(o.marginLeft||0)+parseFloat(o.marginRight||0),r={width:e.offsetWidth+i,height:e.offsetHeight+n};return r}function T(e){var t={left:'right',right:'left',bottom:'top',top:'bottom'};return e.replace(/left|right|bottom|top/g,function(e){return t[e]})}function C(e,t,o){o=o.split('-')[0];var n=S(e),i={width:n.width,height:n.height},r=-1!==['right','left'].indexOf(o),p=r?'top':'left',s=r?'left':'top',d=r?'height':'width',a=r?'width':'height';return i[p]=t[p]+t[d]/2-n[d]/2,i[s]=o===s?t[s]-n[a]:t[T(s)],i}function D(e,t){return Array.prototype.find?e.find(t):e.filter(t)[0]}function N(e,t,o){if(Array.prototype.findIndex)return e.findIndex(function(e){return e[t]===o});var n=D(e,function(e){return e[t]===o});return e.indexOf(n)}function P(t,o,n){var i=void 0===n?t:t.slice(0,N(t,'name',n));return i.forEach(function(t){t['function']&&console.warn('`modifier.function` is deprecated, use `modifier.fn`!');var n=t['function']||t.fn;t.enabled&&e(n)&&(o.offsets.popper=g(o.offsets.popper),o.offsets.reference=g(o.offsets.reference),o=n(o,t))}),o}function k(){if(!this.state.isDestroyed){var e={instance:this,styles:{},arrowStyles:{},attributes:{},flipped:!1,offsets:{}};e.offsets.reference=L(this.state,this.popper,this.reference,this.options.positionFixed),e.placement=O(this.options.placement,e.offsets.reference,this.popper,this.reference,this.options.modifiers.flip.boundariesElement,this.options.modifiers.flip.padding),e.originalPlacement=e.placement,e.positionFixed=this.options.positionFixed,e.offsets.popper=C(this.popper,e.offsets.reference,e.placement),e.offsets.popper.position=this.options.positionFixed?'fixed':'absolute',e=P(this.modifiers,e),this.state.isCreated?this.options.onUpdate(e):(this.state.isCreated=!0,this.options.onCreate(e))}}function W(e,t){return e.some(function(e){var o=e.name,n=e.enabled;return n&&o===t})}function B(e){for(var t=[!1,'ms','Webkit','Moz','O'],o=e.charAt(0).toUpperCase()+e.slice(1),n=0;n<t.length;n++){var i=t[n],r=i?''+i+o:e;if('undefined'!=typeof document.body.style[r])return r}return null}function H(){return this.state.isDestroyed=!0,W(this.modifiers,'applyStyle')&&(this.popper.removeAttribute('x-placement'),this.popper.style.position='',this.popper.style.top='',this.popper.style.left='',this.popper.style.right='',this.popper.style.bottom='',this.popper.style.willChange='',this.popper.style[B('transform')]=''),this.disableEventListeners(),this.options.removeOnDestroy&&this.popper.parentNode.removeChild(this.popper),this}function A(e){var t=e.ownerDocument;return t?t.defaultView:window}function M(e,t,o,i){var r='BODY'===e.nodeName,p=r?e.ownerDocument.defaultView:e;p.addEventListener(t,o,{passive:!0}),r||M(n(p.parentNode),t,o,i),i.push(p)}function F(e,t,o,i){o.updateBound=i,A(e).addEventListener('resize',o.updateBound,{passive:!0});var r=n(e);return M(r,'scroll',o.updateBound,o.scrollParents),o.scrollElement=r,o.eventsEnabled=!0,o}function I(){this.state.eventsEnabled||(this.state=F(this.reference,this.options,this.state,this.scheduleUpdate))}function R(e,t){return A(e).removeEventListener('resize',t.updateBound),t.scrollParents.forEach(function(e){e.removeEventListener('scroll',t.updateBound)}),t.updateBound=null,t.scrollParents=[],t.scrollElement=null,t.eventsEnabled=!1,t}function U(){this.state.eventsEnabled&&(cancelAnimationFrame(this.scheduleUpdate),this.state=R(this.reference,this.state))}function Y(e){return''!==e&&!isNaN(parseFloat(e))&&isFinite(e)}function V(e,t){Object.keys(t).forEach(function(o){var n='';-1!==['width','height','top','right','bottom','left'].indexOf(o)&&Y(t[o])&&(n='px'),e.style[o]=t[o]+n})}function j(e,t){Object.keys(t).forEach(function(o){var n=t[o];!1===n?e.removeAttribute(o):e.setAttribute(o,t[o])})}function q(e,t){var o=e.offsets,n=o.popper,i=o.reference,r=$,p=function(e){return e},s=r(i.width),d=r(n.width),a=-1!==['left','right'].indexOf(e.placement),l=-1!==e.placement.indexOf('-'),f=t?a||l||s%2==d%2?r:Z:p,m=t?r:p;return{left:f(1==s%2&&1==d%2&&!l&&t?n.left-1:n.left),top:m(n.top),bottom:m(n.bottom),right:f(n.right)}}function K(e,t,o){var n=D(e,function(e){var o=e.name;return o===t}),i=!!n&&e.some(function(e){return e.name===o&&e.enabled&&e.order<n.order});if(!i){var r='`'+t+'`';console.warn('`'+o+'`'+' modifier is required by '+r+' modifier in order to work, be sure to include it before '+r+'!')}return i}function z(e){return'end'===e?'start':'start'===e?'end':e}function G(e){var t=1<arguments.length&&void 0!==arguments[1]&&arguments[1],o=ce.indexOf(e),n=ce.slice(o+1).concat(ce.slice(0,o));return t?n.reverse():n}function _(e,t,o,n){var i=e.match(/((?:\-|\+)?\d*\.?\d*)(.*)/),r=+i[1],p=i[2];if(!r)return e;if(0===p.indexOf('%')){var s;switch(p){case'%p':s=o;break;case'%':case'%r':default:s=n;}var d=g(s);return d[t]/100*r}if('vh'===p||'vw'===p){var a;return a='vh'===p?ee(document.documentElement.clientHeight,window.innerHeight||0):ee(document.documentElement.clientWidth,window.innerWidth||0),a/100*r}return r}function X(e,t,o,n){var i=[0,0],r=-1!==['right','left'].indexOf(n),p=e.split(/(\+|\-)/).map(function(e){return e.trim()}),s=p.indexOf(D(p,function(e){return-1!==e.search(/,|\s/)}));p[s]&&-1===p[s].indexOf(',')&&console.warn('Offsets separated by white space(s) are deprecated, use a comma (,) instead.');var d=/\s*,\s*|\s+/,a=-1===s?[p]:[p.slice(0,s).concat([p[s].split(d)[0]]),[p[s].split(d)[1]].concat(p.slice(s+1))];return a=a.map(function(e,n){var i=(1===n?!r:r)?'height':'width',p=!1;return e.reduce(function(e,t){return''===e[e.length-1]&&-1!==['+','-'].indexOf(t)?(e[e.length-1]=t,p=!0,e):p?(e[e.length-1]+=t,p=!1,e):e.concat(t)},[]).map(function(e){return _(e,i,t,o)})}),a.forEach(function(e,t){e.forEach(function(o,n){Y(o)&&(i[t]+=o*('-'===e[n-1]?-1:1))})}),i}function J(e,t){var o,n=t.offset,i=e.placement,r=e.offsets,p=r.popper,s=r.reference,d=i.split('-')[0];return o=Y(+n)?[+n,0]:X(n,p,s,d),'left'===d?(p.top+=o[0],p.left-=o[1]):'right'===d?(p.top+=o[0],p.left+=o[1]):'top'===d?(p.left+=o[0],p.top-=o[1]):'bottom'===d&&(p.left+=o[0],p.top+=o[1]),e.popper=p,e}for(var Q=Math.min,Z=Math.floor,$=Math.round,ee=Math.max,te='undefined'!=typeof window&&'undefined'!=typeof document,oe=['Edge','Trident','Firefox'],ne=0,ie=0;ie<oe.length;ie+=1)if(te&&0<=navigator.userAgent.indexOf(oe[ie])){ne=1;break}var i=te&&window.Promise,re=i?function(e){var t=!1;return function(){t||(t=!0,window.Promise.resolve().then(function(){t=!1,e()}))}}:function(e){var t=!1;return function(){t||(t=!0,setTimeout(function(){t=!1,e()},ne))}},pe=te&&!!(window.MSInputMethodContext&&document.documentMode),se=te&&/MSIE 10/.test(navigator.userAgent),de=function(e,t){if(!(e instanceof t))throw new TypeError('Cannot call a class as a function')},ae=function(){function e(e,t){for(var o,n=0;n<t.length;n++)o=t[n],o.enumerable=o.enumerable||!1,o.configurable=!0,'value'in o&&(o.writable=!0),Object.defineProperty(e,o.key,o)}return function(t,o,n){return o&&e(t.prototype,o),n&&e(t,n),t}}(),le=function(e,t,o){return t in e?Object.defineProperty(e,t,{value:o,enumerable:!0,configurable:!0,writable:!0}):e[t]=o,e},fe=Object.assign||function(e){for(var t,o=1;o<arguments.length;o++)for(var n in t=arguments[o],t)Object.prototype.hasOwnProperty.call(t,n)&&(e[n]=t[n]);return e},me=te&&/Firefox/i.test(navigator.userAgent),he=['auto-start','auto','auto-end','top-start','top','top-end','right-start','right','right-end','bottom-end','bottom','bottom-start','left-end','left','left-start'],ce=he.slice(3),ge={FLIP:'flip',CLOCKWISE:'clockwise',COUNTERCLOCKWISE:'counterclockwise'},ue=function(){function t(o,n){var i=this,r=2<arguments.length&&void 0!==arguments[2]?arguments[2]:{};de(this,t),this.scheduleUpdate=function(){return requestAnimationFrame(i.update)},this.update=re(this.update.bind(this)),this.options=fe({},t.Defaults,r),this.state={isDestroyed:!1,isCreated:!1,scrollParents:[]},this.reference=o&&o.jquery?o[0]:o,this.popper=n&&n.jquery?n[0]:n,this.options.modifiers={},Object.keys(fe({},t.Defaults.modifiers,r.modifiers)).forEach(function(e){i.options.modifiers[e]=fe({},t.Defaults.modifiers[e]||{},r.modifiers?r.modifiers[e]:{})}),this.modifiers=Object.keys(this.options.modifiers).map(function(e){return fe({name:e},i.options.modifiers[e])}).sort(function(e,t){return e.order-t.order}),this.modifiers.forEach(function(t){t.enabled&&e(t.onLoad)&&t.onLoad(i.reference,i.popper,i.options,t,i.state)}),this.update();var p=this.options.eventsEnabled;p&&this.enableEventListeners(),this.state.eventsEnabled=p}return ae(t,[{key:'update',value:function(){return k.call(this)}},{key:'destroy',value:function(){return H.call(this)}},{key:'enableEventListeners',value:function(){return I.call(this)}},{key:'disableEventListeners',value:function(){return U.call(this)}}]),t}();return ue.Utils=('undefined'==typeof window?global:window).PopperUtils,ue.placements=he,ue.Defaults={placement:'bottom',positionFixed:!1,eventsEnabled:!0,removeOnDestroy:!1,onCreate:function(){},onUpdate:function(){},modifiers:{shift:{order:100,enabled:!0,fn:function(e){var t=e.placement,o=t.split('-')[0],n=t.split('-')[1];if(n){var i=e.offsets,r=i.reference,p=i.popper,s=-1!==['bottom','top'].indexOf(o),d=s?'left':'top',a=s?'width':'height',l={start:le({},d,r[d]),end:le({},d,r[d]+r[a]-p[a])};e.offsets.popper=fe({},p,l[n])}return e}},offset:{order:200,enabled:!0,fn:J,offset:0},preventOverflow:{order:300,enabled:!0,fn:function(e,t){var o=t.boundariesElement||p(e.instance.popper);e.instance.reference===o&&(o=p(o));var n=B('transform'),i=e.instance.popper.style,r=i.top,s=i.left,d=i[n];i.top='',i.left='',i[n]='';var a=v(e.instance.popper,e.instance.reference,t.padding,o,e.positionFixed);i.top=r,i.left=s,i[n]=d,t.boundaries=a;var l=t.priority,f=e.offsets.popper,m={primary:function(e){var o=f[e];return f[e]<a[e]&&!t.escapeWithReference&&(o=ee(f[e],a[e])),le({},e,o)},secondary:function(e){var o='right'===e?'left':'top',n=f[o];return f[e]>a[e]&&!t.escapeWithReference&&(n=Q(f[o],a[e]-('right'===e?f.width:f.height))),le({},o,n)}};return l.forEach(function(e){var t=-1===['left','top'].indexOf(e)?'secondary':'primary';f=fe({},f,m[t](e))}),e.offsets.popper=f,e},priority:['left','right','top','bottom'],padding:5,boundariesElement:'scrollParent'},keepTogether:{order:400,enabled:!0,fn:function(e){var t=e.offsets,o=t.popper,n=t.reference,i=e.placement.split('-')[0],r=Z,p=-1!==['top','bottom'].indexOf(i),s=p?'right':'bottom',d=p?'left':'top',a=p?'width':'height';return o[s]<r(n[d])&&(e.offsets.popper[d]=r(n[d])-o[a]),o[d]>r(n[s])&&(e.offsets.popper[d]=r(n[s])),e}},arrow:{order:500,enabled:!0,fn:function(e,o){var n;if(!K(e.instance.modifiers,'arrow','keepTogether'))return e;var i=o.element;if('string'==typeof i){if(i=e.instance.popper.querySelector(i),!i)return e;}else if(!e.instance.popper.contains(i))return console.warn('WARNING: `arrow.element` must be child of its popper element!'),e;var r=e.placement.split('-')[0],p=e.offsets,s=p.popper,d=p.reference,a=-1!==['left','right'].indexOf(r),l=a?'height':'width',f=a?'Top':'Left',m=f.toLowerCase(),h=a?'left':'top',c=a?'bottom':'right',u=S(i)[l];d[c]-u<s[m]&&(e.offsets.popper[m]-=s[m]-(d[c]-u)),d[m]+u>s[c]&&(e.offsets.popper[m]+=d[m]+u-s[c]),e.offsets.popper=g(e.offsets.popper);var b=d[m]+d[l]/2-u/2,w=t(e.instance.popper),y=parseFloat(w['margin'+f],10),E=parseFloat(w['border'+f+'Width'],10),v=b-e.offsets.popper[m]-y-E;return v=ee(Q(s[l]-u,v),0),e.arrowElement=i,e.offsets.arrow=(n={},le(n,m,$(v)),le(n,h,''),n),e},element:'[x-arrow]'},flip:{order:600,enabled:!0,fn:function(e,t){if(W(e.instance.modifiers,'inner'))return e;if(e.flipped&&e.placement===e.originalPlacement)return e;var o=v(e.instance.popper,e.instance.reference,t.padding,t.boundariesElement,e.positionFixed),n=e.placement.split('-')[0],i=T(n),r=e.placement.split('-')[1]||'',p=[];switch(t.behavior){case ge.FLIP:p=[n,i];break;case ge.CLOCKWISE:p=G(n);break;case ge.COUNTERCLOCKWISE:p=G(n,!0);break;default:p=t.behavior;}return p.forEach(function(s,d){if(n!==s||p.length===d+1)return e;n=e.placement.split('-')[0],i=T(n);var a=e.offsets.popper,l=e.offsets.reference,f=Z,m='left'===n&&f(a.right)>f(l.left)||'right'===n&&f(a.left)<f(l.right)||'top'===n&&f(a.bottom)>f(l.top)||'bottom'===n&&f(a.top)<f(l.bottom),h=f(a.left)<f(o.left),c=f(a.right)>f(o.right),g=f(a.top)<f(o.top),u=f(a.bottom)>f(o.bottom),b='left'===n&&h||'right'===n&&c||'top'===n&&g||'bottom'===n&&u,w=-1!==['top','bottom'].indexOf(n),y=!!t.flipVariations&&(w&&'start'===r&&h||w&&'end'===r&&c||!w&&'start'===r&&g||!w&&'end'===r&&u),E=!!t.flipVariationsByContent&&(w&&'start'===r&&c||w&&'end'===r&&h||!w&&'start'===r&&u||!w&&'end'===r&&g),v=y||E;(m||b||v)&&(e.flipped=!0,(m||b)&&(n=p[d+1]),v&&(r=z(r)),e.placement=n+(r?'-'+r:''),e.offsets.popper=fe({},e.offsets.popper,C(e.instance.popper,e.offsets.reference,e.placement)),e=P(e.instance.modifiers,e,'flip'))}),e},behavior:'flip',padding:5,boundariesElement:'viewport',flipVariations:!1,flipVariationsByContent:!1},inner:{order:700,enabled:!1,fn:function(e){var t=e.placement,o=t.split('-')[0],n=e.offsets,i=n.popper,r=n.reference,p=-1!==['left','right'].indexOf(o),s=-1===['top','left'].indexOf(o);return i[p?'left':'top']=r[o]-(s?i[p?'width':'height']:0),e.placement=T(t),e.offsets.popper=g(i),e}},hide:{order:800,enabled:!0,fn:function(e){if(!K(e.instance.modifiers,'hide','preventOverflow'))return e;var t=e.offsets.reference,o=D(e.instance.modifiers,function(e){return'preventOverflow'===e.name}).boundaries;if(t.bottom<o.top||t.left>o.right||t.top>o.bottom||t.right<o.left){if(!0===e.hide)return e;e.hide=!0,e.attributes['x-out-of-boundaries']=''}else{if(!1===e.hide)return e;e.hide=!1,e.attributes['x-out-of-boundaries']=!1}return e}},computeStyle:{order:850,enabled:!0,fn:function(e,t){var o=t.x,n=t.y,i=e.offsets.popper,r=D(e.instance.modifiers,function(e){return'applyStyle'===e.name}).gpuAcceleration;void 0!==r&&console.warn('WARNING: `gpuAcceleration` option moved to `computeStyle` modifier and will not be supported in future versions of Popper.js!');var s,d,a=void 0===r?t.gpuAcceleration:r,l=p(e.instance.popper),f=u(l),m={position:i.position},h=q(e,2>window.devicePixelRatio||!me),c='bottom'===o?'top':'bottom',g='right'===n?'left':'right',b=B('transform');if(d='bottom'==c?'HTML'===l.nodeName?-l.clientHeight+h.bottom:-f.height+h.bottom:h.top,s='right'==g?'HTML'===l.nodeName?-l.clientWidth+h.right:-f.width+h.right:h.left,a&&b)m[b]='translate3d('+s+'px, '+d+'px, 0)',m[c]=0,m[g]=0,m.willChange='transform';else{var w='bottom'==c?-1:1,y='right'==g?-1:1;m[c]=d*w,m[g]=s*y,m.willChange=c+', '+g}var E={"x-placement":e.placement};return e.attributes=fe({},E,e.attributes),e.styles=fe({},m,e.styles),e.arrowStyles=fe({},e.offsets.arrow,e.arrowStyles),e},gpuAcceleration:!0,x:'bottom',y:'right'},applyStyle:{order:900,enabled:!0,fn:function(e){return V(e.instance.popper,e.styles),j(e.instance.popper,e.attributes),e.arrowElement&&Object.keys(e.arrowStyles).length&&V(e.arrowElement,e.arrowStyles),e},onLoad:function(e,t,o,n,i){var r=L(i,t,e,o.positionFixed),p=O(o.placement,r,t,e,o.modifiers.flip.boundariesElement,o.modifiers.flip.padding);return t.setAttribute('x-placement',p),V(t,{position:o.positionFixed?'fixed':'absolute'}),o},gpuAcceleration:void 0}}},ue});
  22866. //# sourceMappingURL=popper.min.js.map
  22867. /*! jQuery v3.4.1 | (c) JS Foundation and other contributors | jquery.org/license */
  22868. !function(e,t){"use strict";"object"==typeof module&&"object"==typeof module.exports?module.exports=e.document?t(e,!0):function(e){if(!e.document)throw new Error("jQuery requires a window with a document");return t(e)}:t(e)}("undefined"!=typeof window?window:this,function(C,e){"use strict";var t=[],E=C.document,r=Object.getPrototypeOf,s=t.slice,g=t.concat,u=t.push,i=t.indexOf,n={},o=n.toString,v=n.hasOwnProperty,a=v.toString,l=a.call(Object),y={},m=function(e){return"function"==typeof e&&"number"!=typeof e.nodeType},x=function(e){return null!=e&&e===e.window},c={type:!0,src:!0,nonce:!0,noModule:!0};function b(e,t,n){var r,i,o=(n=n||E).createElement("script");if(o.text=e,t)for(r in c)(i=t[r]||t.getAttribute&&t.getAttribute(r))&&o.setAttribute(r,i);n.head.appendChild(o).parentNode.removeChild(o)}function w(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?n[o.call(e)]||"object":typeof e}var f="3.4.1",k=function(e,t){return new k.fn.init(e,t)},p=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g;function d(e){var t=!!e&&"length"in e&&e.length,n=w(e);return!m(e)&&!x(e)&&("array"===n||0===t||"number"==typeof t&&0<t&&t-1 in e)}k.fn=k.prototype={jquery:f,constructor:k,length:0,toArray:function(){return s.call(this)},get:function(e){return null==e?s.call(this):e<0?this[e+this.length]:this[e]},pushStack:function(e){var t=k.merge(this.constructor(),e);return t.prevObject=this,t},each:function(e){return k.each(this,e)},map:function(n){return this.pushStack(k.map(this,function(e,t){return n.call(e,t,e)}))},slice:function(){return this.pushStack(s.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(e){var t=this.length,n=+e+(e<0?t:0);return this.pushStack(0<=n&&n<t?[this[n]]:[])},end:function(){return this.prevObject||this.constructor()},push:u,sort:t.sort,splice:t.splice},k.extend=k.fn.extend=function(){var e,t,n,r,i,o,a=arguments[0]||{},s=1,u=arguments.length,l=!1;for("boolean"==typeof a&&(l=a,a=arguments[s]||{},s++),"object"==typeof a||m(a)||(a={}),s===u&&(a=this,s--);s<u;s++)if(null!=(e=arguments[s]))for(t in e)r=e[t],"__proto__"!==t&&a!==r&&(l&&r&&(k.isPlainObject(r)||(i=Array.isArray(r)))?(n=a[t],o=i&&!Array.isArray(n)?[]:i||k.isPlainObject(n)?n:{},i=!1,a[t]=k.extend(l,o,r)):void 0!==r&&(a[t]=r));return a},k.extend({expando:"jQuery"+(f+Math.random()).replace(/\D/g,""),isReady:!0,error:function(e){throw new Error(e)},noop:function(){},isPlainObject:function(e){var t,n;return!(!e||"[object Object]"!==o.call(e))&&(!(t=r(e))||"function"==typeof(n=v.call(t,"constructor")&&t.constructor)&&a.call(n)===l)},isEmptyObject:function(e){var t;for(t in e)return!1;return!0},globalEval:function(e,t){b(e,{nonce:t&&t.nonce})},each:function(e,t){var n,r=0;if(d(e)){for(n=e.length;r<n;r++)if(!1===t.call(e[r],r,e[r]))break}else for(r in e)if(!1===t.call(e[r],r,e[r]))break;return e},trim:function(e){return null==e?"":(e+"").replace(p,"")},makeArray:function(e,t){var n=t||[];return null!=e&&(d(Object(e))?k.merge(n,"string"==typeof e?[e]:e):u.call(n,e)),n},inArray:function(e,t,n){return null==t?-1:i.call(t,e,n)},merge:function(e,t){for(var n=+t.length,r=0,i=e.length;r<n;r++)e[i++]=t[r];return e.length=i,e},grep:function(e,t,n){for(var r=[],i=0,o=e.length,a=!n;i<o;i++)!t(e[i],i)!==a&&r.push(e[i]);return r},map:function(e,t,n){var r,i,o=0,a=[];if(d(e))for(r=e.length;o<r;o++)null!=(i=t(e[o],o,n))&&a.push(i);else for(o in e)null!=(i=t(e[o],o,n))&&a.push(i);return g.apply([],a)},guid:1,support:y}),"function"==typeof Symbol&&(k.fn[Symbol.iterator]=t[Symbol.iterator]),k.each("Boolean Number String Function Array Date RegExp Object Error Symbol".split(" "),function(e,t){n["[object "+t+"]"]=t.toLowerCase()});var h=function(n){var e,d,b,o,i,h,f,g,w,u,l,T,C,a,E,v,s,c,y,k="sizzle"+1*new Date,m=n.document,S=0,r=0,p=ue(),x=ue(),N=ue(),A=ue(),D=function(e,t){return e===t&&(l=!0),0},j={}.hasOwnProperty,t=[],q=t.pop,L=t.push,H=t.push,O=t.slice,P=function(e,t){for(var n=0,r=e.length;n<r;n++)if(e[n]===t)return n;return-1},R="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",M="[\\x20\\t\\r\\n\\f]",I="(?:\\\\.|[\\w-]|[^\0-\\xa0])+",W="\\["+M+"*("+I+")(?:"+M+"*([*^$|!~]?=)"+M+"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|("+I+"))|)"+M+"*\\]",$=":("+I+")(?:\\((('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|((?:\\\\.|[^\\\\()[\\]]|"+W+")*)|.*)\\)|)",F=new RegExp(M+"+","g"),B=new RegExp("^"+M+"+|((?:^|[^\\\\])(?:\\\\.)*)"+M+"+$","g"),_=new RegExp("^"+M+"*,"+M+"*"),z=new RegExp("^"+M+"*([>+~]|"+M+")"+M+"*"),U=new RegExp(M+"|>"),X=new RegExp($),V=new RegExp("^"+I+"$"),G={ID:new RegExp("^#("+I+")"),CLASS:new RegExp("^\\.("+I+")"),TAG:new RegExp("^("+I+"|[*])"),ATTR:new RegExp("^"+W),PSEUDO:new RegExp("^"+$),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+M+"*(even|odd|(([+-]|)(\\d*)n|)"+M+"*(?:([+-]|)"+M+"*(\\d+)|))"+M+"*\\)|)","i"),bool:new RegExp("^(?:"+R+")$","i"),needsContext:new RegExp("^"+M+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+M+"*((?:-\\d)?\\d*)"+M+"*\\)|)(?=[^-]|$)","i")},Y=/HTML$/i,Q=/^(?:input|select|textarea|button)$/i,J=/^h\d$/i,K=/^[^{]+\{\s*\[native \w/,Z=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,ee=/[+~]/,te=new RegExp("\\\\([\\da-f]{1,6}"+M+"?|("+M+")|.)","ig"),ne=function(e,t,n){var r="0x"+t-65536;return r!=r||n?t:r<0?String.fromCharCode(r+65536):String.fromCharCode(r>>10|55296,1023&r|56320)},re=/([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g,ie=function(e,t){return t?"\0"===e?"\ufffd":e.slice(0,-1)+"\\"+e.charCodeAt(e.length-1).toString(16)+" ":"\\"+e},oe=function(){T()},ae=be(function(e){return!0===e.disabled&&"fieldset"===e.nodeName.toLowerCase()},{dir:"parentNode",next:"legend"});try{H.apply(t=O.call(m.childNodes),m.childNodes),t[m.childNodes.length].nodeType}catch(e){H={apply:t.length?function(e,t){L.apply(e,O.call(t))}:function(e,t){var n=e.length,r=0;while(e[n++]=t[r++]);e.length=n-1}}}function se(t,e,n,r){var i,o,a,s,u,l,c,f=e&&e.ownerDocument,p=e?e.nodeType:9;if(n=n||[],"string"!=typeof t||!t||1!==p&&9!==p&&11!==p)return n;if(!r&&((e?e.ownerDocument||e:m)!==C&&T(e),e=e||C,E)){if(11!==p&&(u=Z.exec(t)))if(i=u[1]){if(9===p){if(!(a=e.getElementById(i)))return n;if(a.id===i)return n.push(a),n}else if(f&&(a=f.getElementById(i))&&y(e,a)&&a.id===i)return n.push(a),n}else{if(u[2])return H.apply(n,e.getElementsByTagName(t)),n;if((i=u[3])&&d.getElementsByClassName&&e.getElementsByClassName)return H.apply(n,e.getElementsByClassName(i)),n}if(d.qsa&&!A[t+" "]&&(!v||!v.test(t))&&(1!==p||"object"!==e.nodeName.toLowerCase())){if(c=t,f=e,1===p&&U.test(t)){(s=e.getAttribute("id"))?s=s.replace(re,ie):e.setAttribute("id",s=k),o=(l=h(t)).length;while(o--)l[o]="#"+s+" "+xe(l[o]);c=l.join(","),f=ee.test(t)&&ye(e.parentNode)||e}try{return H.apply(n,f.querySelectorAll(c)),n}catch(e){A(t,!0)}finally{s===k&&e.removeAttribute("id")}}}return g(t.replace(B,"$1"),e,n,r)}function ue(){var r=[];return function e(t,n){return r.push(t+" ")>b.cacheLength&&delete e[r.shift()],e[t+" "]=n}}function le(e){return e[k]=!0,e}function ce(e){var t=C.createElement("fieldset");try{return!!e(t)}catch(e){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function fe(e,t){var n=e.split("|"),r=n.length;while(r--)b.attrHandle[n[r]]=t}function pe(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&e.sourceIndex-t.sourceIndex;if(r)return r;if(n)while(n=n.nextSibling)if(n===t)return-1;return e?1:-1}function de(t){return function(e){return"input"===e.nodeName.toLowerCase()&&e.type===t}}function he(n){return function(e){var t=e.nodeName.toLowerCase();return("input"===t||"button"===t)&&e.type===n}}function ge(t){return function(e){return"form"in e?e.parentNode&&!1===e.disabled?"label"in e?"label"in e.parentNode?e.parentNode.disabled===t:e.disabled===t:e.isDisabled===t||e.isDisabled!==!t&&ae(e)===t:e.disabled===t:"label"in e&&e.disabled===t}}function ve(a){return le(function(o){return o=+o,le(function(e,t){var n,r=a([],e.length,o),i=r.length;while(i--)e[n=r[i]]&&(e[n]=!(t[n]=e[n]))})})}function ye(e){return e&&"undefined"!=typeof e.getElementsByTagName&&e}for(e in d=se.support={},i=se.isXML=function(e){var t=e.namespaceURI,n=(e.ownerDocument||e).documentElement;return!Y.test(t||n&&n.nodeName||"HTML")},T=se.setDocument=function(e){var t,n,r=e?e.ownerDocument||e:m;return r!==C&&9===r.nodeType&&r.documentElement&&(a=(C=r).documentElement,E=!i(C),m!==C&&(n=C.defaultView)&&n.top!==n&&(n.addEventListener?n.addEventListener("unload",oe,!1):n.attachEvent&&n.attachEvent("onunload",oe)),d.attributes=ce(function(e){return e.className="i",!e.getAttribute("className")}),d.getElementsByTagName=ce(function(e){return e.appendChild(C.createComment("")),!e.getElementsByTagName("*").length}),d.getElementsByClassName=K.test(C.getElementsByClassName),d.getById=ce(function(e){return a.appendChild(e).id=k,!C.getElementsByName||!C.getElementsByName(k).length}),d.getById?(b.filter.ID=function(e){var t=e.replace(te,ne);return function(e){return e.getAttribute("id")===t}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n=t.getElementById(e);return n?[n]:[]}}):(b.filter.ID=function(e){var n=e.replace(te,ne);return function(e){var t="undefined"!=typeof e.getAttributeNode&&e.getAttributeNode("id");return t&&t.value===n}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n,r,i,o=t.getElementById(e);if(o){if((n=o.getAttributeNode("id"))&&n.value===e)return[o];i=t.getElementsByName(e),r=0;while(o=i[r++])if((n=o.getAttributeNode("id"))&&n.value===e)return[o]}return[]}}),b.find.TAG=d.getElementsByTagName?function(e,t){return"undefined"!=typeof t.getElementsByTagName?t.getElementsByTagName(e):d.qsa?t.querySelectorAll(e):void 0}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){while(n=o[i++])1===n.nodeType&&r.push(n);return r}return o},b.find.CLASS=d.getElementsByClassName&&function(e,t){if("undefined"!=typeof t.getElementsByClassName&&E)return t.getElementsByClassName(e)},s=[],v=[],(d.qsa=K.test(C.querySelectorAll))&&(ce(function(e){a.appendChild(e).innerHTML="<a id='"+k+"'></a><select id='"+k+"-\r\\' msallowcapture=''><option selected=''></option></select>",e.querySelectorAll("[msallowcapture^='']").length&&v.push("[*^$]="+M+"*(?:''|\"\")"),e.querySelectorAll("[selected]").length||v.push("\\["+M+"*(?:value|"+R+")"),e.querySelectorAll("[id~="+k+"-]").length||v.push("~="),e.querySelectorAll(":checked").length||v.push(":checked"),e.querySelectorAll("a#"+k+"+*").length||v.push(".#.+[+~]")}),ce(function(e){e.innerHTML="<a href='' disabled='disabled'></a><select disabled='disabled'><option/></select>";var t=C.createElement("input");t.setAttribute("type","hidden"),e.appendChild(t).setAttribute("name","D"),e.querySelectorAll("[name=d]").length&&v.push("name"+M+"*[*^$|!~]?="),2!==e.querySelectorAll(":enabled").length&&v.push(":enabled",":disabled"),a.appendChild(e).disabled=!0,2!==e.querySelectorAll(":disabled").length&&v.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),v.push(",.*:")})),(d.matchesSelector=K.test(c=a.matches||a.webkitMatchesSelector||a.mozMatchesSelector||a.oMatchesSelector||a.msMatchesSelector))&&ce(function(e){d.disconnectedMatch=c.call(e,"*"),c.call(e,"[s!='']:x"),s.push("!=",$)}),v=v.length&&new RegExp(v.join("|")),s=s.length&&new RegExp(s.join("|")),t=K.test(a.compareDocumentPosition),y=t||K.test(a.contains)?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)while(t=t.parentNode)if(t===e)return!0;return!1},D=t?function(e,t){if(e===t)return l=!0,0;var n=!e.compareDocumentPosition-!t.compareDocumentPosition;return n||(1&(n=(e.ownerDocument||e)===(t.ownerDocument||t)?e.compareDocumentPosition(t):1)||!d.sortDetached&&t.compareDocumentPosition(e)===n?e===C||e.ownerDocument===m&&y(m,e)?-1:t===C||t.ownerDocument===m&&y(m,t)?1:u?P(u,e)-P(u,t):0:4&n?-1:1)}:function(e,t){if(e===t)return l=!0,0;var n,r=0,i=e.parentNode,o=t.parentNode,a=[e],s=[t];if(!i||!o)return e===C?-1:t===C?1:i?-1:o?1:u?P(u,e)-P(u,t):0;if(i===o)return pe(e,t);n=e;while(n=n.parentNode)a.unshift(n);n=t;while(n=n.parentNode)s.unshift(n);while(a[r]===s[r])r++;return r?pe(a[r],s[r]):a[r]===m?-1:s[r]===m?1:0}),C},se.matches=function(e,t){return se(e,null,null,t)},se.matchesSelector=function(e,t){if((e.ownerDocument||e)!==C&&T(e),d.matchesSelector&&E&&!A[t+" "]&&(!s||!s.test(t))&&(!v||!v.test(t)))try{var n=c.call(e,t);if(n||d.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(e){A(t,!0)}return 0<se(t,C,null,[e]).length},se.contains=function(e,t){return(e.ownerDocument||e)!==C&&T(e),y(e,t)},se.attr=function(e,t){(e.ownerDocument||e)!==C&&T(e);var n=b.attrHandle[t.toLowerCase()],r=n&&j.call(b.attrHandle,t.toLowerCase())?n(e,t,!E):void 0;return void 0!==r?r:d.attributes||!E?e.getAttribute(t):(r=e.getAttributeNode(t))&&r.specified?r.value:null},se.escape=function(e){return(e+"").replace(re,ie)},se.error=function(e){throw new Error("Syntax error, unrecognized expression: "+e)},se.uniqueSort=function(e){var t,n=[],r=0,i=0;if(l=!d.detectDuplicates,u=!d.sortStable&&e.slice(0),e.sort(D),l){while(t=e[i++])t===e[i]&&(r=n.push(i));while(r--)e.splice(n[r],1)}return u=null,e},o=se.getText=function(e){var t,n="",r=0,i=e.nodeType;if(i){if(1===i||9===i||11===i){if("string"==typeof e.textContent)return e.textContent;for(e=e.firstChild;e;e=e.nextSibling)n+=o(e)}else if(3===i||4===i)return e.nodeValue}else while(t=e[r++])n+=o(t);return n},(b=se.selectors={cacheLength:50,createPseudo:le,match:G,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(te,ne),e[3]=(e[3]||e[4]||e[5]||"").replace(te,ne),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||se.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&se.error(e[0]),e},PSEUDO:function(e){var t,n=!e[6]&&e[2];return G.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||"":n&&X.test(n)&&(t=h(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(te,ne).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=p[e+" "];return t||(t=new RegExp("(^|"+M+")"+e+"("+M+"|$)"))&&p(e,function(e){return t.test("string"==typeof e.className&&e.className||"undefined"!=typeof e.getAttribute&&e.getAttribute("class")||"")})},ATTR:function(n,r,i){return function(e){var t=se.attr(e,n);return null==t?"!="===r:!r||(t+="","="===r?t===i:"!="===r?t!==i:"^="===r?i&&0===t.indexOf(i):"*="===r?i&&-1<t.indexOf(i):"$="===r?i&&t.slice(-i.length)===i:"~="===r?-1<(" "+t.replace(F," ")+" ").indexOf(i):"|="===r&&(t===i||t.slice(0,i.length+1)===i+"-"))}},CHILD:function(h,e,t,g,v){var y="nth"!==h.slice(0,3),m="last"!==h.slice(-4),x="of-type"===e;return 1===g&&0===v?function(e){return!!e.parentNode}:function(e,t,n){var r,i,o,a,s,u,l=y!==m?"nextSibling":"previousSibling",c=e.parentNode,f=x&&e.nodeName.toLowerCase(),p=!n&&!x,d=!1;if(c){if(y){while(l){a=e;while(a=a[l])if(x?a.nodeName.toLowerCase()===f:1===a.nodeType)return!1;u=l="only"===h&&!u&&"nextSibling"}return!0}if(u=[m?c.firstChild:c.lastChild],m&&p){d=(s=(r=(i=(o=(a=c)[k]||(a[k]={}))[a.uniqueID]||(o[a.uniqueID]={}))[h]||[])[0]===S&&r[1])&&r[2],a=s&&c.childNodes[s];while(a=++s&&a&&a[l]||(d=s=0)||u.pop())if(1===a.nodeType&&++d&&a===e){i[h]=[S,s,d];break}}else if(p&&(d=s=(r=(i=(o=(a=e)[k]||(a[k]={}))[a.uniqueID]||(o[a.uniqueID]={}))[h]||[])[0]===S&&r[1]),!1===d)while(a=++s&&a&&a[l]||(d=s=0)||u.pop())if((x?a.nodeName.toLowerCase()===f:1===a.nodeType)&&++d&&(p&&((i=(o=a[k]||(a[k]={}))[a.uniqueID]||(o[a.uniqueID]={}))[h]=[S,d]),a===e))break;return(d-=v)===g||d%g==0&&0<=d/g}}},PSEUDO:function(e,o){var t,a=b.pseudos[e]||b.setFilters[e.toLowerCase()]||se.error("unsupported pseudo: "+e);return a[k]?a(o):1<a.length?(t=[e,e,"",o],b.setFilters.hasOwnProperty(e.toLowerCase())?le(function(e,t){var n,r=a(e,o),i=r.length;while(i--)e[n=P(e,r[i])]=!(t[n]=r[i])}):function(e){return a(e,0,t)}):a}},pseudos:{not:le(function(e){var r=[],i=[],s=f(e.replace(B,"$1"));return s[k]?le(function(e,t,n,r){var i,o=s(e,null,r,[]),a=e.length;while(a--)(i=o[a])&&(e[a]=!(t[a]=i))}):function(e,t,n){return r[0]=e,s(r,null,n,i),r[0]=null,!i.pop()}}),has:le(function(t){return function(e){return 0<se(t,e).length}}),contains:le(function(t){return t=t.replace(te,ne),function(e){return-1<(e.textContent||o(e)).indexOf(t)}}),lang:le(function(n){return V.test(n||"")||se.error("unsupported lang: "+n),n=n.replace(te,ne).toLowerCase(),function(e){var t;do{if(t=E?e.lang:e.getAttribute("xml:lang")||e.getAttribute("lang"))return(t=t.toLowerCase())===n||0===t.indexOf(n+"-")}while((e=e.parentNode)&&1===e.nodeType);return!1}}),target:function(e){var t=n.location&&n.location.hash;return t&&t.slice(1)===e.id},root:function(e){return e===a},focus:function(e){return e===C.activeElement&&(!C.hasFocus||C.hasFocus())&&!!(e.type||e.href||~e.tabIndex)},enabled:ge(!1),disabled:ge(!0),checked:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&!!e.checked||"option"===t&&!!e.selected},selected:function(e){return e.parentNode&&e.parentNode.selectedIndex,!0===e.selected},empty:function(e){for(e=e.firstChild;e;e=e.nextSibling)if(e.nodeType<6)return!1;return!0},parent:function(e){return!b.pseudos.empty(e)},header:function(e){return J.test(e.nodeName)},input:function(e){return Q.test(e.nodeName)},button:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&"button"===e.type||"button"===t},text:function(e){var t;return"input"===e.nodeName.toLowerCase()&&"text"===e.type&&(null==(t=e.getAttribute("type"))||"text"===t.toLowerCase())},first:ve(function(){return[0]}),last:ve(function(e,t){return[t-1]}),eq:ve(function(e,t,n){return[n<0?n+t:n]}),even:ve(function(e,t){for(var n=0;n<t;n+=2)e.push(n);return e}),odd:ve(function(e,t){for(var n=1;n<t;n+=2)e.push(n);return e}),lt:ve(function(e,t,n){for(var r=n<0?n+t:t<n?t:n;0<=--r;)e.push(r);return e}),gt:ve(function(e,t,n){for(var r=n<0?n+t:n;++r<t;)e.push(r);return e})}}).pseudos.nth=b.pseudos.eq,{radio:!0,checkbox:!0,file:!0,password:!0,image:!0})b.pseudos[e]=de(e);for(e in{submit:!0,reset:!0})b.pseudos[e]=he(e);function me(){}function xe(e){for(var t=0,n=e.length,r="";t<n;t++)r+=e[t].value;return r}function be(s,e,t){var u=e.dir,l=e.next,c=l||u,f=t&&"parentNode"===c,p=r++;return e.first?function(e,t,n){while(e=e[u])if(1===e.nodeType||f)return s(e,t,n);return!1}:function(e,t,n){var r,i,o,a=[S,p];if(n){while(e=e[u])if((1===e.nodeType||f)&&s(e,t,n))return!0}else while(e=e[u])if(1===e.nodeType||f)if(i=(o=e[k]||(e[k]={}))[e.uniqueID]||(o[e.uniqueID]={}),l&&l===e.nodeName.toLowerCase())e=e[u]||e;else{if((r=i[c])&&r[0]===S&&r[1]===p)return a[2]=r[2];if((i[c]=a)[2]=s(e,t,n))return!0}return!1}}function we(i){return 1<i.length?function(e,t,n){var r=i.length;while(r--)if(!i[r](e,t,n))return!1;return!0}:i[0]}function Te(e,t,n,r,i){for(var o,a=[],s=0,u=e.length,l=null!=t;s<u;s++)(o=e[s])&&(n&&!n(o,r,i)||(a.push(o),l&&t.push(s)));return a}function Ce(d,h,g,v,y,e){return v&&!v[k]&&(v=Ce(v)),y&&!y[k]&&(y=Ce(y,e)),le(function(e,t,n,r){var i,o,a,s=[],u=[],l=t.length,c=e||function(e,t,n){for(var r=0,i=t.length;r<i;r++)se(e,t[r],n);return n}(h||"*",n.nodeType?[n]:n,[]),f=!d||!e&&h?c:Te(c,s,d,n,r),p=g?y||(e?d:l||v)?[]:t:f;if(g&&g(f,p,n,r),v){i=Te(p,u),v(i,[],n,r),o=i.length;while(o--)(a=i[o])&&(p[u[o]]=!(f[u[o]]=a))}if(e){if(y||d){if(y){i=[],o=p.length;while(o--)(a=p[o])&&i.push(f[o]=a);y(null,p=[],i,r)}o=p.length;while(o--)(a=p[o])&&-1<(i=y?P(e,a):s[o])&&(e[i]=!(t[i]=a))}}else p=Te(p===t?p.splice(l,p.length):p),y?y(null,t,p,r):H.apply(t,p)})}function Ee(e){for(var i,t,n,r=e.length,o=b.relative[e[0].type],a=o||b.relative[" "],s=o?1:0,u=be(function(e){return e===i},a,!0),l=be(function(e){return-1<P(i,e)},a,!0),c=[function(e,t,n){var r=!o&&(n||t!==w)||((i=t).nodeType?u(e,t,n):l(e,t,n));return i=null,r}];s<r;s++)if(t=b.relative[e[s].type])c=[be(we(c),t)];else{if((t=b.filter[e[s].type].apply(null,e[s].matches))[k]){for(n=++s;n<r;n++)if(b.relative[e[n].type])break;return Ce(1<s&&we(c),1<s&&xe(e.slice(0,s-1).concat({value:" "===e[s-2].type?"*":""})).replace(B,"$1"),t,s<n&&Ee(e.slice(s,n)),n<r&&Ee(e=e.slice(n)),n<r&&xe(e))}c.push(t)}return we(c)}return me.prototype=b.filters=b.pseudos,b.setFilters=new me,h=se.tokenize=function(e,t){var n,r,i,o,a,s,u,l=x[e+" "];if(l)return t?0:l.slice(0);a=e,s=[],u=b.preFilter;while(a){for(o in n&&!(r=_.exec(a))||(r&&(a=a.slice(r[0].length)||a),s.push(i=[])),n=!1,(r=z.exec(a))&&(n=r.shift(),i.push({value:n,type:r[0].replace(B," ")}),a=a.slice(n.length)),b.filter)!(r=G[o].exec(a))||u[o]&&!(r=u[o](r))||(n=r.shift(),i.push({value:n,type:o,matches:r}),a=a.slice(n.length));if(!n)break}return t?a.length:a?se.error(e):x(e,s).slice(0)},f=se.compile=function(e,t){var n,v,y,m,x,r,i=[],o=[],a=N[e+" "];if(!a){t||(t=h(e)),n=t.length;while(n--)(a=Ee(t[n]))[k]?i.push(a):o.push(a);(a=N(e,(v=o,m=0<(y=i).length,x=0<v.length,r=function(e,t,n,r,i){var o,a,s,u=0,l="0",c=e&&[],f=[],p=w,d=e||x&&b.find.TAG("*",i),h=S+=null==p?1:Math.random()||.1,g=d.length;for(i&&(w=t===C||t||i);l!==g&&null!=(o=d[l]);l++){if(x&&o){a=0,t||o.ownerDocument===C||(T(o),n=!E);while(s=v[a++])if(s(o,t||C,n)){r.push(o);break}i&&(S=h)}m&&((o=!s&&o)&&u--,e&&c.push(o))}if(u+=l,m&&l!==u){a=0;while(s=y[a++])s(c,f,t,n);if(e){if(0<u)while(l--)c[l]||f[l]||(f[l]=q.call(r));f=Te(f)}H.apply(r,f),i&&!e&&0<f.length&&1<u+y.length&&se.uniqueSort(r)}return i&&(S=h,w=p),c},m?le(r):r))).selector=e}return a},g=se.select=function(e,t,n,r){var i,o,a,s,u,l="function"==typeof e&&e,c=!r&&h(e=l.selector||e);if(n=n||[],1===c.length){if(2<(o=c[0]=c[0].slice(0)).length&&"ID"===(a=o[0]).type&&9===t.nodeType&&E&&b.relative[o[1].type]){if(!(t=(b.find.ID(a.matches[0].replace(te,ne),t)||[])[0]))return n;l&&(t=t.parentNode),e=e.slice(o.shift().value.length)}i=G.needsContext.test(e)?0:o.length;while(i--){if(a=o[i],b.relative[s=a.type])break;if((u=b.find[s])&&(r=u(a.matches[0].replace(te,ne),ee.test(o[0].type)&&ye(t.parentNode)||t))){if(o.splice(i,1),!(e=r.length&&xe(o)))return H.apply(n,r),n;break}}}return(l||f(e,c))(r,t,!E,n,!t||ee.test(e)&&ye(t.parentNode)||t),n},d.sortStable=k.split("").sort(D).join("")===k,d.detectDuplicates=!!l,T(),d.sortDetached=ce(function(e){return 1&e.compareDocumentPosition(C.createElement("fieldset"))}),ce(function(e){return e.innerHTML="<a href='#'></a>","#"===e.firstChild.getAttribute("href")})||fe("type|href|height|width",function(e,t,n){if(!n)return e.getAttribute(t,"type"===t.toLowerCase()?1:2)}),d.attributes&&ce(function(e){return e.innerHTML="<input/>",e.firstChild.setAttribute("value",""),""===e.firstChild.getAttribute("value")})||fe("value",function(e,t,n){if(!n&&"input"===e.nodeName.toLowerCase())return e.defaultValue}),ce(function(e){return null==e.getAttribute("disabled")})||fe(R,function(e,t,n){var r;if(!n)return!0===e[t]?t.toLowerCase():(r=e.getAttributeNode(t))&&r.specified?r.value:null}),se}(C);k.find=h,k.expr=h.selectors,k.expr[":"]=k.expr.pseudos,k.uniqueSort=k.unique=h.uniqueSort,k.text=h.getText,k.isXMLDoc=h.isXML,k.contains=h.contains,k.escapeSelector=h.escape;var T=function(e,t,n){var r=[],i=void 0!==n;while((e=e[t])&&9!==e.nodeType)if(1===e.nodeType){if(i&&k(e).is(n))break;r.push(e)}return r},S=function(e,t){for(var n=[];e;e=e.nextSibling)1===e.nodeType&&e!==t&&n.push(e);return n},N=k.expr.match.needsContext;function A(e,t){return e.nodeName&&e.nodeName.toLowerCase()===t.toLowerCase()}var D=/^<([a-z][^\/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i;function j(e,n,r){return m(n)?k.grep(e,function(e,t){return!!n.call(e,t,e)!==r}):n.nodeType?k.grep(e,function(e){return e===n!==r}):"string"!=typeof n?k.grep(e,function(e){return-1<i.call(n,e)!==r}):k.filter(n,e,r)}k.filter=function(e,t,n){var r=t[0];return n&&(e=":not("+e+")"),1===t.length&&1===r.nodeType?k.find.matchesSelector(r,e)?[r]:[]:k.find.matches(e,k.grep(t,function(e){return 1===e.nodeType}))},k.fn.extend({find:function(e){var t,n,r=this.length,i=this;if("string"!=typeof e)return this.pushStack(k(e).filter(function(){for(t=0;t<r;t++)if(k.contains(i[t],this))return!0}));for(n=this.pushStack([]),t=0;t<r;t++)k.find(e,i[t],n);return 1<r?k.uniqueSort(n):n},filter:function(e){return this.pushStack(j(this,e||[],!1))},not:function(e){return this.pushStack(j(this,e||[],!0))},is:function(e){return!!j(this,"string"==typeof e&&N.test(e)?k(e):e||[],!1).length}});var q,L=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]+))$/;(k.fn.init=function(e,t,n){var r,i;if(!e)return this;if(n=n||q,"string"==typeof e){if(!(r="<"===e[0]&&">"===e[e.length-1]&&3<=e.length?[null,e,null]:L.exec(e))||!r[1]&&t)return!t||t.jquery?(t||n).find(e):this.constructor(t).find(e);if(r[1]){if(t=t instanceof k?t[0]:t,k.merge(this,k.parseHTML(r[1],t&&t.nodeType?t.ownerDocument||t:E,!0)),D.test(r[1])&&k.isPlainObject(t))for(r in t)m(this[r])?this[r](t[r]):this.attr(r,t[r]);return this}return(i=E.getElementById(r[2]))&&(this[0]=i,this.length=1),this}return e.nodeType?(this[0]=e,this.length=1,this):m(e)?void 0!==n.ready?n.ready(e):e(k):k.makeArray(e,this)}).prototype=k.fn,q=k(E);var H=/^(?:parents|prev(?:Until|All))/,O={children:!0,contents:!0,next:!0,prev:!0};function P(e,t){while((e=e[t])&&1!==e.nodeType);return e}k.fn.extend({has:function(e){var t=k(e,this),n=t.length;return this.filter(function(){for(var e=0;e<n;e++)if(k.contains(this,t[e]))return!0})},closest:function(e,t){var n,r=0,i=this.length,o=[],a="string"!=typeof e&&k(e);if(!N.test(e))for(;r<i;r++)for(n=this[r];n&&n!==t;n=n.parentNode)if(n.nodeType<11&&(a?-1<a.index(n):1===n.nodeType&&k.find.matchesSelector(n,e))){o.push(n);break}return this.pushStack(1<o.length?k.uniqueSort(o):o)},index:function(e){return e?"string"==typeof e?i.call(k(e),this[0]):i.call(this,e.jquery?e[0]:e):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(e,t){return this.pushStack(k.uniqueSort(k.merge(this.get(),k(e,t))))},addBack:function(e){return this.add(null==e?this.prevObject:this.prevObject.filter(e))}}),k.each({parent:function(e){var t=e.parentNode;return t&&11!==t.nodeType?t:null},parents:function(e){return T(e,"parentNode")},parentsUntil:function(e,t,n){return T(e,"parentNode",n)},next:function(e){return P(e,"nextSibling")},prev:function(e){return P(e,"previousSibling")},nextAll:function(e){return T(e,"nextSibling")},prevAll:function(e){return T(e,"previousSibling")},nextUntil:function(e,t,n){return T(e,"nextSibling",n)},prevUntil:function(e,t,n){return T(e,"previousSibling",n)},siblings:function(e){return S((e.parentNode||{}).firstChild,e)},children:function(e){return S(e.firstChild)},contents:function(e){return"undefined"!=typeof e.contentDocument?e.contentDocument:(A(e,"template")&&(e=e.content||e),k.merge([],e.childNodes))}},function(r,i){k.fn[r]=function(e,t){var n=k.map(this,i,e);return"Until"!==r.slice(-5)&&(t=e),t&&"string"==typeof t&&(n=k.filter(t,n)),1<this.length&&(O[r]||k.uniqueSort(n),H.test(r)&&n.reverse()),this.pushStack(n)}});var R=/[^\x20\t\r\n\f]+/g;function M(e){return e}function I(e){throw e}function W(e,t,n,r){var i;try{e&&m(i=e.promise)?i.call(e).done(t).fail(n):e&&m(i=e.then)?i.call(e,t,n):t.apply(void 0,[e].slice(r))}catch(e){n.apply(void 0,[e])}}k.Callbacks=function(r){var e,n;r="string"==typeof r?(e=r,n={},k.each(e.match(R)||[],function(e,t){n[t]=!0}),n):k.extend({},r);var i,t,o,a,s=[],u=[],l=-1,c=function(){for(a=a||r.once,o=i=!0;u.length;l=-1){t=u.shift();while(++l<s.length)!1===s[l].apply(t[0],t[1])&&r.stopOnFalse&&(l=s.length,t=!1)}r.memory||(t=!1),i=!1,a&&(s=t?[]:"")},f={add:function(){return s&&(t&&!i&&(l=s.length-1,u.push(t)),function n(e){k.each(e,function(e,t){m(t)?r.unique&&f.has(t)||s.push(t):t&&t.length&&"string"!==w(t)&&n(t)})}(arguments),t&&!i&&c()),this},remove:function(){return k.each(arguments,function(e,t){var n;while(-1<(n=k.inArray(t,s,n)))s.splice(n,1),n<=l&&l--}),this},has:function(e){return e?-1<k.inArray(e,s):0<s.length},empty:function(){return s&&(s=[]),this},disable:function(){return a=u=[],s=t="",this},disabled:function(){return!s},lock:function(){return a=u=[],t||i||(s=t=""),this},locked:function(){return!!a},fireWith:function(e,t){return a||(t=[e,(t=t||[]).slice?t.slice():t],u.push(t),i||c()),this},fire:function(){return f.fireWith(this,arguments),this},fired:function(){return!!o}};return f},k.extend({Deferred:function(e){var o=[["notify","progress",k.Callbacks("memory"),k.Callbacks("memory"),2],["resolve","done",k.Callbacks("once memory"),k.Callbacks("once memory"),0,"resolved"],["reject","fail",k.Callbacks("once memory"),k.Callbacks("once memory"),1,"rejected"]],i="pending",a={state:function(){return i},always:function(){return s.done(arguments).fail(arguments),this},"catch":function(e){return a.then(null,e)},pipe:function(){var i=arguments;return k.Deferred(function(r){k.each(o,function(e,t){var n=m(i[t[4]])&&i[t[4]];s[t[1]](function(){var e=n&&n.apply(this,arguments);e&&m(e.promise)?e.promise().progress(r.notify).done(r.resolve).fail(r.reject):r[t[0]+"With"](this,n?[e]:arguments)})}),i=null}).promise()},then:function(t,n,r){var u=0;function l(i,o,a,s){return function(){var n=this,r=arguments,e=function(){var e,t;if(!(i<u)){if((e=a.apply(n,r))===o.promise())throw new TypeError("Thenable self-resolution");t=e&&("object"==typeof e||"function"==typeof e)&&e.then,m(t)?s?t.call(e,l(u,o,M,s),l(u,o,I,s)):(u++,t.call(e,l(u,o,M,s),l(u,o,I,s),l(u,o,M,o.notifyWith))):(a!==M&&(n=void 0,r=[e]),(s||o.resolveWith)(n,r))}},t=s?e:function(){try{e()}catch(e){k.Deferred.exceptionHook&&k.Deferred.exceptionHook(e,t.stackTrace),u<=i+1&&(a!==I&&(n=void 0,r=[e]),o.rejectWith(n,r))}};i?t():(k.Deferred.getStackHook&&(t.stackTrace=k.Deferred.getStackHook()),C.setTimeout(t))}}return k.Deferred(function(e){o[0][3].add(l(0,e,m(r)?r:M,e.notifyWith)),o[1][3].add(l(0,e,m(t)?t:M)),o[2][3].add(l(0,e,m(n)?n:I))}).promise()},promise:function(e){return null!=e?k.extend(e,a):a}},s={};return k.each(o,function(e,t){var n=t[2],r=t[5];a[t[1]]=n.add,r&&n.add(function(){i=r},o[3-e][2].disable,o[3-e][3].disable,o[0][2].lock,o[0][3].lock),n.add(t[3].fire),s[t[0]]=function(){return s[t[0]+"With"](this===s?void 0:this,arguments),this},s[t[0]+"With"]=n.fireWith}),a.promise(s),e&&e.call(s,s),s},when:function(e){var n=arguments.length,t=n,r=Array(t),i=s.call(arguments),o=k.Deferred(),a=function(t){return function(e){r[t]=this,i[t]=1<arguments.length?s.call(arguments):e,--n||o.resolveWith(r,i)}};if(n<=1&&(W(e,o.done(a(t)).resolve,o.reject,!n),"pending"===o.state()||m(i[t]&&i[t].then)))return o.then();while(t--)W(i[t],a(t),o.reject);return o.promise()}});var $=/^(Eval|Internal|Range|Reference|Syntax|Type|URI)Error$/;k.Deferred.exceptionHook=function(e,t){C.console&&C.console.warn&&e&&$.test(e.name)&&C.console.warn("jQuery.Deferred exception: "+e.message,e.stack,t)},k.readyException=function(e){C.setTimeout(function(){throw e})};var F=k.Deferred();function B(){E.removeEventListener("DOMContentLoaded",B),C.removeEventListener("load",B),k.ready()}k.fn.ready=function(e){return F.then(e)["catch"](function(e){k.readyException(e)}),this},k.extend({isReady:!1,readyWait:1,ready:function(e){(!0===e?--k.readyWait:k.isReady)||(k.isReady=!0)!==e&&0<--k.readyWait||F.resolveWith(E,[k])}}),k.ready.then=F.then,"complete"===E.readyState||"loading"!==E.readyState&&!E.documentElement.doScroll?C.setTimeout(k.ready):(E.addEventListener("DOMContentLoaded",B),C.addEventListener("load",B));var _=function(e,t,n,r,i,o,a){var s=0,u=e.length,l=null==n;if("object"===w(n))for(s in i=!0,n)_(e,t,s,n[s],!0,o,a);else if(void 0!==r&&(i=!0,m(r)||(a=!0),l&&(a?(t.call(e,r),t=null):(l=t,t=function(e,t,n){return l.call(k(e),n)})),t))for(;s<u;s++)t(e[s],n,a?r:r.call(e[s],s,t(e[s],n)));return i?e:l?t.call(e):u?t(e[0],n):o},z=/^-ms-/,U=/-([a-z])/g;function X(e,t){return t.toUpperCase()}function V(e){return e.replace(z,"ms-").replace(U,X)}var G=function(e){return 1===e.nodeType||9===e.nodeType||!+e.nodeType};function Y(){this.expando=k.expando+Y.uid++}Y.uid=1,Y.prototype={cache:function(e){var t=e[this.expando];return t||(t={},G(e)&&(e.nodeType?e[this.expando]=t:Object.defineProperty(e,this.expando,{value:t,configurable:!0}))),t},set:function(e,t,n){var r,i=this.cache(e);if("string"==typeof t)i[V(t)]=n;else for(r in t)i[V(r)]=t[r];return i},get:function(e,t){return void 0===t?this.cache(e):e[this.expando]&&e[this.expando][V(t)]},access:function(e,t,n){return void 0===t||t&&"string"==typeof t&&void 0===n?this.get(e,t):(this.set(e,t,n),void 0!==n?n:t)},remove:function(e,t){var n,r=e[this.expando];if(void 0!==r){if(void 0!==t){n=(t=Array.isArray(t)?t.map(V):(t=V(t))in r?[t]:t.match(R)||[]).length;while(n--)delete r[t[n]]}(void 0===t||k.isEmptyObject(r))&&(e.nodeType?e[this.expando]=void 0:delete e[this.expando])}},hasData:function(e){var t=e[this.expando];return void 0!==t&&!k.isEmptyObject(t)}};var Q=new Y,J=new Y,K=/^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,Z=/[A-Z]/g;function ee(e,t,n){var r,i;if(void 0===n&&1===e.nodeType)if(r="data-"+t.replace(Z,"-$&").toLowerCase(),"string"==typeof(n=e.getAttribute(r))){try{n="true"===(i=n)||"false"!==i&&("null"===i?null:i===+i+""?+i:K.test(i)?JSON.parse(i):i)}catch(e){}J.set(e,t,n)}else n=void 0;return n}k.extend({hasData:function(e){return J.hasData(e)||Q.hasData(e)},data:function(e,t,n){return J.access(e,t,n)},removeData:function(e,t){J.remove(e,t)},_data:function(e,t,n){return Q.access(e,t,n)},_removeData:function(e,t){Q.remove(e,t)}}),k.fn.extend({data:function(n,e){var t,r,i,o=this[0],a=o&&o.attributes;if(void 0===n){if(this.length&&(i=J.get(o),1===o.nodeType&&!Q.get(o,"hasDataAttrs"))){t=a.length;while(t--)a[t]&&0===(r=a[t].name).indexOf("data-")&&(r=V(r.slice(5)),ee(o,r,i[r]));Q.set(o,"hasDataAttrs",!0)}return i}return"object"==typeof n?this.each(function(){J.set(this,n)}):_(this,function(e){var t;if(o&&void 0===e)return void 0!==(t=J.get(o,n))?t:void 0!==(t=ee(o,n))?t:void 0;this.each(function(){J.set(this,n,e)})},null,e,1<arguments.length,null,!0)},removeData:function(e){return this.each(function(){J.remove(this,e)})}}),k.extend({queue:function(e,t,n){var r;if(e)return t=(t||"fx")+"queue",r=Q.get(e,t),n&&(!r||Array.isArray(n)?r=Q.access(e,t,k.makeArray(n)):r.push(n)),r||[]},dequeue:function(e,t){t=t||"fx";var n=k.queue(e,t),r=n.length,i=n.shift(),o=k._queueHooks(e,t);"inprogress"===i&&(i=n.shift(),r--),i&&("fx"===t&&n.unshift("inprogress"),delete o.stop,i.call(e,function(){k.dequeue(e,t)},o)),!r&&o&&o.empty.fire()},_queueHooks:function(e,t){var n=t+"queueHooks";return Q.get(e,n)||Q.access(e,n,{empty:k.Callbacks("once memory").add(function(){Q.remove(e,[t+"queue",n])})})}}),k.fn.extend({queue:function(t,n){var e=2;return"string"!=typeof t&&(n=t,t="fx",e--),arguments.length<e?k.queue(this[0],t):void 0===n?this:this.each(function(){var e=k.queue(this,t,n);k._queueHooks(this,t),"fx"===t&&"inprogress"!==e[0]&&k.dequeue(this,t)})},dequeue:function(e){return this.each(function(){k.dequeue(this,e)})},clearQueue:function(e){return this.queue(e||"fx",[])},promise:function(e,t){var n,r=1,i=k.Deferred(),o=this,a=this.length,s=function(){--r||i.resolveWith(o,[o])};"string"!=typeof e&&(t=e,e=void 0),e=e||"fx";while(a--)(n=Q.get(o[a],e+"queueHooks"))&&n.empty&&(r++,n.empty.add(s));return s(),i.promise(t)}});var te=/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source,ne=new RegExp("^(?:([+-])=|)("+te+")([a-z%]*)$","i"),re=["Top","Right","Bottom","Left"],ie=E.documentElement,oe=function(e){return k.contains(e.ownerDocument,e)},ae={composed:!0};ie.getRootNode&&(oe=function(e){return k.contains(e.ownerDocument,e)||e.getRootNode(ae)===e.ownerDocument});var se=function(e,t){return"none"===(e=t||e).style.display||""===e.style.display&&oe(e)&&"none"===k.css(e,"display")},ue=function(e,t,n,r){var i,o,a={};for(o in t)a[o]=e.style[o],e.style[o]=t[o];for(o in i=n.apply(e,r||[]),t)e.style[o]=a[o];return i};function le(e,t,n,r){var i,o,a=20,s=r?function(){return r.cur()}:function(){return k.css(e,t,"")},u=s(),l=n&&n[3]||(k.cssNumber[t]?"":"px"),c=e.nodeType&&(k.cssNumber[t]||"px"!==l&&+u)&&ne.exec(k.css(e,t));if(c&&c[3]!==l){u/=2,l=l||c[3],c=+u||1;while(a--)k.style(e,t,c+l),(1-o)*(1-(o=s()/u||.5))<=0&&(a=0),c/=o;c*=2,k.style(e,t,c+l),n=n||[]}return n&&(c=+c||+u||0,i=n[1]?c+(n[1]+1)*n[2]:+n[2],r&&(r.unit=l,r.start=c,r.end=i)),i}var ce={};function fe(e,t){for(var n,r,i,o,a,s,u,l=[],c=0,f=e.length;c<f;c++)(r=e[c]).style&&(n=r.style.display,t?("none"===n&&(l[c]=Q.get(r,"display")||null,l[c]||(r.style.display="")),""===r.style.display&&se(r)&&(l[c]=(u=a=o=void 0,a=(i=r).ownerDocument,s=i.nodeName,(u=ce[s])||(o=a.body.appendChild(a.createElement(s)),u=k.css(o,"display"),o.parentNode.removeChild(o),"none"===u&&(u="block"),ce[s]=u)))):"none"!==n&&(l[c]="none",Q.set(r,"display",n)));for(c=0;c<f;c++)null!=l[c]&&(e[c].style.display=l[c]);return e}k.fn.extend({show:function(){return fe(this,!0)},hide:function(){return fe(this)},toggle:function(e){return"boolean"==typeof e?e?this.show():this.hide():this.each(function(){se(this)?k(this).show():k(this).hide()})}});var pe=/^(?:checkbox|radio)$/i,de=/<([a-z][^\/\0>\x20\t\r\n\f]*)/i,he=/^$|^module$|\/(?:java|ecma)script/i,ge={option:[1,"<select multiple='multiple'>","</select>"],thead:[1,"<table>","</table>"],col:[2,"<table><colgroup>","</colgroup></table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],_default:[0,"",""]};function ve(e,t){var n;return n="undefined"!=typeof e.getElementsByTagName?e.getElementsByTagName(t||"*"):"undefined"!=typeof e.querySelectorAll?e.querySelectorAll(t||"*"):[],void 0===t||t&&A(e,t)?k.merge([e],n):n}function ye(e,t){for(var n=0,r=e.length;n<r;n++)Q.set(e[n],"globalEval",!t||Q.get(t[n],"globalEval"))}ge.optgroup=ge.option,ge.tbody=ge.tfoot=ge.colgroup=ge.caption=ge.thead,ge.th=ge.td;var me,xe,be=/<|&#?\w+;/;function we(e,t,n,r,i){for(var o,a,s,u,l,c,f=t.createDocumentFragment(),p=[],d=0,h=e.length;d<h;d++)if((o=e[d])||0===o)if("object"===w(o))k.merge(p,o.nodeType?[o]:o);else if(be.test(o)){a=a||f.appendChild(t.createElement("div")),s=(de.exec(o)||["",""])[1].toLowerCase(),u=ge[s]||ge._default,a.innerHTML=u[1]+k.htmlPrefilter(o)+u[2],c=u[0];while(c--)a=a.lastChild;k.merge(p,a.childNodes),(a=f.firstChild).textContent=""}else p.push(t.createTextNode(o));f.textContent="",d=0;while(o=p[d++])if(r&&-1<k.inArray(o,r))i&&i.push(o);else if(l=oe(o),a=ve(f.appendChild(o),"script"),l&&ye(a),n){c=0;while(o=a[c++])he.test(o.type||"")&&n.push(o)}return f}me=E.createDocumentFragment().appendChild(E.createElement("div")),(xe=E.createElement("input")).setAttribute("type","radio"),xe.setAttribute("checked","checked"),xe.setAttribute("name","t"),me.appendChild(xe),y.checkClone=me.cloneNode(!0).cloneNode(!0).lastChild.checked,me.innerHTML="<textarea>x</textarea>",y.noCloneChecked=!!me.cloneNode(!0).lastChild.defaultValue;var Te=/^key/,Ce=/^(?:mouse|pointer|contextmenu|drag|drop)|click/,Ee=/^([^.]*)(?:\.(.+)|)/;function ke(){return!0}function Se(){return!1}function Ne(e,t){return e===function(){try{return E.activeElement}catch(e){}}()==("focus"===t)}function Ae(e,t,n,r,i,o){var a,s;if("object"==typeof t){for(s in"string"!=typeof n&&(r=r||n,n=void 0),t)Ae(e,s,n,r,t[s],o);return e}if(null==r&&null==i?(i=n,r=n=void 0):null==i&&("string"==typeof n?(i=r,r=void 0):(i=r,r=n,n=void 0)),!1===i)i=Se;else if(!i)return e;return 1===o&&(a=i,(i=function(e){return k().off(e),a.apply(this,arguments)}).guid=a.guid||(a.guid=k.guid++)),e.each(function(){k.event.add(this,t,i,r,n)})}function De(e,i,o){o?(Q.set(e,i,!1),k.event.add(e,i,{namespace:!1,handler:function(e){var t,n,r=Q.get(this,i);if(1&e.isTrigger&&this[i]){if(r.length)(k.event.special[i]||{}).delegateType&&e.stopPropagation();else if(r=s.call(arguments),Q.set(this,i,r),t=o(this,i),this[i](),r!==(n=Q.get(this,i))||t?Q.set(this,i,!1):n={},r!==n)return e.stopImmediatePropagation(),e.preventDefault(),n.value}else r.length&&(Q.set(this,i,{value:k.event.trigger(k.extend(r[0],k.Event.prototype),r.slice(1),this)}),e.stopImmediatePropagation())}})):void 0===Q.get(e,i)&&k.event.add(e,i,ke)}k.event={global:{},add:function(t,e,n,r,i){var o,a,s,u,l,c,f,p,d,h,g,v=Q.get(t);if(v){n.handler&&(n=(o=n).handler,i=o.selector),i&&k.find.matchesSelector(ie,i),n.guid||(n.guid=k.guid++),(u=v.events)||(u=v.events={}),(a=v.handle)||(a=v.handle=function(e){return"undefined"!=typeof k&&k.event.triggered!==e.type?k.event.dispatch.apply(t,arguments):void 0}),l=(e=(e||"").match(R)||[""]).length;while(l--)d=g=(s=Ee.exec(e[l])||[])[1],h=(s[2]||"").split(".").sort(),d&&(f=k.event.special[d]||{},d=(i?f.delegateType:f.bindType)||d,f=k.event.special[d]||{},c=k.extend({type:d,origType:g,data:r,handler:n,guid:n.guid,selector:i,needsContext:i&&k.expr.match.needsContext.test(i),namespace:h.join(".")},o),(p=u[d])||((p=u[d]=[]).delegateCount=0,f.setup&&!1!==f.setup.call(t,r,h,a)||t.addEventListener&&t.addEventListener(d,a)),f.add&&(f.add.call(t,c),c.handler.guid||(c.handler.guid=n.guid)),i?p.splice(p.delegateCount++,0,c):p.push(c),k.event.global[d]=!0)}},remove:function(e,t,n,r,i){var o,a,s,u,l,c,f,p,d,h,g,v=Q.hasData(e)&&Q.get(e);if(v&&(u=v.events)){l=(t=(t||"").match(R)||[""]).length;while(l--)if(d=g=(s=Ee.exec(t[l])||[])[1],h=(s[2]||"").split(".").sort(),d){f=k.event.special[d]||{},p=u[d=(r?f.delegateType:f.bindType)||d]||[],s=s[2]&&new RegExp("(^|\\.)"+h.join("\\.(?:.*\\.|)")+"(\\.|$)"),a=o=p.length;while(o--)c=p[o],!i&&g!==c.origType||n&&n.guid!==c.guid||s&&!s.test(c.namespace)||r&&r!==c.selector&&("**"!==r||!c.selector)||(p.splice(o,1),c.selector&&p.delegateCount--,f.remove&&f.remove.call(e,c));a&&!p.length&&(f.teardown&&!1!==f.teardown.call(e,h,v.handle)||k.removeEvent(e,d,v.handle),delete u[d])}else for(d in u)k.event.remove(e,d+t[l],n,r,!0);k.isEmptyObject(u)&&Q.remove(e,"handle events")}},dispatch:function(e){var t,n,r,i,o,a,s=k.event.fix(e),u=new Array(arguments.length),l=(Q.get(this,"events")||{})[s.type]||[],c=k.event.special[s.type]||{};for(u[0]=s,t=1;t<arguments.length;t++)u[t]=arguments[t];if(s.delegateTarget=this,!c.preDispatch||!1!==c.preDispatch.call(this,s)){a=k.event.handlers.call(this,s,l),t=0;while((i=a[t++])&&!s.isPropagationStopped()){s.currentTarget=i.elem,n=0;while((o=i.handlers[n++])&&!s.isImmediatePropagationStopped())s.rnamespace&&!1!==o.namespace&&!s.rnamespace.test(o.namespace)||(s.handleObj=o,s.data=o.data,void 0!==(r=((k.event.special[o.origType]||{}).handle||o.handler).apply(i.elem,u))&&!1===(s.result=r)&&(s.preventDefault(),s.stopPropagation()))}return c.postDispatch&&c.postDispatch.call(this,s),s.result}},handlers:function(e,t){var n,r,i,o,a,s=[],u=t.delegateCount,l=e.target;if(u&&l.nodeType&&!("click"===e.type&&1<=e.button))for(;l!==this;l=l.parentNode||this)if(1===l.nodeType&&("click"!==e.type||!0!==l.disabled)){for(o=[],a={},n=0;n<u;n++)void 0===a[i=(r=t[n]).selector+" "]&&(a[i]=r.needsContext?-1<k(i,this).index(l):k.find(i,this,null,[l]).length),a[i]&&o.push(r);o.length&&s.push({elem:l,handlers:o})}return l=this,u<t.length&&s.push({elem:l,handlers:t.slice(u)}),s},addProp:function(t,e){Object.defineProperty(k.Event.prototype,t,{enumerable:!0,configurable:!0,get:m(e)?function(){if(this.originalEvent)return e(this.originalEvent)}:function(){if(this.originalEvent)return this.originalEvent[t]},set:function(e){Object.defineProperty(this,t,{enumerable:!0,configurable:!0,writable:!0,value:e})}})},fix:function(e){return e[k.expando]?e:new k.Event(e)},special:{load:{noBubble:!0},click:{setup:function(e){var t=this||e;return pe.test(t.type)&&t.click&&A(t,"input")&&De(t,"click",ke),!1},trigger:function(e){var t=this||e;return pe.test(t.type)&&t.click&&A(t,"input")&&De(t,"click"),!0},_default:function(e){var t=e.target;return pe.test(t.type)&&t.click&&A(t,"input")&&Q.get(t,"click")||A(t,"a")}},beforeunload:{postDispatch:function(e){void 0!==e.result&&e.originalEvent&&(e.originalEvent.returnValue=e.result)}}}},k.removeEvent=function(e,t,n){e.removeEventListener&&e.removeEventListener(t,n)},k.Event=function(e,t){if(!(this instanceof k.Event))return new k.Event(e,t);e&&e.type?(this.originalEvent=e,this.type=e.type,this.isDefaultPrevented=e.defaultPrevented||void 0===e.defaultPrevented&&!1===e.returnValue?ke:Se,this.target=e.target&&3===e.target.nodeType?e.target.parentNode:e.target,this.currentTarget=e.currentTarget,this.relatedTarget=e.relatedTarget):this.type=e,t&&k.extend(this,t),this.timeStamp=e&&e.timeStamp||Date.now(),this[k.expando]=!0},k.Event.prototype={constructor:k.Event,isDefaultPrevented:Se,isPropagationStopped:Se,isImmediatePropagationStopped:Se,isSimulated:!1,preventDefault:function(){var e=this.originalEvent;this.isDefaultPrevented=ke,e&&!this.isSimulated&&e.preventDefault()},stopPropagation:function(){var e=this.originalEvent;this.isPropagationStopped=ke,e&&!this.isSimulated&&e.stopPropagation()},stopImmediatePropagation:function(){var e=this.originalEvent;this.isImmediatePropagationStopped=ke,e&&!this.isSimulated&&e.stopImmediatePropagation(),this.stopPropagation()}},k.each({altKey:!0,bubbles:!0,cancelable:!0,changedTouches:!0,ctrlKey:!0,detail:!0,eventPhase:!0,metaKey:!0,pageX:!0,pageY:!0,shiftKey:!0,view:!0,"char":!0,code:!0,charCode:!0,key:!0,keyCode:!0,button:!0,buttons:!0,clientX:!0,clientY:!0,offsetX:!0,offsetY:!0,pointerId:!0,pointerType:!0,screenX:!0,screenY:!0,targetTouches:!0,toElement:!0,touches:!0,which:function(e){var t=e.button;return null==e.which&&Te.test(e.type)?null!=e.charCode?e.charCode:e.keyCode:!e.which&&void 0!==t&&Ce.test(e.type)?1&t?1:2&t?3:4&t?2:0:e.which}},k.event.addProp),k.each({focus:"focusin",blur:"focusout"},function(e,t){k.event.special[e]={setup:function(){return De(this,e,Ne),!1},trigger:function(){return De(this,e),!0},delegateType:t}}),k.each({mouseenter:"mouseover",mouseleave:"mouseout",pointerenter:"pointerover",pointerleave:"pointerout"},function(e,i){k.event.special[e]={delegateType:i,bindType:i,handle:function(e){var t,n=e.relatedTarget,r=e.handleObj;return n&&(n===this||k.contains(this,n))||(e.type=r.origType,t=r.handler.apply(this,arguments),e.type=i),t}}}),k.fn.extend({on:function(e,t,n,r){return Ae(this,e,t,n,r)},one:function(e,t,n,r){return Ae(this,e,t,n,r,1)},off:function(e,t,n){var r,i;if(e&&e.preventDefault&&e.handleObj)return r=e.handleObj,k(e.delegateTarget).off(r.namespace?r.origType+"."+r.namespace:r.origType,r.selector,r.handler),this;if("object"==typeof e){for(i in e)this.off(i,t,e[i]);return this}return!1!==t&&"function"!=typeof t||(n=t,t=void 0),!1===n&&(n=Se),this.each(function(){k.event.remove(this,e,n,t)})}});var je=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([a-z][^\/\0>\x20\t\r\n\f]*)[^>]*)\/>/gi,qe=/<script|<style|<link/i,Le=/checked\s*(?:[^=]|=\s*.checked.)/i,He=/^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g;function Oe(e,t){return A(e,"table")&&A(11!==t.nodeType?t:t.firstChild,"tr")&&k(e).children("tbody")[0]||e}function Pe(e){return e.type=(null!==e.getAttribute("type"))+"/"+e.type,e}function Re(e){return"true/"===(e.type||"").slice(0,5)?e.type=e.type.slice(5):e.removeAttribute("type"),e}function Me(e,t){var n,r,i,o,a,s,u,l;if(1===t.nodeType){if(Q.hasData(e)&&(o=Q.access(e),a=Q.set(t,o),l=o.events))for(i in delete a.handle,a.events={},l)for(n=0,r=l[i].length;n<r;n++)k.event.add(t,i,l[i][n]);J.hasData(e)&&(s=J.access(e),u=k.extend({},s),J.set(t,u))}}function Ie(n,r,i,o){r=g.apply([],r);var e,t,a,s,u,l,c=0,f=n.length,p=f-1,d=r[0],h=m(d);if(h||1<f&&"string"==typeof d&&!y.checkClone&&Le.test(d))return n.each(function(e){var t=n.eq(e);h&&(r[0]=d.call(this,e,t.html())),Ie(t,r,i,o)});if(f&&(t=(e=we(r,n[0].ownerDocument,!1,n,o)).firstChild,1===e.childNodes.length&&(e=t),t||o)){for(s=(a=k.map(ve(e,"script"),Pe)).length;c<f;c++)u=e,c!==p&&(u=k.clone(u,!0,!0),s&&k.merge(a,ve(u,"script"))),i.call(n[c],u,c);if(s)for(l=a[a.length-1].ownerDocument,k.map(a,Re),c=0;c<s;c++)u=a[c],he.test(u.type||"")&&!Q.access(u,"globalEval")&&k.contains(l,u)&&(u.src&&"module"!==(u.type||"").toLowerCase()?k._evalUrl&&!u.noModule&&k._evalUrl(u.src,{nonce:u.nonce||u.getAttribute("nonce")}):b(u.textContent.replace(He,""),u,l))}return n}function We(e,t,n){for(var r,i=t?k.filter(t,e):e,o=0;null!=(r=i[o]);o++)n||1!==r.nodeType||k.cleanData(ve(r)),r.parentNode&&(n&&oe(r)&&ye(ve(r,"script")),r.parentNode.removeChild(r));return e}k.extend({htmlPrefilter:function(e){return e.replace(je,"<$1></$2>")},clone:function(e,t,n){var r,i,o,a,s,u,l,c=e.cloneNode(!0),f=oe(e);if(!(y.noCloneChecked||1!==e.nodeType&&11!==e.nodeType||k.isXMLDoc(e)))for(a=ve(c),r=0,i=(o=ve(e)).length;r<i;r++)s=o[r],u=a[r],void 0,"input"===(l=u.nodeName.toLowerCase())&&pe.test(s.type)?u.checked=s.checked:"input"!==l&&"textarea"!==l||(u.defaultValue=s.defaultValue);if(t)if(n)for(o=o||ve(e),a=a||ve(c),r=0,i=o.length;r<i;r++)Me(o[r],a[r]);else Me(e,c);return 0<(a=ve(c,"script")).length&&ye(a,!f&&ve(e,"script")),c},cleanData:function(e){for(var t,n,r,i=k.event.special,o=0;void 0!==(n=e[o]);o++)if(G(n)){if(t=n[Q.expando]){if(t.events)for(r in t.events)i[r]?k.event.remove(n,r):k.removeEvent(n,r,t.handle);n[Q.expando]=void 0}n[J.expando]&&(n[J.expando]=void 0)}}}),k.fn.extend({detach:function(e){return We(this,e,!0)},remove:function(e){return We(this,e)},text:function(e){return _(this,function(e){return void 0===e?k.text(this):this.empty().each(function(){1!==this.nodeType&&11!==this.nodeType&&9!==this.nodeType||(this.textContent=e)})},null,e,arguments.length)},append:function(){return Ie(this,arguments,function(e){1!==this.nodeType&&11!==this.nodeType&&9!==this.nodeType||Oe(this,e).appendChild(e)})},prepend:function(){return Ie(this,arguments,function(e){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var t=Oe(this,e);t.insertBefore(e,t.firstChild)}})},before:function(){return Ie(this,arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this)})},after:function(){return Ie(this,arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this.nextSibling)})},empty:function(){for(var e,t=0;null!=(e=this[t]);t++)1===e.nodeType&&(k.cleanData(ve(e,!1)),e.textContent="");return this},clone:function(e,t){return e=null!=e&&e,t=null==t?e:t,this.map(function(){return k.clone(this,e,t)})},html:function(e){return _(this,function(e){var t=this[0]||{},n=0,r=this.length;if(void 0===e&&1===t.nodeType)return t.innerHTML;if("string"==typeof e&&!qe.test(e)&&!ge[(de.exec(e)||["",""])[1].toLowerCase()]){e=k.htmlPrefilter(e);try{for(;n<r;n++)1===(t=this[n]||{}).nodeType&&(k.cleanData(ve(t,!1)),t.innerHTML=e);t=0}catch(e){}}t&&this.empty().append(e)},null,e,arguments.length)},replaceWith:function(){var n=[];return Ie(this,arguments,function(e){var t=this.parentNode;k.inArray(this,n)<0&&(k.cleanData(ve(this)),t&&t.replaceChild(e,this))},n)}}),k.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(e,a){k.fn[e]=function(e){for(var t,n=[],r=k(e),i=r.length-1,o=0;o<=i;o++)t=o===i?this:this.clone(!0),k(r[o])[a](t),u.apply(n,t.get());return this.pushStack(n)}});var $e=new RegExp("^("+te+")(?!px)[a-z%]+$","i"),Fe=function(e){var t=e.ownerDocument.defaultView;return t&&t.opener||(t=C),t.getComputedStyle(e)},Be=new RegExp(re.join("|"),"i");function _e(e,t,n){var r,i,o,a,s=e.style;return(n=n||Fe(e))&&(""!==(a=n.getPropertyValue(t)||n[t])||oe(e)||(a=k.style(e,t)),!y.pixelBoxStyles()&&$e.test(a)&&Be.test(t)&&(r=s.width,i=s.minWidth,o=s.maxWidth,s.minWidth=s.maxWidth=s.width=a,a=n.width,s.width=r,s.minWidth=i,s.maxWidth=o)),void 0!==a?a+"":a}function ze(e,t){return{get:function(){if(!e())return(this.get=t).apply(this,arguments);delete this.get}}}!function(){function e(){if(u){s.style.cssText="position:absolute;left:-11111px;width:60px;margin-top:1px;padding:0;border:0",u.style.cssText="position:relative;display:block;box-sizing:border-box;overflow:scroll;margin:auto;border:1px;padding:1px;width:60%;top:1%",ie.appendChild(s).appendChild(u);var e=C.getComputedStyle(u);n="1%"!==e.top,a=12===t(e.marginLeft),u.style.right="60%",o=36===t(e.right),r=36===t(e.width),u.style.position="absolute",i=12===t(u.offsetWidth/3),ie.removeChild(s),u=null}}function t(e){return Math.round(parseFloat(e))}var n,r,i,o,a,s=E.createElement("div"),u=E.createElement("div");u.style&&(u.style.backgroundClip="content-box",u.cloneNode(!0).style.backgroundClip="",y.clearCloneStyle="content-box"===u.style.backgroundClip,k.extend(y,{boxSizingReliable:function(){return e(),r},pixelBoxStyles:function(){return e(),o},pixelPosition:function(){return e(),n},reliableMarginLeft:function(){return e(),a},scrollboxSize:function(){return e(),i}}))}();var Ue=["Webkit","Moz","ms"],Xe=E.createElement("div").style,Ve={};function Ge(e){var t=k.cssProps[e]||Ve[e];return t||(e in Xe?e:Ve[e]=function(e){var t=e[0].toUpperCase()+e.slice(1),n=Ue.length;while(n--)if((e=Ue[n]+t)in Xe)return e}(e)||e)}var Ye=/^(none|table(?!-c[ea]).+)/,Qe=/^--/,Je={position:"absolute",visibility:"hidden",display:"block"},Ke={letterSpacing:"0",fontWeight:"400"};function Ze(e,t,n){var r=ne.exec(t);return r?Math.max(0,r[2]-(n||0))+(r[3]||"px"):t}function et(e,t,n,r,i,o){var a="width"===t?1:0,s=0,u=0;if(n===(r?"border":"content"))return 0;for(;a<4;a+=2)"margin"===n&&(u+=k.css(e,n+re[a],!0,i)),r?("content"===n&&(u-=k.css(e,"padding"+re[a],!0,i)),"margin"!==n&&(u-=k.css(e,"border"+re[a]+"Width",!0,i))):(u+=k.css(e,"padding"+re[a],!0,i),"padding"!==n?u+=k.css(e,"border"+re[a]+"Width",!0,i):s+=k.css(e,"border"+re[a]+"Width",!0,i));return!r&&0<=o&&(u+=Math.max(0,Math.ceil(e["offset"+t[0].toUpperCase()+t.slice(1)]-o-u-s-.5))||0),u}function tt(e,t,n){var r=Fe(e),i=(!y.boxSizingReliable()||n)&&"border-box"===k.css(e,"boxSizing",!1,r),o=i,a=_e(e,t,r),s="offset"+t[0].toUpperCase()+t.slice(1);if($e.test(a)){if(!n)return a;a="auto"}return(!y.boxSizingReliable()&&i||"auto"===a||!parseFloat(a)&&"inline"===k.css(e,"display",!1,r))&&e.getClientRects().length&&(i="border-box"===k.css(e,"boxSizing",!1,r),(o=s in e)&&(a=e[s])),(a=parseFloat(a)||0)+et(e,t,n||(i?"border":"content"),o,r,a)+"px"}function nt(e,t,n,r,i){return new nt.prototype.init(e,t,n,r,i)}k.extend({cssHooks:{opacity:{get:function(e,t){if(t){var n=_e(e,"opacity");return""===n?"1":n}}}},cssNumber:{animationIterationCount:!0,columnCount:!0,fillOpacity:!0,flexGrow:!0,flexShrink:!0,fontWeight:!0,gridArea:!0,gridColumn:!0,gridColumnEnd:!0,gridColumnStart:!0,gridRow:!0,gridRowEnd:!0,gridRowStart:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{},style:function(e,t,n,r){if(e&&3!==e.nodeType&&8!==e.nodeType&&e.style){var i,o,a,s=V(t),u=Qe.test(t),l=e.style;if(u||(t=Ge(s)),a=k.cssHooks[t]||k.cssHooks[s],void 0===n)return a&&"get"in a&&void 0!==(i=a.get(e,!1,r))?i:l[t];"string"===(o=typeof n)&&(i=ne.exec(n))&&i[1]&&(n=le(e,t,i),o="number"),null!=n&&n==n&&("number"!==o||u||(n+=i&&i[3]||(k.cssNumber[s]?"":"px")),y.clearCloneStyle||""!==n||0!==t.indexOf("background")||(l[t]="inherit"),a&&"set"in a&&void 0===(n=a.set(e,n,r))||(u?l.setProperty(t,n):l[t]=n))}},css:function(e,t,n,r){var i,o,a,s=V(t);return Qe.test(t)||(t=Ge(s)),(a=k.cssHooks[t]||k.cssHooks[s])&&"get"in a&&(i=a.get(e,!0,n)),void 0===i&&(i=_e(e,t,r)),"normal"===i&&t in Ke&&(i=Ke[t]),""===n||n?(o=parseFloat(i),!0===n||isFinite(o)?o||0:i):i}}),k.each(["height","width"],function(e,u){k.cssHooks[u]={get:function(e,t,n){if(t)return!Ye.test(k.css(e,"display"))||e.getClientRects().length&&e.getBoundingClientRect().width?tt(e,u,n):ue(e,Je,function(){return tt(e,u,n)})},set:function(e,t,n){var r,i=Fe(e),o=!y.scrollboxSize()&&"absolute"===i.position,a=(o||n)&&"border-box"===k.css(e,"boxSizing",!1,i),s=n?et(e,u,n,a,i):0;return a&&o&&(s-=Math.ceil(e["offset"+u[0].toUpperCase()+u.slice(1)]-parseFloat(i[u])-et(e,u,"border",!1,i)-.5)),s&&(r=ne.exec(t))&&"px"!==(r[3]||"px")&&(e.style[u]=t,t=k.css(e,u)),Ze(0,t,s)}}}),k.cssHooks.marginLeft=ze(y.reliableMarginLeft,function(e,t){if(t)return(parseFloat(_e(e,"marginLeft"))||e.getBoundingClientRect().left-ue(e,{marginLeft:0},function(){return e.getBoundingClientRect().left}))+"px"}),k.each({margin:"",padding:"",border:"Width"},function(i,o){k.cssHooks[i+o]={expand:function(e){for(var t=0,n={},r="string"==typeof e?e.split(" "):[e];t<4;t++)n[i+re[t]+o]=r[t]||r[t-2]||r[0];return n}},"margin"!==i&&(k.cssHooks[i+o].set=Ze)}),k.fn.extend({css:function(e,t){return _(this,function(e,t,n){var r,i,o={},a=0;if(Array.isArray(t)){for(r=Fe(e),i=t.length;a<i;a++)o[t[a]]=k.css(e,t[a],!1,r);return o}return void 0!==n?k.style(e,t,n):k.css(e,t)},e,t,1<arguments.length)}}),((k.Tween=nt).prototype={constructor:nt,init:function(e,t,n,r,i,o){this.elem=e,this.prop=n,this.easing=i||k.easing._default,this.options=t,this.start=this.now=this.cur(),this.end=r,this.unit=o||(k.cssNumber[n]?"":"px")},cur:function(){var e=nt.propHooks[this.prop];return e&&e.get?e.get(this):nt.propHooks._default.get(this)},run:function(e){var t,n=nt.propHooks[this.prop];return this.options.duration?this.pos=t=k.easing[this.easing](e,this.options.duration*e,0,1,this.options.duration):this.pos=t=e,this.now=(this.end-this.start)*t+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),n&&n.set?n.set(this):nt.propHooks._default.set(this),this}}).init.prototype=nt.prototype,(nt.propHooks={_default:{get:function(e){var t;return 1!==e.elem.nodeType||null!=e.elem[e.prop]&&null==e.elem.style[e.prop]?e.elem[e.prop]:(t=k.css(e.elem,e.prop,""))&&"auto"!==t?t:0},set:function(e){k.fx.step[e.prop]?k.fx.step[e.prop](e):1!==e.elem.nodeType||!k.cssHooks[e.prop]&&null==e.elem.style[Ge(e.prop)]?e.elem[e.prop]=e.now:k.style(e.elem,e.prop,e.now+e.unit)}}}).scrollTop=nt.propHooks.scrollLeft={set:function(e){e.elem.nodeType&&e.elem.parentNode&&(e.elem[e.prop]=e.now)}},k.easing={linear:function(e){return e},swing:function(e){return.5-Math.cos(e*Math.PI)/2},_default:"swing"},k.fx=nt.prototype.init,k.fx.step={};var rt,it,ot,at,st=/^(?:toggle|show|hide)$/,ut=/queueHooks$/;function lt(){it&&(!1===E.hidden&&C.requestAnimationFrame?C.requestAnimationFrame(lt):C.setTimeout(lt,k.fx.interval),k.fx.tick())}function ct(){return C.setTimeout(function(){rt=void 0}),rt=Date.now()}function ft(e,t){var n,r=0,i={height:e};for(t=t?1:0;r<4;r+=2-t)i["margin"+(n=re[r])]=i["padding"+n]=e;return t&&(i.opacity=i.width=e),i}function pt(e,t,n){for(var r,i=(dt.tweeners[t]||[]).concat(dt.tweeners["*"]),o=0,a=i.length;o<a;o++)if(r=i[o].call(n,t,e))return r}function dt(o,e,t){var n,a,r=0,i=dt.prefilters.length,s=k.Deferred().always(function(){delete u.elem}),u=function(){if(a)return!1;for(var e=rt||ct(),t=Math.max(0,l.startTime+l.duration-e),n=1-(t/l.duration||0),r=0,i=l.tweens.length;r<i;r++)l.tweens[r].run(n);return s.notifyWith(o,[l,n,t]),n<1&&i?t:(i||s.notifyWith(o,[l,1,0]),s.resolveWith(o,[l]),!1)},l=s.promise({elem:o,props:k.extend({},e),opts:k.extend(!0,{specialEasing:{},easing:k.easing._default},t),originalProperties:e,originalOptions:t,startTime:rt||ct(),duration:t.duration,tweens:[],createTween:function(e,t){var n=k.Tween(o,l.opts,e,t,l.opts.specialEasing[e]||l.opts.easing);return l.tweens.push(n),n},stop:function(e){var t=0,n=e?l.tweens.length:0;if(a)return this;for(a=!0;t<n;t++)l.tweens[t].run(1);return e?(s.notifyWith(o,[l,1,0]),s.resolveWith(o,[l,e])):s.rejectWith(o,[l,e]),this}}),c=l.props;for(!function(e,t){var n,r,i,o,a;for(n in e)if(i=t[r=V(n)],o=e[n],Array.isArray(o)&&(i=o[1],o=e[n]=o[0]),n!==r&&(e[r]=o,delete e[n]),(a=k.cssHooks[r])&&"expand"in a)for(n in o=a.expand(o),delete e[r],o)n in e||(e[n]=o[n],t[n]=i);else t[r]=i}(c,l.opts.specialEasing);r<i;r++)if(n=dt.prefilters[r].call(l,o,c,l.opts))return m(n.stop)&&(k._queueHooks(l.elem,l.opts.queue).stop=n.stop.bind(n)),n;return k.map(c,pt,l),m(l.opts.start)&&l.opts.start.call(o,l),l.progress(l.opts.progress).done(l.opts.done,l.opts.complete).fail(l.opts.fail).always(l.opts.always),k.fx.timer(k.extend(u,{elem:o,anim:l,queue:l.opts.queue})),l}k.Animation=k.extend(dt,{tweeners:{"*":[function(e,t){var n=this.createTween(e,t);return le(n.elem,e,ne.exec(t),n),n}]},tweener:function(e,t){m(e)?(t=e,e=["*"]):e=e.match(R);for(var n,r=0,i=e.length;r<i;r++)n=e[r],dt.tweeners[n]=dt.tweeners[n]||[],dt.tweeners[n].unshift(t)},prefilters:[function(e,t,n){var r,i,o,a,s,u,l,c,f="width"in t||"height"in t,p=this,d={},h=e.style,g=e.nodeType&&se(e),v=Q.get(e,"fxshow");for(r in n.queue||(null==(a=k._queueHooks(e,"fx")).unqueued&&(a.unqueued=0,s=a.empty.fire,a.empty.fire=function(){a.unqueued||s()}),a.unqueued++,p.always(function(){p.always(function(){a.unqueued--,k.queue(e,"fx").length||a.empty.fire()})})),t)if(i=t[r],st.test(i)){if(delete t[r],o=o||"toggle"===i,i===(g?"hide":"show")){if("show"!==i||!v||void 0===v[r])continue;g=!0}d[r]=v&&v[r]||k.style(e,r)}if((u=!k.isEmptyObject(t))||!k.isEmptyObject(d))for(r in f&&1===e.nodeType&&(n.overflow=[h.overflow,h.overflowX,h.overflowY],null==(l=v&&v.display)&&(l=Q.get(e,"display")),"none"===(c=k.css(e,"display"))&&(l?c=l:(fe([e],!0),l=e.style.display||l,c=k.css(e,"display"),fe([e]))),("inline"===c||"inline-block"===c&&null!=l)&&"none"===k.css(e,"float")&&(u||(p.done(function(){h.display=l}),null==l&&(c=h.display,l="none"===c?"":c)),h.display="inline-block")),n.overflow&&(h.overflow="hidden",p.always(function(){h.overflow=n.overflow[0],h.overflowX=n.overflow[1],h.overflowY=n.overflow[2]})),u=!1,d)u||(v?"hidden"in v&&(g=v.hidden):v=Q.access(e,"fxshow",{display:l}),o&&(v.hidden=!g),g&&fe([e],!0),p.done(function(){for(r in g||fe([e]),Q.remove(e,"fxshow"),d)k.style(e,r,d[r])})),u=pt(g?v[r]:0,r,p),r in v||(v[r]=u.start,g&&(u.end=u.start,u.start=0))}],prefilter:function(e,t){t?dt.prefilters.unshift(e):dt.prefilters.push(e)}}),k.speed=function(e,t,n){var r=e&&"object"==typeof e?k.extend({},e):{complete:n||!n&&t||m(e)&&e,duration:e,easing:n&&t||t&&!m(t)&&t};return k.fx.off?r.duration=0:"number"!=typeof r.duration&&(r.duration in k.fx.speeds?r.duration=k.fx.speeds[r.duration]:r.duration=k.fx.speeds._default),null!=r.queue&&!0!==r.queue||(r.queue="fx"),r.old=r.complete,r.complete=function(){m(r.old)&&r.old.call(this),r.queue&&k.dequeue(this,r.queue)},r},k.fn.extend({fadeTo:function(e,t,n,r){return this.filter(se).css("opacity",0).show().end().animate({opacity:t},e,n,r)},animate:function(t,e,n,r){var i=k.isEmptyObject(t),o=k.speed(e,n,r),a=function(){var e=dt(this,k.extend({},t),o);(i||Q.get(this,"finish"))&&e.stop(!0)};return a.finish=a,i||!1===o.queue?this.each(a):this.queue(o.queue,a)},stop:function(i,e,o){var a=function(e){var t=e.stop;delete e.stop,t(o)};return"string"!=typeof i&&(o=e,e=i,i=void 0),e&&!1!==i&&this.queue(i||"fx",[]),this.each(function(){var e=!0,t=null!=i&&i+"queueHooks",n=k.timers,r=Q.get(this);if(t)r[t]&&r[t].stop&&a(r[t]);else for(t in r)r[t]&&r[t].stop&&ut.test(t)&&a(r[t]);for(t=n.length;t--;)n[t].elem!==this||null!=i&&n[t].queue!==i||(n[t].anim.stop(o),e=!1,n.splice(t,1));!e&&o||k.dequeue(this,i)})},finish:function(a){return!1!==a&&(a=a||"fx"),this.each(function(){var e,t=Q.get(this),n=t[a+"queue"],r=t[a+"queueHooks"],i=k.timers,o=n?n.length:0;for(t.finish=!0,k.queue(this,a,[]),r&&r.stop&&r.stop.call(this,!0),e=i.length;e--;)i[e].elem===this&&i[e].queue===a&&(i[e].anim.stop(!0),i.splice(e,1));for(e=0;e<o;e++)n[e]&&n[e].finish&&n[e].finish.call(this);delete t.finish})}}),k.each(["toggle","show","hide"],function(e,r){var i=k.fn[r];k.fn[r]=function(e,t,n){return null==e||"boolean"==typeof e?i.apply(this,arguments):this.animate(ft(r,!0),e,t,n)}}),k.each({slideDown:ft("show"),slideUp:ft("hide"),slideToggle:ft("toggle"),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(e,r){k.fn[e]=function(e,t,n){return this.animate(r,e,t,n)}}),k.timers=[],k.fx.tick=function(){var e,t=0,n=k.timers;for(rt=Date.now();t<n.length;t++)(e=n[t])()||n[t]!==e||n.splice(t--,1);n.length||k.fx.stop(),rt=void 0},k.fx.timer=function(e){k.timers.push(e),k.fx.start()},k.fx.interval=13,k.fx.start=function(){it||(it=!0,lt())},k.fx.stop=function(){it=null},k.fx.speeds={slow:600,fast:200,_default:400},k.fn.delay=function(r,e){return r=k.fx&&k.fx.speeds[r]||r,e=e||"fx",this.queue(e,function(e,t){var n=C.setTimeout(e,r);t.stop=function(){C.clearTimeout(n)}})},ot=E.createElement("input"),at=E.createElement("select").appendChild(E.createElement("option")),ot.type="checkbox",y.checkOn=""!==ot.value,y.optSelected=at.selected,(ot=E.createElement("input")).value="t",ot.type="radio",y.radioValue="t"===ot.value;var ht,gt=k.expr.attrHandle;k.fn.extend({attr:function(e,t){return _(this,k.attr,e,t,1<arguments.length)},removeAttr:function(e){return this.each(function(){k.removeAttr(this,e)})}}),k.extend({attr:function(e,t,n){var r,i,o=e.nodeType;if(3!==o&&8!==o&&2!==o)return"undefined"==typeof e.getAttribute?k.prop(e,t,n):(1===o&&k.isXMLDoc(e)||(i=k.attrHooks[t.toLowerCase()]||(k.expr.match.bool.test(t)?ht:void 0)),void 0!==n?null===n?void k.removeAttr(e,t):i&&"set"in i&&void 0!==(r=i.set(e,n,t))?r:(e.setAttribute(t,n+""),n):i&&"get"in i&&null!==(r=i.get(e,t))?r:null==(r=k.find.attr(e,t))?void 0:r)},attrHooks:{type:{set:function(e,t){if(!y.radioValue&&"radio"===t&&A(e,"input")){var n=e.value;return e.setAttribute("type",t),n&&(e.value=n),t}}}},removeAttr:function(e,t){var n,r=0,i=t&&t.match(R);if(i&&1===e.nodeType)while(n=i[r++])e.removeAttribute(n)}}),ht={set:function(e,t,n){return!1===t?k.removeAttr(e,n):e.setAttribute(n,n),n}},k.each(k.expr.match.bool.source.match(/\w+/g),function(e,t){var a=gt[t]||k.find.attr;gt[t]=function(e,t,n){var r,i,o=t.toLowerCase();return n||(i=gt[o],gt[o]=r,r=null!=a(e,t,n)?o:null,gt[o]=i),r}});var vt=/^(?:input|select|textarea|button)$/i,yt=/^(?:a|area)$/i;function mt(e){return(e.match(R)||[]).join(" ")}function xt(e){return e.getAttribute&&e.getAttribute("class")||""}function bt(e){return Array.isArray(e)?e:"string"==typeof e&&e.match(R)||[]}k.fn.extend({prop:function(e,t){return _(this,k.prop,e,t,1<arguments.length)},removeProp:function(e){return this.each(function(){delete this[k.propFix[e]||e]})}}),k.extend({prop:function(e,t,n){var r,i,o=e.nodeType;if(3!==o&&8!==o&&2!==o)return 1===o&&k.isXMLDoc(e)||(t=k.propFix[t]||t,i=k.propHooks[t]),void 0!==n?i&&"set"in i&&void 0!==(r=i.set(e,n,t))?r:e[t]=n:i&&"get"in i&&null!==(r=i.get(e,t))?r:e[t]},propHooks:{tabIndex:{get:function(e){var t=k.find.attr(e,"tabindex");return t?parseInt(t,10):vt.test(e.nodeName)||yt.test(e.nodeName)&&e.href?0:-1}}},propFix:{"for":"htmlFor","class":"className"}}),y.optSelected||(k.propHooks.selected={get:function(e){var t=e.parentNode;return t&&t.parentNode&&t.parentNode.selectedIndex,null},set:function(e){var t=e.parentNode;t&&(t.selectedIndex,t.parentNode&&t.parentNode.selectedIndex)}}),k.each(["tabIndex","readOnly","maxLength","cellSpacing","cellPadding","rowSpan","colSpan","useMap","frameBorder","contentEditable"],function(){k.propFix[this.toLowerCase()]=this}),k.fn.extend({addClass:function(t){var e,n,r,i,o,a,s,u=0;if(m(t))return this.each(function(e){k(this).addClass(t.call(this,e,xt(this)))});if((e=bt(t)).length)while(n=this[u++])if(i=xt(n),r=1===n.nodeType&&" "+mt(i)+" "){a=0;while(o=e[a++])r.indexOf(" "+o+" ")<0&&(r+=o+" ");i!==(s=mt(r))&&n.setAttribute("class",s)}return this},removeClass:function(t){var e,n,r,i,o,a,s,u=0;if(m(t))return this.each(function(e){k(this).removeClass(t.call(this,e,xt(this)))});if(!arguments.length)return this.attr("class","");if((e=bt(t)).length)while(n=this[u++])if(i=xt(n),r=1===n.nodeType&&" "+mt(i)+" "){a=0;while(o=e[a++])while(-1<r.indexOf(" "+o+" "))r=r.replace(" "+o+" "," ");i!==(s=mt(r))&&n.setAttribute("class",s)}return this},toggleClass:function(i,t){var o=typeof i,a="string"===o||Array.isArray(i);return"boolean"==typeof t&&a?t?this.addClass(i):this.removeClass(i):m(i)?this.each(function(e){k(this).toggleClass(i.call(this,e,xt(this),t),t)}):this.each(function(){var e,t,n,r;if(a){t=0,n=k(this),r=bt(i);while(e=r[t++])n.hasClass(e)?n.removeClass(e):n.addClass(e)}else void 0!==i&&"boolean"!==o||((e=xt(this))&&Q.set(this,"__className__",e),this.setAttribute&&this.setAttribute("class",e||!1===i?"":Q.get(this,"__className__")||""))})},hasClass:function(e){var t,n,r=0;t=" "+e+" ";while(n=this[r++])if(1===n.nodeType&&-1<(" "+mt(xt(n))+" ").indexOf(t))return!0;return!1}});var wt=/\r/g;k.fn.extend({val:function(n){var r,e,i,t=this[0];return arguments.length?(i=m(n),this.each(function(e){var t;1===this.nodeType&&(null==(t=i?n.call(this,e,k(this).val()):n)?t="":"number"==typeof t?t+="":Array.isArray(t)&&(t=k.map(t,function(e){return null==e?"":e+""})),(r=k.valHooks[this.type]||k.valHooks[this.nodeName.toLowerCase()])&&"set"in r&&void 0!==r.set(this,t,"value")||(this.value=t))})):t?(r=k.valHooks[t.type]||k.valHooks[t.nodeName.toLowerCase()])&&"get"in r&&void 0!==(e=r.get(t,"value"))?e:"string"==typeof(e=t.value)?e.replace(wt,""):null==e?"":e:void 0}}),k.extend({valHooks:{option:{get:function(e){var t=k.find.attr(e,"value");return null!=t?t:mt(k.text(e))}},select:{get:function(e){var t,n,r,i=e.options,o=e.selectedIndex,a="select-one"===e.type,s=a?null:[],u=a?o+1:i.length;for(r=o<0?u:a?o:0;r<u;r++)if(((n=i[r]).selected||r===o)&&!n.disabled&&(!n.parentNode.disabled||!A(n.parentNode,"optgroup"))){if(t=k(n).val(),a)return t;s.push(t)}return s},set:function(e,t){var n,r,i=e.options,o=k.makeArray(t),a=i.length;while(a--)((r=i[a]).selected=-1<k.inArray(k.valHooks.option.get(r),o))&&(n=!0);return n||(e.selectedIndex=-1),o}}}}),k.each(["radio","checkbox"],function(){k.valHooks[this]={set:function(e,t){if(Array.isArray(t))return e.checked=-1<k.inArray(k(e).val(),t)}},y.checkOn||(k.valHooks[this].get=function(e){return null===e.getAttribute("value")?"on":e.value})}),y.focusin="onfocusin"in C;var Tt=/^(?:focusinfocus|focusoutblur)$/,Ct=function(e){e.stopPropagation()};k.extend(k.event,{trigger:function(e,t,n,r){var i,o,a,s,u,l,c,f,p=[n||E],d=v.call(e,"type")?e.type:e,h=v.call(e,"namespace")?e.namespace.split("."):[];if(o=f=a=n=n||E,3!==n.nodeType&&8!==n.nodeType&&!Tt.test(d+k.event.triggered)&&(-1<d.indexOf(".")&&(d=(h=d.split(".")).shift(),h.sort()),u=d.indexOf(":")<0&&"on"+d,(e=e[k.expando]?e:new k.Event(d,"object"==typeof e&&e)).isTrigger=r?2:3,e.namespace=h.join("."),e.rnamespace=e.namespace?new RegExp("(^|\\.)"+h.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,e.result=void 0,e.target||(e.target=n),t=null==t?[e]:k.makeArray(t,[e]),c=k.event.special[d]||{},r||!c.trigger||!1!==c.trigger.apply(n,t))){if(!r&&!c.noBubble&&!x(n)){for(s=c.delegateType||d,Tt.test(s+d)||(o=o.parentNode);o;o=o.parentNode)p.push(o),a=o;a===(n.ownerDocument||E)&&p.push(a.defaultView||a.parentWindow||C)}i=0;while((o=p[i++])&&!e.isPropagationStopped())f=o,e.type=1<i?s:c.bindType||d,(l=(Q.get(o,"events")||{})[e.type]&&Q.get(o,"handle"))&&l.apply(o,t),(l=u&&o[u])&&l.apply&&G(o)&&(e.result=l.apply(o,t),!1===e.result&&e.preventDefault());return e.type=d,r||e.isDefaultPrevented()||c._default&&!1!==c._default.apply(p.pop(),t)||!G(n)||u&&m(n[d])&&!x(n)&&((a=n[u])&&(n[u]=null),k.event.triggered=d,e.isPropagationStopped()&&f.addEventListener(d,Ct),n[d](),e.isPropagationStopped()&&f.removeEventListener(d,Ct),k.event.triggered=void 0,a&&(n[u]=a)),e.result}},simulate:function(e,t,n){var r=k.extend(new k.Event,n,{type:e,isSimulated:!0});k.event.trigger(r,null,t)}}),k.fn.extend({trigger:function(e,t){return this.each(function(){k.event.trigger(e,t,this)})},triggerHandler:function(e,t){var n=this[0];if(n)return k.event.trigger(e,t,n,!0)}}),y.focusin||k.each({focus:"focusin",blur:"focusout"},function(n,r){var i=function(e){k.event.simulate(r,e.target,k.event.fix(e))};k.event.special[r]={setup:function(){var e=this.ownerDocument||this,t=Q.access(e,r);t||e.addEventListener(n,i,!0),Q.access(e,r,(t||0)+1)},teardown:function(){var e=this.ownerDocument||this,t=Q.access(e,r)-1;t?Q.access(e,r,t):(e.removeEventListener(n,i,!0),Q.remove(e,r))}}});var Et=C.location,kt=Date.now(),St=/\?/;k.parseXML=function(e){var t;if(!e||"string"!=typeof e)return null;try{t=(new C.DOMParser).parseFromString(e,"text/xml")}catch(e){t=void 0}return t&&!t.getElementsByTagName("parsererror").length||k.error("Invalid XML: "+e),t};var Nt=/\[\]$/,At=/\r?\n/g,Dt=/^(?:submit|button|image|reset|file)$/i,jt=/^(?:input|select|textarea|keygen)/i;function qt(n,e,r,i){var t;if(Array.isArray(e))k.each(e,function(e,t){r||Nt.test(n)?i(n,t):qt(n+"["+("object"==typeof t&&null!=t?e:"")+"]",t,r,i)});else if(r||"object"!==w(e))i(n,e);else for(t in e)qt(n+"["+t+"]",e[t],r,i)}k.param=function(e,t){var n,r=[],i=function(e,t){var n=m(t)?t():t;r[r.length]=encodeURIComponent(e)+"="+encodeURIComponent(null==n?"":n)};if(null==e)return"";if(Array.isArray(e)||e.jquery&&!k.isPlainObject(e))k.each(e,function(){i(this.name,this.value)});else for(n in e)qt(n,e[n],t,i);return r.join("&")},k.fn.extend({serialize:function(){return k.param(this.serializeArray())},serializeArray:function(){return this.map(function(){var e=k.prop(this,"elements");return e?k.makeArray(e):this}).filter(function(){var e=this.type;return this.name&&!k(this).is(":disabled")&&jt.test(this.nodeName)&&!Dt.test(e)&&(this.checked||!pe.test(e))}).map(function(e,t){var n=k(this).val();return null==n?null:Array.isArray(n)?k.map(n,function(e){return{name:t.name,value:e.replace(At,"\r\n")}}):{name:t.name,value:n.replace(At,"\r\n")}}).get()}});var Lt=/%20/g,Ht=/#.*$/,Ot=/([?&])_=[^&]*/,Pt=/^(.*?):[ \t]*([^\r\n]*)$/gm,Rt=/^(?:GET|HEAD)$/,Mt=/^\/\//,It={},Wt={},$t="*/".concat("*"),Ft=E.createElement("a");function Bt(o){return function(e,t){"string"!=typeof e&&(t=e,e="*");var n,r=0,i=e.toLowerCase().match(R)||[];if(m(t))while(n=i[r++])"+"===n[0]?(n=n.slice(1)||"*",(o[n]=o[n]||[]).unshift(t)):(o[n]=o[n]||[]).push(t)}}function _t(t,i,o,a){var s={},u=t===Wt;function l(e){var r;return s[e]=!0,k.each(t[e]||[],function(e,t){var n=t(i,o,a);return"string"!=typeof n||u||s[n]?u?!(r=n):void 0:(i.dataTypes.unshift(n),l(n),!1)}),r}return l(i.dataTypes[0])||!s["*"]&&l("*")}function zt(e,t){var n,r,i=k.ajaxSettings.flatOptions||{};for(n in t)void 0!==t[n]&&((i[n]?e:r||(r={}))[n]=t[n]);return r&&k.extend(!0,e,r),e}Ft.href=Et.href,k.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:Et.href,type:"GET",isLocal:/^(?:about|app|app-storage|.+-extension|file|res|widget):$/.test(Et.protocol),global:!0,processData:!0,async:!0,contentType:"application/x-www-form-urlencoded; charset=UTF-8",accepts:{"*":$t,text:"text/plain",html:"text/html",xml:"application/xml, text/xml",json:"application/json, text/javascript"},contents:{xml:/\bxml\b/,html:/\bhtml/,json:/\bjson\b/},responseFields:{xml:"responseXML",text:"responseText",json:"responseJSON"},converters:{"* text":String,"text html":!0,"text json":JSON.parse,"text xml":k.parseXML},flatOptions:{url:!0,context:!0}},ajaxSetup:function(e,t){return t?zt(zt(e,k.ajaxSettings),t):zt(k.ajaxSettings,e)},ajaxPrefilter:Bt(It),ajaxTransport:Bt(Wt),ajax:function(e,t){"object"==typeof e&&(t=e,e=void 0),t=t||{};var c,f,p,n,d,r,h,g,i,o,v=k.ajaxSetup({},t),y=v.context||v,m=v.context&&(y.nodeType||y.jquery)?k(y):k.event,x=k.Deferred(),b=k.Callbacks("once memory"),w=v.statusCode||{},a={},s={},u="canceled",T={readyState:0,getResponseHeader:function(e){var t;if(h){if(!n){n={};while(t=Pt.exec(p))n[t[1].toLowerCase()+" "]=(n[t[1].toLowerCase()+" "]||[]).concat(t[2])}t=n[e.toLowerCase()+" "]}return null==t?null:t.join(", ")},getAllResponseHeaders:function(){return h?p:null},setRequestHeader:function(e,t){return null==h&&(e=s[e.toLowerCase()]=s[e.toLowerCase()]||e,a[e]=t),this},overrideMimeType:function(e){return null==h&&(v.mimeType=e),this},statusCode:function(e){var t;if(e)if(h)T.always(e[T.status]);else for(t in e)w[t]=[w[t],e[t]];return this},abort:function(e){var t=e||u;return c&&c.abort(t),l(0,t),this}};if(x.promise(T),v.url=((e||v.url||Et.href)+"").replace(Mt,Et.protocol+"//"),v.type=t.method||t.type||v.method||v.type,v.dataTypes=(v.dataType||"*").toLowerCase().match(R)||[""],null==v.crossDomain){r=E.createElement("a");try{r.href=v.url,r.href=r.href,v.crossDomain=Ft.protocol+"//"+Ft.host!=r.protocol+"//"+r.host}catch(e){v.crossDomain=!0}}if(v.data&&v.processData&&"string"!=typeof v.data&&(v.data=k.param(v.data,v.traditional)),_t(It,v,t,T),h)return T;for(i in(g=k.event&&v.global)&&0==k.active++&&k.event.trigger("ajaxStart"),v.type=v.type.toUpperCase(),v.hasContent=!Rt.test(v.type),f=v.url.replace(Ht,""),v.hasContent?v.data&&v.processData&&0===(v.contentType||"").indexOf("application/x-www-form-urlencoded")&&(v.data=v.data.replace(Lt,"+")):(o=v.url.slice(f.length),v.data&&(v.processData||"string"==typeof v.data)&&(f+=(St.test(f)?"&":"?")+v.data,delete v.data),!1===v.cache&&(f=f.replace(Ot,"$1"),o=(St.test(f)?"&":"?")+"_="+kt+++o),v.url=f+o),v.ifModified&&(k.lastModified[f]&&T.setRequestHeader("If-Modified-Since",k.lastModified[f]),k.etag[f]&&T.setRequestHeader("If-None-Match",k.etag[f])),(v.data&&v.hasContent&&!1!==v.contentType||t.contentType)&&T.setRequestHeader("Content-Type",v.contentType),T.setRequestHeader("Accept",v.dataTypes[0]&&v.accepts[v.dataTypes[0]]?v.accepts[v.dataTypes[0]]+("*"!==v.dataTypes[0]?", "+$t+"; q=0.01":""):v.accepts["*"]),v.headers)T.setRequestHeader(i,v.headers[i]);if(v.beforeSend&&(!1===v.beforeSend.call(y,T,v)||h))return T.abort();if(u="abort",b.add(v.complete),T.done(v.success),T.fail(v.error),c=_t(Wt,v,t,T)){if(T.readyState=1,g&&m.trigger("ajaxSend",[T,v]),h)return T;v.async&&0<v.timeout&&(d=C.setTimeout(function(){T.abort("timeout")},v.timeout));try{h=!1,c.send(a,l)}catch(e){if(h)throw e;l(-1,e)}}else l(-1,"No Transport");function l(e,t,n,r){var i,o,a,s,u,l=t;h||(h=!0,d&&C.clearTimeout(d),c=void 0,p=r||"",T.readyState=0<e?4:0,i=200<=e&&e<300||304===e,n&&(s=function(e,t,n){var r,i,o,a,s=e.contents,u=e.dataTypes;while("*"===u[0])u.shift(),void 0===r&&(r=e.mimeType||t.getResponseHeader("Content-Type"));if(r)for(i in s)if(s[i]&&s[i].test(r)){u.unshift(i);break}if(u[0]in n)o=u[0];else{for(i in n){if(!u[0]||e.converters[i+" "+u[0]]){o=i;break}a||(a=i)}o=o||a}if(o)return o!==u[0]&&u.unshift(o),n[o]}(v,T,n)),s=function(e,t,n,r){var i,o,a,s,u,l={},c=e.dataTypes.slice();if(c[1])for(a in e.converters)l[a.toLowerCase()]=e.converters[a];o=c.shift();while(o)if(e.responseFields[o]&&(n[e.responseFields[o]]=t),!u&&r&&e.dataFilter&&(t=e.dataFilter(t,e.dataType)),u=o,o=c.shift())if("*"===o)o=u;else if("*"!==u&&u!==o){if(!(a=l[u+" "+o]||l["* "+o]))for(i in l)if((s=i.split(" "))[1]===o&&(a=l[u+" "+s[0]]||l["* "+s[0]])){!0===a?a=l[i]:!0!==l[i]&&(o=s[0],c.unshift(s[1]));break}if(!0!==a)if(a&&e["throws"])t=a(t);else try{t=a(t)}catch(e){return{state:"parsererror",error:a?e:"No conversion from "+u+" to "+o}}}return{state:"success",data:t}}(v,s,T,i),i?(v.ifModified&&((u=T.getResponseHeader("Last-Modified"))&&(k.lastModified[f]=u),(u=T.getResponseHeader("etag"))&&(k.etag[f]=u)),204===e||"HEAD"===v.type?l="nocontent":304===e?l="notmodified":(l=s.state,o=s.data,i=!(a=s.error))):(a=l,!e&&l||(l="error",e<0&&(e=0))),T.status=e,T.statusText=(t||l)+"",i?x.resolveWith(y,[o,l,T]):x.rejectWith(y,[T,l,a]),T.statusCode(w),w=void 0,g&&m.trigger(i?"ajaxSuccess":"ajaxError",[T,v,i?o:a]),b.fireWith(y,[T,l]),g&&(m.trigger("ajaxComplete",[T,v]),--k.active||k.event.trigger("ajaxStop")))}return T},getJSON:function(e,t,n){return k.get(e,t,n,"json")},getScript:function(e,t){return k.get(e,void 0,t,"script")}}),k.each(["get","post"],function(e,i){k[i]=function(e,t,n,r){return m(t)&&(r=r||n,n=t,t=void 0),k.ajax(k.extend({url:e,type:i,dataType:r,data:t,success:n},k.isPlainObject(e)&&e))}}),k._evalUrl=function(e,t){return k.ajax({url:e,type:"GET",dataType:"script",cache:!0,async:!1,global:!1,converters:{"text script":function(){}},dataFilter:function(e){k.globalEval(e,t)}})},k.fn.extend({wrapAll:function(e){var t;return this[0]&&(m(e)&&(e=e.call(this[0])),t=k(e,this[0].ownerDocument).eq(0).clone(!0),this[0].parentNode&&t.insertBefore(this[0]),t.map(function(){var e=this;while(e.firstElementChild)e=e.firstElementChild;return e}).append(this)),this},wrapInner:function(n){return m(n)?this.each(function(e){k(this).wrapInner(n.call(this,e))}):this.each(function(){var e=k(this),t=e.contents();t.length?t.wrapAll(n):e.append(n)})},wrap:function(t){var n=m(t);return this.each(function(e){k(this).wrapAll(n?t.call(this,e):t)})},unwrap:function(e){return this.parent(e).not("body").each(function(){k(this).replaceWith(this.childNodes)}),this}}),k.expr.pseudos.hidden=function(e){return!k.expr.pseudos.visible(e)},k.expr.pseudos.visible=function(e){return!!(e.offsetWidth||e.offsetHeight||e.getClientRects().length)},k.ajaxSettings.xhr=function(){try{return new C.XMLHttpRequest}catch(e){}};var Ut={0:200,1223:204},Xt=k.ajaxSettings.xhr();y.cors=!!Xt&&"withCredentials"in Xt,y.ajax=Xt=!!Xt,k.ajaxTransport(function(i){var o,a;if(y.cors||Xt&&!i.crossDomain)return{send:function(e,t){var n,r=i.xhr();if(r.open(i.type,i.url,i.async,i.username,i.password),i.xhrFields)for(n in i.xhrFields)r[n]=i.xhrFields[n];for(n in i.mimeType&&r.overrideMimeType&&r.overrideMimeType(i.mimeType),i.crossDomain||e["X-Requested-With"]||(e["X-Requested-With"]="XMLHttpRequest"),e)r.setRequestHeader(n,e[n]);o=function(e){return function(){o&&(o=a=r.onload=r.onerror=r.onabort=r.ontimeout=r.onreadystatechange=null,"abort"===e?r.abort():"error"===e?"number"!=typeof r.status?t(0,"error"):t(r.status,r.statusText):t(Ut[r.status]||r.status,r.statusText,"text"!==(r.responseType||"text")||"string"!=typeof r.responseText?{binary:r.response}:{text:r.responseText},r.getAllResponseHeaders()))}},r.onload=o(),a=r.onerror=r.ontimeout=o("error"),void 0!==r.onabort?r.onabort=a:r.onreadystatechange=function(){4===r.readyState&&C.setTimeout(function(){o&&a()})},o=o("abort");try{r.send(i.hasContent&&i.data||null)}catch(e){if(o)throw e}},abort:function(){o&&o()}}}),k.ajaxPrefilter(function(e){e.crossDomain&&(e.contents.script=!1)}),k.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/\b(?:java|ecma)script\b/},converters:{"text script":function(e){return k.globalEval(e),e}}}),k.ajaxPrefilter("script",function(e){void 0===e.cache&&(e.cache=!1),e.crossDomain&&(e.type="GET")}),k.ajaxTransport("script",function(n){var r,i;if(n.crossDomain||n.scriptAttrs)return{send:function(e,t){r=k("<script>").attr(n.scriptAttrs||{}).prop({charset:n.scriptCharset,src:n.url}).on("load error",i=function(e){r.remove(),i=null,e&&t("error"===e.type?404:200,e.type)}),E.head.appendChild(r[0])},abort:function(){i&&i()}}});var Vt,Gt=[],Yt=/(=)\?(?=&|$)|\?\?/;k.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var e=Gt.pop()||k.expando+"_"+kt++;return this[e]=!0,e}}),k.ajaxPrefilter("json jsonp",function(e,t,n){var r,i,o,a=!1!==e.jsonp&&(Yt.test(e.url)?"url":"string"==typeof e.data&&0===(e.contentType||"").indexOf("application/x-www-form-urlencoded")&&Yt.test(e.data)&&"data");if(a||"jsonp"===e.dataTypes[0])return r=e.jsonpCallback=m(e.jsonpCallback)?e.jsonpCallback():e.jsonpCallback,a?e[a]=e[a].replace(Yt,"$1"+r):!1!==e.jsonp&&(e.url+=(St.test(e.url)?"&":"?")+e.jsonp+"="+r),e.converters["script json"]=function(){return o||k.error(r+" was not called"),o[0]},e.dataTypes[0]="json",i=C[r],C[r]=function(){o=arguments},n.always(function(){void 0===i?k(C).removeProp(r):C[r]=i,e[r]&&(e.jsonpCallback=t.jsonpCallback,Gt.push(r)),o&&m(i)&&i(o[0]),o=i=void 0}),"script"}),y.createHTMLDocument=((Vt=E.implementation.createHTMLDocument("").body).innerHTML="<form></form><form></form>",2===Vt.childNodes.length),k.parseHTML=function(e,t,n){return"string"!=typeof e?[]:("boolean"==typeof t&&(n=t,t=!1),t||(y.createHTMLDocument?((r=(t=E.implementation.createHTMLDocument("")).createElement("base")).href=E.location.href,t.head.appendChild(r)):t=E),o=!n&&[],(i=D.exec(e))?[t.createElement(i[1])]:(i=we([e],t,o),o&&o.length&&k(o).remove(),k.merge([],i.childNodes)));var r,i,o},k.fn.load=function(e,t,n){var r,i,o,a=this,s=e.indexOf(" ");return-1<s&&(r=mt(e.slice(s)),e=e.slice(0,s)),m(t)?(n=t,t=void 0):t&&"object"==typeof t&&(i="POST"),0<a.length&&k.ajax({url:e,type:i||"GET",dataType:"html",data:t}).done(function(e){o=arguments,a.html(r?k("<div>").append(k.parseHTML(e)).find(r):e)}).always(n&&function(e,t){a.each(function(){n.apply(this,o||[e.responseText,t,e])})}),this},k.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(e,t){k.fn[t]=function(e){return this.on(t,e)}}),k.expr.pseudos.animated=function(t){return k.grep(k.timers,function(e){return t===e.elem}).length},k.offset={setOffset:function(e,t,n){var r,i,o,a,s,u,l=k.css(e,"position"),c=k(e),f={};"static"===l&&(e.style.position="relative"),s=c.offset(),o=k.css(e,"top"),u=k.css(e,"left"),("absolute"===l||"fixed"===l)&&-1<(o+u).indexOf("auto")?(a=(r=c.position()).top,i=r.left):(a=parseFloat(o)||0,i=parseFloat(u)||0),m(t)&&(t=t.call(e,n,k.extend({},s))),null!=t.top&&(f.top=t.top-s.top+a),null!=t.left&&(f.left=t.left-s.left+i),"using"in t?t.using.call(e,f):c.css(f)}},k.fn.extend({offset:function(t){if(arguments.length)return void 0===t?this:this.each(function(e){k.offset.setOffset(this,t,e)});var e,n,r=this[0];return r?r.getClientRects().length?(e=r.getBoundingClientRect(),n=r.ownerDocument.defaultView,{top:e.top+n.pageYOffset,left:e.left+n.pageXOffset}):{top:0,left:0}:void 0},position:function(){if(this[0]){var e,t,n,r=this[0],i={top:0,left:0};if("fixed"===k.css(r,"position"))t=r.getBoundingClientRect();else{t=this.offset(),n=r.ownerDocument,e=r.offsetParent||n.documentElement;while(e&&(e===n.body||e===n.documentElement)&&"static"===k.css(e,"position"))e=e.parentNode;e&&e!==r&&1===e.nodeType&&((i=k(e).offset()).top+=k.css(e,"borderTopWidth",!0),i.left+=k.css(e,"borderLeftWidth",!0))}return{top:t.top-i.top-k.css(r,"marginTop",!0),left:t.left-i.left-k.css(r,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var e=this.offsetParent;while(e&&"static"===k.css(e,"position"))e=e.offsetParent;return e||ie})}}),k.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(t,i){var o="pageYOffset"===i;k.fn[t]=function(e){return _(this,function(e,t,n){var r;if(x(e)?r=e:9===e.nodeType&&(r=e.defaultView),void 0===n)return r?r[i]:e[t];r?r.scrollTo(o?r.pageXOffset:n,o?n:r.pageYOffset):e[t]=n},t,e,arguments.length)}}),k.each(["top","left"],function(e,n){k.cssHooks[n]=ze(y.pixelPosition,function(e,t){if(t)return t=_e(e,n),$e.test(t)?k(e).position()[n]+"px":t})}),k.each({Height:"height",Width:"width"},function(a,s){k.each({padding:"inner"+a,content:s,"":"outer"+a},function(r,o){k.fn[o]=function(e,t){var n=arguments.length&&(r||"boolean"!=typeof e),i=r||(!0===e||!0===t?"margin":"border");return _(this,function(e,t,n){var r;return x(e)?0===o.indexOf("outer")?e["inner"+a]:e.document.documentElement["client"+a]:9===e.nodeType?(r=e.documentElement,Math.max(e.body["scroll"+a],r["scroll"+a],e.body["offset"+a],r["offset"+a],r["client"+a])):void 0===n?k.css(e,t,i):k.style(e,t,n,i)},s,n?e:void 0,n)}})}),k.each("blur focus focusin focusout resize scroll click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup contextmenu".split(" "),function(e,n){k.fn[n]=function(e,t){return 0<arguments.length?this.on(n,null,e,t):this.trigger(n)}}),k.fn.extend({hover:function(e,t){return this.mouseenter(e).mouseleave(t||e)}}),k.fn.extend({bind:function(e,t,n){return this.on(e,null,t,n)},unbind:function(e,t){return this.off(e,null,t)},delegate:function(e,t,n,r){return this.on(t,e,n,r)},undelegate:function(e,t,n){return 1===arguments.length?this.off(e,"**"):this.off(t,e||"**",n)}}),k.proxy=function(e,t){var n,r,i;if("string"==typeof t&&(n=e[t],t=e,e=n),m(e))return r=s.call(arguments,2),(i=function(){return e.apply(t||this,r.concat(s.call(arguments)))}).guid=e.guid=e.guid||k.guid++,i},k.holdReady=function(e){e?k.readyWait++:k.ready(!0)},k.isArray=Array.isArray,k.parseJSON=JSON.parse,k.nodeName=A,k.isFunction=m,k.isWindow=x,k.camelCase=V,k.type=w,k.now=Date.now,k.isNumeric=function(e){var t=k.type(e);return("number"===t||"string"===t)&&!isNaN(e-parseFloat(e))},"function"==typeof define&&define.amd&&define("jquery",[],function(){return k});var Qt=C.jQuery,Jt=C.$;return k.noConflict=function(e){return C.$===k&&(C.$=Jt),e&&C.jQuery===k&&(C.jQuery=Qt),k},e||(C.jQuery=C.$=k),k});
  22869. /*!
  22870. * Bootstrap v4.3.1 (https://getbootstrap.com/)
  22871. * Copyright 2011-2019 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors)
  22872. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
  22873. */
  22874. !function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports,require("jquery"),require("popper.js")):"function"==typeof define&&define.amd?define(["exports","jquery","popper.js"],e):e((t=t||self).bootstrap={},t.jQuery,t.Popper)}(this,function(t,g,u){"use strict";function i(t,e){for(var n=0;n<e.length;n++){var i=e[n];i.enumerable=i.enumerable||!1,i.configurable=!0,"value"in i&&(i.writable=!0),Object.defineProperty(t,i.key,i)}}function s(t,e,n){return e&&i(t.prototype,e),n&&i(t,n),t}function l(o){for(var t=1;t<arguments.length;t++){var r=null!=arguments[t]?arguments[t]:{},e=Object.keys(r);"function"==typeof Object.getOwnPropertySymbols&&(e=e.concat(Object.getOwnPropertySymbols(r).filter(function(t){return Object.getOwnPropertyDescriptor(r,t).enumerable}))),e.forEach(function(t){var e,n,i;e=o,i=r[n=t],n in e?Object.defineProperty(e,n,{value:i,enumerable:!0,configurable:!0,writable:!0}):e[n]=i})}return o}g=g&&g.hasOwnProperty("default")?g.default:g,u=u&&u.hasOwnProperty("default")?u.default:u;var e="transitionend";function n(t){var e=this,n=!1;return g(this).one(_.TRANSITION_END,function(){n=!0}),setTimeout(function(){n||_.triggerTransitionEnd(e)},t),this}var _={TRANSITION_END:"bsTransitionEnd",getUID:function(t){for(;t+=~~(1e6*Math.random()),document.getElementById(t););return t},getSelectorFromElement:function(t){var e=t.getAttribute("data-target");if(!e||"#"===e){var n=t.getAttribute("href");e=n&&"#"!==n?n.trim():""}try{return document.querySelector(e)?e:null}catch(t){return null}},getTransitionDurationFromElement:function(t){if(!t)return 0;var e=g(t).css("transition-duration"),n=g(t).css("transition-delay"),i=parseFloat(e),o=parseFloat(n);return i||o?(e=e.split(",")[0],n=n.split(",")[0],1e3*(parseFloat(e)+parseFloat(n))):0},reflow:function(t){return t.offsetHeight},triggerTransitionEnd:function(t){g(t).trigger(e)},supportsTransitionEnd:function(){return Boolean(e)},isElement:function(t){return(t[0]||t).nodeType},typeCheckConfig:function(t,e,n){for(var i in n)if(Object.prototype.hasOwnProperty.call(n,i)){var o=n[i],r=e[i],s=r&&_.isElement(r)?"element":(a=r,{}.toString.call(a).match(/\s([a-z]+)/i)[1].toLowerCase());if(!new RegExp(o).test(s))throw new Error(t.toUpperCase()+': Option "'+i+'" provided type "'+s+'" but expected type "'+o+'".')}var a},findShadowRoot:function(t){if(!document.documentElement.attachShadow)return null;if("function"!=typeof t.getRootNode)return t instanceof ShadowRoot?t:t.parentNode?_.findShadowRoot(t.parentNode):null;var e=t.getRootNode();return e instanceof ShadowRoot?e:null}};g.fn.emulateTransitionEnd=n,g.event.special[_.TRANSITION_END]={bindType:e,delegateType:e,handle:function(t){if(g(t.target).is(this))return t.handleObj.handler.apply(this,arguments)}};var o="alert",r="bs.alert",a="."+r,c=g.fn[o],h={CLOSE:"close"+a,CLOSED:"closed"+a,CLICK_DATA_API:"click"+a+".data-api"},f="alert",d="fade",m="show",p=function(){function i(t){this._element=t}var t=i.prototype;return t.close=function(t){var e=this._element;t&&(e=this._getRootElement(t)),this._triggerCloseEvent(e).isDefaultPrevented()||this._removeElement(e)},t.dispose=function(){g.removeData(this._element,r),this._element=null},t._getRootElement=function(t){var e=_.getSelectorFromElement(t),n=!1;return e&&(n=document.querySelector(e)),n||(n=g(t).closest("."+f)[0]),n},t._triggerCloseEvent=function(t){var e=g.Event(h.CLOSE);return g(t).trigger(e),e},t._removeElement=function(e){var n=this;if(g(e).removeClass(m),g(e).hasClass(d)){var t=_.getTransitionDurationFromElement(e);g(e).one(_.TRANSITION_END,function(t){return n._destroyElement(e,t)}).emulateTransitionEnd(t)}else this._destroyElement(e)},t._destroyElement=function(t){g(t).detach().trigger(h.CLOSED).remove()},i._jQueryInterface=function(n){return this.each(function(){var t=g(this),e=t.data(r);e||(e=new i(this),t.data(r,e)),"close"===n&&e[n](this)})},i._handleDismiss=function(e){return function(t){t&&t.preventDefault(),e.close(this)}},s(i,null,[{key:"VERSION",get:function(){return"4.3.1"}}]),i}();g(document).on(h.CLICK_DATA_API,'[data-dismiss="alert"]',p._handleDismiss(new p)),g.fn[o]=p._jQueryInterface,g.fn[o].Constructor=p,g.fn[o].noConflict=function(){return g.fn[o]=c,p._jQueryInterface};var v="button",y="bs.button",E="."+y,C=".data-api",T=g.fn[v],S="active",b="btn",I="focus",D='[data-toggle^="button"]',w='[data-toggle="buttons"]',A='input:not([type="hidden"])',N=".active",O=".btn",k={CLICK_DATA_API:"click"+E+C,FOCUS_BLUR_DATA_API:"focus"+E+C+" blur"+E+C},P=function(){function n(t){this._element=t}var t=n.prototype;return t.toggle=function(){var t=!0,e=!0,n=g(this._element).closest(w)[0];if(n){var i=this._element.querySelector(A);if(i){if("radio"===i.type)if(i.checked&&this._element.classList.contains(S))t=!1;else{var o=n.querySelector(N);o&&g(o).removeClass(S)}if(t){if(i.hasAttribute("disabled")||n.hasAttribute("disabled")||i.classList.contains("disabled")||n.classList.contains("disabled"))return;i.checked=!this._element.classList.contains(S),g(i).trigger("change")}i.focus(),e=!1}}e&&this._element.setAttribute("aria-pressed",!this._element.classList.contains(S)),t&&g(this._element).toggleClass(S)},t.dispose=function(){g.removeData(this._element,y),this._element=null},n._jQueryInterface=function(e){return this.each(function(){var t=g(this).data(y);t||(t=new n(this),g(this).data(y,t)),"toggle"===e&&t[e]()})},s(n,null,[{key:"VERSION",get:function(){return"4.3.1"}}]),n}();g(document).on(k.CLICK_DATA_API,D,function(t){t.preventDefault();var e=t.target;g(e).hasClass(b)||(e=g(e).closest(O)),P._jQueryInterface.call(g(e),"toggle")}).on(k.FOCUS_BLUR_DATA_API,D,function(t){var e=g(t.target).closest(O)[0];g(e).toggleClass(I,/^focus(in)?$/.test(t.type))}),g.fn[v]=P._jQueryInterface,g.fn[v].Constructor=P,g.fn[v].noConflict=function(){return g.fn[v]=T,P._jQueryInterface};var L="carousel",j="bs.carousel",H="."+j,R=".data-api",x=g.fn[L],F={interval:5e3,keyboard:!0,slide:!1,pause:"hover",wrap:!0,touch:!0},U={interval:"(number|boolean)",keyboard:"boolean",slide:"(boolean|string)",pause:"(string|boolean)",wrap:"boolean",touch:"boolean"},W="next",q="prev",M="left",K="right",Q={SLIDE:"slide"+H,SLID:"slid"+H,KEYDOWN:"keydown"+H,MOUSEENTER:"mouseenter"+H,MOUSELEAVE:"mouseleave"+H,TOUCHSTART:"touchstart"+H,TOUCHMOVE:"touchmove"+H,TOUCHEND:"touchend"+H,POINTERDOWN:"pointerdown"+H,POINTERUP:"pointerup"+H,DRAG_START:"dragstart"+H,LOAD_DATA_API:"load"+H+R,CLICK_DATA_API:"click"+H+R},B="carousel",V="active",Y="slide",z="carousel-item-right",X="carousel-item-left",$="carousel-item-next",G="carousel-item-prev",J="pointer-event",Z=".active",tt=".active.carousel-item",et=".carousel-item",nt=".carousel-item img",it=".carousel-item-next, .carousel-item-prev",ot=".carousel-indicators",rt="[data-slide], [data-slide-to]",st='[data-ride="carousel"]',at={TOUCH:"touch",PEN:"pen"},lt=function(){function r(t,e){this._items=null,this._interval=null,this._activeElement=null,this._isPaused=!1,this._isSliding=!1,this.touchTimeout=null,this.touchStartX=0,this.touchDeltaX=0,this._config=this._getConfig(e),this._element=t,this._indicatorsElement=this._element.querySelector(ot),this._touchSupported="ontouchstart"in document.documentElement||0<navigator.maxTouchPoints,this._pointerEvent=Boolean(window.PointerEvent||window.MSPointerEvent),this._addEventListeners()}var t=r.prototype;return t.next=function(){this._isSliding||this._slide(W)},t.nextWhenVisible=function(){!document.hidden&&g(this._element).is(":visible")&&"hidden"!==g(this._element).css("visibility")&&this.next()},t.prev=function(){this._isSliding||this._slide(q)},t.pause=function(t){t||(this._isPaused=!0),this._element.querySelector(it)&&(_.triggerTransitionEnd(this._element),this.cycle(!0)),clearInterval(this._interval),this._interval=null},t.cycle=function(t){t||(this._isPaused=!1),this._interval&&(clearInterval(this._interval),this._interval=null),this._config.interval&&!this._isPaused&&(this._interval=setInterval((document.visibilityState?this.nextWhenVisible:this.next).bind(this),this._config.interval))},t.to=function(t){var e=this;this._activeElement=this._element.querySelector(tt);var n=this._getItemIndex(this._activeElement);if(!(t>this._items.length-1||t<0))if(this._isSliding)g(this._element).one(Q.SLID,function(){return e.to(t)});else{if(n===t)return this.pause(),void this.cycle();var i=n<t?W:q;this._slide(i,this._items[t])}},t.dispose=function(){g(this._element).off(H),g.removeData(this._element,j),this._items=null,this._config=null,this._element=null,this._interval=null,this._isPaused=null,this._isSliding=null,this._activeElement=null,this._indicatorsElement=null},t._getConfig=function(t){return t=l({},F,t),_.typeCheckConfig(L,t,U),t},t._handleSwipe=function(){var t=Math.abs(this.touchDeltaX);if(!(t<=40)){var e=t/this.touchDeltaX;0<e&&this.prev(),e<0&&this.next()}},t._addEventListeners=function(){var e=this;this._config.keyboard&&g(this._element).on(Q.KEYDOWN,function(t){return e._keydown(t)}),"hover"===this._config.pause&&g(this._element).on(Q.MOUSEENTER,function(t){return e.pause(t)}).on(Q.MOUSELEAVE,function(t){return e.cycle(t)}),this._config.touch&&this._addTouchEventListeners()},t._addTouchEventListeners=function(){var n=this;if(this._touchSupported){var e=function(t){n._pointerEvent&&at[t.originalEvent.pointerType.toUpperCase()]?n.touchStartX=t.originalEvent.clientX:n._pointerEvent||(n.touchStartX=t.originalEvent.touches[0].clientX)},i=function(t){n._pointerEvent&&at[t.originalEvent.pointerType.toUpperCase()]&&(n.touchDeltaX=t.originalEvent.clientX-n.touchStartX),n._handleSwipe(),"hover"===n._config.pause&&(n.pause(),n.touchTimeout&&clearTimeout(n.touchTimeout),n.touchTimeout=setTimeout(function(t){return n.cycle(t)},500+n._config.interval))};g(this._element.querySelectorAll(nt)).on(Q.DRAG_START,function(t){return t.preventDefault()}),this._pointerEvent?(g(this._element).on(Q.POINTERDOWN,function(t){return e(t)}),g(this._element).on(Q.POINTERUP,function(t){return i(t)}),this._element.classList.add(J)):(g(this._element).on(Q.TOUCHSTART,function(t){return e(t)}),g(this._element).on(Q.TOUCHMOVE,function(t){var e;(e=t).originalEvent.touches&&1<e.originalEvent.touches.length?n.touchDeltaX=0:n.touchDeltaX=e.originalEvent.touches[0].clientX-n.touchStartX}),g(this._element).on(Q.TOUCHEND,function(t){return i(t)}))}},t._keydown=function(t){if(!/input|textarea/i.test(t.target.tagName))switch(t.which){case 37:t.preventDefault(),this.prev();break;case 39:t.preventDefault(),this.next()}},t._getItemIndex=function(t){return this._items=t&&t.parentNode?[].slice.call(t.parentNode.querySelectorAll(et)):[],this._items.indexOf(t)},t._getItemByDirection=function(t,e){var n=t===W,i=t===q,o=this._getItemIndex(e),r=this._items.length-1;if((i&&0===o||n&&o===r)&&!this._config.wrap)return e;var s=(o+(t===q?-1:1))%this._items.length;return-1===s?this._items[this._items.length-1]:this._items[s]},t._triggerSlideEvent=function(t,e){var n=this._getItemIndex(t),i=this._getItemIndex(this._element.querySelector(tt)),o=g.Event(Q.SLIDE,{relatedTarget:t,direction:e,from:i,to:n});return g(this._element).trigger(o),o},t._setActiveIndicatorElement=function(t){if(this._indicatorsElement){var e=[].slice.call(this._indicatorsElement.querySelectorAll(Z));g(e).removeClass(V);var n=this._indicatorsElement.children[this._getItemIndex(t)];n&&g(n).addClass(V)}},t._slide=function(t,e){var n,i,o,r=this,s=this._element.querySelector(tt),a=this._getItemIndex(s),l=e||s&&this._getItemByDirection(t,s),c=this._getItemIndex(l),h=Boolean(this._interval);if(o=t===W?(n=X,i=$,M):(n=z,i=G,K),l&&g(l).hasClass(V))this._isSliding=!1;else if(!this._triggerSlideEvent(l,o).isDefaultPrevented()&&s&&l){this._isSliding=!0,h&&this.pause(),this._setActiveIndicatorElement(l);var u=g.Event(Q.SLID,{relatedTarget:l,direction:o,from:a,to:c});if(g(this._element).hasClass(Y)){g(l).addClass(i),_.reflow(l),g(s).addClass(n),g(l).addClass(n);var f=parseInt(l.getAttribute("data-interval"),10);this._config.interval=f?(this._config.defaultInterval=this._config.defaultInterval||this._config.interval,f):this._config.defaultInterval||this._config.interval;var d=_.getTransitionDurationFromElement(s);g(s).one(_.TRANSITION_END,function(){g(l).removeClass(n+" "+i).addClass(V),g(s).removeClass(V+" "+i+" "+n),r._isSliding=!1,setTimeout(function(){return g(r._element).trigger(u)},0)}).emulateTransitionEnd(d)}else g(s).removeClass(V),g(l).addClass(V),this._isSliding=!1,g(this._element).trigger(u);h&&this.cycle()}},r._jQueryInterface=function(i){return this.each(function(){var t=g(this).data(j),e=l({},F,g(this).data());"object"==typeof i&&(e=l({},e,i));var n="string"==typeof i?i:e.slide;if(t||(t=new r(this,e),g(this).data(j,t)),"number"==typeof i)t.to(i);else if("string"==typeof n){if("undefined"==typeof t[n])throw new TypeError('No method named "'+n+'"');t[n]()}else e.interval&&e.ride&&(t.pause(),t.cycle())})},r._dataApiClickHandler=function(t){var e=_.getSelectorFromElement(this);if(e){var n=g(e)[0];if(n&&g(n).hasClass(B)){var i=l({},g(n).data(),g(this).data()),o=this.getAttribute("data-slide-to");o&&(i.interval=!1),r._jQueryInterface.call(g(n),i),o&&g(n).data(j).to(o),t.preventDefault()}}},s(r,null,[{key:"VERSION",get:function(){return"4.3.1"}},{key:"Default",get:function(){return F}}]),r}();g(document).on(Q.CLICK_DATA_API,rt,lt._dataApiClickHandler),g(window).on(Q.LOAD_DATA_API,function(){for(var t=[].slice.call(document.querySelectorAll(st)),e=0,n=t.length;e<n;e++){var i=g(t[e]);lt._jQueryInterface.call(i,i.data())}}),g.fn[L]=lt._jQueryInterface,g.fn[L].Constructor=lt,g.fn[L].noConflict=function(){return g.fn[L]=x,lt._jQueryInterface};var ct="collapse",ht="bs.collapse",ut="."+ht,ft=g.fn[ct],dt={toggle:!0,parent:""},gt={toggle:"boolean",parent:"(string|element)"},_t={SHOW:"show"+ut,SHOWN:"shown"+ut,HIDE:"hide"+ut,HIDDEN:"hidden"+ut,CLICK_DATA_API:"click"+ut+".data-api"},mt="show",pt="collapse",vt="collapsing",yt="collapsed",Et="width",Ct="height",Tt=".show, .collapsing",St='[data-toggle="collapse"]',bt=function(){function a(e,t){this._isTransitioning=!1,this._element=e,this._config=this._getConfig(t),this._triggerArray=[].slice.call(document.querySelectorAll('[data-toggle="collapse"][href="#'+e.id+'"],[data-toggle="collapse"][data-target="#'+e.id+'"]'));for(var n=[].slice.call(document.querySelectorAll(St)),i=0,o=n.length;i<o;i++){var r=n[i],s=_.getSelectorFromElement(r),a=[].slice.call(document.querySelectorAll(s)).filter(function(t){return t===e});null!==s&&0<a.length&&(this._selector=s,this._triggerArray.push(r))}this._parent=this._config.parent?this._getParent():null,this._config.parent||this._addAriaAndCollapsedClass(this._element,this._triggerArray),this._config.toggle&&this.toggle()}var t=a.prototype;return t.toggle=function(){g(this._element).hasClass(mt)?this.hide():this.show()},t.show=function(){var t,e,n=this;if(!this._isTransitioning&&!g(this._element).hasClass(mt)&&(this._parent&&0===(t=[].slice.call(this._parent.querySelectorAll(Tt)).filter(function(t){return"string"==typeof n._config.parent?t.getAttribute("data-parent")===n._config.parent:t.classList.contains(pt)})).length&&(t=null),!(t&&(e=g(t).not(this._selector).data(ht))&&e._isTransitioning))){var i=g.Event(_t.SHOW);if(g(this._element).trigger(i),!i.isDefaultPrevented()){t&&(a._jQueryInterface.call(g(t).not(this._selector),"hide"),e||g(t).data(ht,null));var o=this._getDimension();g(this._element).removeClass(pt).addClass(vt),this._element.style[o]=0,this._triggerArray.length&&g(this._triggerArray).removeClass(yt).attr("aria-expanded",!0),this.setTransitioning(!0);var r="scroll"+(o[0].toUpperCase()+o.slice(1)),s=_.getTransitionDurationFromElement(this._element);g(this._element).one(_.TRANSITION_END,function(){g(n._element).removeClass(vt).addClass(pt).addClass(mt),n._element.style[o]="",n.setTransitioning(!1),g(n._element).trigger(_t.SHOWN)}).emulateTransitionEnd(s),this._element.style[o]=this._element[r]+"px"}}},t.hide=function(){var t=this;if(!this._isTransitioning&&g(this._element).hasClass(mt)){var e=g.Event(_t.HIDE);if(g(this._element).trigger(e),!e.isDefaultPrevented()){var n=this._getDimension();this._element.style[n]=this._element.getBoundingClientRect()[n]+"px",_.reflow(this._element),g(this._element).addClass(vt).removeClass(pt).removeClass(mt);var i=this._triggerArray.length;if(0<i)for(var o=0;o<i;o++){var r=this._triggerArray[o],s=_.getSelectorFromElement(r);if(null!==s)g([].slice.call(document.querySelectorAll(s))).hasClass(mt)||g(r).addClass(yt).attr("aria-expanded",!1)}this.setTransitioning(!0);this._element.style[n]="";var a=_.getTransitionDurationFromElement(this._element);g(this._element).one(_.TRANSITION_END,function(){t.setTransitioning(!1),g(t._element).removeClass(vt).addClass(pt).trigger(_t.HIDDEN)}).emulateTransitionEnd(a)}}},t.setTransitioning=function(t){this._isTransitioning=t},t.dispose=function(){g.removeData(this._element,ht),this._config=null,this._parent=null,this._element=null,this._triggerArray=null,this._isTransitioning=null},t._getConfig=function(t){return(t=l({},dt,t)).toggle=Boolean(t.toggle),_.typeCheckConfig(ct,t,gt),t},t._getDimension=function(){return g(this._element).hasClass(Et)?Et:Ct},t._getParent=function(){var t,n=this;_.isElement(this._config.parent)?(t=this._config.parent,"undefined"!=typeof this._config.parent.jquery&&(t=this._config.parent[0])):t=document.querySelector(this._config.parent);var e='[data-toggle="collapse"][data-parent="'+this._config.parent+'"]',i=[].slice.call(t.querySelectorAll(e));return g(i).each(function(t,e){n._addAriaAndCollapsedClass(a._getTargetFromElement(e),[e])}),t},t._addAriaAndCollapsedClass=function(t,e){var n=g(t).hasClass(mt);e.length&&g(e).toggleClass(yt,!n).attr("aria-expanded",n)},a._getTargetFromElement=function(t){var e=_.getSelectorFromElement(t);return e?document.querySelector(e):null},a._jQueryInterface=function(i){return this.each(function(){var t=g(this),e=t.data(ht),n=l({},dt,t.data(),"object"==typeof i&&i?i:{});if(!e&&n.toggle&&/show|hide/.test(i)&&(n.toggle=!1),e||(e=new a(this,n),t.data(ht,e)),"string"==typeof i){if("undefined"==typeof e[i])throw new TypeError('No method named "'+i+'"');e[i]()}})},s(a,null,[{key:"VERSION",get:function(){return"4.3.1"}},{key:"Default",get:function(){return dt}}]),a}();g(document).on(_t.CLICK_DATA_API,St,function(t){"A"===t.currentTarget.tagName&&t.preventDefault();var n=g(this),e=_.getSelectorFromElement(this),i=[].slice.call(document.querySelectorAll(e));g(i).each(function(){var t=g(this),e=t.data(ht)?"toggle":n.data();bt._jQueryInterface.call(t,e)})}),g.fn[ct]=bt._jQueryInterface,g.fn[ct].Constructor=bt,g.fn[ct].noConflict=function(){return g.fn[ct]=ft,bt._jQueryInterface};var It="dropdown",Dt="bs.dropdown",wt="."+Dt,At=".data-api",Nt=g.fn[It],Ot=new RegExp("38|40|27"),kt={HIDE:"hide"+wt,HIDDEN:"hidden"+wt,SHOW:"show"+wt,SHOWN:"shown"+wt,CLICK:"click"+wt,CLICK_DATA_API:"click"+wt+At,KEYDOWN_DATA_API:"keydown"+wt+At,KEYUP_DATA_API:"keyup"+wt+At},Pt="disabled",Lt="show",jt="dropup",Ht="dropright",Rt="dropleft",xt="dropdown-menu-right",Ft="position-static",Ut='[data-toggle="dropdown"]',Wt=".dropdown form",qt=".dropdown-menu",Mt=".navbar-nav",Kt=".dropdown-menu .dropdown-item:not(.disabled):not(:disabled)",Qt="top-start",Bt="top-end",Vt="bottom-start",Yt="bottom-end",zt="right-start",Xt="left-start",$t={offset:0,flip:!0,boundary:"scrollParent",reference:"toggle",display:"dynamic"},Gt={offset:"(number|string|function)",flip:"boolean",boundary:"(string|element)",reference:"(string|element)",display:"string"},Jt=function(){function c(t,e){this._element=t,this._popper=null,this._config=this._getConfig(e),this._menu=this._getMenuElement(),this._inNavbar=this._detectNavbar(),this._addEventListeners()}var t=c.prototype;return t.toggle=function(){if(!this._element.disabled&&!g(this._element).hasClass(Pt)){var t=c._getParentFromElement(this._element),e=g(this._menu).hasClass(Lt);if(c._clearMenus(),!e){var n={relatedTarget:this._element},i=g.Event(kt.SHOW,n);if(g(t).trigger(i),!i.isDefaultPrevented()){if(!this._inNavbar){if("undefined"==typeof u)throw new TypeError("Bootstrap's dropdowns require Popper.js (https://popper.js.org/)");var o=this._element;"parent"===this._config.reference?o=t:_.isElement(this._config.reference)&&(o=this._config.reference,"undefined"!=typeof this._config.reference.jquery&&(o=this._config.reference[0])),"scrollParent"!==this._config.boundary&&g(t).addClass(Ft),this._popper=new u(o,this._menu,this._getPopperConfig())}"ontouchstart"in document.documentElement&&0===g(t).closest(Mt).length&&g(document.body).children().on("mouseover",null,g.noop),this._element.focus(),this._element.setAttribute("aria-expanded",!0),g(this._menu).toggleClass(Lt),g(t).toggleClass(Lt).trigger(g.Event(kt.SHOWN,n))}}}},t.show=function(){if(!(this._element.disabled||g(this._element).hasClass(Pt)||g(this._menu).hasClass(Lt))){var t={relatedTarget:this._element},e=g.Event(kt.SHOW,t),n=c._getParentFromElement(this._element);g(n).trigger(e),e.isDefaultPrevented()||(g(this._menu).toggleClass(Lt),g(n).toggleClass(Lt).trigger(g.Event(kt.SHOWN,t)))}},t.hide=function(){if(!this._element.disabled&&!g(this._element).hasClass(Pt)&&g(this._menu).hasClass(Lt)){var t={relatedTarget:this._element},e=g.Event(kt.HIDE,t),n=c._getParentFromElement(this._element);g(n).trigger(e),e.isDefaultPrevented()||(g(this._menu).toggleClass(Lt),g(n).toggleClass(Lt).trigger(g.Event(kt.HIDDEN,t)))}},t.dispose=function(){g.removeData(this._element,Dt),g(this._element).off(wt),this._element=null,(this._menu=null)!==this._popper&&(this._popper.destroy(),this._popper=null)},t.update=function(){this._inNavbar=this._detectNavbar(),null!==this._popper&&this._popper.scheduleUpdate()},t._addEventListeners=function(){var e=this;g(this._element).on(kt.CLICK,function(t){t.preventDefault(),t.stopPropagation(),e.toggle()})},t._getConfig=function(t){return t=l({},this.constructor.Default,g(this._element).data(),t),_.typeCheckConfig(It,t,this.constructor.DefaultType),t},t._getMenuElement=function(){if(!this._menu){var t=c._getParentFromElement(this._element);t&&(this._menu=t.querySelector(qt))}return this._menu},t._getPlacement=function(){var t=g(this._element.parentNode),e=Vt;return t.hasClass(jt)?(e=Qt,g(this._menu).hasClass(xt)&&(e=Bt)):t.hasClass(Ht)?e=zt:t.hasClass(Rt)?e=Xt:g(this._menu).hasClass(xt)&&(e=Yt),e},t._detectNavbar=function(){return 0<g(this._element).closest(".navbar").length},t._getOffset=function(){var e=this,t={};return"function"==typeof this._config.offset?t.fn=function(t){return t.offsets=l({},t.offsets,e._config.offset(t.offsets,e._element)||{}),t}:t.offset=this._config.offset,t},t._getPopperConfig=function(){var t={placement:this._getPlacement(),modifiers:{offset:this._getOffset(),flip:{enabled:this._config.flip},preventOverflow:{boundariesElement:this._config.boundary}}};return"static"===this._config.display&&(t.modifiers.applyStyle={enabled:!1}),t},c._jQueryInterface=function(e){return this.each(function(){var t=g(this).data(Dt);if(t||(t=new c(this,"object"==typeof e?e:null),g(this).data(Dt,t)),"string"==typeof e){if("undefined"==typeof t[e])throw new TypeError('No method named "'+e+'"');t[e]()}})},c._clearMenus=function(t){if(!t||3!==t.which&&("keyup"!==t.type||9===t.which))for(var e=[].slice.call(document.querySelectorAll(Ut)),n=0,i=e.length;n<i;n++){var o=c._getParentFromElement(e[n]),r=g(e[n]).data(Dt),s={relatedTarget:e[n]};if(t&&"click"===t.type&&(s.clickEvent=t),r){var a=r._menu;if(g(o).hasClass(Lt)&&!(t&&("click"===t.type&&/input|textarea/i.test(t.target.tagName)||"keyup"===t.type&&9===t.which)&&g.contains(o,t.target))){var l=g.Event(kt.HIDE,s);g(o).trigger(l),l.isDefaultPrevented()||("ontouchstart"in document.documentElement&&g(document.body).children().off("mouseover",null,g.noop),e[n].setAttribute("aria-expanded","false"),g(a).removeClass(Lt),g(o).removeClass(Lt).trigger(g.Event(kt.HIDDEN,s)))}}}},c._getParentFromElement=function(t){var e,n=_.getSelectorFromElement(t);return n&&(e=document.querySelector(n)),e||t.parentNode},c._dataApiKeydownHandler=function(t){if((/input|textarea/i.test(t.target.tagName)?!(32===t.which||27!==t.which&&(40!==t.which&&38!==t.which||g(t.target).closest(qt).length)):Ot.test(t.which))&&(t.preventDefault(),t.stopPropagation(),!this.disabled&&!g(this).hasClass(Pt))){var e=c._getParentFromElement(this),n=g(e).hasClass(Lt);if(n&&(!n||27!==t.which&&32!==t.which)){var i=[].slice.call(e.querySelectorAll(Kt));if(0!==i.length){var o=i.indexOf(t.target);38===t.which&&0<o&&o--,40===t.which&&o<i.length-1&&o++,o<0&&(o=0),i[o].focus()}}else{if(27===t.which){var r=e.querySelector(Ut);g(r).trigger("focus")}g(this).trigger("click")}}},s(c,null,[{key:"VERSION",get:function(){return"4.3.1"}},{key:"Default",get:function(){return $t}},{key:"DefaultType",get:function(){return Gt}}]),c}();g(document).on(kt.KEYDOWN_DATA_API,Ut,Jt._dataApiKeydownHandler).on(kt.KEYDOWN_DATA_API,qt,Jt._dataApiKeydownHandler).on(kt.CLICK_DATA_API+" "+kt.KEYUP_DATA_API,Jt._clearMenus).on(kt.CLICK_DATA_API,Ut,function(t){t.preventDefault(),t.stopPropagation(),Jt._jQueryInterface.call(g(this),"toggle")}).on(kt.CLICK_DATA_API,Wt,function(t){t.stopPropagation()}),g.fn[It]=Jt._jQueryInterface,g.fn[It].Constructor=Jt,g.fn[It].noConflict=function(){return g.fn[It]=Nt,Jt._jQueryInterface};var Zt="modal",te="bs.modal",ee="."+te,ne=g.fn[Zt],ie={backdrop:!0,keyboard:!0,focus:!0,show:!0},oe={backdrop:"(boolean|string)",keyboard:"boolean",focus:"boolean",show:"boolean"},re={HIDE:"hide"+ee,HIDDEN:"hidden"+ee,SHOW:"show"+ee,SHOWN:"shown"+ee,FOCUSIN:"focusin"+ee,RESIZE:"resize"+ee,CLICK_DISMISS:"click.dismiss"+ee,KEYDOWN_DISMISS:"keydown.dismiss"+ee,MOUSEUP_DISMISS:"mouseup.dismiss"+ee,MOUSEDOWN_DISMISS:"mousedown.dismiss"+ee,CLICK_DATA_API:"click"+ee+".data-api"},se="modal-dialog-scrollable",ae="modal-scrollbar-measure",le="modal-backdrop",ce="modal-open",he="fade",ue="show",fe=".modal-dialog",de=".modal-body",ge='[data-toggle="modal"]',_e='[data-dismiss="modal"]',me=".fixed-top, .fixed-bottom, .is-fixed, .sticky-top",pe=".sticky-top",ve=function(){function o(t,e){this._config=this._getConfig(e),this._element=t,this._dialog=t.querySelector(fe),this._backdrop=null,this._isShown=!1,this._isBodyOverflowing=!1,this._ignoreBackdropClick=!1,this._isTransitioning=!1,this._scrollbarWidth=0}var t=o.prototype;return t.toggle=function(t){return this._isShown?this.hide():this.show(t)},t.show=function(t){var e=this;if(!this._isShown&&!this._isTransitioning){g(this._element).hasClass(he)&&(this._isTransitioning=!0);var n=g.Event(re.SHOW,{relatedTarget:t});g(this._element).trigger(n),this._isShown||n.isDefaultPrevented()||(this._isShown=!0,this._checkScrollbar(),this._setScrollbar(),this._adjustDialog(),this._setEscapeEvent(),this._setResizeEvent(),g(this._element).on(re.CLICK_DISMISS,_e,function(t){return e.hide(t)}),g(this._dialog).on(re.MOUSEDOWN_DISMISS,function(){g(e._element).one(re.MOUSEUP_DISMISS,function(t){g(t.target).is(e._element)&&(e._ignoreBackdropClick=!0)})}),this._showBackdrop(function(){return e._showElement(t)}))}},t.hide=function(t){var e=this;if(t&&t.preventDefault(),this._isShown&&!this._isTransitioning){var n=g.Event(re.HIDE);if(g(this._element).trigger(n),this._isShown&&!n.isDefaultPrevented()){this._isShown=!1;var i=g(this._element).hasClass(he);if(i&&(this._isTransitioning=!0),this._setEscapeEvent(),this._setResizeEvent(),g(document).off(re.FOCUSIN),g(this._element).removeClass(ue),g(this._element).off(re.CLICK_DISMISS),g(this._dialog).off(re.MOUSEDOWN_DISMISS),i){var o=_.getTransitionDurationFromElement(this._element);g(this._element).one(_.TRANSITION_END,function(t){return e._hideModal(t)}).emulateTransitionEnd(o)}else this._hideModal()}}},t.dispose=function(){[window,this._element,this._dialog].forEach(function(t){return g(t).off(ee)}),g(document).off(re.FOCUSIN),g.removeData(this._element,te),this._config=null,this._element=null,this._dialog=null,this._backdrop=null,this._isShown=null,this._isBodyOverflowing=null,this._ignoreBackdropClick=null,this._isTransitioning=null,this._scrollbarWidth=null},t.handleUpdate=function(){this._adjustDialog()},t._getConfig=function(t){return t=l({},ie,t),_.typeCheckConfig(Zt,t,oe),t},t._showElement=function(t){var e=this,n=g(this._element).hasClass(he);this._element.parentNode&&this._element.parentNode.nodeType===Node.ELEMENT_NODE||document.body.appendChild(this._element),this._element.style.display="block",this._element.removeAttribute("aria-hidden"),this._element.setAttribute("aria-modal",!0),g(this._dialog).hasClass(se)?this._dialog.querySelector(de).scrollTop=0:this._element.scrollTop=0,n&&_.reflow(this._element),g(this._element).addClass(ue),this._config.focus&&this._enforceFocus();var i=g.Event(re.SHOWN,{relatedTarget:t}),o=function(){e._config.focus&&e._element.focus(),e._isTransitioning=!1,g(e._element).trigger(i)};if(n){var r=_.getTransitionDurationFromElement(this._dialog);g(this._dialog).one(_.TRANSITION_END,o).emulateTransitionEnd(r)}else o()},t._enforceFocus=function(){var e=this;g(document).off(re.FOCUSIN).on(re.FOCUSIN,function(t){document!==t.target&&e._element!==t.target&&0===g(e._element).has(t.target).length&&e._element.focus()})},t._setEscapeEvent=function(){var e=this;this._isShown&&this._config.keyboard?g(this._element).on(re.KEYDOWN_DISMISS,function(t){27===t.which&&(t.preventDefault(),e.hide())}):this._isShown||g(this._element).off(re.KEYDOWN_DISMISS)},t._setResizeEvent=function(){var e=this;this._isShown?g(window).on(re.RESIZE,function(t){return e.handleUpdate(t)}):g(window).off(re.RESIZE)},t._hideModal=function(){var t=this;this._element.style.display="none",this._element.setAttribute("aria-hidden",!0),this._element.removeAttribute("aria-modal"),this._isTransitioning=!1,this._showBackdrop(function(){g(document.body).removeClass(ce),t._resetAdjustments(),t._resetScrollbar(),g(t._element).trigger(re.HIDDEN)})},t._removeBackdrop=function(){this._backdrop&&(g(this._backdrop).remove(),this._backdrop=null)},t._showBackdrop=function(t){var e=this,n=g(this._element).hasClass(he)?he:"";if(this._isShown&&this._config.backdrop){if(this._backdrop=document.createElement("div"),this._backdrop.className=le,n&&this._backdrop.classList.add(n),g(this._backdrop).appendTo(document.body),g(this._element).on(re.CLICK_DISMISS,function(t){e._ignoreBackdropClick?e._ignoreBackdropClick=!1:t.target===t.currentTarget&&("static"===e._config.backdrop?e._element.focus():e.hide())}),n&&_.reflow(this._backdrop),g(this._backdrop).addClass(ue),!t)return;if(!n)return void t();var i=_.getTransitionDurationFromElement(this._backdrop);g(this._backdrop).one(_.TRANSITION_END,t).emulateTransitionEnd(i)}else if(!this._isShown&&this._backdrop){g(this._backdrop).removeClass(ue);var o=function(){e._removeBackdrop(),t&&t()};if(g(this._element).hasClass(he)){var r=_.getTransitionDurationFromElement(this._backdrop);g(this._backdrop).one(_.TRANSITION_END,o).emulateTransitionEnd(r)}else o()}else t&&t()},t._adjustDialog=function(){var t=this._element.scrollHeight>document.documentElement.clientHeight;!this._isBodyOverflowing&&t&&(this._element.style.paddingLeft=this._scrollbarWidth+"px"),this._isBodyOverflowing&&!t&&(this._element.style.paddingRight=this._scrollbarWidth+"px")},t._resetAdjustments=function(){this._element.style.paddingLeft="",this._element.style.paddingRight=""},t._checkScrollbar=function(){var t=document.body.getBoundingClientRect();this._isBodyOverflowing=t.left+t.right<window.innerWidth,this._scrollbarWidth=this._getScrollbarWidth()},t._setScrollbar=function(){var o=this;if(this._isBodyOverflowing){var t=[].slice.call(document.querySelectorAll(me)),e=[].slice.call(document.querySelectorAll(pe));g(t).each(function(t,e){var n=e.style.paddingRight,i=g(e).css("padding-right");g(e).data("padding-right",n).css("padding-right",parseFloat(i)+o._scrollbarWidth+"px")}),g(e).each(function(t,e){var n=e.style.marginRight,i=g(e).css("margin-right");g(e).data("margin-right",n).css("margin-right",parseFloat(i)-o._scrollbarWidth+"px")});var n=document.body.style.paddingRight,i=g(document.body).css("padding-right");g(document.body).data("padding-right",n).css("padding-right",parseFloat(i)+this._scrollbarWidth+"px")}g(document.body).addClass(ce)},t._resetScrollbar=function(){var t=[].slice.call(document.querySelectorAll(me));g(t).each(function(t,e){var n=g(e).data("padding-right");g(e).removeData("padding-right"),e.style.paddingRight=n||""});var e=[].slice.call(document.querySelectorAll(""+pe));g(e).each(function(t,e){var n=g(e).data("margin-right");"undefined"!=typeof n&&g(e).css("margin-right",n).removeData("margin-right")});var n=g(document.body).data("padding-right");g(document.body).removeData("padding-right"),document.body.style.paddingRight=n||""},t._getScrollbarWidth=function(){var t=document.createElement("div");t.className=ae,document.body.appendChild(t);var e=t.getBoundingClientRect().width-t.clientWidth;return document.body.removeChild(t),e},o._jQueryInterface=function(n,i){return this.each(function(){var t=g(this).data(te),e=l({},ie,g(this).data(),"object"==typeof n&&n?n:{});if(t||(t=new o(this,e),g(this).data(te,t)),"string"==typeof n){if("undefined"==typeof t[n])throw new TypeError('No method named "'+n+'"');t[n](i)}else e.show&&t.show(i)})},s(o,null,[{key:"VERSION",get:function(){return"4.3.1"}},{key:"Default",get:function(){return ie}}]),o}();g(document).on(re.CLICK_DATA_API,ge,function(t){var e,n=this,i=_.getSelectorFromElement(this);i&&(e=document.querySelector(i));var o=g(e).data(te)?"toggle":l({},g(e).data(),g(this).data());"A"!==this.tagName&&"AREA"!==this.tagName||t.preventDefault();var r=g(e).one(re.SHOW,function(t){t.isDefaultPrevented()||r.one(re.HIDDEN,function(){g(n).is(":visible")&&n.focus()})});ve._jQueryInterface.call(g(e),o,this)}),g.fn[Zt]=ve._jQueryInterface,g.fn[Zt].Constructor=ve,g.fn[Zt].noConflict=function(){return g.fn[Zt]=ne,ve._jQueryInterface};var ye=["background","cite","href","itemtype","longdesc","poster","src","xlink:href"],Ee={"*":["class","dir","id","lang","role",/^aria-[\w-]*$/i],a:["target","href","title","rel"],area:[],b:[],br:[],col:[],code:[],div:[],em:[],hr:[],h1:[],h2:[],h3:[],h4:[],h5:[],h6:[],i:[],img:["src","alt","title","width","height"],li:[],ol:[],p:[],pre:[],s:[],small:[],span:[],sub:[],sup:[],strong:[],u:[],ul:[]},Ce=/^(?:(?:https?|mailto|ftp|tel|file):|[^&:/?#]*(?:[/?#]|$))/gi,Te=/^data:(?:image\/(?:bmp|gif|jpeg|jpg|png|tiff|webp)|video\/(?:mpeg|mp4|ogg|webm)|audio\/(?:mp3|oga|ogg|opus));base64,[a-z0-9+/]+=*$/i;function Se(t,s,e){if(0===t.length)return t;if(e&&"function"==typeof e)return e(t);for(var n=(new window.DOMParser).parseFromString(t,"text/html"),a=Object.keys(s),l=[].slice.call(n.body.querySelectorAll("*")),i=function(t,e){var n=l[t],i=n.nodeName.toLowerCase();if(-1===a.indexOf(n.nodeName.toLowerCase()))return n.parentNode.removeChild(n),"continue";var o=[].slice.call(n.attributes),r=[].concat(s["*"]||[],s[i]||[]);o.forEach(function(t){(function(t,e){var n=t.nodeName.toLowerCase();if(-1!==e.indexOf(n))return-1===ye.indexOf(n)||Boolean(t.nodeValue.match(Ce)||t.nodeValue.match(Te));for(var i=e.filter(function(t){return t instanceof RegExp}),o=0,r=i.length;o<r;o++)if(n.match(i[o]))return!0;return!1})(t,r)||n.removeAttribute(t.nodeName)})},o=0,r=l.length;o<r;o++)i(o);return n.body.innerHTML}var be="tooltip",Ie="bs.tooltip",De="."+Ie,we=g.fn[be],Ae="bs-tooltip",Ne=new RegExp("(^|\\s)"+Ae+"\\S+","g"),Oe=["sanitize","whiteList","sanitizeFn"],ke={animation:"boolean",template:"string",title:"(string|element|function)",trigger:"string",delay:"(number|object)",html:"boolean",selector:"(string|boolean)",placement:"(string|function)",offset:"(number|string|function)",container:"(string|element|boolean)",fallbackPlacement:"(string|array)",boundary:"(string|element)",sanitize:"boolean",sanitizeFn:"(null|function)",whiteList:"object"},Pe={AUTO:"auto",TOP:"top",RIGHT:"right",BOTTOM:"bottom",LEFT:"left"},Le={animation:!0,template:'<div class="tooltip" role="tooltip"><div class="arrow"></div><div class="tooltip-inner"></div></div>',trigger:"hover focus",title:"",delay:0,html:!1,selector:!1,placement:"top",offset:0,container:!1,fallbackPlacement:"flip",boundary:"scrollParent",sanitize:!0,sanitizeFn:null,whiteList:Ee},je="show",He="out",Re={HIDE:"hide"+De,HIDDEN:"hidden"+De,SHOW:"show"+De,SHOWN:"shown"+De,INSERTED:"inserted"+De,CLICK:"click"+De,FOCUSIN:"focusin"+De,FOCUSOUT:"focusout"+De,MOUSEENTER:"mouseenter"+De,MOUSELEAVE:"mouseleave"+De},xe="fade",Fe="show",Ue=".tooltip-inner",We=".arrow",qe="hover",Me="focus",Ke="click",Qe="manual",Be=function(){function i(t,e){if("undefined"==typeof u)throw new TypeError("Bootstrap's tooltips require Popper.js (https://popper.js.org/)");this._isEnabled=!0,this._timeout=0,this._hoverState="",this._activeTrigger={},this._popper=null,this.element=t,this.config=this._getConfig(e),this.tip=null,this._setListeners()}var t=i.prototype;return t.enable=function(){this._isEnabled=!0},t.disable=function(){this._isEnabled=!1},t.toggleEnabled=function(){this._isEnabled=!this._isEnabled},t.toggle=function(t){if(this._isEnabled)if(t){var e=this.constructor.DATA_KEY,n=g(t.currentTarget).data(e);n||(n=new this.constructor(t.currentTarget,this._getDelegateConfig()),g(t.currentTarget).data(e,n)),n._activeTrigger.click=!n._activeTrigger.click,n._isWithActiveTrigger()?n._enter(null,n):n._leave(null,n)}else{if(g(this.getTipElement()).hasClass(Fe))return void this._leave(null,this);this._enter(null,this)}},t.dispose=function(){clearTimeout(this._timeout),g.removeData(this.element,this.constructor.DATA_KEY),g(this.element).off(this.constructor.EVENT_KEY),g(this.element).closest(".modal").off("hide.bs.modal"),this.tip&&g(this.tip).remove(),this._isEnabled=null,this._timeout=null,this._hoverState=null,(this._activeTrigger=null)!==this._popper&&this._popper.destroy(),this._popper=null,this.element=null,this.config=null,this.tip=null},t.show=function(){var e=this;if("none"===g(this.element).css("display"))throw new Error("Please use show on visible elements");var t=g.Event(this.constructor.Event.SHOW);if(this.isWithContent()&&this._isEnabled){g(this.element).trigger(t);var n=_.findShadowRoot(this.element),i=g.contains(null!==n?n:this.element.ownerDocument.documentElement,this.element);if(t.isDefaultPrevented()||!i)return;var o=this.getTipElement(),r=_.getUID(this.constructor.NAME);o.setAttribute("id",r),this.element.setAttribute("aria-describedby",r),this.setContent(),this.config.animation&&g(o).addClass(xe);var s="function"==typeof this.config.placement?this.config.placement.call(this,o,this.element):this.config.placement,a=this._getAttachment(s);this.addAttachmentClass(a);var l=this._getContainer();g(o).data(this.constructor.DATA_KEY,this),g.contains(this.element.ownerDocument.documentElement,this.tip)||g(o).appendTo(l),g(this.element).trigger(this.constructor.Event.INSERTED),this._popper=new u(this.element,o,{placement:a,modifiers:{offset:this._getOffset(),flip:{behavior:this.config.fallbackPlacement},arrow:{element:We},preventOverflow:{boundariesElement:this.config.boundary}},onCreate:function(t){t.originalPlacement!==t.placement&&e._handlePopperPlacementChange(t)},onUpdate:function(t){return e._handlePopperPlacementChange(t)}}),g(o).addClass(Fe),"ontouchstart"in document.documentElement&&g(document.body).children().on("mouseover",null,g.noop);var c=function(){e.config.animation&&e._fixTransition();var t=e._hoverState;e._hoverState=null,g(e.element).trigger(e.constructor.Event.SHOWN),t===He&&e._leave(null,e)};if(g(this.tip).hasClass(xe)){var h=_.getTransitionDurationFromElement(this.tip);g(this.tip).one(_.TRANSITION_END,c).emulateTransitionEnd(h)}else c()}},t.hide=function(t){var e=this,n=this.getTipElement(),i=g.Event(this.constructor.Event.HIDE),o=function(){e._hoverState!==je&&n.parentNode&&n.parentNode.removeChild(n),e._cleanTipClass(),e.element.removeAttribute("aria-describedby"),g(e.element).trigger(e.constructor.Event.HIDDEN),null!==e._popper&&e._popper.destroy(),t&&t()};if(g(this.element).trigger(i),!i.isDefaultPrevented()){if(g(n).removeClass(Fe),"ontouchstart"in document.documentElement&&g(document.body).children().off("mouseover",null,g.noop),this._activeTrigger[Ke]=!1,this._activeTrigger[Me]=!1,this._activeTrigger[qe]=!1,g(this.tip).hasClass(xe)){var r=_.getTransitionDurationFromElement(n);g(n).one(_.TRANSITION_END,o).emulateTransitionEnd(r)}else o();this._hoverState=""}},t.update=function(){null!==this._popper&&this._popper.scheduleUpdate()},t.isWithContent=function(){return Boolean(this.getTitle())},t.addAttachmentClass=function(t){g(this.getTipElement()).addClass(Ae+"-"+t)},t.getTipElement=function(){return this.tip=this.tip||g(this.config.template)[0],this.tip},t.setContent=function(){var t=this.getTipElement();this.setElementContent(g(t.querySelectorAll(Ue)),this.getTitle()),g(t).removeClass(xe+" "+Fe)},t.setElementContent=function(t,e){"object"!=typeof e||!e.nodeType&&!e.jquery?this.config.html?(this.config.sanitize&&(e=Se(e,this.config.whiteList,this.config.sanitizeFn)),t.html(e)):t.text(e):this.config.html?g(e).parent().is(t)||t.empty().append(e):t.text(g(e).text())},t.getTitle=function(){var t=this.element.getAttribute("data-original-title");return t||(t="function"==typeof this.config.title?this.config.title.call(this.element):this.config.title),t},t._getOffset=function(){var e=this,t={};return"function"==typeof this.config.offset?t.fn=function(t){return t.offsets=l({},t.offsets,e.config.offset(t.offsets,e.element)||{}),t}:t.offset=this.config.offset,t},t._getContainer=function(){return!1===this.config.container?document.body:_.isElement(this.config.container)?g(this.config.container):g(document).find(this.config.container)},t._getAttachment=function(t){return Pe[t.toUpperCase()]},t._setListeners=function(){var i=this;this.config.trigger.split(" ").forEach(function(t){if("click"===t)g(i.element).on(i.constructor.Event.CLICK,i.config.selector,function(t){return i.toggle(t)});else if(t!==Qe){var e=t===qe?i.constructor.Event.MOUSEENTER:i.constructor.Event.FOCUSIN,n=t===qe?i.constructor.Event.MOUSELEAVE:i.constructor.Event.FOCUSOUT;g(i.element).on(e,i.config.selector,function(t){return i._enter(t)}).on(n,i.config.selector,function(t){return i._leave(t)})}}),g(this.element).closest(".modal").on("hide.bs.modal",function(){i.element&&i.hide()}),this.config.selector?this.config=l({},this.config,{trigger:"manual",selector:""}):this._fixTitle()},t._fixTitle=function(){var t=typeof this.element.getAttribute("data-original-title");(this.element.getAttribute("title")||"string"!==t)&&(this.element.setAttribute("data-original-title",this.element.getAttribute("title")||""),this.element.setAttribute("title",""))},t._enter=function(t,e){var n=this.constructor.DATA_KEY;(e=e||g(t.currentTarget).data(n))||(e=new this.constructor(t.currentTarget,this._getDelegateConfig()),g(t.currentTarget).data(n,e)),t&&(e._activeTrigger["focusin"===t.type?Me:qe]=!0),g(e.getTipElement()).hasClass(Fe)||e._hoverState===je?e._hoverState=je:(clearTimeout(e._timeout),e._hoverState=je,e.config.delay&&e.config.delay.show?e._timeout=setTimeout(function(){e._hoverState===je&&e.show()},e.config.delay.show):e.show())},t._leave=function(t,e){var n=this.constructor.DATA_KEY;(e=e||g(t.currentTarget).data(n))||(e=new this.constructor(t.currentTarget,this._getDelegateConfig()),g(t.currentTarget).data(n,e)),t&&(e._activeTrigger["focusout"===t.type?Me:qe]=!1),e._isWithActiveTrigger()||(clearTimeout(e._timeout),e._hoverState=He,e.config.delay&&e.config.delay.hide?e._timeout=setTimeout(function(){e._hoverState===He&&e.hide()},e.config.delay.hide):e.hide())},t._isWithActiveTrigger=function(){for(var t in this._activeTrigger)if(this._activeTrigger[t])return!0;return!1},t._getConfig=function(t){var e=g(this.element).data();return Object.keys(e).forEach(function(t){-1!==Oe.indexOf(t)&&delete e[t]}),"number"==typeof(t=l({},this.constructor.Default,e,"object"==typeof t&&t?t:{})).delay&&(t.delay={show:t.delay,hide:t.delay}),"number"==typeof t.title&&(t.title=t.title.toString()),"number"==typeof t.content&&(t.content=t.content.toString()),_.typeCheckConfig(be,t,this.constructor.DefaultType),t.sanitize&&(t.template=Se(t.template,t.whiteList,t.sanitizeFn)),t},t._getDelegateConfig=function(){var t={};if(this.config)for(var e in this.config)this.constructor.Default[e]!==this.config[e]&&(t[e]=this.config[e]);return t},t._cleanTipClass=function(){var t=g(this.getTipElement()),e=t.attr("class").match(Ne);null!==e&&e.length&&t.removeClass(e.join(""))},t._handlePopperPlacementChange=function(t){var e=t.instance;this.tip=e.popper,this._cleanTipClass(),this.addAttachmentClass(this._getAttachment(t.placement))},t._fixTransition=function(){var t=this.getTipElement(),e=this.config.animation;null===t.getAttribute("x-placement")&&(g(t).removeClass(xe),this.config.animation=!1,this.hide(),this.show(),this.config.animation=e)},i._jQueryInterface=function(n){return this.each(function(){var t=g(this).data(Ie),e="object"==typeof n&&n;if((t||!/dispose|hide/.test(n))&&(t||(t=new i(this,e),g(this).data(Ie,t)),"string"==typeof n)){if("undefined"==typeof t[n])throw new TypeError('No method named "'+n+'"');t[n]()}})},s(i,null,[{key:"VERSION",get:function(){return"4.3.1"}},{key:"Default",get:function(){return Le}},{key:"NAME",get:function(){return be}},{key:"DATA_KEY",get:function(){return Ie}},{key:"Event",get:function(){return Re}},{key:"EVENT_KEY",get:function(){return De}},{key:"DefaultType",get:function(){return ke}}]),i}();g.fn[be]=Be._jQueryInterface,g.fn[be].Constructor=Be,g.fn[be].noConflict=function(){return g.fn[be]=we,Be._jQueryInterface};var Ve="popover",Ye="bs.popover",ze="."+Ye,Xe=g.fn[Ve],$e="bs-popover",Ge=new RegExp("(^|\\s)"+$e+"\\S+","g"),Je=l({},Be.Default,{placement:"right",trigger:"click",content:"",template:'<div class="popover" role="tooltip"><div class="arrow"></div><h3 class="popover-header"></h3><div class="popover-body"></div></div>'}),Ze=l({},Be.DefaultType,{content:"(string|element|function)"}),tn="fade",en="show",nn=".popover-header",on=".popover-body",rn={HIDE:"hide"+ze,HIDDEN:"hidden"+ze,SHOW:"show"+ze,SHOWN:"shown"+ze,INSERTED:"inserted"+ze,CLICK:"click"+ze,FOCUSIN:"focusin"+ze,FOCUSOUT:"focusout"+ze,MOUSEENTER:"mouseenter"+ze,MOUSELEAVE:"mouseleave"+ze},sn=function(t){var e,n;function i(){return t.apply(this,arguments)||this}n=t,(e=i).prototype=Object.create(n.prototype),(e.prototype.constructor=e).__proto__=n;var o=i.prototype;return o.isWithContent=function(){return this.getTitle()||this._getContent()},o.addAttachmentClass=function(t){g(this.getTipElement()).addClass($e+"-"+t)},o.getTipElement=function(){return this.tip=this.tip||g(this.config.template)[0],this.tip},o.setContent=function(){var t=g(this.getTipElement());this.setElementContent(t.find(nn),this.getTitle());var e=this._getContent();"function"==typeof e&&(e=e.call(this.element)),this.setElementContent(t.find(on),e),t.removeClass(tn+" "+en)},o._getContent=function(){return this.element.getAttribute("data-content")||this.config.content},o._cleanTipClass=function(){var t=g(this.getTipElement()),e=t.attr("class").match(Ge);null!==e&&0<e.length&&t.removeClass(e.join(""))},i._jQueryInterface=function(n){return this.each(function(){var t=g(this).data(Ye),e="object"==typeof n?n:null;if((t||!/dispose|hide/.test(n))&&(t||(t=new i(this,e),g(this).data(Ye,t)),"string"==typeof n)){if("undefined"==typeof t[n])throw new TypeError('No method named "'+n+'"');t[n]()}})},s(i,null,[{key:"VERSION",get:function(){return"4.3.1"}},{key:"Default",get:function(){return Je}},{key:"NAME",get:function(){return Ve}},{key:"DATA_KEY",get:function(){return Ye}},{key:"Event",get:function(){return rn}},{key:"EVENT_KEY",get:function(){return ze}},{key:"DefaultType",get:function(){return Ze}}]),i}(Be);g.fn[Ve]=sn._jQueryInterface,g.fn[Ve].Constructor=sn,g.fn[Ve].noConflict=function(){return g.fn[Ve]=Xe,sn._jQueryInterface};var an="scrollspy",ln="bs.scrollspy",cn="."+ln,hn=g.fn[an],un={offset:10,method:"auto",target:""},fn={offset:"number",method:"string",target:"(string|element)"},dn={ACTIVATE:"activate"+cn,SCROLL:"scroll"+cn,LOAD_DATA_API:"load"+cn+".data-api"},gn="dropdown-item",_n="active",mn='[data-spy="scroll"]',pn=".nav, .list-group",vn=".nav-link",yn=".nav-item",En=".list-group-item",Cn=".dropdown",Tn=".dropdown-item",Sn=".dropdown-toggle",bn="offset",In="position",Dn=function(){function n(t,e){var n=this;this._element=t,this._scrollElement="BODY"===t.tagName?window:t,this._config=this._getConfig(e),this._selector=this._config.target+" "+vn+","+this._config.target+" "+En+","+this._config.target+" "+Tn,this._offsets=[],this._targets=[],this._activeTarget=null,this._scrollHeight=0,g(this._scrollElement).on(dn.SCROLL,function(t){return n._process(t)}),this.refresh(),this._process()}var t=n.prototype;return t.refresh=function(){var e=this,t=this._scrollElement===this._scrollElement.window?bn:In,o="auto"===this._config.method?t:this._config.method,r=o===In?this._getScrollTop():0;this._offsets=[],this._targets=[],this._scrollHeight=this._getScrollHeight(),[].slice.call(document.querySelectorAll(this._selector)).map(function(t){var e,n=_.getSelectorFromElement(t);if(n&&(e=document.querySelector(n)),e){var i=e.getBoundingClientRect();if(i.width||i.height)return[g(e)[o]().top+r,n]}return null}).filter(function(t){return t}).sort(function(t,e){return t[0]-e[0]}).forEach(function(t){e._offsets.push(t[0]),e._targets.push(t[1])})},t.dispose=function(){g.removeData(this._element,ln),g(this._scrollElement).off(cn),this._element=null,this._scrollElement=null,this._config=null,this._selector=null,this._offsets=null,this._targets=null,this._activeTarget=null,this._scrollHeight=null},t._getConfig=function(t){if("string"!=typeof(t=l({},un,"object"==typeof t&&t?t:{})).target){var e=g(t.target).attr("id");e||(e=_.getUID(an),g(t.target).attr("id",e)),t.target="#"+e}return _.typeCheckConfig(an,t,fn),t},t._getScrollTop=function(){return this._scrollElement===window?this._scrollElement.pageYOffset:this._scrollElement.scrollTop},t._getScrollHeight=function(){return this._scrollElement.scrollHeight||Math.max(document.body.scrollHeight,document.documentElement.scrollHeight)},t._getOffsetHeight=function(){return this._scrollElement===window?window.innerHeight:this._scrollElement.getBoundingClientRect().height},t._process=function(){var t=this._getScrollTop()+this._config.offset,e=this._getScrollHeight(),n=this._config.offset+e-this._getOffsetHeight();if(this._scrollHeight!==e&&this.refresh(),n<=t){var i=this._targets[this._targets.length-1];this._activeTarget!==i&&this._activate(i)}else{if(this._activeTarget&&t<this._offsets[0]&&0<this._offsets[0])return this._activeTarget=null,void this._clear();for(var o=this._offsets.length;o--;){this._activeTarget!==this._targets[o]&&t>=this._offsets[o]&&("undefined"==typeof this._offsets[o+1]||t<this._offsets[o+1])&&this._activate(this._targets[o])}}},t._activate=function(e){this._activeTarget=e,this._clear();var t=this._selector.split(",").map(function(t){return t+'[data-target="'+e+'"],'+t+'[href="'+e+'"]'}),n=g([].slice.call(document.querySelectorAll(t.join(","))));n.hasClass(gn)?(n.closest(Cn).find(Sn).addClass(_n),n.addClass(_n)):(n.addClass(_n),n.parents(pn).prev(vn+", "+En).addClass(_n),n.parents(pn).prev(yn).children(vn).addClass(_n)),g(this._scrollElement).trigger(dn.ACTIVATE,{relatedTarget:e})},t._clear=function(){[].slice.call(document.querySelectorAll(this._selector)).filter(function(t){return t.classList.contains(_n)}).forEach(function(t){return t.classList.remove(_n)})},n._jQueryInterface=function(e){return this.each(function(){var t=g(this).data(ln);if(t||(t=new n(this,"object"==typeof e&&e),g(this).data(ln,t)),"string"==typeof e){if("undefined"==typeof t[e])throw new TypeError('No method named "'+e+'"');t[e]()}})},s(n,null,[{key:"VERSION",get:function(){return"4.3.1"}},{key:"Default",get:function(){return un}}]),n}();g(window).on(dn.LOAD_DATA_API,function(){for(var t=[].slice.call(document.querySelectorAll(mn)),e=t.length;e--;){var n=g(t[e]);Dn._jQueryInterface.call(n,n.data())}}),g.fn[an]=Dn._jQueryInterface,g.fn[an].Constructor=Dn,g.fn[an].noConflict=function(){return g.fn[an]=hn,Dn._jQueryInterface};var wn="bs.tab",An="."+wn,Nn=g.fn.tab,On={HIDE:"hide"+An,HIDDEN:"hidden"+An,SHOW:"show"+An,SHOWN:"shown"+An,CLICK_DATA_API:"click"+An+".data-api"},kn="dropdown-menu",Pn="active",Ln="disabled",jn="fade",Hn="show",Rn=".dropdown",xn=".nav, .list-group",Fn=".active",Un="> li > .active",Wn='[data-toggle="tab"], [data-toggle="pill"], [data-toggle="list"]',qn=".dropdown-toggle",Mn="> .dropdown-menu .active",Kn=function(){function i(t){this._element=t}var t=i.prototype;return t.show=function(){var n=this;if(!(this._element.parentNode&&this._element.parentNode.nodeType===Node.ELEMENT_NODE&&g(this._element).hasClass(Pn)||g(this._element).hasClass(Ln))){var t,i,e=g(this._element).closest(xn)[0],o=_.getSelectorFromElement(this._element);if(e){var r="UL"===e.nodeName||"OL"===e.nodeName?Un:Fn;i=(i=g.makeArray(g(e).find(r)))[i.length-1]}var s=g.Event(On.HIDE,{relatedTarget:this._element}),a=g.Event(On.SHOW,{relatedTarget:i});if(i&&g(i).trigger(s),g(this._element).trigger(a),!a.isDefaultPrevented()&&!s.isDefaultPrevented()){o&&(t=document.querySelector(o)),this._activate(this._element,e);var l=function(){var t=g.Event(On.HIDDEN,{relatedTarget:n._element}),e=g.Event(On.SHOWN,{relatedTarget:i});g(i).trigger(t),g(n._element).trigger(e)};t?this._activate(t,t.parentNode,l):l()}}},t.dispose=function(){g.removeData(this._element,wn),this._element=null},t._activate=function(t,e,n){var i=this,o=(!e||"UL"!==e.nodeName&&"OL"!==e.nodeName?g(e).children(Fn):g(e).find(Un))[0],r=n&&o&&g(o).hasClass(jn),s=function(){return i._transitionComplete(t,o,n)};if(o&&r){var a=_.getTransitionDurationFromElement(o);g(o).removeClass(Hn).one(_.TRANSITION_END,s).emulateTransitionEnd(a)}else s()},t._transitionComplete=function(t,e,n){if(e){g(e).removeClass(Pn);var i=g(e.parentNode).find(Mn)[0];i&&g(i).removeClass(Pn),"tab"===e.getAttribute("role")&&e.setAttribute("aria-selected",!1)}if(g(t).addClass(Pn),"tab"===t.getAttribute("role")&&t.setAttribute("aria-selected",!0),_.reflow(t),t.classList.contains(jn)&&t.classList.add(Hn),t.parentNode&&g(t.parentNode).hasClass(kn)){var o=g(t).closest(Rn)[0];if(o){var r=[].slice.call(o.querySelectorAll(qn));g(r).addClass(Pn)}t.setAttribute("aria-expanded",!0)}n&&n()},i._jQueryInterface=function(n){return this.each(function(){var t=g(this),e=t.data(wn);if(e||(e=new i(this),t.data(wn,e)),"string"==typeof n){if("undefined"==typeof e[n])throw new TypeError('No method named "'+n+'"');e[n]()}})},s(i,null,[{key:"VERSION",get:function(){return"4.3.1"}}]),i}();g(document).on(On.CLICK_DATA_API,Wn,function(t){t.preventDefault(),Kn._jQueryInterface.call(g(this),"show")}),g.fn.tab=Kn._jQueryInterface,g.fn.tab.Constructor=Kn,g.fn.tab.noConflict=function(){return g.fn.tab=Nn,Kn._jQueryInterface};var Qn="toast",Bn="bs.toast",Vn="."+Bn,Yn=g.fn[Qn],zn={CLICK_DISMISS:"click.dismiss"+Vn,HIDE:"hide"+Vn,HIDDEN:"hidden"+Vn,SHOW:"show"+Vn,SHOWN:"shown"+Vn},Xn="fade",$n="hide",Gn="show",Jn="showing",Zn={animation:"boolean",autohide:"boolean",delay:"number"},ti={animation:!0,autohide:!0,delay:500},ei='[data-dismiss="toast"]',ni=function(){function i(t,e){this._element=t,this._config=this._getConfig(e),this._timeout=null,this._setListeners()}var t=i.prototype;return t.show=function(){var t=this;g(this._element).trigger(zn.SHOW),this._config.animation&&this._element.classList.add(Xn);var e=function(){t._element.classList.remove(Jn),t._element.classList.add(Gn),g(t._element).trigger(zn.SHOWN),t._config.autohide&&t.hide()};if(this._element.classList.remove($n),this._element.classList.add(Jn),this._config.animation){var n=_.getTransitionDurationFromElement(this._element);g(this._element).one(_.TRANSITION_END,e).emulateTransitionEnd(n)}else e()},t.hide=function(t){var e=this;this._element.classList.contains(Gn)&&(g(this._element).trigger(zn.HIDE),t?this._close():this._timeout=setTimeout(function(){e._close()},this._config.delay))},t.dispose=function(){clearTimeout(this._timeout),this._timeout=null,this._element.classList.contains(Gn)&&this._element.classList.remove(Gn),g(this._element).off(zn.CLICK_DISMISS),g.removeData(this._element,Bn),this._element=null,this._config=null},t._getConfig=function(t){return t=l({},ti,g(this._element).data(),"object"==typeof t&&t?t:{}),_.typeCheckConfig(Qn,t,this.constructor.DefaultType),t},t._setListeners=function(){var t=this;g(this._element).on(zn.CLICK_DISMISS,ei,function(){return t.hide(!0)})},t._close=function(){var t=this,e=function(){t._element.classList.add($n),g(t._element).trigger(zn.HIDDEN)};if(this._element.classList.remove(Gn),this._config.animation){var n=_.getTransitionDurationFromElement(this._element);g(this._element).one(_.TRANSITION_END,e).emulateTransitionEnd(n)}else e()},i._jQueryInterface=function(n){return this.each(function(){var t=g(this),e=t.data(Bn);if(e||(e=new i(this,"object"==typeof n&&n),t.data(Bn,e)),"string"==typeof n){if("undefined"==typeof e[n])throw new TypeError('No method named "'+n+'"');e[n](this)}})},s(i,null,[{key:"VERSION",get:function(){return"4.3.1"}},{key:"DefaultType",get:function(){return Zn}},{key:"Default",get:function(){return ti}}]),i}();g.fn[Qn]=ni._jQueryInterface,g.fn[Qn].Constructor=ni,g.fn[Qn].noConflict=function(){return g.fn[Qn]=Yn,ni._jQueryInterface},function(){if("undefined"==typeof g)throw new TypeError("Bootstrap's JavaScript requires jQuery. jQuery must be included before Bootstrap's JavaScript.");var t=g.fn.jquery.split(" ")[0].split(".");if(t[0]<2&&t[1]<9||1===t[0]&&9===t[1]&&t[2]<1||4<=t[0])throw new Error("Bootstrap's JavaScript requires at least jQuery v1.9.1 but less than v4.0.0")}(),t.Util=_,t.Alert=p,t.Button=P,t.Carousel=lt,t.Collapse=bt,t.Dropdown=Jt,t.Modal=ve,t.Popover=sn,t.Scrollspy=Dn,t.Tab=Kn,t.Toast=ni,t.Tooltip=Be,Object.defineProperty(t,"__esModule",{value:!0})});
  22875. //# sourceMappingURL=bootstrap.min.js.map <tr>
  22876. <td class="{{lines_level}}">{{icon}}{{name}}</td>
  22877. <td class="{{lines_level}} big">{{lines_bar}}</td>
  22878. <td class="{{lines_level}} small"><div align="right">{{lines_executed_percent}}</div></td>
  22879. <td class="{{lines_level}} small"><div align="right">{{lines_number}}</div></td>
  22880. <td class="{{methods_level}} big">{{methods_bar}}</td>
  22881. <td class="{{methods_level}} small"><div align="right">{{methods_tested_percent}}</div></td>
  22882. <td class="{{methods_level}} small"><div align="right">{{methods_number}}</div></td>
  22883. <td class="{{classes_level}} big">{{classes_bar}}</td>
  22884. <td class="{{classes_level}} small"><div align="right">{{classes_tested_percent}}</div></td>
  22885. <td class="{{classes_level}} small"><div align="right">{{classes_number}}</div></td>
  22886. </tr>
  22887. <div class="progress">
  22888. <div class="progress-bar bg-{{level}}" role="progressbar" aria-valuenow="{{percent}}" aria-valuemin="0" aria-valuemax="100" style="width: {{percent}}%">
  22889. <span class="sr-only">{{percent}}% covered ({{level}})</span>
  22890. </div>
  22891. </div>
  22892. <tr>
  22893. <td class="{{methods_level}}" colspan="4">{{name}}</td>
  22894. <td class="{{methods_level}} big">{{methods_bar}}</td>
  22895. <td class="{{methods_level}} small"><div align="right">{{methods_tested_percent}}</div></td>
  22896. <td class="{{methods_level}} small"><div align="right">{{methods_number}}</div></td>
  22897. <td class="{{methods_level}} small">{{crap}}</td>
  22898. <td class="{{lines_level}} big">{{lines_bar}}</td>
  22899. <td class="{{lines_level}} small"><div align="right">{{lines_executed_percent}}</div></td>
  22900. <td class="{{lines_level}} small"><div align="right">{{lines_number}}</div></td>
  22901. </tr>
  22902. /*!
  22903. * Bootstrap v4.3.1 (https://getbootstrap.com/)
  22904. * Copyright 2011-2019 The Bootstrap Authors
  22905. * Copyright 2011-2019 Twitter, Inc.
  22906. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
  22907. */:root{--blue:#007bff;--indigo:#6610f2;--purple:#6f42c1;--pink:#e83e8c;--red:#dc3545;--orange:#fd7e14;--yellow:#ffc107;--green:#28a745;--teal:#20c997;--cyan:#17a2b8;--white:#fff;--gray:#6c757d;--gray-dark:#343a40;--primary:#007bff;--secondary:#6c757d;--success:#28a745;--info:#17a2b8;--warning:#ffc107;--danger:#dc3545;--light:#f8f9fa;--dark:#343a40;--breakpoint-xs:0;--breakpoint-sm:576px;--breakpoint-md:768px;--breakpoint-lg:992px;--breakpoint-xl:1200px;--font-family-sans-serif:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";--font-family-monospace:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace}*,::after,::before{box-sizing:border-box}html{font-family:sans-serif;line-height:1.15;-webkit-text-size-adjust:100%;-webkit-tap-highlight-color:transparent}article,aside,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}body{margin:0;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";font-size:1rem;font-weight:400;line-height:1.5;color:#212529;text-align:left;background-color:#fff}[tabindex="-1"]:focus{outline:0!important}hr{box-sizing:content-box;height:0;overflow:visible}h1,h2,h3,h4,h5,h6{margin-top:0;margin-bottom:.5rem}p{margin-top:0;margin-bottom:1rem}abbr[data-original-title],abbr[title]{text-decoration:underline;-webkit-text-decoration:underline dotted;text-decoration:underline dotted;cursor:help;border-bottom:0;-webkit-text-decoration-skip-ink:none;text-decoration-skip-ink:none}address{margin-bottom:1rem;font-style:normal;line-height:inherit}dl,ol,ul{margin-top:0;margin-bottom:1rem}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}dt{font-weight:700}dd{margin-bottom:.5rem;margin-left:0}blockquote{margin:0 0 1rem}b,strong{font-weight:bolder}small{font-size:80%}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}a{color:#007bff;text-decoration:none;background-color:transparent}a:hover{color:#0056b3;text-decoration:underline}a:not([href]):not([tabindex]){color:inherit;text-decoration:none}a:not([href]):not([tabindex]):focus,a:not([href]):not([tabindex]):hover{color:inherit;text-decoration:none}a:not([href]):not([tabindex]):focus{outline:0}code,kbd,pre,samp{font-family:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;font-size:1em}pre{margin-top:0;margin-bottom:1rem;overflow:auto}figure{margin:0 0 1rem}img{vertical-align:middle;border-style:none}svg{overflow:hidden;vertical-align:middle}table{border-collapse:collapse}caption{padding-top:.75rem;padding-bottom:.75rem;color:#6c757d;text-align:left;caption-side:bottom}th{text-align:inherit}label{display:inline-block;margin-bottom:.5rem}button{border-radius:0}button:focus{outline:1px dotted;outline:5px auto -webkit-focus-ring-color}button,input,optgroup,select,textarea{margin:0;font-family:inherit;font-size:inherit;line-height:inherit}button,input{overflow:visible}button,select{text-transform:none}select{word-wrap:normal}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}[type=button]:not(:disabled),[type=reset]:not(:disabled),[type=submit]:not(:disabled),button:not(:disabled){cursor:pointer}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{padding:0;border-style:none}input[type=checkbox],input[type=radio]{box-sizing:border-box;padding:0}input[type=date],input[type=datetime-local],input[type=month],input[type=time]{-webkit-appearance:listbox}textarea{overflow:auto;resize:vertical}fieldset{min-width:0;padding:0;margin:0;border:0}legend{display:block;width:100%;max-width:100%;padding:0;margin-bottom:.5rem;font-size:1.5rem;line-height:inherit;color:inherit;white-space:normal}progress{vertical-align:baseline}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{outline-offset:-2px;-webkit-appearance:none}[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{font:inherit;-webkit-appearance:button}output{display:inline-block}summary{display:list-item;cursor:pointer}template{display:none}[hidden]{display:none!important}.h1,.h2,.h3,.h4,.h5,.h6,h1,h2,h3,h4,h5,h6{margin-bottom:.5rem;font-weight:500;line-height:1.2}.h1,h1{font-size:2.5rem}.h2,h2{font-size:2rem}.h3,h3{font-size:1.75rem}.h4,h4{font-size:1.5rem}.h5,h5{font-size:1.25rem}.h6,h6{font-size:1rem}.lead{font-size:1.25rem;font-weight:300}.display-1{font-size:6rem;font-weight:300;line-height:1.2}.display-2{font-size:5.5rem;font-weight:300;line-height:1.2}.display-3{font-size:4.5rem;font-weight:300;line-height:1.2}.display-4{font-size:3.5rem;font-weight:300;line-height:1.2}hr{margin-top:1rem;margin-bottom:1rem;border:0;border-top:1px solid rgba(0,0,0,.1)}.small,small{font-size:80%;font-weight:400}.mark,mark{padding:.2em;background-color:#fcf8e3}.list-unstyled{padding-left:0;list-style:none}.list-inline{padding-left:0;list-style:none}.list-inline-item{display:inline-block}.list-inline-item:not(:last-child){margin-right:.5rem}.initialism{font-size:90%;text-transform:uppercase}.blockquote{margin-bottom:1rem;font-size:1.25rem}.blockquote-footer{display:block;font-size:80%;color:#6c757d}.blockquote-footer::before{content:"\2014\00A0"}.img-fluid{max-width:100%;height:auto}.img-thumbnail{padding:.25rem;background-color:#fff;border:1px solid #dee2e6;border-radius:.25rem;max-width:100%;height:auto}.figure{display:inline-block}.figure-img{margin-bottom:.5rem;line-height:1}.figure-caption{font-size:90%;color:#6c757d}code{font-size:87.5%;color:#e83e8c;word-break:break-word}a>code{color:inherit}kbd{padding:.2rem .4rem;font-size:87.5%;color:#fff;background-color:#212529;border-radius:.2rem}kbd kbd{padding:0;font-size:100%;font-weight:700}pre{display:block;font-size:87.5%;color:#212529}pre code{font-size:inherit;color:inherit;word-break:normal}.pre-scrollable{max-height:340px;overflow-y:scroll}.container{width:100%;padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}@media (min-width:576px){.container{max-width:540px}}@media (min-width:768px){.container{max-width:720px}}@media (min-width:992px){.container{max-width:960px}}@media (min-width:1200px){.container{max-width:1140px}}.container-fluid{width:100%;padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}.row{display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;margin-right:-15px;margin-left:-15px}.no-gutters{margin-right:0;margin-left:0}.no-gutters>.col,.no-gutters>[class*=col-]{padding-right:0;padding-left:0}.col,.col-1,.col-10,.col-11,.col-12,.col-2,.col-3,.col-4,.col-5,.col-6,.col-7,.col-8,.col-9,.col-auto,.col-lg,.col-lg-1,.col-lg-10,.col-lg-11,.col-lg-12,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9,.col-lg-auto,.col-md,.col-md-1,.col-md-10,.col-md-11,.col-md-12,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9,.col-md-auto,.col-sm,.col-sm-1,.col-sm-10,.col-sm-11,.col-sm-12,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-sm-auto,.col-xl,.col-xl-1,.col-xl-10,.col-xl-11,.col-xl-12,.col-xl-2,.col-xl-3,.col-xl-4,.col-xl-5,.col-xl-6,.col-xl-7,.col-xl-8,.col-xl-9,.col-xl-auto{position:relative;width:100%;padding-right:15px;padding-left:15px}.col{-ms-flex-preferred-size:0;flex-basis:0;-ms-flex-positive:1;flex-grow:1;max-width:100%}.col-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:100%}.col-1{-ms-flex:0 0 8.333333%;flex:0 0 8.333333%;max-width:8.333333%}.col-2{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-3{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-4{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.col-5{-ms-flex:0 0 41.666667%;flex:0 0 41.666667%;max-width:41.666667%}.col-6{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-7{-ms-flex:0 0 58.333333%;flex:0 0 58.333333%;max-width:58.333333%}.col-8{-ms-flex:0 0 66.666667%;flex:0 0 66.666667%;max-width:66.666667%}.col-9{-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-10{-ms-flex:0 0 83.333333%;flex:0 0 83.333333%;max-width:83.333333%}.col-11{-ms-flex:0 0 91.666667%;flex:0 0 91.666667%;max-width:91.666667%}.col-12{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-first{-ms-flex-order:-1;order:-1}.order-last{-ms-flex-order:13;order:13}.order-0{-ms-flex-order:0;order:0}.order-1{-ms-flex-order:1;order:1}.order-2{-ms-flex-order:2;order:2}.order-3{-ms-flex-order:3;order:3}.order-4{-ms-flex-order:4;order:4}.order-5{-ms-flex-order:5;order:5}.order-6{-ms-flex-order:6;order:6}.order-7{-ms-flex-order:7;order:7}.order-8{-ms-flex-order:8;order:8}.order-9{-ms-flex-order:9;order:9}.order-10{-ms-flex-order:10;order:10}.order-11{-ms-flex-order:11;order:11}.order-12{-ms-flex-order:12;order:12}.offset-1{margin-left:8.333333%}.offset-2{margin-left:16.666667%}.offset-3{margin-left:25%}.offset-4{margin-left:33.333333%}.offset-5{margin-left:41.666667%}.offset-6{margin-left:50%}.offset-7{margin-left:58.333333%}.offset-8{margin-left:66.666667%}.offset-9{margin-left:75%}.offset-10{margin-left:83.333333%}.offset-11{margin-left:91.666667%}@media (min-width:576px){.col-sm{-ms-flex-preferred-size:0;flex-basis:0;-ms-flex-positive:1;flex-grow:1;max-width:100%}.col-sm-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:100%}.col-sm-1{-ms-flex:0 0 8.333333%;flex:0 0 8.333333%;max-width:8.333333%}.col-sm-2{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-sm-3{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-sm-4{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.col-sm-5{-ms-flex:0 0 41.666667%;flex:0 0 41.666667%;max-width:41.666667%}.col-sm-6{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-sm-7{-ms-flex:0 0 58.333333%;flex:0 0 58.333333%;max-width:58.333333%}.col-sm-8{-ms-flex:0 0 66.666667%;flex:0 0 66.666667%;max-width:66.666667%}.col-sm-9{-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-sm-10{-ms-flex:0 0 83.333333%;flex:0 0 83.333333%;max-width:83.333333%}.col-sm-11{-ms-flex:0 0 91.666667%;flex:0 0 91.666667%;max-width:91.666667%}.col-sm-12{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-sm-first{-ms-flex-order:-1;order:-1}.order-sm-last{-ms-flex-order:13;order:13}.order-sm-0{-ms-flex-order:0;order:0}.order-sm-1{-ms-flex-order:1;order:1}.order-sm-2{-ms-flex-order:2;order:2}.order-sm-3{-ms-flex-order:3;order:3}.order-sm-4{-ms-flex-order:4;order:4}.order-sm-5{-ms-flex-order:5;order:5}.order-sm-6{-ms-flex-order:6;order:6}.order-sm-7{-ms-flex-order:7;order:7}.order-sm-8{-ms-flex-order:8;order:8}.order-sm-9{-ms-flex-order:9;order:9}.order-sm-10{-ms-flex-order:10;order:10}.order-sm-11{-ms-flex-order:11;order:11}.order-sm-12{-ms-flex-order:12;order:12}.offset-sm-0{margin-left:0}.offset-sm-1{margin-left:8.333333%}.offset-sm-2{margin-left:16.666667%}.offset-sm-3{margin-left:25%}.offset-sm-4{margin-left:33.333333%}.offset-sm-5{margin-left:41.666667%}.offset-sm-6{margin-left:50%}.offset-sm-7{margin-left:58.333333%}.offset-sm-8{margin-left:66.666667%}.offset-sm-9{margin-left:75%}.offset-sm-10{margin-left:83.333333%}.offset-sm-11{margin-left:91.666667%}}@media (min-width:768px){.col-md{-ms-flex-preferred-size:0;flex-basis:0;-ms-flex-positive:1;flex-grow:1;max-width:100%}.col-md-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:100%}.col-md-1{-ms-flex:0 0 8.333333%;flex:0 0 8.333333%;max-width:8.333333%}.col-md-2{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-md-3{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-md-4{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.col-md-5{-ms-flex:0 0 41.666667%;flex:0 0 41.666667%;max-width:41.666667%}.col-md-6{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-md-7{-ms-flex:0 0 58.333333%;flex:0 0 58.333333%;max-width:58.333333%}.col-md-8{-ms-flex:0 0 66.666667%;flex:0 0 66.666667%;max-width:66.666667%}.col-md-9{-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-md-10{-ms-flex:0 0 83.333333%;flex:0 0 83.333333%;max-width:83.333333%}.col-md-11{-ms-flex:0 0 91.666667%;flex:0 0 91.666667%;max-width:91.666667%}.col-md-12{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-md-first{-ms-flex-order:-1;order:-1}.order-md-last{-ms-flex-order:13;order:13}.order-md-0{-ms-flex-order:0;order:0}.order-md-1{-ms-flex-order:1;order:1}.order-md-2{-ms-flex-order:2;order:2}.order-md-3{-ms-flex-order:3;order:3}.order-md-4{-ms-flex-order:4;order:4}.order-md-5{-ms-flex-order:5;order:5}.order-md-6{-ms-flex-order:6;order:6}.order-md-7{-ms-flex-order:7;order:7}.order-md-8{-ms-flex-order:8;order:8}.order-md-9{-ms-flex-order:9;order:9}.order-md-10{-ms-flex-order:10;order:10}.order-md-11{-ms-flex-order:11;order:11}.order-md-12{-ms-flex-order:12;order:12}.offset-md-0{margin-left:0}.offset-md-1{margin-left:8.333333%}.offset-md-2{margin-left:16.666667%}.offset-md-3{margin-left:25%}.offset-md-4{margin-left:33.333333%}.offset-md-5{margin-left:41.666667%}.offset-md-6{margin-left:50%}.offset-md-7{margin-left:58.333333%}.offset-md-8{margin-left:66.666667%}.offset-md-9{margin-left:75%}.offset-md-10{margin-left:83.333333%}.offset-md-11{margin-left:91.666667%}}@media (min-width:992px){.col-lg{-ms-flex-preferred-size:0;flex-basis:0;-ms-flex-positive:1;flex-grow:1;max-width:100%}.col-lg-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:100%}.col-lg-1{-ms-flex:0 0 8.333333%;flex:0 0 8.333333%;max-width:8.333333%}.col-lg-2{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-lg-3{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-lg-4{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.col-lg-5{-ms-flex:0 0 41.666667%;flex:0 0 41.666667%;max-width:41.666667%}.col-lg-6{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-lg-7{-ms-flex:0 0 58.333333%;flex:0 0 58.333333%;max-width:58.333333%}.col-lg-8{-ms-flex:0 0 66.666667%;flex:0 0 66.666667%;max-width:66.666667%}.col-lg-9{-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-lg-10{-ms-flex:0 0 83.333333%;flex:0 0 83.333333%;max-width:83.333333%}.col-lg-11{-ms-flex:0 0 91.666667%;flex:0 0 91.666667%;max-width:91.666667%}.col-lg-12{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-lg-first{-ms-flex-order:-1;order:-1}.order-lg-last{-ms-flex-order:13;order:13}.order-lg-0{-ms-flex-order:0;order:0}.order-lg-1{-ms-flex-order:1;order:1}.order-lg-2{-ms-flex-order:2;order:2}.order-lg-3{-ms-flex-order:3;order:3}.order-lg-4{-ms-flex-order:4;order:4}.order-lg-5{-ms-flex-order:5;order:5}.order-lg-6{-ms-flex-order:6;order:6}.order-lg-7{-ms-flex-order:7;order:7}.order-lg-8{-ms-flex-order:8;order:8}.order-lg-9{-ms-flex-order:9;order:9}.order-lg-10{-ms-flex-order:10;order:10}.order-lg-11{-ms-flex-order:11;order:11}.order-lg-12{-ms-flex-order:12;order:12}.offset-lg-0{margin-left:0}.offset-lg-1{margin-left:8.333333%}.offset-lg-2{margin-left:16.666667%}.offset-lg-3{margin-left:25%}.offset-lg-4{margin-left:33.333333%}.offset-lg-5{margin-left:41.666667%}.offset-lg-6{margin-left:50%}.offset-lg-7{margin-left:58.333333%}.offset-lg-8{margin-left:66.666667%}.offset-lg-9{margin-left:75%}.offset-lg-10{margin-left:83.333333%}.offset-lg-11{margin-left:91.666667%}}@media (min-width:1200px){.col-xl{-ms-flex-preferred-size:0;flex-basis:0;-ms-flex-positive:1;flex-grow:1;max-width:100%}.col-xl-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:100%}.col-xl-1{-ms-flex:0 0 8.333333%;flex:0 0 8.333333%;max-width:8.333333%}.col-xl-2{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-xl-3{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-xl-4{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.col-xl-5{-ms-flex:0 0 41.666667%;flex:0 0 41.666667%;max-width:41.666667%}.col-xl-6{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-xl-7{-ms-flex:0 0 58.333333%;flex:0 0 58.333333%;max-width:58.333333%}.col-xl-8{-ms-flex:0 0 66.666667%;flex:0 0 66.666667%;max-width:66.666667%}.col-xl-9{-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-xl-10{-ms-flex:0 0 83.333333%;flex:0 0 83.333333%;max-width:83.333333%}.col-xl-11{-ms-flex:0 0 91.666667%;flex:0 0 91.666667%;max-width:91.666667%}.col-xl-12{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-xl-first{-ms-flex-order:-1;order:-1}.order-xl-last{-ms-flex-order:13;order:13}.order-xl-0{-ms-flex-order:0;order:0}.order-xl-1{-ms-flex-order:1;order:1}.order-xl-2{-ms-flex-order:2;order:2}.order-xl-3{-ms-flex-order:3;order:3}.order-xl-4{-ms-flex-order:4;order:4}.order-xl-5{-ms-flex-order:5;order:5}.order-xl-6{-ms-flex-order:6;order:6}.order-xl-7{-ms-flex-order:7;order:7}.order-xl-8{-ms-flex-order:8;order:8}.order-xl-9{-ms-flex-order:9;order:9}.order-xl-10{-ms-flex-order:10;order:10}.order-xl-11{-ms-flex-order:11;order:11}.order-xl-12{-ms-flex-order:12;order:12}.offset-xl-0{margin-left:0}.offset-xl-1{margin-left:8.333333%}.offset-xl-2{margin-left:16.666667%}.offset-xl-3{margin-left:25%}.offset-xl-4{margin-left:33.333333%}.offset-xl-5{margin-left:41.666667%}.offset-xl-6{margin-left:50%}.offset-xl-7{margin-left:58.333333%}.offset-xl-8{margin-left:66.666667%}.offset-xl-9{margin-left:75%}.offset-xl-10{margin-left:83.333333%}.offset-xl-11{margin-left:91.666667%}}.table{width:100%;margin-bottom:1rem;color:#212529}.table td,.table th{padding:.75rem;vertical-align:top;border-top:1px solid #dee2e6}.table thead th{vertical-align:bottom;border-bottom:2px solid #dee2e6}.table tbody+tbody{border-top:2px solid #dee2e6}.table-sm td,.table-sm th{padding:.3rem}.table-bordered{border:1px solid #dee2e6}.table-bordered td,.table-bordered th{border:1px solid #dee2e6}.table-bordered thead td,.table-bordered thead th{border-bottom-width:2px}.table-borderless tbody+tbody,.table-borderless td,.table-borderless th,.table-borderless thead th{border:0}.table-striped tbody tr:nth-of-type(odd){background-color:rgba(0,0,0,.05)}.table-hover tbody tr:hover{color:#212529;background-color:rgba(0,0,0,.075)}.table-primary,.table-primary>td,.table-primary>th{background-color:#b8daff}.table-primary tbody+tbody,.table-primary td,.table-primary th,.table-primary thead th{border-color:#7abaff}.table-hover .table-primary:hover{background-color:#9fcdff}.table-hover .table-primary:hover>td,.table-hover .table-primary:hover>th{background-color:#9fcdff}.table-secondary,.table-secondary>td,.table-secondary>th{background-color:#d6d8db}.table-secondary tbody+tbody,.table-secondary td,.table-secondary th,.table-secondary thead th{border-color:#b3b7bb}.table-hover .table-secondary:hover{background-color:#c8cbcf}.table-hover .table-secondary:hover>td,.table-hover .table-secondary:hover>th{background-color:#c8cbcf}.table-success,.table-success>td,.table-success>th{background-color:#c3e6cb}.table-success tbody+tbody,.table-success td,.table-success th,.table-success thead th{border-color:#8fd19e}.table-hover .table-success:hover{background-color:#b1dfbb}.table-hover .table-success:hover>td,.table-hover .table-success:hover>th{background-color:#b1dfbb}.table-info,.table-info>td,.table-info>th{background-color:#bee5eb}.table-info tbody+tbody,.table-info td,.table-info th,.table-info thead th{border-color:#86cfda}.table-hover .table-info:hover{background-color:#abdde5}.table-hover .table-info:hover>td,.table-hover .table-info:hover>th{background-color:#abdde5}.table-warning,.table-warning>td,.table-warning>th{background-color:#ffeeba}.table-warning tbody+tbody,.table-warning td,.table-warning th,.table-warning thead th{border-color:#ffdf7e}.table-hover .table-warning:hover{background-color:#ffe8a1}.table-hover .table-warning:hover>td,.table-hover .table-warning:hover>th{background-color:#ffe8a1}.table-danger,.table-danger>td,.table-danger>th{background-color:#f5c6cb}.table-danger tbody+tbody,.table-danger td,.table-danger th,.table-danger thead th{border-color:#ed969e}.table-hover .table-danger:hover{background-color:#f1b0b7}.table-hover .table-danger:hover>td,.table-hover .table-danger:hover>th{background-color:#f1b0b7}.table-light,.table-light>td,.table-light>th{background-color:#fdfdfe}.table-light tbody+tbody,.table-light td,.table-light th,.table-light thead th{border-color:#fbfcfc}.table-hover .table-light:hover{background-color:#ececf6}.table-hover .table-light:hover>td,.table-hover .table-light:hover>th{background-color:#ececf6}.table-dark,.table-dark>td,.table-dark>th{background-color:#c6c8ca}.table-dark tbody+tbody,.table-dark td,.table-dark th,.table-dark thead th{border-color:#95999c}.table-hover .table-dark:hover{background-color:#b9bbbe}.table-hover .table-dark:hover>td,.table-hover .table-dark:hover>th{background-color:#b9bbbe}.table-active,.table-active>td,.table-active>th{background-color:rgba(0,0,0,.075)}.table-hover .table-active:hover{background-color:rgba(0,0,0,.075)}.table-hover .table-active:hover>td,.table-hover .table-active:hover>th{background-color:rgba(0,0,0,.075)}.table .thead-dark th{color:#fff;background-color:#343a40;border-color:#454d55}.table .thead-light th{color:#495057;background-color:#e9ecef;border-color:#dee2e6}.table-dark{color:#fff;background-color:#343a40}.table-dark td,.table-dark th,.table-dark thead th{border-color:#454d55}.table-dark.table-bordered{border:0}.table-dark.table-striped tbody tr:nth-of-type(odd){background-color:rgba(255,255,255,.05)}.table-dark.table-hover tbody tr:hover{color:#fff;background-color:rgba(255,255,255,.075)}@media (max-width:575.98px){.table-responsive-sm{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch}.table-responsive-sm>.table-bordered{border:0}}@media (max-width:767.98px){.table-responsive-md{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch}.table-responsive-md>.table-bordered{border:0}}@media (max-width:991.98px){.table-responsive-lg{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch}.table-responsive-lg>.table-bordered{border:0}}@media (max-width:1199.98px){.table-responsive-xl{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch}.table-responsive-xl>.table-bordered{border:0}}.table-responsive{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch}.table-responsive>.table-bordered{border:0}.form-control{display:block;width:100%;height:calc(1.5em + .75rem + 2px);padding:.375rem .75rem;font-size:1rem;font-weight:400;line-height:1.5;color:#495057;background-color:#fff;background-clip:padding-box;border:1px solid #ced4da;border-radius:.25rem;transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.form-control{transition:none}}.form-control::-ms-expand{background-color:transparent;border:0}.form-control:focus{color:#495057;background-color:#fff;border-color:#80bdff;outline:0;box-shadow:0 0 0 .2rem rgba(0,123,255,.25)}.form-control::-webkit-input-placeholder{color:#6c757d;opacity:1}.form-control::-moz-placeholder{color:#6c757d;opacity:1}.form-control:-ms-input-placeholder{color:#6c757d;opacity:1}.form-control::-ms-input-placeholder{color:#6c757d;opacity:1}.form-control::placeholder{color:#6c757d;opacity:1}.form-control:disabled,.form-control[readonly]{background-color:#e9ecef;opacity:1}select.form-control:focus::-ms-value{color:#495057;background-color:#fff}.form-control-file,.form-control-range{display:block;width:100%}.col-form-label{padding-top:calc(.375rem + 1px);padding-bottom:calc(.375rem + 1px);margin-bottom:0;font-size:inherit;line-height:1.5}.col-form-label-lg{padding-top:calc(.5rem + 1px);padding-bottom:calc(.5rem + 1px);font-size:1.25rem;line-height:1.5}.col-form-label-sm{padding-top:calc(.25rem + 1px);padding-bottom:calc(.25rem + 1px);font-size:.875rem;line-height:1.5}.form-control-plaintext{display:block;width:100%;padding-top:.375rem;padding-bottom:.375rem;margin-bottom:0;line-height:1.5;color:#212529;background-color:transparent;border:solid transparent;border-width:1px 0}.form-control-plaintext.form-control-lg,.form-control-plaintext.form-control-sm{padding-right:0;padding-left:0}.form-control-sm{height:calc(1.5em + .5rem + 2px);padding:.25rem .5rem;font-size:.875rem;line-height:1.5;border-radius:.2rem}.form-control-lg{height:calc(1.5em + 1rem + 2px);padding:.5rem 1rem;font-size:1.25rem;line-height:1.5;border-radius:.3rem}select.form-control[multiple],select.form-control[size]{height:auto}textarea.form-control{height:auto}.form-group{margin-bottom:1rem}.form-text{display:block;margin-top:.25rem}.form-row{display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;margin-right:-5px;margin-left:-5px}.form-row>.col,.form-row>[class*=col-]{padding-right:5px;padding-left:5px}.form-check{position:relative;display:block;padding-left:1.25rem}.form-check-input{position:absolute;margin-top:.3rem;margin-left:-1.25rem}.form-check-input:disabled~.form-check-label{color:#6c757d}.form-check-label{margin-bottom:0}.form-check-inline{display:-ms-inline-flexbox;display:inline-flex;-ms-flex-align:center;align-items:center;padding-left:0;margin-right:.75rem}.form-check-inline .form-check-input{position:static;margin-top:0;margin-right:.3125rem;margin-left:0}.valid-feedback{display:none;width:100%;margin-top:.25rem;font-size:80%;color:#28a745}.valid-tooltip{position:absolute;top:100%;z-index:5;display:none;max-width:100%;padding:.25rem .5rem;margin-top:.1rem;font-size:.875rem;line-height:1.5;color:#fff;background-color:rgba(40,167,69,.9);border-radius:.25rem}.form-control.is-valid,.was-validated .form-control:valid{border-color:#28a745;padding-right:calc(1.5em + .75rem);background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3e%3cpath fill='%2328a745' d='M2.3 6.73L.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3e%3c/svg%3e");background-repeat:no-repeat;background-position:center right calc(.375em + .1875rem);background-size:calc(.75em + .375rem) calc(.75em + .375rem)}.form-control.is-valid:focus,.was-validated .form-control:valid:focus{border-color:#28a745;box-shadow:0 0 0 .2rem rgba(40,167,69,.25)}.form-control.is-valid~.valid-feedback,.form-control.is-valid~.valid-tooltip,.was-validated .form-control:valid~.valid-feedback,.was-validated .form-control:valid~.valid-tooltip{display:block}.was-validated textarea.form-control:valid,textarea.form-control.is-valid{padding-right:calc(1.5em + .75rem);background-position:top calc(.375em + .1875rem) right calc(.375em + .1875rem)}.custom-select.is-valid,.was-validated .custom-select:valid{border-color:#28a745;padding-right:calc((1em + .75rem) * 3 / 4 + 1.75rem);background:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 5'%3e%3cpath fill='%23343a40' d='M2 0L0 2h4zm0 5L0 3h4z'/%3e%3c/svg%3e") no-repeat right .75rem center/8px 10px,url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3e%3cpath fill='%2328a745' d='M2.3 6.73L.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3e%3c/svg%3e") #fff no-repeat center right 1.75rem/calc(.75em + .375rem) calc(.75em + .375rem)}.custom-select.is-valid:focus,.was-validated .custom-select:valid:focus{border-color:#28a745;box-shadow:0 0 0 .2rem rgba(40,167,69,.25)}.custom-select.is-valid~.valid-feedback,.custom-select.is-valid~.valid-tooltip,.was-validated .custom-select:valid~.valid-feedback,.was-validated .custom-select:valid~.valid-tooltip{display:block}.form-control-file.is-valid~.valid-feedback,.form-control-file.is-valid~.valid-tooltip,.was-validated .form-control-file:valid~.valid-feedback,.was-validated .form-control-file:valid~.valid-tooltip{display:block}.form-check-input.is-valid~.form-check-label,.was-validated .form-check-input:valid~.form-check-label{color:#28a745}.form-check-input.is-valid~.valid-feedback,.form-check-input.is-valid~.valid-tooltip,.was-validated .form-check-input:valid~.valid-feedback,.was-validated .form-check-input:valid~.valid-tooltip{display:block}.custom-control-input.is-valid~.custom-control-label,.was-validated .custom-control-input:valid~.custom-control-label{color:#28a745}.custom-control-input.is-valid~.custom-control-label::before,.was-validated .custom-control-input:valid~.custom-control-label::before{border-color:#28a745}.custom-control-input.is-valid~.valid-feedback,.custom-control-input.is-valid~.valid-tooltip,.was-validated .custom-control-input:valid~.valid-feedback,.was-validated .custom-control-input:valid~.valid-tooltip{display:block}.custom-control-input.is-valid:checked~.custom-control-label::before,.was-validated .custom-control-input:valid:checked~.custom-control-label::before{border-color:#34ce57;background-color:#34ce57}.custom-control-input.is-valid:focus~.custom-control-label::before,.was-validated .custom-control-input:valid:focus~.custom-control-label::before{box-shadow:0 0 0 .2rem rgba(40,167,69,.25)}.custom-control-input.is-valid:focus:not(:checked)~.custom-control-label::before,.was-validated .custom-control-input:valid:focus:not(:checked)~.custom-control-label::before{border-color:#28a745}.custom-file-input.is-valid~.custom-file-label,.was-validated .custom-file-input:valid~.custom-file-label{border-color:#28a745}.custom-file-input.is-valid~.valid-feedback,.custom-file-input.is-valid~.valid-tooltip,.was-validated .custom-file-input:valid~.valid-feedback,.was-validated .custom-file-input:valid~.valid-tooltip{display:block}.custom-file-input.is-valid:focus~.custom-file-label,.was-validated .custom-file-input:valid:focus~.custom-file-label{border-color:#28a745;box-shadow:0 0 0 .2rem rgba(40,167,69,.25)}.invalid-feedback{display:none;width:100%;margin-top:.25rem;font-size:80%;color:#dc3545}.invalid-tooltip{position:absolute;top:100%;z-index:5;display:none;max-width:100%;padding:.25rem .5rem;margin-top:.1rem;font-size:.875rem;line-height:1.5;color:#fff;background-color:rgba(220,53,69,.9);border-radius:.25rem}.form-control.is-invalid,.was-validated .form-control:invalid{border-color:#dc3545;padding-right:calc(1.5em + .75rem);background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='%23dc3545' viewBox='-2 -2 7 7'%3e%3cpath stroke='%23dc3545' d='M0 0l3 3m0-3L0 3'/%3e%3ccircle r='.5'/%3e%3ccircle cx='3' r='.5'/%3e%3ccircle cy='3' r='.5'/%3e%3ccircle cx='3' cy='3' r='.5'/%3e%3c/svg%3E");background-repeat:no-repeat;background-position:center right calc(.375em + .1875rem);background-size:calc(.75em + .375rem) calc(.75em + .375rem)}.form-control.is-invalid:focus,.was-validated .form-control:invalid:focus{border-color:#dc3545;box-shadow:0 0 0 .2rem rgba(220,53,69,.25)}.form-control.is-invalid~.invalid-feedback,.form-control.is-invalid~.invalid-tooltip,.was-validated .form-control:invalid~.invalid-feedback,.was-validated .form-control:invalid~.invalid-tooltip{display:block}.was-validated textarea.form-control:invalid,textarea.form-control.is-invalid{padding-right:calc(1.5em + .75rem);background-position:top calc(.375em + .1875rem) right calc(.375em + .1875rem)}.custom-select.is-invalid,.was-validated .custom-select:invalid{border-color:#dc3545;padding-right:calc((1em + .75rem) * 3 / 4 + 1.75rem);background:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 5'%3e%3cpath fill='%23343a40' d='M2 0L0 2h4zm0 5L0 3h4z'/%3e%3c/svg%3e") no-repeat right .75rem center/8px 10px,url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='%23dc3545' viewBox='-2 -2 7 7'%3e%3cpath stroke='%23dc3545' d='M0 0l3 3m0-3L0 3'/%3e%3ccircle r='.5'/%3e%3ccircle cx='3' r='.5'/%3e%3ccircle cy='3' r='.5'/%3e%3ccircle cx='3' cy='3' r='.5'/%3e%3c/svg%3E") #fff no-repeat center right 1.75rem/calc(.75em + .375rem) calc(.75em + .375rem)}.custom-select.is-invalid:focus,.was-validated .custom-select:invalid:focus{border-color:#dc3545;box-shadow:0 0 0 .2rem rgba(220,53,69,.25)}.custom-select.is-invalid~.invalid-feedback,.custom-select.is-invalid~.invalid-tooltip,.was-validated .custom-select:invalid~.invalid-feedback,.was-validated .custom-select:invalid~.invalid-tooltip{display:block}.form-control-file.is-invalid~.invalid-feedback,.form-control-file.is-invalid~.invalid-tooltip,.was-validated .form-control-file:invalid~.invalid-feedback,.was-validated .form-control-file:invalid~.invalid-tooltip{display:block}.form-check-input.is-invalid~.form-check-label,.was-validated .form-check-input:invalid~.form-check-label{color:#dc3545}.form-check-input.is-invalid~.invalid-feedback,.form-check-input.is-invalid~.invalid-tooltip,.was-validated .form-check-input:invalid~.invalid-feedback,.was-validated .form-check-input:invalid~.invalid-tooltip{display:block}.custom-control-input.is-invalid~.custom-control-label,.was-validated .custom-control-input:invalid~.custom-control-label{color:#dc3545}.custom-control-input.is-invalid~.custom-control-label::before,.was-validated .custom-control-input:invalid~.custom-control-label::before{border-color:#dc3545}.custom-control-input.is-invalid~.invalid-feedback,.custom-control-input.is-invalid~.invalid-tooltip,.was-validated .custom-control-input:invalid~.invalid-feedback,.was-validated .custom-control-input:invalid~.invalid-tooltip{display:block}.custom-control-input.is-invalid:checked~.custom-control-label::before,.was-validated .custom-control-input:invalid:checked~.custom-control-label::before{border-color:#e4606d;background-color:#e4606d}.custom-control-input.is-invalid:focus~.custom-control-label::before,.was-validated .custom-control-input:invalid:focus~.custom-control-label::before{box-shadow:0 0 0 .2rem rgba(220,53,69,.25)}.custom-control-input.is-invalid:focus:not(:checked)~.custom-control-label::before,.was-validated .custom-control-input:invalid:focus:not(:checked)~.custom-control-label::before{border-color:#dc3545}.custom-file-input.is-invalid~.custom-file-label,.was-validated .custom-file-input:invalid~.custom-file-label{border-color:#dc3545}.custom-file-input.is-invalid~.invalid-feedback,.custom-file-input.is-invalid~.invalid-tooltip,.was-validated .custom-file-input:invalid~.invalid-feedback,.was-validated .custom-file-input:invalid~.invalid-tooltip{display:block}.custom-file-input.is-invalid:focus~.custom-file-label,.was-validated .custom-file-input:invalid:focus~.custom-file-label{border-color:#dc3545;box-shadow:0 0 0 .2rem rgba(220,53,69,.25)}.form-inline{display:-ms-flexbox;display:flex;-ms-flex-flow:row wrap;flex-flow:row wrap;-ms-flex-align:center;align-items:center}.form-inline .form-check{width:100%}@media (min-width:576px){.form-inline label{display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center;-ms-flex-pack:center;justify-content:center;margin-bottom:0}.form-inline .form-group{display:-ms-flexbox;display:flex;-ms-flex:0 0 auto;flex:0 0 auto;-ms-flex-flow:row wrap;flex-flow:row wrap;-ms-flex-align:center;align-items:center;margin-bottom:0}.form-inline .form-control{display:inline-block;width:auto;vertical-align:middle}.form-inline .form-control-plaintext{display:inline-block}.form-inline .custom-select,.form-inline .input-group{width:auto}.form-inline .form-check{display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center;-ms-flex-pack:center;justify-content:center;width:auto;padding-left:0}.form-inline .form-check-input{position:relative;-ms-flex-negative:0;flex-shrink:0;margin-top:0;margin-right:.25rem;margin-left:0}.form-inline .custom-control{-ms-flex-align:center;align-items:center;-ms-flex-pack:center;justify-content:center}.form-inline .custom-control-label{margin-bottom:0}}.btn{display:inline-block;font-weight:400;color:#212529;text-align:center;vertical-align:middle;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;background-color:transparent;border:1px solid transparent;padding:.375rem .75rem;font-size:1rem;line-height:1.5;border-radius:.25rem;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.btn{transition:none}}.btn:hover{color:#212529;text-decoration:none}.btn.focus,.btn:focus{outline:0;box-shadow:0 0 0 .2rem rgba(0,123,255,.25)}.btn.disabled,.btn:disabled{opacity:.65}a.btn.disabled,fieldset:disabled a.btn{pointer-events:none}.btn-primary{color:#fff;background-color:#007bff;border-color:#007bff}.btn-primary:hover{color:#fff;background-color:#0069d9;border-color:#0062cc}.btn-primary.focus,.btn-primary:focus{box-shadow:0 0 0 .2rem rgba(38,143,255,.5)}.btn-primary.disabled,.btn-primary:disabled{color:#fff;background-color:#007bff;border-color:#007bff}.btn-primary:not(:disabled):not(.disabled).active,.btn-primary:not(:disabled):not(.disabled):active,.show>.btn-primary.dropdown-toggle{color:#fff;background-color:#0062cc;border-color:#005cbf}.btn-primary:not(:disabled):not(.disabled).active:focus,.btn-primary:not(:disabled):not(.disabled):active:focus,.show>.btn-primary.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(38,143,255,.5)}.btn-secondary{color:#fff;background-color:#6c757d;border-color:#6c757d}.btn-secondary:hover{color:#fff;background-color:#5a6268;border-color:#545b62}.btn-secondary.focus,.btn-secondary:focus{box-shadow:0 0 0 .2rem rgba(130,138,145,.5)}.btn-secondary.disabled,.btn-secondary:disabled{color:#fff;background-color:#6c757d;border-color:#6c757d}.btn-secondary:not(:disabled):not(.disabled).active,.btn-secondary:not(:disabled):not(.disabled):active,.show>.btn-secondary.dropdown-toggle{color:#fff;background-color:#545b62;border-color:#4e555b}.btn-secondary:not(:disabled):not(.disabled).active:focus,.btn-secondary:not(:disabled):not(.disabled):active:focus,.show>.btn-secondary.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(130,138,145,.5)}.btn-success{color:#fff;background-color:#28a745;border-color:#28a745}.btn-success:hover{color:#fff;background-color:#218838;border-color:#1e7e34}.btn-success.focus,.btn-success:focus{box-shadow:0 0 0 .2rem rgba(72,180,97,.5)}.btn-success.disabled,.btn-success:disabled{color:#fff;background-color:#28a745;border-color:#28a745}.btn-success:not(:disabled):not(.disabled).active,.btn-success:not(:disabled):not(.disabled):active,.show>.btn-success.dropdown-toggle{color:#fff;background-color:#1e7e34;border-color:#1c7430}.btn-success:not(:disabled):not(.disabled).active:focus,.btn-success:not(:disabled):not(.disabled):active:focus,.show>.btn-success.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(72,180,97,.5)}.btn-info{color:#fff;background-color:#17a2b8;border-color:#17a2b8}.btn-info:hover{color:#fff;background-color:#138496;border-color:#117a8b}.btn-info.focus,.btn-info:focus{box-shadow:0 0 0 .2rem rgba(58,176,195,.5)}.btn-info.disabled,.btn-info:disabled{color:#fff;background-color:#17a2b8;border-color:#17a2b8}.btn-info:not(:disabled):not(.disabled).active,.btn-info:not(:disabled):not(.disabled):active,.show>.btn-info.dropdown-toggle{color:#fff;background-color:#117a8b;border-color:#10707f}.btn-info:not(:disabled):not(.disabled).active:focus,.btn-info:not(:disabled):not(.disabled):active:focus,.show>.btn-info.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(58,176,195,.5)}.btn-warning{color:#212529;background-color:#ffc107;border-color:#ffc107}.btn-warning:hover{color:#212529;background-color:#e0a800;border-color:#d39e00}.btn-warning.focus,.btn-warning:focus{box-shadow:0 0 0 .2rem rgba(222,170,12,.5)}.btn-warning.disabled,.btn-warning:disabled{color:#212529;background-color:#ffc107;border-color:#ffc107}.btn-warning:not(:disabled):not(.disabled).active,.btn-warning:not(:disabled):not(.disabled):active,.show>.btn-warning.dropdown-toggle{color:#212529;background-color:#d39e00;border-color:#c69500}.btn-warning:not(:disabled):not(.disabled).active:focus,.btn-warning:not(:disabled):not(.disabled):active:focus,.show>.btn-warning.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(222,170,12,.5)}.btn-danger{color:#fff;background-color:#dc3545;border-color:#dc3545}.btn-danger:hover{color:#fff;background-color:#c82333;border-color:#bd2130}.btn-danger.focus,.btn-danger:focus{box-shadow:0 0 0 .2rem rgba(225,83,97,.5)}.btn-danger.disabled,.btn-danger:disabled{color:#fff;background-color:#dc3545;border-color:#dc3545}.btn-danger:not(:disabled):not(.disabled).active,.btn-danger:not(:disabled):not(.disabled):active,.show>.btn-danger.dropdown-toggle{color:#fff;background-color:#bd2130;border-color:#b21f2d}.btn-danger:not(:disabled):not(.disabled).active:focus,.btn-danger:not(:disabled):not(.disabled):active:focus,.show>.btn-danger.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(225,83,97,.5)}.btn-light{color:#212529;background-color:#f8f9fa;border-color:#f8f9fa}.btn-light:hover{color:#212529;background-color:#e2e6ea;border-color:#dae0e5}.btn-light.focus,.btn-light:focus{box-shadow:0 0 0 .2rem rgba(216,217,219,.5)}.btn-light.disabled,.btn-light:disabled{color:#212529;background-color:#f8f9fa;border-color:#f8f9fa}.btn-light:not(:disabled):not(.disabled).active,.btn-light:not(:disabled):not(.disabled):active,.show>.btn-light.dropdown-toggle{color:#212529;background-color:#dae0e5;border-color:#d3d9df}.btn-light:not(:disabled):not(.disabled).active:focus,.btn-light:not(:disabled):not(.disabled):active:focus,.show>.btn-light.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(216,217,219,.5)}.btn-dark{color:#fff;background-color:#343a40;border-color:#343a40}.btn-dark:hover{color:#fff;background-color:#23272b;border-color:#1d2124}.btn-dark.focus,.btn-dark:focus{box-shadow:0 0 0 .2rem rgba(82,88,93,.5)}.btn-dark.disabled,.btn-dark:disabled{color:#fff;background-color:#343a40;border-color:#343a40}.btn-dark:not(:disabled):not(.disabled).active,.btn-dark:not(:disabled):not(.disabled):active,.show>.btn-dark.dropdown-toggle{color:#fff;background-color:#1d2124;border-color:#171a1d}.btn-dark:not(:disabled):not(.disabled).active:focus,.btn-dark:not(:disabled):not(.disabled):active:focus,.show>.btn-dark.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(82,88,93,.5)}.btn-outline-primary{color:#007bff;border-color:#007bff}.btn-outline-primary:hover{color:#fff;background-color:#007bff;border-color:#007bff}.btn-outline-primary.focus,.btn-outline-primary:focus{box-shadow:0 0 0 .2rem rgba(0,123,255,.5)}.btn-outline-primary.disabled,.btn-outline-primary:disabled{color:#007bff;background-color:transparent}.btn-outline-primary:not(:disabled):not(.disabled).active,.btn-outline-primary:not(:disabled):not(.disabled):active,.show>.btn-outline-primary.dropdown-toggle{color:#fff;background-color:#007bff;border-color:#007bff}.btn-outline-primary:not(:disabled):not(.disabled).active:focus,.btn-outline-primary:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-primary.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(0,123,255,.5)}.btn-outline-secondary{color:#6c757d;border-color:#6c757d}.btn-outline-secondary:hover{color:#fff;background-color:#6c757d;border-color:#6c757d}.btn-outline-secondary.focus,.btn-outline-secondary:focus{box-shadow:0 0 0 .2rem rgba(108,117,125,.5)}.btn-outline-secondary.disabled,.btn-outline-secondary:disabled{color:#6c757d;background-color:transparent}.btn-outline-secondary:not(:disabled):not(.disabled).active,.btn-outline-secondary:not(:disabled):not(.disabled):active,.show>.btn-outline-secondary.dropdown-toggle{color:#fff;background-color:#6c757d;border-color:#6c757d}.btn-outline-secondary:not(:disabled):not(.disabled).active:focus,.btn-outline-secondary:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-secondary.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(108,117,125,.5)}.btn-outline-success{color:#28a745;border-color:#28a745}.btn-outline-success:hover{color:#fff;background-color:#28a745;border-color:#28a745}.btn-outline-success.focus,.btn-outline-success:focus{box-shadow:0 0 0 .2rem rgba(40,167,69,.5)}.btn-outline-success.disabled,.btn-outline-success:disabled{color:#28a745;background-color:transparent}.btn-outline-success:not(:disabled):not(.disabled).active,.btn-outline-success:not(:disabled):not(.disabled):active,.show>.btn-outline-success.dropdown-toggle{color:#fff;background-color:#28a745;border-color:#28a745}.btn-outline-success:not(:disabled):not(.disabled).active:focus,.btn-outline-success:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-success.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(40,167,69,.5)}.btn-outline-info{color:#17a2b8;border-color:#17a2b8}.btn-outline-info:hover{color:#fff;background-color:#17a2b8;border-color:#17a2b8}.btn-outline-info.focus,.btn-outline-info:focus{box-shadow:0 0 0 .2rem rgba(23,162,184,.5)}.btn-outline-info.disabled,.btn-outline-info:disabled{color:#17a2b8;background-color:transparent}.btn-outline-info:not(:disabled):not(.disabled).active,.btn-outline-info:not(:disabled):not(.disabled):active,.show>.btn-outline-info.dropdown-toggle{color:#fff;background-color:#17a2b8;border-color:#17a2b8}.btn-outline-info:not(:disabled):not(.disabled).active:focus,.btn-outline-info:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-info.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(23,162,184,.5)}.btn-outline-warning{color:#ffc107;border-color:#ffc107}.btn-outline-warning:hover{color:#212529;background-color:#ffc107;border-color:#ffc107}.btn-outline-warning.focus,.btn-outline-warning:focus{box-shadow:0 0 0 .2rem rgba(255,193,7,.5)}.btn-outline-warning.disabled,.btn-outline-warning:disabled{color:#ffc107;background-color:transparent}.btn-outline-warning:not(:disabled):not(.disabled).active,.btn-outline-warning:not(:disabled):not(.disabled):active,.show>.btn-outline-warning.dropdown-toggle{color:#212529;background-color:#ffc107;border-color:#ffc107}.btn-outline-warning:not(:disabled):not(.disabled).active:focus,.btn-outline-warning:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-warning.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(255,193,7,.5)}.btn-outline-danger{color:#dc3545;border-color:#dc3545}.btn-outline-danger:hover{color:#fff;background-color:#dc3545;border-color:#dc3545}.btn-outline-danger.focus,.btn-outline-danger:focus{box-shadow:0 0 0 .2rem rgba(220,53,69,.5)}.btn-outline-danger.disabled,.btn-outline-danger:disabled{color:#dc3545;background-color:transparent}.btn-outline-danger:not(:disabled):not(.disabled).active,.btn-outline-danger:not(:disabled):not(.disabled):active,.show>.btn-outline-danger.dropdown-toggle{color:#fff;background-color:#dc3545;border-color:#dc3545}.btn-outline-danger:not(:disabled):not(.disabled).active:focus,.btn-outline-danger:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-danger.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(220,53,69,.5)}.btn-outline-light{color:#f8f9fa;border-color:#f8f9fa}.btn-outline-light:hover{color:#212529;background-color:#f8f9fa;border-color:#f8f9fa}.btn-outline-light.focus,.btn-outline-light:focus{box-shadow:0 0 0 .2rem rgba(248,249,250,.5)}.btn-outline-light.disabled,.btn-outline-light:disabled{color:#f8f9fa;background-color:transparent}.btn-outline-light:not(:disabled):not(.disabled).active,.btn-outline-light:not(:disabled):not(.disabled):active,.show>.btn-outline-light.dropdown-toggle{color:#212529;background-color:#f8f9fa;border-color:#f8f9fa}.btn-outline-light:not(:disabled):not(.disabled).active:focus,.btn-outline-light:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-light.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(248,249,250,.5)}.btn-outline-dark{color:#343a40;border-color:#343a40}.btn-outline-dark:hover{color:#fff;background-color:#343a40;border-color:#343a40}.btn-outline-dark.focus,.btn-outline-dark:focus{box-shadow:0 0 0 .2rem rgba(52,58,64,.5)}.btn-outline-dark.disabled,.btn-outline-dark:disabled{color:#343a40;background-color:transparent}.btn-outline-dark:not(:disabled):not(.disabled).active,.btn-outline-dark:not(:disabled):not(.disabled):active,.show>.btn-outline-dark.dropdown-toggle{color:#fff;background-color:#343a40;border-color:#343a40}.btn-outline-dark:not(:disabled):not(.disabled).active:focus,.btn-outline-dark:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-dark.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(52,58,64,.5)}.btn-link{font-weight:400;color:#007bff;text-decoration:none}.btn-link:hover{color:#0056b3;text-decoration:underline}.btn-link.focus,.btn-link:focus{text-decoration:underline;box-shadow:none}.btn-link.disabled,.btn-link:disabled{color:#6c757d;pointer-events:none}.btn-group-lg>.btn,.btn-lg{padding:.5rem 1rem;font-size:1.25rem;line-height:1.5;border-radius:.3rem}.btn-group-sm>.btn,.btn-sm{padding:.25rem .5rem;font-size:.875rem;line-height:1.5;border-radius:.2rem}.btn-block{display:block;width:100%}.btn-block+.btn-block{margin-top:.5rem}input[type=button].btn-block,input[type=reset].btn-block,input[type=submit].btn-block{width:100%}.fade{transition:opacity .15s linear}@media (prefers-reduced-motion:reduce){.fade{transition:none}}.fade:not(.show){opacity:0}.collapse:not(.show){display:none}.collapsing{position:relative;height:0;overflow:hidden;transition:height .35s ease}@media (prefers-reduced-motion:reduce){.collapsing{transition:none}}.dropdown,.dropleft,.dropright,.dropup{position:relative}.dropdown-toggle{white-space:nowrap}.dropdown-toggle::after{display:inline-block;margin-left:.255em;vertical-align:.255em;content:"";border-top:.3em solid;border-right:.3em solid transparent;border-bottom:0;border-left:.3em solid transparent}.dropdown-toggle:empty::after{margin-left:0}.dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;display:none;float:left;min-width:10rem;padding:.5rem 0;margin:.125rem 0 0;font-size:1rem;color:#212529;text-align:left;list-style:none;background-color:#fff;background-clip:padding-box;border:1px solid rgba(0,0,0,.15);border-radius:.25rem}.dropdown-menu-left{right:auto;left:0}.dropdown-menu-right{right:0;left:auto}@media (min-width:576px){.dropdown-menu-sm-left{right:auto;left:0}.dropdown-menu-sm-right{right:0;left:auto}}@media (min-width:768px){.dropdown-menu-md-left{right:auto;left:0}.dropdown-menu-md-right{right:0;left:auto}}@media (min-width:992px){.dropdown-menu-lg-left{right:auto;left:0}.dropdown-menu-lg-right{right:0;left:auto}}@media (min-width:1200px){.dropdown-menu-xl-left{right:auto;left:0}.dropdown-menu-xl-right{right:0;left:auto}}.dropup .dropdown-menu{top:auto;bottom:100%;margin-top:0;margin-bottom:.125rem}.dropup .dropdown-toggle::after{display:inline-block;margin-left:.255em;vertical-align:.255em;content:"";border-top:0;border-right:.3em solid transparent;border-bottom:.3em solid;border-left:.3em solid transparent}.dropup .dropdown-toggle:empty::after{margin-left:0}.dropright .dropdown-menu{top:0;right:auto;left:100%;margin-top:0;margin-left:.125rem}.dropright .dropdown-toggle::after{display:inline-block;margin-left:.255em;vertical-align:.255em;content:"";border-top:.3em solid transparent;border-right:0;border-bottom:.3em solid transparent;border-left:.3em solid}.dropright .dropdown-toggle:empty::after{margin-left:0}.dropright .dropdown-toggle::after{vertical-align:0}.dropleft .dropdown-menu{top:0;right:100%;left:auto;margin-top:0;margin-right:.125rem}.dropleft .dropdown-toggle::after{display:inline-block;margin-left:.255em;vertical-align:.255em;content:""}.dropleft .dropdown-toggle::after{display:none}.dropleft .dropdown-toggle::before{display:inline-block;margin-right:.255em;vertical-align:.255em;content:"";border-top:.3em solid transparent;border-right:.3em solid;border-bottom:.3em solid transparent}.dropleft .dropdown-toggle:empty::after{margin-left:0}.dropleft .dropdown-toggle::before{vertical-align:0}.dropdown-menu[x-placement^=bottom],.dropdown-menu[x-placement^=left],.dropdown-menu[x-placement^=right],.dropdown-menu[x-placement^=top]{right:auto;bottom:auto}.dropdown-divider{height:0;margin:.5rem 0;overflow:hidden;border-top:1px solid #e9ecef}.dropdown-item{display:block;width:100%;padding:.25rem 1.5rem;clear:both;font-weight:400;color:#212529;text-align:inherit;white-space:nowrap;background-color:transparent;border:0}.dropdown-item:focus,.dropdown-item:hover{color:#16181b;text-decoration:none;background-color:#f8f9fa}.dropdown-item.active,.dropdown-item:active{color:#fff;text-decoration:none;background-color:#007bff}.dropdown-item.disabled,.dropdown-item:disabled{color:#6c757d;pointer-events:none;background-color:transparent}.dropdown-menu.show{display:block}.dropdown-header{display:block;padding:.5rem 1.5rem;margin-bottom:0;font-size:.875rem;color:#6c757d;white-space:nowrap}.dropdown-item-text{display:block;padding:.25rem 1.5rem;color:#212529}.btn-group,.btn-group-vertical{position:relative;display:-ms-inline-flexbox;display:inline-flex;vertical-align:middle}.btn-group-vertical>.btn,.btn-group>.btn{position:relative;-ms-flex:1 1 auto;flex:1 1 auto}.btn-group-vertical>.btn:hover,.btn-group>.btn:hover{z-index:1}.btn-group-vertical>.btn.active,.btn-group-vertical>.btn:active,.btn-group-vertical>.btn:focus,.btn-group>.btn.active,.btn-group>.btn:active,.btn-group>.btn:focus{z-index:1}.btn-toolbar{display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;-ms-flex-pack:start;justify-content:flex-start}.btn-toolbar .input-group{width:auto}.btn-group>.btn-group:not(:first-child),.btn-group>.btn:not(:first-child){margin-left:-1px}.btn-group>.btn-group:not(:last-child)>.btn,.btn-group>.btn:not(:last-child):not(.dropdown-toggle){border-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn-group:not(:first-child)>.btn,.btn-group>.btn:not(:first-child){border-top-left-radius:0;border-bottom-left-radius:0}.dropdown-toggle-split{padding-right:.5625rem;padding-left:.5625rem}.dropdown-toggle-split::after,.dropright .dropdown-toggle-split::after,.dropup .dropdown-toggle-split::after{margin-left:0}.dropleft .dropdown-toggle-split::before{margin-right:0}.btn-group-sm>.btn+.dropdown-toggle-split,.btn-sm+.dropdown-toggle-split{padding-right:.375rem;padding-left:.375rem}.btn-group-lg>.btn+.dropdown-toggle-split,.btn-lg+.dropdown-toggle-split{padding-right:.75rem;padding-left:.75rem}.btn-group-vertical{-ms-flex-direction:column;flex-direction:column;-ms-flex-align:start;align-items:flex-start;-ms-flex-pack:center;justify-content:center}.btn-group-vertical>.btn,.btn-group-vertical>.btn-group{width:100%}.btn-group-vertical>.btn-group:not(:first-child),.btn-group-vertical>.btn:not(:first-child){margin-top:-1px}.btn-group-vertical>.btn-group:not(:last-child)>.btn,.btn-group-vertical>.btn:not(:last-child):not(.dropdown-toggle){border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn-group:not(:first-child)>.btn,.btn-group-vertical>.btn:not(:first-child){border-top-left-radius:0;border-top-right-radius:0}.btn-group-toggle>.btn,.btn-group-toggle>.btn-group>.btn{margin-bottom:0}.btn-group-toggle>.btn input[type=checkbox],.btn-group-toggle>.btn input[type=radio],.btn-group-toggle>.btn-group>.btn input[type=checkbox],.btn-group-toggle>.btn-group>.btn input[type=radio]{position:absolute;clip:rect(0,0,0,0);pointer-events:none}.input-group{position:relative;display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;-ms-flex-align:stretch;align-items:stretch;width:100%}.input-group>.custom-file,.input-group>.custom-select,.input-group>.form-control,.input-group>.form-control-plaintext{position:relative;-ms-flex:1 1 auto;flex:1 1 auto;width:1%;margin-bottom:0}.input-group>.custom-file+.custom-file,.input-group>.custom-file+.custom-select,.input-group>.custom-file+.form-control,.input-group>.custom-select+.custom-file,.input-group>.custom-select+.custom-select,.input-group>.custom-select+.form-control,.input-group>.form-control+.custom-file,.input-group>.form-control+.custom-select,.input-group>.form-control+.form-control,.input-group>.form-control-plaintext+.custom-file,.input-group>.form-control-plaintext+.custom-select,.input-group>.form-control-plaintext+.form-control{margin-left:-1px}.input-group>.custom-file .custom-file-input:focus~.custom-file-label,.input-group>.custom-select:focus,.input-group>.form-control:focus{z-index:3}.input-group>.custom-file .custom-file-input:focus{z-index:4}.input-group>.custom-select:not(:last-child),.input-group>.form-control:not(:last-child){border-top-right-radius:0;border-bottom-right-radius:0}.input-group>.custom-select:not(:first-child),.input-group>.form-control:not(:first-child){border-top-left-radius:0;border-bottom-left-radius:0}.input-group>.custom-file{display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center}.input-group>.custom-file:not(:last-child) .custom-file-label,.input-group>.custom-file:not(:last-child) .custom-file-label::after{border-top-right-radius:0;border-bottom-right-radius:0}.input-group>.custom-file:not(:first-child) .custom-file-label{border-top-left-radius:0;border-bottom-left-radius:0}.input-group-append,.input-group-prepend{display:-ms-flexbox;display:flex}.input-group-append .btn,.input-group-prepend .btn{position:relative;z-index:2}.input-group-append .btn:focus,.input-group-prepend .btn:focus{z-index:3}.input-group-append .btn+.btn,.input-group-append .btn+.input-group-text,.input-group-append .input-group-text+.btn,.input-group-append .input-group-text+.input-group-text,.input-group-prepend .btn+.btn,.input-group-prepend .btn+.input-group-text,.input-group-prepend .input-group-text+.btn,.input-group-prepend .input-group-text+.input-group-text{margin-left:-1px}.input-group-prepend{margin-right:-1px}.input-group-append{margin-left:-1px}.input-group-text{display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center;padding:.375rem .75rem;margin-bottom:0;font-size:1rem;font-weight:400;line-height:1.5;color:#495057;text-align:center;white-space:nowrap;background-color:#e9ecef;border:1px solid #ced4da;border-radius:.25rem}.input-group-text input[type=checkbox],.input-group-text input[type=radio]{margin-top:0}.input-group-lg>.custom-select,.input-group-lg>.form-control:not(textarea){height:calc(1.5em + 1rem + 2px)}.input-group-lg>.custom-select,.input-group-lg>.form-control,.input-group-lg>.input-group-append>.btn,.input-group-lg>.input-group-append>.input-group-text,.input-group-lg>.input-group-prepend>.btn,.input-group-lg>.input-group-prepend>.input-group-text{padding:.5rem 1rem;font-size:1.25rem;line-height:1.5;border-radius:.3rem}.input-group-sm>.custom-select,.input-group-sm>.form-control:not(textarea){height:calc(1.5em + .5rem + 2px)}.input-group-sm>.custom-select,.input-group-sm>.form-control,.input-group-sm>.input-group-append>.btn,.input-group-sm>.input-group-append>.input-group-text,.input-group-sm>.input-group-prepend>.btn,.input-group-sm>.input-group-prepend>.input-group-text{padding:.25rem .5rem;font-size:.875rem;line-height:1.5;border-radius:.2rem}.input-group-lg>.custom-select,.input-group-sm>.custom-select{padding-right:1.75rem}.input-group>.input-group-append:last-child>.btn:not(:last-child):not(.dropdown-toggle),.input-group>.input-group-append:last-child>.input-group-text:not(:last-child),.input-group>.input-group-append:not(:last-child)>.btn,.input-group>.input-group-append:not(:last-child)>.input-group-text,.input-group>.input-group-prepend>.btn,.input-group>.input-group-prepend>.input-group-text{border-top-right-radius:0;border-bottom-right-radius:0}.input-group>.input-group-append>.btn,.input-group>.input-group-append>.input-group-text,.input-group>.input-group-prepend:first-child>.btn:not(:first-child),.input-group>.input-group-prepend:first-child>.input-group-text:not(:first-child),.input-group>.input-group-prepend:not(:first-child)>.btn,.input-group>.input-group-prepend:not(:first-child)>.input-group-text{border-top-left-radius:0;border-bottom-left-radius:0}.custom-control{position:relative;display:block;min-height:1.5rem;padding-left:1.5rem}.custom-control-inline{display:-ms-inline-flexbox;display:inline-flex;margin-right:1rem}.custom-control-input{position:absolute;z-index:-1;opacity:0}.custom-control-input:checked~.custom-control-label::before{color:#fff;border-color:#007bff;background-color:#007bff}.custom-control-input:focus~.custom-control-label::before{box-shadow:0 0 0 .2rem rgba(0,123,255,.25)}.custom-control-input:focus:not(:checked)~.custom-control-label::before{border-color:#80bdff}.custom-control-input:not(:disabled):active~.custom-control-label::before{color:#fff;background-color:#b3d7ff;border-color:#b3d7ff}.custom-control-input:disabled~.custom-control-label{color:#6c757d}.custom-control-input:disabled~.custom-control-label::before{background-color:#e9ecef}.custom-control-label{position:relative;margin-bottom:0;vertical-align:top}.custom-control-label::before{position:absolute;top:.25rem;left:-1.5rem;display:block;width:1rem;height:1rem;pointer-events:none;content:"";background-color:#fff;border:#adb5bd solid 1px}.custom-control-label::after{position:absolute;top:.25rem;left:-1.5rem;display:block;width:1rem;height:1rem;content:"";background:no-repeat 50%/50% 50%}.custom-checkbox .custom-control-label::before{border-radius:.25rem}.custom-checkbox .custom-control-input:checked~.custom-control-label::after{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3e%3cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3e%3c/svg%3e")}.custom-checkbox .custom-control-input:indeterminate~.custom-control-label::before{border-color:#007bff;background-color:#007bff}.custom-checkbox .custom-control-input:indeterminate~.custom-control-label::after{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 4'%3e%3cpath stroke='%23fff' d='M0 2h4'/%3e%3c/svg%3e")}.custom-checkbox .custom-control-input:disabled:checked~.custom-control-label::before{background-color:rgba(0,123,255,.5)}.custom-checkbox .custom-control-input:disabled:indeterminate~.custom-control-label::before{background-color:rgba(0,123,255,.5)}.custom-radio .custom-control-label::before{border-radius:50%}.custom-radio .custom-control-input:checked~.custom-control-label::after{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%23fff'/%3e%3c/svg%3e")}.custom-radio .custom-control-input:disabled:checked~.custom-control-label::before{background-color:rgba(0,123,255,.5)}.custom-switch{padding-left:2.25rem}.custom-switch .custom-control-label::before{left:-2.25rem;width:1.75rem;pointer-events:all;border-radius:.5rem}.custom-switch .custom-control-label::after{top:calc(.25rem + 2px);left:calc(-2.25rem + 2px);width:calc(1rem - 4px);height:calc(1rem - 4px);background-color:#adb5bd;border-radius:.5rem;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out,-webkit-transform .15s ease-in-out;transition:transform .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:transform .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out,-webkit-transform .15s ease-in-out}@media (prefers-reduced-motion:reduce){.custom-switch .custom-control-label::after{transition:none}}.custom-switch .custom-control-input:checked~.custom-control-label::after{background-color:#fff;-webkit-transform:translateX(.75rem);transform:translateX(.75rem)}.custom-switch .custom-control-input:disabled:checked~.custom-control-label::before{background-color:rgba(0,123,255,.5)}.custom-select{display:inline-block;width:100%;height:calc(1.5em + .75rem + 2px);padding:.375rem 1.75rem .375rem .75rem;font-size:1rem;font-weight:400;line-height:1.5;color:#495057;vertical-align:middle;background:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 5'%3e%3cpath fill='%23343a40' d='M2 0L0 2h4zm0 5L0 3h4z'/%3e%3c/svg%3e") no-repeat right .75rem center/8px 10px;background-color:#fff;border:1px solid #ced4da;border-radius:.25rem;-webkit-appearance:none;-moz-appearance:none;appearance:none}.custom-select:focus{border-color:#80bdff;outline:0;box-shadow:0 0 0 .2rem rgba(0,123,255,.25)}.custom-select:focus::-ms-value{color:#495057;background-color:#fff}.custom-select[multiple],.custom-select[size]:not([size="1"]){height:auto;padding-right:.75rem;background-image:none}.custom-select:disabled{color:#6c757d;background-color:#e9ecef}.custom-select::-ms-expand{display:none}.custom-select-sm{height:calc(1.5em + .5rem + 2px);padding-top:.25rem;padding-bottom:.25rem;padding-left:.5rem;font-size:.875rem}.custom-select-lg{height:calc(1.5em + 1rem + 2px);padding-top:.5rem;padding-bottom:.5rem;padding-left:1rem;font-size:1.25rem}.custom-file{position:relative;display:inline-block;width:100%;height:calc(1.5em + .75rem + 2px);margin-bottom:0}.custom-file-input{position:relative;z-index:2;width:100%;height:calc(1.5em + .75rem + 2px);margin:0;opacity:0}.custom-file-input:focus~.custom-file-label{border-color:#80bdff;box-shadow:0 0 0 .2rem rgba(0,123,255,.25)}.custom-file-input:disabled~.custom-file-label{background-color:#e9ecef}.custom-file-input:lang(en)~.custom-file-label::after{content:"Browse"}.custom-file-input~.custom-file-label[data-browse]::after{content:attr(data-browse)}.custom-file-label{position:absolute;top:0;right:0;left:0;z-index:1;height:calc(1.5em + .75rem + 2px);padding:.375rem .75rem;font-weight:400;line-height:1.5;color:#495057;background-color:#fff;border:1px solid #ced4da;border-radius:.25rem}.custom-file-label::after{position:absolute;top:0;right:0;bottom:0;z-index:3;display:block;height:calc(1.5em + .75rem);padding:.375rem .75rem;line-height:1.5;color:#495057;content:"Browse";background-color:#e9ecef;border-left:inherit;border-radius:0 .25rem .25rem 0}.custom-range{width:100%;height:calc(1rem + .4rem);padding:0;background-color:transparent;-webkit-appearance:none;-moz-appearance:none;appearance:none}.custom-range:focus{outline:0}.custom-range:focus::-webkit-slider-thumb{box-shadow:0 0 0 1px #fff,0 0 0 .2rem rgba(0,123,255,.25)}.custom-range:focus::-moz-range-thumb{box-shadow:0 0 0 1px #fff,0 0 0 .2rem rgba(0,123,255,.25)}.custom-range:focus::-ms-thumb{box-shadow:0 0 0 1px #fff,0 0 0 .2rem rgba(0,123,255,.25)}.custom-range::-moz-focus-outer{border:0}.custom-range::-webkit-slider-thumb{width:1rem;height:1rem;margin-top:-.25rem;background-color:#007bff;border:0;border-radius:1rem;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;-webkit-appearance:none;appearance:none}@media (prefers-reduced-motion:reduce){.custom-range::-webkit-slider-thumb{transition:none}}.custom-range::-webkit-slider-thumb:active{background-color:#b3d7ff}.custom-range::-webkit-slider-runnable-track{width:100%;height:.5rem;color:transparent;cursor:pointer;background-color:#dee2e6;border-color:transparent;border-radius:1rem}.custom-range::-moz-range-thumb{width:1rem;height:1rem;background-color:#007bff;border:0;border-radius:1rem;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;-moz-appearance:none;appearance:none}@media (prefers-reduced-motion:reduce){.custom-range::-moz-range-thumb{transition:none}}.custom-range::-moz-range-thumb:active{background-color:#b3d7ff}.custom-range::-moz-range-track{width:100%;height:.5rem;color:transparent;cursor:pointer;background-color:#dee2e6;border-color:transparent;border-radius:1rem}.custom-range::-ms-thumb{width:1rem;height:1rem;margin-top:0;margin-right:.2rem;margin-left:.2rem;background-color:#007bff;border:0;border-radius:1rem;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;appearance:none}@media (prefers-reduced-motion:reduce){.custom-range::-ms-thumb{transition:none}}.custom-range::-ms-thumb:active{background-color:#b3d7ff}.custom-range::-ms-track{width:100%;height:.5rem;color:transparent;cursor:pointer;background-color:transparent;border-color:transparent;border-width:.5rem}.custom-range::-ms-fill-lower{background-color:#dee2e6;border-radius:1rem}.custom-range::-ms-fill-upper{margin-right:15px;background-color:#dee2e6;border-radius:1rem}.custom-range:disabled::-webkit-slider-thumb{background-color:#adb5bd}.custom-range:disabled::-webkit-slider-runnable-track{cursor:default}.custom-range:disabled::-moz-range-thumb{background-color:#adb5bd}.custom-range:disabled::-moz-range-track{cursor:default}.custom-range:disabled::-ms-thumb{background-color:#adb5bd}.custom-control-label::before,.custom-file-label,.custom-select{transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.custom-control-label::before,.custom-file-label,.custom-select{transition:none}}.nav{display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;padding-left:0;margin-bottom:0;list-style:none}.nav-link{display:block;padding:.5rem 1rem}.nav-link:focus,.nav-link:hover{text-decoration:none}.nav-link.disabled{color:#6c757d;pointer-events:none;cursor:default}.nav-tabs{border-bottom:1px solid #dee2e6}.nav-tabs .nav-item{margin-bottom:-1px}.nav-tabs .nav-link{border:1px solid transparent;border-top-left-radius:.25rem;border-top-right-radius:.25rem}.nav-tabs .nav-link:focus,.nav-tabs .nav-link:hover{border-color:#e9ecef #e9ecef #dee2e6}.nav-tabs .nav-link.disabled{color:#6c757d;background-color:transparent;border-color:transparent}.nav-tabs .nav-item.show .nav-link,.nav-tabs .nav-link.active{color:#495057;background-color:#fff;border-color:#dee2e6 #dee2e6 #fff}.nav-tabs .dropdown-menu{margin-top:-1px;border-top-left-radius:0;border-top-right-radius:0}.nav-pills .nav-link{border-radius:.25rem}.nav-pills .nav-link.active,.nav-pills .show>.nav-link{color:#fff;background-color:#007bff}.nav-fill .nav-item{-ms-flex:1 1 auto;flex:1 1 auto;text-align:center}.nav-justified .nav-item{-ms-flex-preferred-size:0;flex-basis:0;-ms-flex-positive:1;flex-grow:1;text-align:center}.tab-content>.tab-pane{display:none}.tab-content>.active{display:block}.navbar{position:relative;display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;-ms-flex-align:center;align-items:center;-ms-flex-pack:justify;justify-content:space-between;padding:.5rem 1rem}.navbar>.container,.navbar>.container-fluid{display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;-ms-flex-align:center;align-items:center;-ms-flex-pack:justify;justify-content:space-between}.navbar-brand{display:inline-block;padding-top:.3125rem;padding-bottom:.3125rem;margin-right:1rem;font-size:1.25rem;line-height:inherit;white-space:nowrap}.navbar-brand:focus,.navbar-brand:hover{text-decoration:none}.navbar-nav{display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;padding-left:0;margin-bottom:0;list-style:none}.navbar-nav .nav-link{padding-right:0;padding-left:0}.navbar-nav .dropdown-menu{position:static;float:none}.navbar-text{display:inline-block;padding-top:.5rem;padding-bottom:.5rem}.navbar-collapse{-ms-flex-preferred-size:100%;flex-basis:100%;-ms-flex-positive:1;flex-grow:1;-ms-flex-align:center;align-items:center}.navbar-toggler{padding:.25rem .75rem;font-size:1.25rem;line-height:1;background-color:transparent;border:1px solid transparent;border-radius:.25rem}.navbar-toggler:focus,.navbar-toggler:hover{text-decoration:none}.navbar-toggler-icon{display:inline-block;width:1.5em;height:1.5em;vertical-align:middle;content:"";background:no-repeat center center;background-size:100% 100%}@media (max-width:575.98px){.navbar-expand-sm>.container,.navbar-expand-sm>.container-fluid{padding-right:0;padding-left:0}}@media (min-width:576px){.navbar-expand-sm{-ms-flex-flow:row nowrap;flex-flow:row nowrap;-ms-flex-pack:start;justify-content:flex-start}.navbar-expand-sm .navbar-nav{-ms-flex-direction:row;flex-direction:row}.navbar-expand-sm .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-sm .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand-sm>.container,.navbar-expand-sm>.container-fluid{-ms-flex-wrap:nowrap;flex-wrap:nowrap}.navbar-expand-sm .navbar-collapse{display:-ms-flexbox!important;display:flex!important;-ms-flex-preferred-size:auto;flex-basis:auto}.navbar-expand-sm .navbar-toggler{display:none}}@media (max-width:767.98px){.navbar-expand-md>.container,.navbar-expand-md>.container-fluid{padding-right:0;padding-left:0}}@media (min-width:768px){.navbar-expand-md{-ms-flex-flow:row nowrap;flex-flow:row nowrap;-ms-flex-pack:start;justify-content:flex-start}.navbar-expand-md .navbar-nav{-ms-flex-direction:row;flex-direction:row}.navbar-expand-md .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-md .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand-md>.container,.navbar-expand-md>.container-fluid{-ms-flex-wrap:nowrap;flex-wrap:nowrap}.navbar-expand-md .navbar-collapse{display:-ms-flexbox!important;display:flex!important;-ms-flex-preferred-size:auto;flex-basis:auto}.navbar-expand-md .navbar-toggler{display:none}}@media (max-width:991.98px){.navbar-expand-lg>.container,.navbar-expand-lg>.container-fluid{padding-right:0;padding-left:0}}@media (min-width:992px){.navbar-expand-lg{-ms-flex-flow:row nowrap;flex-flow:row nowrap;-ms-flex-pack:start;justify-content:flex-start}.navbar-expand-lg .navbar-nav{-ms-flex-direction:row;flex-direction:row}.navbar-expand-lg .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-lg .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand-lg>.container,.navbar-expand-lg>.container-fluid{-ms-flex-wrap:nowrap;flex-wrap:nowrap}.navbar-expand-lg .navbar-collapse{display:-ms-flexbox!important;display:flex!important;-ms-flex-preferred-size:auto;flex-basis:auto}.navbar-expand-lg .navbar-toggler{display:none}}@media (max-width:1199.98px){.navbar-expand-xl>.container,.navbar-expand-xl>.container-fluid{padding-right:0;padding-left:0}}@media (min-width:1200px){.navbar-expand-xl{-ms-flex-flow:row nowrap;flex-flow:row nowrap;-ms-flex-pack:start;justify-content:flex-start}.navbar-expand-xl .navbar-nav{-ms-flex-direction:row;flex-direction:row}.navbar-expand-xl .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-xl .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand-xl>.container,.navbar-expand-xl>.container-fluid{-ms-flex-wrap:nowrap;flex-wrap:nowrap}.navbar-expand-xl .navbar-collapse{display:-ms-flexbox!important;display:flex!important;-ms-flex-preferred-size:auto;flex-basis:auto}.navbar-expand-xl .navbar-toggler{display:none}}.navbar-expand{-ms-flex-flow:row nowrap;flex-flow:row nowrap;-ms-flex-pack:start;justify-content:flex-start}.navbar-expand>.container,.navbar-expand>.container-fluid{padding-right:0;padding-left:0}.navbar-expand .navbar-nav{-ms-flex-direction:row;flex-direction:row}.navbar-expand .navbar-nav .dropdown-menu{position:absolute}.navbar-expand .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand>.container,.navbar-expand>.container-fluid{-ms-flex-wrap:nowrap;flex-wrap:nowrap}.navbar-expand .navbar-collapse{display:-ms-flexbox!important;display:flex!important;-ms-flex-preferred-size:auto;flex-basis:auto}.navbar-expand .navbar-toggler{display:none}.navbar-light .navbar-brand{color:rgba(0,0,0,.9)}.navbar-light .navbar-brand:focus,.navbar-light .navbar-brand:hover{color:rgba(0,0,0,.9)}.navbar-light .navbar-nav .nav-link{color:rgba(0,0,0,.5)}.navbar-light .navbar-nav .nav-link:focus,.navbar-light .navbar-nav .nav-link:hover{color:rgba(0,0,0,.7)}.navbar-light .navbar-nav .nav-link.disabled{color:rgba(0,0,0,.3)}.navbar-light .navbar-nav .active>.nav-link,.navbar-light .navbar-nav .nav-link.active,.navbar-light .navbar-nav .nav-link.show,.navbar-light .navbar-nav .show>.nav-link{color:rgba(0,0,0,.9)}.navbar-light .navbar-toggler{color:rgba(0,0,0,.5);border-color:rgba(0,0,0,.1)}.navbar-light .navbar-toggler-icon{background-image:url("data:image/svg+xml,%3csvg viewBox='0 0 30 30' xmlns='http://www.w3.org/2000/svg'%3e%3cpath stroke='rgba(0, 0, 0, 0.5)' stroke-width='2' stroke-linecap='round' stroke-miterlimit='10' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e")}.navbar-light .navbar-text{color:rgba(0,0,0,.5)}.navbar-light .navbar-text a{color:rgba(0,0,0,.9)}.navbar-light .navbar-text a:focus,.navbar-light .navbar-text a:hover{color:rgba(0,0,0,.9)}.navbar-dark .navbar-brand{color:#fff}.navbar-dark .navbar-brand:focus,.navbar-dark .navbar-brand:hover{color:#fff}.navbar-dark .navbar-nav .nav-link{color:rgba(255,255,255,.5)}.navbar-dark .navbar-nav .nav-link:focus,.navbar-dark .navbar-nav .nav-link:hover{color:rgba(255,255,255,.75)}.navbar-dark .navbar-nav .nav-link.disabled{color:rgba(255,255,255,.25)}.navbar-dark .navbar-nav .active>.nav-link,.navbar-dark .navbar-nav .nav-link.active,.navbar-dark .navbar-nav .nav-link.show,.navbar-dark .navbar-nav .show>.nav-link{color:#fff}.navbar-dark .navbar-toggler{color:rgba(255,255,255,.5);border-color:rgba(255,255,255,.1)}.navbar-dark .navbar-toggler-icon{background-image:url("data:image/svg+xml,%3csvg viewBox='0 0 30 30' xmlns='http://www.w3.org/2000/svg'%3e%3cpath stroke='rgba(255, 255, 255, 0.5)' stroke-width='2' stroke-linecap='round' stroke-miterlimit='10' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e")}.navbar-dark .navbar-text{color:rgba(255,255,255,.5)}.navbar-dark .navbar-text a{color:#fff}.navbar-dark .navbar-text a:focus,.navbar-dark .navbar-text a:hover{color:#fff}.card{position:relative;display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;min-width:0;word-wrap:break-word;background-color:#fff;background-clip:border-box;border:1px solid rgba(0,0,0,.125);border-radius:.25rem}.card>hr{margin-right:0;margin-left:0}.card>.list-group:first-child .list-group-item:first-child{border-top-left-radius:.25rem;border-top-right-radius:.25rem}.card>.list-group:last-child .list-group-item:last-child{border-bottom-right-radius:.25rem;border-bottom-left-radius:.25rem}.card-body{-ms-flex:1 1 auto;flex:1 1 auto;padding:1.25rem}.card-title{margin-bottom:.75rem}.card-subtitle{margin-top:-.375rem;margin-bottom:0}.card-text:last-child{margin-bottom:0}.card-link:hover{text-decoration:none}.card-link+.card-link{margin-left:1.25rem}.card-header{padding:.75rem 1.25rem;margin-bottom:0;background-color:rgba(0,0,0,.03);border-bottom:1px solid rgba(0,0,0,.125)}.card-header:first-child{border-radius:calc(.25rem - 1px) calc(.25rem - 1px) 0 0}.card-header+.list-group .list-group-item:first-child{border-top:0}.card-footer{padding:.75rem 1.25rem;background-color:rgba(0,0,0,.03);border-top:1px solid rgba(0,0,0,.125)}.card-footer:last-child{border-radius:0 0 calc(.25rem - 1px) calc(.25rem - 1px)}.card-header-tabs{margin-right:-.625rem;margin-bottom:-.75rem;margin-left:-.625rem;border-bottom:0}.card-header-pills{margin-right:-.625rem;margin-left:-.625rem}.card-img-overlay{position:absolute;top:0;right:0;bottom:0;left:0;padding:1.25rem}.card-img{width:100%;border-radius:calc(.25rem - 1px)}.card-img-top{width:100%;border-top-left-radius:calc(.25rem - 1px);border-top-right-radius:calc(.25rem - 1px)}.card-img-bottom{width:100%;border-bottom-right-radius:calc(.25rem - 1px);border-bottom-left-radius:calc(.25rem - 1px)}.card-deck{display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column}.card-deck .card{margin-bottom:15px}@media (min-width:576px){.card-deck{-ms-flex-flow:row wrap;flex-flow:row wrap;margin-right:-15px;margin-left:-15px}.card-deck .card{display:-ms-flexbox;display:flex;-ms-flex:1 0 0%;flex:1 0 0%;-ms-flex-direction:column;flex-direction:column;margin-right:15px;margin-bottom:0;margin-left:15px}}.card-group{display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column}.card-group>.card{margin-bottom:15px}@media (min-width:576px){.card-group{-ms-flex-flow:row wrap;flex-flow:row wrap}.card-group>.card{-ms-flex:1 0 0%;flex:1 0 0%;margin-bottom:0}.card-group>.card+.card{margin-left:0;border-left:0}.card-group>.card:not(:last-child){border-top-right-radius:0;border-bottom-right-radius:0}.card-group>.card:not(:last-child) .card-header,.card-group>.card:not(:last-child) .card-img-top{border-top-right-radius:0}.card-group>.card:not(:last-child) .card-footer,.card-group>.card:not(:last-child) .card-img-bottom{border-bottom-right-radius:0}.card-group>.card:not(:first-child){border-top-left-radius:0;border-bottom-left-radius:0}.card-group>.card:not(:first-child) .card-header,.card-group>.card:not(:first-child) .card-img-top{border-top-left-radius:0}.card-group>.card:not(:first-child) .card-footer,.card-group>.card:not(:first-child) .card-img-bottom{border-bottom-left-radius:0}}.card-columns .card{margin-bottom:.75rem}@media (min-width:576px){.card-columns{-webkit-column-count:3;-moz-column-count:3;column-count:3;-webkit-column-gap:1.25rem;-moz-column-gap:1.25rem;column-gap:1.25rem;orphans:1;widows:1}.card-columns .card{display:inline-block;width:100%}}.accordion>.card{overflow:hidden}.accordion>.card:not(:first-of-type) .card-header:first-child{border-radius:0}.accordion>.card:not(:first-of-type):not(:last-of-type){border-bottom:0;border-radius:0}.accordion>.card:first-of-type{border-bottom:0;border-bottom-right-radius:0;border-bottom-left-radius:0}.accordion>.card:last-of-type{border-top-left-radius:0;border-top-right-radius:0}.accordion>.card .card-header{margin-bottom:-1px}.breadcrumb{display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;padding:.75rem 1rem;margin-bottom:1rem;list-style:none;background-color:#e9ecef;border-radius:.25rem}.breadcrumb-item+.breadcrumb-item{padding-left:.5rem}.breadcrumb-item+.breadcrumb-item::before{display:inline-block;padding-right:.5rem;color:#6c757d;content:"/"}.breadcrumb-item+.breadcrumb-item:hover::before{text-decoration:underline}.breadcrumb-item+.breadcrumb-item:hover::before{text-decoration:none}.breadcrumb-item.active{color:#6c757d}.pagination{display:-ms-flexbox;display:flex;padding-left:0;list-style:none;border-radius:.25rem}.page-link{position:relative;display:block;padding:.5rem .75rem;margin-left:-1px;line-height:1.25;color:#007bff;background-color:#fff;border:1px solid #dee2e6}.page-link:hover{z-index:2;color:#0056b3;text-decoration:none;background-color:#e9ecef;border-color:#dee2e6}.page-link:focus{z-index:2;outline:0;box-shadow:0 0 0 .2rem rgba(0,123,255,.25)}.page-item:first-child .page-link{margin-left:0;border-top-left-radius:.25rem;border-bottom-left-radius:.25rem}.page-item:last-child .page-link{border-top-right-radius:.25rem;border-bottom-right-radius:.25rem}.page-item.active .page-link{z-index:1;color:#fff;background-color:#007bff;border-color:#007bff}.page-item.disabled .page-link{color:#6c757d;pointer-events:none;cursor:auto;background-color:#fff;border-color:#dee2e6}.pagination-lg .page-link{padding:.75rem 1.5rem;font-size:1.25rem;line-height:1.5}.pagination-lg .page-item:first-child .page-link{border-top-left-radius:.3rem;border-bottom-left-radius:.3rem}.pagination-lg .page-item:last-child .page-link{border-top-right-radius:.3rem;border-bottom-right-radius:.3rem}.pagination-sm .page-link{padding:.25rem .5rem;font-size:.875rem;line-height:1.5}.pagination-sm .page-item:first-child .page-link{border-top-left-radius:.2rem;border-bottom-left-radius:.2rem}.pagination-sm .page-item:last-child .page-link{border-top-right-radius:.2rem;border-bottom-right-radius:.2rem}.badge{display:inline-block;padding:.25em .4em;font-size:75%;font-weight:700;line-height:1;text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:.25rem;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.badge{transition:none}}a.badge:focus,a.badge:hover{text-decoration:none}.badge:empty{display:none}.btn .badge{position:relative;top:-1px}.badge-pill{padding-right:.6em;padding-left:.6em;border-radius:10rem}.badge-primary{color:#fff;background-color:#007bff}a.badge-primary:focus,a.badge-primary:hover{color:#fff;background-color:#0062cc}a.badge-primary.focus,a.badge-primary:focus{outline:0;box-shadow:0 0 0 .2rem rgba(0,123,255,.5)}.badge-secondary{color:#fff;background-color:#6c757d}a.badge-secondary:focus,a.badge-secondary:hover{color:#fff;background-color:#545b62}a.badge-secondary.focus,a.badge-secondary:focus{outline:0;box-shadow:0 0 0 .2rem rgba(108,117,125,.5)}.badge-success{color:#fff;background-color:#28a745}a.badge-success:focus,a.badge-success:hover{color:#fff;background-color:#1e7e34}a.badge-success.focus,a.badge-success:focus{outline:0;box-shadow:0 0 0 .2rem rgba(40,167,69,.5)}.badge-info{color:#fff;background-color:#17a2b8}a.badge-info:focus,a.badge-info:hover{color:#fff;background-color:#117a8b}a.badge-info.focus,a.badge-info:focus{outline:0;box-shadow:0 0 0 .2rem rgba(23,162,184,.5)}.badge-warning{color:#212529;background-color:#ffc107}a.badge-warning:focus,a.badge-warning:hover{color:#212529;background-color:#d39e00}a.badge-warning.focus,a.badge-warning:focus{outline:0;box-shadow:0 0 0 .2rem rgba(255,193,7,.5)}.badge-danger{color:#fff;background-color:#dc3545}a.badge-danger:focus,a.badge-danger:hover{color:#fff;background-color:#bd2130}a.badge-danger.focus,a.badge-danger:focus{outline:0;box-shadow:0 0 0 .2rem rgba(220,53,69,.5)}.badge-light{color:#212529;background-color:#f8f9fa}a.badge-light:focus,a.badge-light:hover{color:#212529;background-color:#dae0e5}a.badge-light.focus,a.badge-light:focus{outline:0;box-shadow:0 0 0 .2rem rgba(248,249,250,.5)}.badge-dark{color:#fff;background-color:#343a40}a.badge-dark:focus,a.badge-dark:hover{color:#fff;background-color:#1d2124}a.badge-dark.focus,a.badge-dark:focus{outline:0;box-shadow:0 0 0 .2rem rgba(52,58,64,.5)}.jumbotron{padding:2rem 1rem;margin-bottom:2rem;background-color:#e9ecef;border-radius:.3rem}@media (min-width:576px){.jumbotron{padding:4rem 2rem}}.jumbotron-fluid{padding-right:0;padding-left:0;border-radius:0}.alert{position:relative;padding:.75rem 1.25rem;margin-bottom:1rem;border:1px solid transparent;border-radius:.25rem}.alert-heading{color:inherit}.alert-link{font-weight:700}.alert-dismissible{padding-right:4rem}.alert-dismissible .close{position:absolute;top:0;right:0;padding:.75rem 1.25rem;color:inherit}.alert-primary{color:#004085;background-color:#cce5ff;border-color:#b8daff}.alert-primary hr{border-top-color:#9fcdff}.alert-primary .alert-link{color:#002752}.alert-secondary{color:#383d41;background-color:#e2e3e5;border-color:#d6d8db}.alert-secondary hr{border-top-color:#c8cbcf}.alert-secondary .alert-link{color:#202326}.alert-success{color:#155724;background-color:#d4edda;border-color:#c3e6cb}.alert-success hr{border-top-color:#b1dfbb}.alert-success .alert-link{color:#0b2e13}.alert-info{color:#0c5460;background-color:#d1ecf1;border-color:#bee5eb}.alert-info hr{border-top-color:#abdde5}.alert-info .alert-link{color:#062c33}.alert-warning{color:#856404;background-color:#fff3cd;border-color:#ffeeba}.alert-warning hr{border-top-color:#ffe8a1}.alert-warning .alert-link{color:#533f03}.alert-danger{color:#721c24;background-color:#f8d7da;border-color:#f5c6cb}.alert-danger hr{border-top-color:#f1b0b7}.alert-danger .alert-link{color:#491217}.alert-light{color:#818182;background-color:#fefefe;border-color:#fdfdfe}.alert-light hr{border-top-color:#ececf6}.alert-light .alert-link{color:#686868}.alert-dark{color:#1b1e21;background-color:#d6d8d9;border-color:#c6c8ca}.alert-dark hr{border-top-color:#b9bbbe}.alert-dark .alert-link{color:#040505}@-webkit-keyframes progress-bar-stripes{from{background-position:1rem 0}to{background-position:0 0}}@keyframes progress-bar-stripes{from{background-position:1rem 0}to{background-position:0 0}}.progress{display:-ms-flexbox;display:flex;height:1rem;overflow:hidden;font-size:.75rem;background-color:#e9ecef;border-radius:.25rem}.progress-bar{display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;-ms-flex-pack:center;justify-content:center;color:#fff;text-align:center;white-space:nowrap;background-color:#007bff;transition:width .6s ease}@media (prefers-reduced-motion:reduce){.progress-bar{transition:none}}.progress-bar-striped{background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-size:1rem 1rem}.progress-bar-animated{-webkit-animation:progress-bar-stripes 1s linear infinite;animation:progress-bar-stripes 1s linear infinite}@media (prefers-reduced-motion:reduce){.progress-bar-animated{-webkit-animation:none;animation:none}}.media{display:-ms-flexbox;display:flex;-ms-flex-align:start;align-items:flex-start}.media-body{-ms-flex:1;flex:1}.list-group{display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;padding-left:0;margin-bottom:0}.list-group-item-action{width:100%;color:#495057;text-align:inherit}.list-group-item-action:focus,.list-group-item-action:hover{z-index:1;color:#495057;text-decoration:none;background-color:#f8f9fa}.list-group-item-action:active{color:#212529;background-color:#e9ecef}.list-group-item{position:relative;display:block;padding:.75rem 1.25rem;margin-bottom:-1px;background-color:#fff;border:1px solid rgba(0,0,0,.125)}.list-group-item:first-child{border-top-left-radius:.25rem;border-top-right-radius:.25rem}.list-group-item:last-child{margin-bottom:0;border-bottom-right-radius:.25rem;border-bottom-left-radius:.25rem}.list-group-item.disabled,.list-group-item:disabled{color:#6c757d;pointer-events:none;background-color:#fff}.list-group-item.active{z-index:2;color:#fff;background-color:#007bff;border-color:#007bff}.list-group-horizontal{-ms-flex-direction:row;flex-direction:row}.list-group-horizontal .list-group-item{margin-right:-1px;margin-bottom:0}.list-group-horizontal .list-group-item:first-child{border-top-left-radius:.25rem;border-bottom-left-radius:.25rem;border-top-right-radius:0}.list-group-horizontal .list-group-item:last-child{margin-right:0;border-top-right-radius:.25rem;border-bottom-right-radius:.25rem;border-bottom-left-radius:0}@media (min-width:576px){.list-group-horizontal-sm{-ms-flex-direction:row;flex-direction:row}.list-group-horizontal-sm .list-group-item{margin-right:-1px;margin-bottom:0}.list-group-horizontal-sm .list-group-item:first-child{border-top-left-radius:.25rem;border-bottom-left-radius:.25rem;border-top-right-radius:0}.list-group-horizontal-sm .list-group-item:last-child{margin-right:0;border-top-right-radius:.25rem;border-bottom-right-radius:.25rem;border-bottom-left-radius:0}}@media (min-width:768px){.list-group-horizontal-md{-ms-flex-direction:row;flex-direction:row}.list-group-horizontal-md .list-group-item{margin-right:-1px;margin-bottom:0}.list-group-horizontal-md .list-group-item:first-child{border-top-left-radius:.25rem;border-bottom-left-radius:.25rem;border-top-right-radius:0}.list-group-horizontal-md .list-group-item:last-child{margin-right:0;border-top-right-radius:.25rem;border-bottom-right-radius:.25rem;border-bottom-left-radius:0}}@media (min-width:992px){.list-group-horizontal-lg{-ms-flex-direction:row;flex-direction:row}.list-group-horizontal-lg .list-group-item{margin-right:-1px;margin-bottom:0}.list-group-horizontal-lg .list-group-item:first-child{border-top-left-radius:.25rem;border-bottom-left-radius:.25rem;border-top-right-radius:0}.list-group-horizontal-lg .list-group-item:last-child{margin-right:0;border-top-right-radius:.25rem;border-bottom-right-radius:.25rem;border-bottom-left-radius:0}}@media (min-width:1200px){.list-group-horizontal-xl{-ms-flex-direction:row;flex-direction:row}.list-group-horizontal-xl .list-group-item{margin-right:-1px;margin-bottom:0}.list-group-horizontal-xl .list-group-item:first-child{border-top-left-radius:.25rem;border-bottom-left-radius:.25rem;border-top-right-radius:0}.list-group-horizontal-xl .list-group-item:last-child{margin-right:0;border-top-right-radius:.25rem;border-bottom-right-radius:.25rem;border-bottom-left-radius:0}}.list-group-flush .list-group-item{border-right:0;border-left:0;border-radius:0}.list-group-flush .list-group-item:last-child{margin-bottom:-1px}.list-group-flush:first-child .list-group-item:first-child{border-top:0}.list-group-flush:last-child .list-group-item:last-child{margin-bottom:0;border-bottom:0}.list-group-item-primary{color:#004085;background-color:#b8daff}.list-group-item-primary.list-group-item-action:focus,.list-group-item-primary.list-group-item-action:hover{color:#004085;background-color:#9fcdff}.list-group-item-primary.list-group-item-action.active{color:#fff;background-color:#004085;border-color:#004085}.list-group-item-secondary{color:#383d41;background-color:#d6d8db}.list-group-item-secondary.list-group-item-action:focus,.list-group-item-secondary.list-group-item-action:hover{color:#383d41;background-color:#c8cbcf}.list-group-item-secondary.list-group-item-action.active{color:#fff;background-color:#383d41;border-color:#383d41}.list-group-item-success{color:#155724;background-color:#c3e6cb}.list-group-item-success.list-group-item-action:focus,.list-group-item-success.list-group-item-action:hover{color:#155724;background-color:#b1dfbb}.list-group-item-success.list-group-item-action.active{color:#fff;background-color:#155724;border-color:#155724}.list-group-item-info{color:#0c5460;background-color:#bee5eb}.list-group-item-info.list-group-item-action:focus,.list-group-item-info.list-group-item-action:hover{color:#0c5460;background-color:#abdde5}.list-group-item-info.list-group-item-action.active{color:#fff;background-color:#0c5460;border-color:#0c5460}.list-group-item-warning{color:#856404;background-color:#ffeeba}.list-group-item-warning.list-group-item-action:focus,.list-group-item-warning.list-group-item-action:hover{color:#856404;background-color:#ffe8a1}.list-group-item-warning.list-group-item-action.active{color:#fff;background-color:#856404;border-color:#856404}.list-group-item-danger{color:#721c24;background-color:#f5c6cb}.list-group-item-danger.list-group-item-action:focus,.list-group-item-danger.list-group-item-action:hover{color:#721c24;background-color:#f1b0b7}.list-group-item-danger.list-group-item-action.active{color:#fff;background-color:#721c24;border-color:#721c24}.list-group-item-light{color:#818182;background-color:#fdfdfe}.list-group-item-light.list-group-item-action:focus,.list-group-item-light.list-group-item-action:hover{color:#818182;background-color:#ececf6}.list-group-item-light.list-group-item-action.active{color:#fff;background-color:#818182;border-color:#818182}.list-group-item-dark{color:#1b1e21;background-color:#c6c8ca}.list-group-item-dark.list-group-item-action:focus,.list-group-item-dark.list-group-item-action:hover{color:#1b1e21;background-color:#b9bbbe}.list-group-item-dark.list-group-item-action.active{color:#fff;background-color:#1b1e21;border-color:#1b1e21}.close{float:right;font-size:1.5rem;font-weight:700;line-height:1;color:#000;text-shadow:0 1px 0 #fff;opacity:.5}.close:hover{color:#000;text-decoration:none}.close:not(:disabled):not(.disabled):focus,.close:not(:disabled):not(.disabled):hover{opacity:.75}button.close{padding:0;background-color:transparent;border:0;-webkit-appearance:none;-moz-appearance:none;appearance:none}a.close.disabled{pointer-events:none}.toast{max-width:350px;overflow:hidden;font-size:.875rem;background-color:rgba(255,255,255,.85);background-clip:padding-box;border:1px solid rgba(0,0,0,.1);box-shadow:0 .25rem .75rem rgba(0,0,0,.1);-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);opacity:0;border-radius:.25rem}.toast:not(:last-child){margin-bottom:.75rem}.toast.showing{opacity:1}.toast.show{display:block;opacity:1}.toast.hide{display:none}.toast-header{display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center;padding:.25rem .75rem;color:#6c757d;background-color:rgba(255,255,255,.85);background-clip:padding-box;border-bottom:1px solid rgba(0,0,0,.05)}.toast-body{padding:.75rem}.modal-open{overflow:hidden}.modal-open .modal{overflow-x:hidden;overflow-y:auto}.modal{position:fixed;top:0;left:0;z-index:1050;display:none;width:100%;height:100%;overflow:hidden;outline:0}.modal-dialog{position:relative;width:auto;margin:.5rem;pointer-events:none}.modal.fade .modal-dialog{transition:-webkit-transform .3s ease-out;transition:transform .3s ease-out;transition:transform .3s ease-out,-webkit-transform .3s ease-out;-webkit-transform:translate(0,-50px);transform:translate(0,-50px)}@media (prefers-reduced-motion:reduce){.modal.fade .modal-dialog{transition:none}}.modal.show .modal-dialog{-webkit-transform:none;transform:none}.modal-dialog-scrollable{display:-ms-flexbox;display:flex;max-height:calc(100% - 1rem)}.modal-dialog-scrollable .modal-content{max-height:calc(100vh - 1rem);overflow:hidden}.modal-dialog-scrollable .modal-footer,.modal-dialog-scrollable .modal-header{-ms-flex-negative:0;flex-shrink:0}.modal-dialog-scrollable .modal-body{overflow-y:auto}.modal-dialog-centered{display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center;min-height:calc(100% - 1rem)}.modal-dialog-centered::before{display:block;height:calc(100vh - 1rem);content:""}.modal-dialog-centered.modal-dialog-scrollable{-ms-flex-direction:column;flex-direction:column;-ms-flex-pack:center;justify-content:center;height:100%}.modal-dialog-centered.modal-dialog-scrollable .modal-content{max-height:none}.modal-dialog-centered.modal-dialog-scrollable::before{content:none}.modal-content{position:relative;display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;width:100%;pointer-events:auto;background-color:#fff;background-clip:padding-box;border:1px solid rgba(0,0,0,.2);border-radius:.3rem;outline:0}.modal-backdrop{position:fixed;top:0;left:0;z-index:1040;width:100vw;height:100vh;background-color:#000}.modal-backdrop.fade{opacity:0}.modal-backdrop.show{opacity:.5}.modal-header{display:-ms-flexbox;display:flex;-ms-flex-align:start;align-items:flex-start;-ms-flex-pack:justify;justify-content:space-between;padding:1rem 1rem;border-bottom:1px solid #dee2e6;border-top-left-radius:.3rem;border-top-right-radius:.3rem}.modal-header .close{padding:1rem 1rem;margin:-1rem -1rem -1rem auto}.modal-title{margin-bottom:0;line-height:1.5}.modal-body{position:relative;-ms-flex:1 1 auto;flex:1 1 auto;padding:1rem}.modal-footer{display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center;-ms-flex-pack:end;justify-content:flex-end;padding:1rem;border-top:1px solid #dee2e6;border-bottom-right-radius:.3rem;border-bottom-left-radius:.3rem}.modal-footer>:not(:first-child){margin-left:.25rem}.modal-footer>:not(:last-child){margin-right:.25rem}.modal-scrollbar-measure{position:absolute;top:-9999px;width:50px;height:50px;overflow:scroll}@media (min-width:576px){.modal-dialog{max-width:500px;margin:1.75rem auto}.modal-dialog-scrollable{max-height:calc(100% - 3.5rem)}.modal-dialog-scrollable .modal-content{max-height:calc(100vh - 3.5rem)}.modal-dialog-centered{min-height:calc(100% - 3.5rem)}.modal-dialog-centered::before{height:calc(100vh - 3.5rem)}.modal-sm{max-width:300px}}@media (min-width:992px){.modal-lg,.modal-xl{max-width:800px}}@media (min-width:1200px){.modal-xl{max-width:1140px}}.tooltip{position:absolute;z-index:1070;display:block;margin:0;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";font-style:normal;font-weight:400;line-height:1.5;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;word-spacing:normal;white-space:normal;line-break:auto;font-size:.875rem;word-wrap:break-word;opacity:0}.tooltip.show{opacity:.9}.tooltip .arrow{position:absolute;display:block;width:.8rem;height:.4rem}.tooltip .arrow::before{position:absolute;content:"";border-color:transparent;border-style:solid}.bs-tooltip-auto[x-placement^=top],.bs-tooltip-top{padding:.4rem 0}.bs-tooltip-auto[x-placement^=top] .arrow,.bs-tooltip-top .arrow{bottom:0}.bs-tooltip-auto[x-placement^=top] .arrow::before,.bs-tooltip-top .arrow::before{top:0;border-width:.4rem .4rem 0;border-top-color:#000}.bs-tooltip-auto[x-placement^=right],.bs-tooltip-right{padding:0 .4rem}.bs-tooltip-auto[x-placement^=right] .arrow,.bs-tooltip-right .arrow{left:0;width:.4rem;height:.8rem}.bs-tooltip-auto[x-placement^=right] .arrow::before,.bs-tooltip-right .arrow::before{right:0;border-width:.4rem .4rem .4rem 0;border-right-color:#000}.bs-tooltip-auto[x-placement^=bottom],.bs-tooltip-bottom{padding:.4rem 0}.bs-tooltip-auto[x-placement^=bottom] .arrow,.bs-tooltip-bottom .arrow{top:0}.bs-tooltip-auto[x-placement^=bottom] .arrow::before,.bs-tooltip-bottom .arrow::before{bottom:0;border-width:0 .4rem .4rem;border-bottom-color:#000}.bs-tooltip-auto[x-placement^=left],.bs-tooltip-left{padding:0 .4rem}.bs-tooltip-auto[x-placement^=left] .arrow,.bs-tooltip-left .arrow{right:0;width:.4rem;height:.8rem}.bs-tooltip-auto[x-placement^=left] .arrow::before,.bs-tooltip-left .arrow::before{left:0;border-width:.4rem 0 .4rem .4rem;border-left-color:#000}.tooltip-inner{max-width:200px;padding:.25rem .5rem;color:#fff;text-align:center;background-color:#000;border-radius:.25rem}.popover{position:absolute;top:0;left:0;z-index:1060;display:block;max-width:276px;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";font-style:normal;font-weight:400;line-height:1.5;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;word-spacing:normal;white-space:normal;line-break:auto;font-size:.875rem;word-wrap:break-word;background-color:#fff;background-clip:padding-box;border:1px solid rgba(0,0,0,.2);border-radius:.3rem}.popover .arrow{position:absolute;display:block;width:1rem;height:.5rem;margin:0 .3rem}.popover .arrow::after,.popover .arrow::before{position:absolute;display:block;content:"";border-color:transparent;border-style:solid}.bs-popover-auto[x-placement^=top],.bs-popover-top{margin-bottom:.5rem}.bs-popover-auto[x-placement^=top]>.arrow,.bs-popover-top>.arrow{bottom:calc((.5rem + 1px) * -1)}.bs-popover-auto[x-placement^=top]>.arrow::before,.bs-popover-top>.arrow::before{bottom:0;border-width:.5rem .5rem 0;border-top-color:rgba(0,0,0,.25)}.bs-popover-auto[x-placement^=top]>.arrow::after,.bs-popover-top>.arrow::after{bottom:1px;border-width:.5rem .5rem 0;border-top-color:#fff}.bs-popover-auto[x-placement^=right],.bs-popover-right{margin-left:.5rem}.bs-popover-auto[x-placement^=right]>.arrow,.bs-popover-right>.arrow{left:calc((.5rem + 1px) * -1);width:.5rem;height:1rem;margin:.3rem 0}.bs-popover-auto[x-placement^=right]>.arrow::before,.bs-popover-right>.arrow::before{left:0;border-width:.5rem .5rem .5rem 0;border-right-color:rgba(0,0,0,.25)}.bs-popover-auto[x-placement^=right]>.arrow::after,.bs-popover-right>.arrow::after{left:1px;border-width:.5rem .5rem .5rem 0;border-right-color:#fff}.bs-popover-auto[x-placement^=bottom],.bs-popover-bottom{margin-top:.5rem}.bs-popover-auto[x-placement^=bottom]>.arrow,.bs-popover-bottom>.arrow{top:calc((.5rem + 1px) * -1)}.bs-popover-auto[x-placement^=bottom]>.arrow::before,.bs-popover-bottom>.arrow::before{top:0;border-width:0 .5rem .5rem .5rem;border-bottom-color:rgba(0,0,0,.25)}.bs-popover-auto[x-placement^=bottom]>.arrow::after,.bs-popover-bottom>.arrow::after{top:1px;border-width:0 .5rem .5rem .5rem;border-bottom-color:#fff}.bs-popover-auto[x-placement^=bottom] .popover-header::before,.bs-popover-bottom .popover-header::before{position:absolute;top:0;left:50%;display:block;width:1rem;margin-left:-.5rem;content:"";border-bottom:1px solid #f7f7f7}.bs-popover-auto[x-placement^=left],.bs-popover-left{margin-right:.5rem}.bs-popover-auto[x-placement^=left]>.arrow,.bs-popover-left>.arrow{right:calc((.5rem + 1px) * -1);width:.5rem;height:1rem;margin:.3rem 0}.bs-popover-auto[x-placement^=left]>.arrow::before,.bs-popover-left>.arrow::before{right:0;border-width:.5rem 0 .5rem .5rem;border-left-color:rgba(0,0,0,.25)}.bs-popover-auto[x-placement^=left]>.arrow::after,.bs-popover-left>.arrow::after{right:1px;border-width:.5rem 0 .5rem .5rem;border-left-color:#fff}.popover-header{padding:.5rem .75rem;margin-bottom:0;font-size:1rem;background-color:#f7f7f7;border-bottom:1px solid #ebebeb;border-top-left-radius:calc(.3rem - 1px);border-top-right-radius:calc(.3rem - 1px)}.popover-header:empty{display:none}.popover-body{padding:.5rem .75rem;color:#212529}.carousel{position:relative}.carousel.pointer-event{-ms-touch-action:pan-y;touch-action:pan-y}.carousel-inner{position:relative;width:100%;overflow:hidden}.carousel-inner::after{display:block;clear:both;content:""}.carousel-item{position:relative;display:none;float:left;width:100%;margin-right:-100%;-webkit-backface-visibility:hidden;backface-visibility:hidden;transition:-webkit-transform .6s ease-in-out;transition:transform .6s ease-in-out;transition:transform .6s ease-in-out,-webkit-transform .6s ease-in-out}@media (prefers-reduced-motion:reduce){.carousel-item{transition:none}}.carousel-item-next,.carousel-item-prev,.carousel-item.active{display:block}.active.carousel-item-right,.carousel-item-next:not(.carousel-item-left){-webkit-transform:translateX(100%);transform:translateX(100%)}.active.carousel-item-left,.carousel-item-prev:not(.carousel-item-right){-webkit-transform:translateX(-100%);transform:translateX(-100%)}.carousel-fade .carousel-item{opacity:0;transition-property:opacity;-webkit-transform:none;transform:none}.carousel-fade .carousel-item-next.carousel-item-left,.carousel-fade .carousel-item-prev.carousel-item-right,.carousel-fade .carousel-item.active{z-index:1;opacity:1}.carousel-fade .active.carousel-item-left,.carousel-fade .active.carousel-item-right{z-index:0;opacity:0;transition:0s .6s opacity}@media (prefers-reduced-motion:reduce){.carousel-fade .active.carousel-item-left,.carousel-fade .active.carousel-item-right{transition:none}}.carousel-control-next,.carousel-control-prev{position:absolute;top:0;bottom:0;z-index:1;display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center;-ms-flex-pack:center;justify-content:center;width:15%;color:#fff;text-align:center;opacity:.5;transition:opacity .15s ease}@media (prefers-reduced-motion:reduce){.carousel-control-next,.carousel-control-prev{transition:none}}.carousel-control-next:focus,.carousel-control-next:hover,.carousel-control-prev:focus,.carousel-control-prev:hover{color:#fff;text-decoration:none;outline:0;opacity:.9}.carousel-control-prev{left:0}.carousel-control-next{right:0}.carousel-control-next-icon,.carousel-control-prev-icon{display:inline-block;width:20px;height:20px;background:no-repeat 50%/100% 100%}.carousel-control-prev-icon{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' viewBox='0 0 8 8'%3e%3cpath d='M5.25 0l-4 4 4 4 1.5-1.5-2.5-2.5 2.5-2.5-1.5-1.5z'/%3e%3c/svg%3e")}.carousel-control-next-icon{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' viewBox='0 0 8 8'%3e%3cpath d='M2.75 0l-1.5 1.5 2.5 2.5-2.5 2.5 1.5 1.5 4-4-4-4z'/%3e%3c/svg%3e")}.carousel-indicators{position:absolute;right:0;bottom:0;left:0;z-index:15;display:-ms-flexbox;display:flex;-ms-flex-pack:center;justify-content:center;padding-left:0;margin-right:15%;margin-left:15%;list-style:none}.carousel-indicators li{box-sizing:content-box;-ms-flex:0 1 auto;flex:0 1 auto;width:30px;height:3px;margin-right:3px;margin-left:3px;text-indent:-999px;cursor:pointer;background-color:#fff;background-clip:padding-box;border-top:10px solid transparent;border-bottom:10px solid transparent;opacity:.5;transition:opacity .6s ease}@media (prefers-reduced-motion:reduce){.carousel-indicators li{transition:none}}.carousel-indicators .active{opacity:1}.carousel-caption{position:absolute;right:15%;bottom:20px;left:15%;z-index:10;padding-top:20px;padding-bottom:20px;color:#fff;text-align:center}@-webkit-keyframes spinner-border{to{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}@keyframes spinner-border{to{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}.spinner-border{display:inline-block;width:2rem;height:2rem;vertical-align:text-bottom;border:.25em solid currentColor;border-right-color:transparent;border-radius:50%;-webkit-animation:spinner-border .75s linear infinite;animation:spinner-border .75s linear infinite}.spinner-border-sm{width:1rem;height:1rem;border-width:.2em}@-webkit-keyframes spinner-grow{0%{-webkit-transform:scale(0);transform:scale(0)}50%{opacity:1}}@keyframes spinner-grow{0%{-webkit-transform:scale(0);transform:scale(0)}50%{opacity:1}}.spinner-grow{display:inline-block;width:2rem;height:2rem;vertical-align:text-bottom;background-color:currentColor;border-radius:50%;opacity:0;-webkit-animation:spinner-grow .75s linear infinite;animation:spinner-grow .75s linear infinite}.spinner-grow-sm{width:1rem;height:1rem}.align-baseline{vertical-align:baseline!important}.align-top{vertical-align:top!important}.align-middle{vertical-align:middle!important}.align-bottom{vertical-align:bottom!important}.align-text-bottom{vertical-align:text-bottom!important}.align-text-top{vertical-align:text-top!important}.bg-primary{background-color:#007bff!important}a.bg-primary:focus,a.bg-primary:hover,button.bg-primary:focus,button.bg-primary:hover{background-color:#0062cc!important}.bg-secondary{background-color:#6c757d!important}a.bg-secondary:focus,a.bg-secondary:hover,button.bg-secondary:focus,button.bg-secondary:hover{background-color:#545b62!important}.bg-success{background-color:#28a745!important}a.bg-success:focus,a.bg-success:hover,button.bg-success:focus,button.bg-success:hover{background-color:#1e7e34!important}.bg-info{background-color:#17a2b8!important}a.bg-info:focus,a.bg-info:hover,button.bg-info:focus,button.bg-info:hover{background-color:#117a8b!important}.bg-warning{background-color:#ffc107!important}a.bg-warning:focus,a.bg-warning:hover,button.bg-warning:focus,button.bg-warning:hover{background-color:#d39e00!important}.bg-danger{background-color:#dc3545!important}a.bg-danger:focus,a.bg-danger:hover,button.bg-danger:focus,button.bg-danger:hover{background-color:#bd2130!important}.bg-light{background-color:#f8f9fa!important}a.bg-light:focus,a.bg-light:hover,button.bg-light:focus,button.bg-light:hover{background-color:#dae0e5!important}.bg-dark{background-color:#343a40!important}a.bg-dark:focus,a.bg-dark:hover,button.bg-dark:focus,button.bg-dark:hover{background-color:#1d2124!important}.bg-white{background-color:#fff!important}.bg-transparent{background-color:transparent!important}.border{border:1px solid #dee2e6!important}.border-top{border-top:1px solid #dee2e6!important}.border-right{border-right:1px solid #dee2e6!important}.border-bottom{border-bottom:1px solid #dee2e6!important}.border-left{border-left:1px solid #dee2e6!important}.border-0{border:0!important}.border-top-0{border-top:0!important}.border-right-0{border-right:0!important}.border-bottom-0{border-bottom:0!important}.border-left-0{border-left:0!important}.border-primary{border-color:#007bff!important}.border-secondary{border-color:#6c757d!important}.border-success{border-color:#28a745!important}.border-info{border-color:#17a2b8!important}.border-warning{border-color:#ffc107!important}.border-danger{border-color:#dc3545!important}.border-light{border-color:#f8f9fa!important}.border-dark{border-color:#343a40!important}.border-white{border-color:#fff!important}.rounded-sm{border-radius:.2rem!important}.rounded{border-radius:.25rem!important}.rounded-top{border-top-left-radius:.25rem!important;border-top-right-radius:.25rem!important}.rounded-right{border-top-right-radius:.25rem!important;border-bottom-right-radius:.25rem!important}.rounded-bottom{border-bottom-right-radius:.25rem!important;border-bottom-left-radius:.25rem!important}.rounded-left{border-top-left-radius:.25rem!important;border-bottom-left-radius:.25rem!important}.rounded-lg{border-radius:.3rem!important}.rounded-circle{border-radius:50%!important}.rounded-pill{border-radius:50rem!important}.rounded-0{border-radius:0!important}.clearfix::after{display:block;clear:both;content:""}.d-none{display:none!important}.d-inline{display:inline!important}.d-inline-block{display:inline-block!important}.d-block{display:block!important}.d-table{display:table!important}.d-table-row{display:table-row!important}.d-table-cell{display:table-cell!important}.d-flex{display:-ms-flexbox!important;display:flex!important}.d-inline-flex{display:-ms-inline-flexbox!important;display:inline-flex!important}@media (min-width:576px){.d-sm-none{display:none!important}.d-sm-inline{display:inline!important}.d-sm-inline-block{display:inline-block!important}.d-sm-block{display:block!important}.d-sm-table{display:table!important}.d-sm-table-row{display:table-row!important}.d-sm-table-cell{display:table-cell!important}.d-sm-flex{display:-ms-flexbox!important;display:flex!important}.d-sm-inline-flex{display:-ms-inline-flexbox!important;display:inline-flex!important}}@media (min-width:768px){.d-md-none{display:none!important}.d-md-inline{display:inline!important}.d-md-inline-block{display:inline-block!important}.d-md-block{display:block!important}.d-md-table{display:table!important}.d-md-table-row{display:table-row!important}.d-md-table-cell{display:table-cell!important}.d-md-flex{display:-ms-flexbox!important;display:flex!important}.d-md-inline-flex{display:-ms-inline-flexbox!important;display:inline-flex!important}}@media (min-width:992px){.d-lg-none{display:none!important}.d-lg-inline{display:inline!important}.d-lg-inline-block{display:inline-block!important}.d-lg-block{display:block!important}.d-lg-table{display:table!important}.d-lg-table-row{display:table-row!important}.d-lg-table-cell{display:table-cell!important}.d-lg-flex{display:-ms-flexbox!important;display:flex!important}.d-lg-inline-flex{display:-ms-inline-flexbox!important;display:inline-flex!important}}@media (min-width:1200px){.d-xl-none{display:none!important}.d-xl-inline{display:inline!important}.d-xl-inline-block{display:inline-block!important}.d-xl-block{display:block!important}.d-xl-table{display:table!important}.d-xl-table-row{display:table-row!important}.d-xl-table-cell{display:table-cell!important}.d-xl-flex{display:-ms-flexbox!important;display:flex!important}.d-xl-inline-flex{display:-ms-inline-flexbox!important;display:inline-flex!important}}@media print{.d-print-none{display:none!important}.d-print-inline{display:inline!important}.d-print-inline-block{display:inline-block!important}.d-print-block{display:block!important}.d-print-table{display:table!important}.d-print-table-row{display:table-row!important}.d-print-table-cell{display:table-cell!important}.d-print-flex{display:-ms-flexbox!important;display:flex!important}.d-print-inline-flex{display:-ms-inline-flexbox!important;display:inline-flex!important}}.embed-responsive{position:relative;display:block;width:100%;padding:0;overflow:hidden}.embed-responsive::before{display:block;content:""}.embed-responsive .embed-responsive-item,.embed-responsive embed,.embed-responsive iframe,.embed-responsive object,.embed-responsive video{position:absolute;top:0;bottom:0;left:0;width:100%;height:100%;border:0}.embed-responsive-21by9::before{padding-top:42.857143%}.embed-responsive-16by9::before{padding-top:56.25%}.embed-responsive-4by3::before{padding-top:75%}.embed-responsive-1by1::before{padding-top:100%}.flex-row{-ms-flex-direction:row!important;flex-direction:row!important}.flex-column{-ms-flex-direction:column!important;flex-direction:column!important}.flex-row-reverse{-ms-flex-direction:row-reverse!important;flex-direction:row-reverse!important}.flex-column-reverse{-ms-flex-direction:column-reverse!important;flex-direction:column-reverse!important}.flex-wrap{-ms-flex-wrap:wrap!important;flex-wrap:wrap!important}.flex-nowrap{-ms-flex-wrap:nowrap!important;flex-wrap:nowrap!important}.flex-wrap-reverse{-ms-flex-wrap:wrap-reverse!important;flex-wrap:wrap-reverse!important}.flex-fill{-ms-flex:1 1 auto!important;flex:1 1 auto!important}.flex-grow-0{-ms-flex-positive:0!important;flex-grow:0!important}.flex-grow-1{-ms-flex-positive:1!important;flex-grow:1!important}.flex-shrink-0{-ms-flex-negative:0!important;flex-shrink:0!important}.flex-shrink-1{-ms-flex-negative:1!important;flex-shrink:1!important}.justify-content-start{-ms-flex-pack:start!important;justify-content:flex-start!important}.justify-content-end{-ms-flex-pack:end!important;justify-content:flex-end!important}.justify-content-center{-ms-flex-pack:center!important;justify-content:center!important}.justify-content-between{-ms-flex-pack:justify!important;justify-content:space-between!important}.justify-content-around{-ms-flex-pack:distribute!important;justify-content:space-around!important}.align-items-start{-ms-flex-align:start!important;align-items:flex-start!important}.align-items-end{-ms-flex-align:end!important;align-items:flex-end!important}.align-items-center{-ms-flex-align:center!important;align-items:center!important}.align-items-baseline{-ms-flex-align:baseline!important;align-items:baseline!important}.align-items-stretch{-ms-flex-align:stretch!important;align-items:stretch!important}.align-content-start{-ms-flex-line-pack:start!important;align-content:flex-start!important}.align-content-end{-ms-flex-line-pack:end!important;align-content:flex-end!important}.align-content-center{-ms-flex-line-pack:center!important;align-content:center!important}.align-content-between{-ms-flex-line-pack:justify!important;align-content:space-between!important}.align-content-around{-ms-flex-line-pack:distribute!important;align-content:space-around!important}.align-content-stretch{-ms-flex-line-pack:stretch!important;align-content:stretch!important}.align-self-auto{-ms-flex-item-align:auto!important;align-self:auto!important}.align-self-start{-ms-flex-item-align:start!important;align-self:flex-start!important}.align-self-end{-ms-flex-item-align:end!important;align-self:flex-end!important}.align-self-center{-ms-flex-item-align:center!important;align-self:center!important}.align-self-baseline{-ms-flex-item-align:baseline!important;align-self:baseline!important}.align-self-stretch{-ms-flex-item-align:stretch!important;align-self:stretch!important}@media (min-width:576px){.flex-sm-row{-ms-flex-direction:row!important;flex-direction:row!important}.flex-sm-column{-ms-flex-direction:column!important;flex-direction:column!important}.flex-sm-row-reverse{-ms-flex-direction:row-reverse!important;flex-direction:row-reverse!important}.flex-sm-column-reverse{-ms-flex-direction:column-reverse!important;flex-direction:column-reverse!important}.flex-sm-wrap{-ms-flex-wrap:wrap!important;flex-wrap:wrap!important}.flex-sm-nowrap{-ms-flex-wrap:nowrap!important;flex-wrap:nowrap!important}.flex-sm-wrap-reverse{-ms-flex-wrap:wrap-reverse!important;flex-wrap:wrap-reverse!important}.flex-sm-fill{-ms-flex:1 1 auto!important;flex:1 1 auto!important}.flex-sm-grow-0{-ms-flex-positive:0!important;flex-grow:0!important}.flex-sm-grow-1{-ms-flex-positive:1!important;flex-grow:1!important}.flex-sm-shrink-0{-ms-flex-negative:0!important;flex-shrink:0!important}.flex-sm-shrink-1{-ms-flex-negative:1!important;flex-shrink:1!important}.justify-content-sm-start{-ms-flex-pack:start!important;justify-content:flex-start!important}.justify-content-sm-end{-ms-flex-pack:end!important;justify-content:flex-end!important}.justify-content-sm-center{-ms-flex-pack:center!important;justify-content:center!important}.justify-content-sm-between{-ms-flex-pack:justify!important;justify-content:space-between!important}.justify-content-sm-around{-ms-flex-pack:distribute!important;justify-content:space-around!important}.align-items-sm-start{-ms-flex-align:start!important;align-items:flex-start!important}.align-items-sm-end{-ms-flex-align:end!important;align-items:flex-end!important}.align-items-sm-center{-ms-flex-align:center!important;align-items:center!important}.align-items-sm-baseline{-ms-flex-align:baseline!important;align-items:baseline!important}.align-items-sm-stretch{-ms-flex-align:stretch!important;align-items:stretch!important}.align-content-sm-start{-ms-flex-line-pack:start!important;align-content:flex-start!important}.align-content-sm-end{-ms-flex-line-pack:end!important;align-content:flex-end!important}.align-content-sm-center{-ms-flex-line-pack:center!important;align-content:center!important}.align-content-sm-between{-ms-flex-line-pack:justify!important;align-content:space-between!important}.align-content-sm-around{-ms-flex-line-pack:distribute!important;align-content:space-around!important}.align-content-sm-stretch{-ms-flex-line-pack:stretch!important;align-content:stretch!important}.align-self-sm-auto{-ms-flex-item-align:auto!important;align-self:auto!important}.align-self-sm-start{-ms-flex-item-align:start!important;align-self:flex-start!important}.align-self-sm-end{-ms-flex-item-align:end!important;align-self:flex-end!important}.align-self-sm-center{-ms-flex-item-align:center!important;align-self:center!important}.align-self-sm-baseline{-ms-flex-item-align:baseline!important;align-self:baseline!important}.align-self-sm-stretch{-ms-flex-item-align:stretch!important;align-self:stretch!important}}@media (min-width:768px){.flex-md-row{-ms-flex-direction:row!important;flex-direction:row!important}.flex-md-column{-ms-flex-direction:column!important;flex-direction:column!important}.flex-md-row-reverse{-ms-flex-direction:row-reverse!important;flex-direction:row-reverse!important}.flex-md-column-reverse{-ms-flex-direction:column-reverse!important;flex-direction:column-reverse!important}.flex-md-wrap{-ms-flex-wrap:wrap!important;flex-wrap:wrap!important}.flex-md-nowrap{-ms-flex-wrap:nowrap!important;flex-wrap:nowrap!important}.flex-md-wrap-reverse{-ms-flex-wrap:wrap-reverse!important;flex-wrap:wrap-reverse!important}.flex-md-fill{-ms-flex:1 1 auto!important;flex:1 1 auto!important}.flex-md-grow-0{-ms-flex-positive:0!important;flex-grow:0!important}.flex-md-grow-1{-ms-flex-positive:1!important;flex-grow:1!important}.flex-md-shrink-0{-ms-flex-negative:0!important;flex-shrink:0!important}.flex-md-shrink-1{-ms-flex-negative:1!important;flex-shrink:1!important}.justify-content-md-start{-ms-flex-pack:start!important;justify-content:flex-start!important}.justify-content-md-end{-ms-flex-pack:end!important;justify-content:flex-end!important}.justify-content-md-center{-ms-flex-pack:center!important;justify-content:center!important}.justify-content-md-between{-ms-flex-pack:justify!important;justify-content:space-between!important}.justify-content-md-around{-ms-flex-pack:distribute!important;justify-content:space-around!important}.align-items-md-start{-ms-flex-align:start!important;align-items:flex-start!important}.align-items-md-end{-ms-flex-align:end!important;align-items:flex-end!important}.align-items-md-center{-ms-flex-align:center!important;align-items:center!important}.align-items-md-baseline{-ms-flex-align:baseline!important;align-items:baseline!important}.align-items-md-stretch{-ms-flex-align:stretch!important;align-items:stretch!important}.align-content-md-start{-ms-flex-line-pack:start!important;align-content:flex-start!important}.align-content-md-end{-ms-flex-line-pack:end!important;align-content:flex-end!important}.align-content-md-center{-ms-flex-line-pack:center!important;align-content:center!important}.align-content-md-between{-ms-flex-line-pack:justify!important;align-content:space-between!important}.align-content-md-around{-ms-flex-line-pack:distribute!important;align-content:space-around!important}.align-content-md-stretch{-ms-flex-line-pack:stretch!important;align-content:stretch!important}.align-self-md-auto{-ms-flex-item-align:auto!important;align-self:auto!important}.align-self-md-start{-ms-flex-item-align:start!important;align-self:flex-start!important}.align-self-md-end{-ms-flex-item-align:end!important;align-self:flex-end!important}.align-self-md-center{-ms-flex-item-align:center!important;align-self:center!important}.align-self-md-baseline{-ms-flex-item-align:baseline!important;align-self:baseline!important}.align-self-md-stretch{-ms-flex-item-align:stretch!important;align-self:stretch!important}}@media (min-width:992px){.flex-lg-row{-ms-flex-direction:row!important;flex-direction:row!important}.flex-lg-column{-ms-flex-direction:column!important;flex-direction:column!important}.flex-lg-row-reverse{-ms-flex-direction:row-reverse!important;flex-direction:row-reverse!important}.flex-lg-column-reverse{-ms-flex-direction:column-reverse!important;flex-direction:column-reverse!important}.flex-lg-wrap{-ms-flex-wrap:wrap!important;flex-wrap:wrap!important}.flex-lg-nowrap{-ms-flex-wrap:nowrap!important;flex-wrap:nowrap!important}.flex-lg-wrap-reverse{-ms-flex-wrap:wrap-reverse!important;flex-wrap:wrap-reverse!important}.flex-lg-fill{-ms-flex:1 1 auto!important;flex:1 1 auto!important}.flex-lg-grow-0{-ms-flex-positive:0!important;flex-grow:0!important}.flex-lg-grow-1{-ms-flex-positive:1!important;flex-grow:1!important}.flex-lg-shrink-0{-ms-flex-negative:0!important;flex-shrink:0!important}.flex-lg-shrink-1{-ms-flex-negative:1!important;flex-shrink:1!important}.justify-content-lg-start{-ms-flex-pack:start!important;justify-content:flex-start!important}.justify-content-lg-end{-ms-flex-pack:end!important;justify-content:flex-end!important}.justify-content-lg-center{-ms-flex-pack:center!important;justify-content:center!important}.justify-content-lg-between{-ms-flex-pack:justify!important;justify-content:space-between!important}.justify-content-lg-around{-ms-flex-pack:distribute!important;justify-content:space-around!important}.align-items-lg-start{-ms-flex-align:start!important;align-items:flex-start!important}.align-items-lg-end{-ms-flex-align:end!important;align-items:flex-end!important}.align-items-lg-center{-ms-flex-align:center!important;align-items:center!important}.align-items-lg-baseline{-ms-flex-align:baseline!important;align-items:baseline!important}.align-items-lg-stretch{-ms-flex-align:stretch!important;align-items:stretch!important}.align-content-lg-start{-ms-flex-line-pack:start!important;align-content:flex-start!important}.align-content-lg-end{-ms-flex-line-pack:end!important;align-content:flex-end!important}.align-content-lg-center{-ms-flex-line-pack:center!important;align-content:center!important}.align-content-lg-between{-ms-flex-line-pack:justify!important;align-content:space-between!important}.align-content-lg-around{-ms-flex-line-pack:distribute!important;align-content:space-around!important}.align-content-lg-stretch{-ms-flex-line-pack:stretch!important;align-content:stretch!important}.align-self-lg-auto{-ms-flex-item-align:auto!important;align-self:auto!important}.align-self-lg-start{-ms-flex-item-align:start!important;align-self:flex-start!important}.align-self-lg-end{-ms-flex-item-align:end!important;align-self:flex-end!important}.align-self-lg-center{-ms-flex-item-align:center!important;align-self:center!important}.align-self-lg-baseline{-ms-flex-item-align:baseline!important;align-self:baseline!important}.align-self-lg-stretch{-ms-flex-item-align:stretch!important;align-self:stretch!important}}@media (min-width:1200px){.flex-xl-row{-ms-flex-direction:row!important;flex-direction:row!important}.flex-xl-column{-ms-flex-direction:column!important;flex-direction:column!important}.flex-xl-row-reverse{-ms-flex-direction:row-reverse!important;flex-direction:row-reverse!important}.flex-xl-column-reverse{-ms-flex-direction:column-reverse!important;flex-direction:column-reverse!important}.flex-xl-wrap{-ms-flex-wrap:wrap!important;flex-wrap:wrap!important}.flex-xl-nowrap{-ms-flex-wrap:nowrap!important;flex-wrap:nowrap!important}.flex-xl-wrap-reverse{-ms-flex-wrap:wrap-reverse!important;flex-wrap:wrap-reverse!important}.flex-xl-fill{-ms-flex:1 1 auto!important;flex:1 1 auto!important}.flex-xl-grow-0{-ms-flex-positive:0!important;flex-grow:0!important}.flex-xl-grow-1{-ms-flex-positive:1!important;flex-grow:1!important}.flex-xl-shrink-0{-ms-flex-negative:0!important;flex-shrink:0!important}.flex-xl-shrink-1{-ms-flex-negative:1!important;flex-shrink:1!important}.justify-content-xl-start{-ms-flex-pack:start!important;justify-content:flex-start!important}.justify-content-xl-end{-ms-flex-pack:end!important;justify-content:flex-end!important}.justify-content-xl-center{-ms-flex-pack:center!important;justify-content:center!important}.justify-content-xl-between{-ms-flex-pack:justify!important;justify-content:space-between!important}.justify-content-xl-around{-ms-flex-pack:distribute!important;justify-content:space-around!important}.align-items-xl-start{-ms-flex-align:start!important;align-items:flex-start!important}.align-items-xl-end{-ms-flex-align:end!important;align-items:flex-end!important}.align-items-xl-center{-ms-flex-align:center!important;align-items:center!important}.align-items-xl-baseline{-ms-flex-align:baseline!important;align-items:baseline!important}.align-items-xl-stretch{-ms-flex-align:stretch!important;align-items:stretch!important}.align-content-xl-start{-ms-flex-line-pack:start!important;align-content:flex-start!important}.align-content-xl-end{-ms-flex-line-pack:end!important;align-content:flex-end!important}.align-content-xl-center{-ms-flex-line-pack:center!important;align-content:center!important}.align-content-xl-between{-ms-flex-line-pack:justify!important;align-content:space-between!important}.align-content-xl-around{-ms-flex-line-pack:distribute!important;align-content:space-around!important}.align-content-xl-stretch{-ms-flex-line-pack:stretch!important;align-content:stretch!important}.align-self-xl-auto{-ms-flex-item-align:auto!important;align-self:auto!important}.align-self-xl-start{-ms-flex-item-align:start!important;align-self:flex-start!important}.align-self-xl-end{-ms-flex-item-align:end!important;align-self:flex-end!important}.align-self-xl-center{-ms-flex-item-align:center!important;align-self:center!important}.align-self-xl-baseline{-ms-flex-item-align:baseline!important;align-self:baseline!important}.align-self-xl-stretch{-ms-flex-item-align:stretch!important;align-self:stretch!important}}.float-left{float:left!important}.float-right{float:right!important}.float-none{float:none!important}@media (min-width:576px){.float-sm-left{float:left!important}.float-sm-right{float:right!important}.float-sm-none{float:none!important}}@media (min-width:768px){.float-md-left{float:left!important}.float-md-right{float:right!important}.float-md-none{float:none!important}}@media (min-width:992px){.float-lg-left{float:left!important}.float-lg-right{float:right!important}.float-lg-none{float:none!important}}@media (min-width:1200px){.float-xl-left{float:left!important}.float-xl-right{float:right!important}.float-xl-none{float:none!important}}.overflow-auto{overflow:auto!important}.overflow-hidden{overflow:hidden!important}.position-static{position:static!important}.position-relative{position:relative!important}.position-absolute{position:absolute!important}.position-fixed{position:fixed!important}.position-sticky{position:-webkit-sticky!important;position:sticky!important}.fixed-top{position:fixed;top:0;right:0;left:0;z-index:1030}.fixed-bottom{position:fixed;right:0;bottom:0;left:0;z-index:1030}@supports ((position:-webkit-sticky) or (position:sticky)){.sticky-top{position:-webkit-sticky;position:sticky;top:0;z-index:1020}}.sr-only{position:absolute;width:1px;height:1px;padding:0;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;overflow:visible;clip:auto;white-space:normal}.shadow-sm{box-shadow:0 .125rem .25rem rgba(0,0,0,.075)!important}.shadow{box-shadow:0 .5rem 1rem rgba(0,0,0,.15)!important}.shadow-lg{box-shadow:0 1rem 3rem rgba(0,0,0,.175)!important}.shadow-none{box-shadow:none!important}.w-25{width:25%!important}.w-50{width:50%!important}.w-75{width:75%!important}.w-100{width:100%!important}.w-auto{width:auto!important}.h-25{height:25%!important}.h-50{height:50%!important}.h-75{height:75%!important}.h-100{height:100%!important}.h-auto{height:auto!important}.mw-100{max-width:100%!important}.mh-100{max-height:100%!important}.min-vw-100{min-width:100vw!important}.min-vh-100{min-height:100vh!important}.vw-100{width:100vw!important}.vh-100{height:100vh!important}.stretched-link::after{position:absolute;top:0;right:0;bottom:0;left:0;z-index:1;pointer-events:auto;content:"";background-color:rgba(0,0,0,0)}.m-0{margin:0!important}.mt-0,.my-0{margin-top:0!important}.mr-0,.mx-0{margin-right:0!important}.mb-0,.my-0{margin-bottom:0!important}.ml-0,.mx-0{margin-left:0!important}.m-1{margin:.25rem!important}.mt-1,.my-1{margin-top:.25rem!important}.mr-1,.mx-1{margin-right:.25rem!important}.mb-1,.my-1{margin-bottom:.25rem!important}.ml-1,.mx-1{margin-left:.25rem!important}.m-2{margin:.5rem!important}.mt-2,.my-2{margin-top:.5rem!important}.mr-2,.mx-2{margin-right:.5rem!important}.mb-2,.my-2{margin-bottom:.5rem!important}.ml-2,.mx-2{margin-left:.5rem!important}.m-3{margin:1rem!important}.mt-3,.my-3{margin-top:1rem!important}.mr-3,.mx-3{margin-right:1rem!important}.mb-3,.my-3{margin-bottom:1rem!important}.ml-3,.mx-3{margin-left:1rem!important}.m-4{margin:1.5rem!important}.mt-4,.my-4{margin-top:1.5rem!important}.mr-4,.mx-4{margin-right:1.5rem!important}.mb-4,.my-4{margin-bottom:1.5rem!important}.ml-4,.mx-4{margin-left:1.5rem!important}.m-5{margin:3rem!important}.mt-5,.my-5{margin-top:3rem!important}.mr-5,.mx-5{margin-right:3rem!important}.mb-5,.my-5{margin-bottom:3rem!important}.ml-5,.mx-5{margin-left:3rem!important}.p-0{padding:0!important}.pt-0,.py-0{padding-top:0!important}.pr-0,.px-0{padding-right:0!important}.pb-0,.py-0{padding-bottom:0!important}.pl-0,.px-0{padding-left:0!important}.p-1{padding:.25rem!important}.pt-1,.py-1{padding-top:.25rem!important}.pr-1,.px-1{padding-right:.25rem!important}.pb-1,.py-1{padding-bottom:.25rem!important}.pl-1,.px-1{padding-left:.25rem!important}.p-2{padding:.5rem!important}.pt-2,.py-2{padding-top:.5rem!important}.pr-2,.px-2{padding-right:.5rem!important}.pb-2,.py-2{padding-bottom:.5rem!important}.pl-2,.px-2{padding-left:.5rem!important}.p-3{padding:1rem!important}.pt-3,.py-3{padding-top:1rem!important}.pr-3,.px-3{padding-right:1rem!important}.pb-3,.py-3{padding-bottom:1rem!important}.pl-3,.px-3{padding-left:1rem!important}.p-4{padding:1.5rem!important}.pt-4,.py-4{padding-top:1.5rem!important}.pr-4,.px-4{padding-right:1.5rem!important}.pb-4,.py-4{padding-bottom:1.5rem!important}.pl-4,.px-4{padding-left:1.5rem!important}.p-5{padding:3rem!important}.pt-5,.py-5{padding-top:3rem!important}.pr-5,.px-5{padding-right:3rem!important}.pb-5,.py-5{padding-bottom:3rem!important}.pl-5,.px-5{padding-left:3rem!important}.m-n1{margin:-.25rem!important}.mt-n1,.my-n1{margin-top:-.25rem!important}.mr-n1,.mx-n1{margin-right:-.25rem!important}.mb-n1,.my-n1{margin-bottom:-.25rem!important}.ml-n1,.mx-n1{margin-left:-.25rem!important}.m-n2{margin:-.5rem!important}.mt-n2,.my-n2{margin-top:-.5rem!important}.mr-n2,.mx-n2{margin-right:-.5rem!important}.mb-n2,.my-n2{margin-bottom:-.5rem!important}.ml-n2,.mx-n2{margin-left:-.5rem!important}.m-n3{margin:-1rem!important}.mt-n3,.my-n3{margin-top:-1rem!important}.mr-n3,.mx-n3{margin-right:-1rem!important}.mb-n3,.my-n3{margin-bottom:-1rem!important}.ml-n3,.mx-n3{margin-left:-1rem!important}.m-n4{margin:-1.5rem!important}.mt-n4,.my-n4{margin-top:-1.5rem!important}.mr-n4,.mx-n4{margin-right:-1.5rem!important}.mb-n4,.my-n4{margin-bottom:-1.5rem!important}.ml-n4,.mx-n4{margin-left:-1.5rem!important}.m-n5{margin:-3rem!important}.mt-n5,.my-n5{margin-top:-3rem!important}.mr-n5,.mx-n5{margin-right:-3rem!important}.mb-n5,.my-n5{margin-bottom:-3rem!important}.ml-n5,.mx-n5{margin-left:-3rem!important}.m-auto{margin:auto!important}.mt-auto,.my-auto{margin-top:auto!important}.mr-auto,.mx-auto{margin-right:auto!important}.mb-auto,.my-auto{margin-bottom:auto!important}.ml-auto,.mx-auto{margin-left:auto!important}@media (min-width:576px){.m-sm-0{margin:0!important}.mt-sm-0,.my-sm-0{margin-top:0!important}.mr-sm-0,.mx-sm-0{margin-right:0!important}.mb-sm-0,.my-sm-0{margin-bottom:0!important}.ml-sm-0,.mx-sm-0{margin-left:0!important}.m-sm-1{margin:.25rem!important}.mt-sm-1,.my-sm-1{margin-top:.25rem!important}.mr-sm-1,.mx-sm-1{margin-right:.25rem!important}.mb-sm-1,.my-sm-1{margin-bottom:.25rem!important}.ml-sm-1,.mx-sm-1{margin-left:.25rem!important}.m-sm-2{margin:.5rem!important}.mt-sm-2,.my-sm-2{margin-top:.5rem!important}.mr-sm-2,.mx-sm-2{margin-right:.5rem!important}.mb-sm-2,.my-sm-2{margin-bottom:.5rem!important}.ml-sm-2,.mx-sm-2{margin-left:.5rem!important}.m-sm-3{margin:1rem!important}.mt-sm-3,.my-sm-3{margin-top:1rem!important}.mr-sm-3,.mx-sm-3{margin-right:1rem!important}.mb-sm-3,.my-sm-3{margin-bottom:1rem!important}.ml-sm-3,.mx-sm-3{margin-left:1rem!important}.m-sm-4{margin:1.5rem!important}.mt-sm-4,.my-sm-4{margin-top:1.5rem!important}.mr-sm-4,.mx-sm-4{margin-right:1.5rem!important}.mb-sm-4,.my-sm-4{margin-bottom:1.5rem!important}.ml-sm-4,.mx-sm-4{margin-left:1.5rem!important}.m-sm-5{margin:3rem!important}.mt-sm-5,.my-sm-5{margin-top:3rem!important}.mr-sm-5,.mx-sm-5{margin-right:3rem!important}.mb-sm-5,.my-sm-5{margin-bottom:3rem!important}.ml-sm-5,.mx-sm-5{margin-left:3rem!important}.p-sm-0{padding:0!important}.pt-sm-0,.py-sm-0{padding-top:0!important}.pr-sm-0,.px-sm-0{padding-right:0!important}.pb-sm-0,.py-sm-0{padding-bottom:0!important}.pl-sm-0,.px-sm-0{padding-left:0!important}.p-sm-1{padding:.25rem!important}.pt-sm-1,.py-sm-1{padding-top:.25rem!important}.pr-sm-1,.px-sm-1{padding-right:.25rem!important}.pb-sm-1,.py-sm-1{padding-bottom:.25rem!important}.pl-sm-1,.px-sm-1{padding-left:.25rem!important}.p-sm-2{padding:.5rem!important}.pt-sm-2,.py-sm-2{padding-top:.5rem!important}.pr-sm-2,.px-sm-2{padding-right:.5rem!important}.pb-sm-2,.py-sm-2{padding-bottom:.5rem!important}.pl-sm-2,.px-sm-2{padding-left:.5rem!important}.p-sm-3{padding:1rem!important}.pt-sm-3,.py-sm-3{padding-top:1rem!important}.pr-sm-3,.px-sm-3{padding-right:1rem!important}.pb-sm-3,.py-sm-3{padding-bottom:1rem!important}.pl-sm-3,.px-sm-3{padding-left:1rem!important}.p-sm-4{padding:1.5rem!important}.pt-sm-4,.py-sm-4{padding-top:1.5rem!important}.pr-sm-4,.px-sm-4{padding-right:1.5rem!important}.pb-sm-4,.py-sm-4{padding-bottom:1.5rem!important}.pl-sm-4,.px-sm-4{padding-left:1.5rem!important}.p-sm-5{padding:3rem!important}.pt-sm-5,.py-sm-5{padding-top:3rem!important}.pr-sm-5,.px-sm-5{padding-right:3rem!important}.pb-sm-5,.py-sm-5{padding-bottom:3rem!important}.pl-sm-5,.px-sm-5{padding-left:3rem!important}.m-sm-n1{margin:-.25rem!important}.mt-sm-n1,.my-sm-n1{margin-top:-.25rem!important}.mr-sm-n1,.mx-sm-n1{margin-right:-.25rem!important}.mb-sm-n1,.my-sm-n1{margin-bottom:-.25rem!important}.ml-sm-n1,.mx-sm-n1{margin-left:-.25rem!important}.m-sm-n2{margin:-.5rem!important}.mt-sm-n2,.my-sm-n2{margin-top:-.5rem!important}.mr-sm-n2,.mx-sm-n2{margin-right:-.5rem!important}.mb-sm-n2,.my-sm-n2{margin-bottom:-.5rem!important}.ml-sm-n2,.mx-sm-n2{margin-left:-.5rem!important}.m-sm-n3{margin:-1rem!important}.mt-sm-n3,.my-sm-n3{margin-top:-1rem!important}.mr-sm-n3,.mx-sm-n3{margin-right:-1rem!important}.mb-sm-n3,.my-sm-n3{margin-bottom:-1rem!important}.ml-sm-n3,.mx-sm-n3{margin-left:-1rem!important}.m-sm-n4{margin:-1.5rem!important}.mt-sm-n4,.my-sm-n4{margin-top:-1.5rem!important}.mr-sm-n4,.mx-sm-n4{margin-right:-1.5rem!important}.mb-sm-n4,.my-sm-n4{margin-bottom:-1.5rem!important}.ml-sm-n4,.mx-sm-n4{margin-left:-1.5rem!important}.m-sm-n5{margin:-3rem!important}.mt-sm-n5,.my-sm-n5{margin-top:-3rem!important}.mr-sm-n5,.mx-sm-n5{margin-right:-3rem!important}.mb-sm-n5,.my-sm-n5{margin-bottom:-3rem!important}.ml-sm-n5,.mx-sm-n5{margin-left:-3rem!important}.m-sm-auto{margin:auto!important}.mt-sm-auto,.my-sm-auto{margin-top:auto!important}.mr-sm-auto,.mx-sm-auto{margin-right:auto!important}.mb-sm-auto,.my-sm-auto{margin-bottom:auto!important}.ml-sm-auto,.mx-sm-auto{margin-left:auto!important}}@media (min-width:768px){.m-md-0{margin:0!important}.mt-md-0,.my-md-0{margin-top:0!important}.mr-md-0,.mx-md-0{margin-right:0!important}.mb-md-0,.my-md-0{margin-bottom:0!important}.ml-md-0,.mx-md-0{margin-left:0!important}.m-md-1{margin:.25rem!important}.mt-md-1,.my-md-1{margin-top:.25rem!important}.mr-md-1,.mx-md-1{margin-right:.25rem!important}.mb-md-1,.my-md-1{margin-bottom:.25rem!important}.ml-md-1,.mx-md-1{margin-left:.25rem!important}.m-md-2{margin:.5rem!important}.mt-md-2,.my-md-2{margin-top:.5rem!important}.mr-md-2,.mx-md-2{margin-right:.5rem!important}.mb-md-2,.my-md-2{margin-bottom:.5rem!important}.ml-md-2,.mx-md-2{margin-left:.5rem!important}.m-md-3{margin:1rem!important}.mt-md-3,.my-md-3{margin-top:1rem!important}.mr-md-3,.mx-md-3{margin-right:1rem!important}.mb-md-3,.my-md-3{margin-bottom:1rem!important}.ml-md-3,.mx-md-3{margin-left:1rem!important}.m-md-4{margin:1.5rem!important}.mt-md-4,.my-md-4{margin-top:1.5rem!important}.mr-md-4,.mx-md-4{margin-right:1.5rem!important}.mb-md-4,.my-md-4{margin-bottom:1.5rem!important}.ml-md-4,.mx-md-4{margin-left:1.5rem!important}.m-md-5{margin:3rem!important}.mt-md-5,.my-md-5{margin-top:3rem!important}.mr-md-5,.mx-md-5{margin-right:3rem!important}.mb-md-5,.my-md-5{margin-bottom:3rem!important}.ml-md-5,.mx-md-5{margin-left:3rem!important}.p-md-0{padding:0!important}.pt-md-0,.py-md-0{padding-top:0!important}.pr-md-0,.px-md-0{padding-right:0!important}.pb-md-0,.py-md-0{padding-bottom:0!important}.pl-md-0,.px-md-0{padding-left:0!important}.p-md-1{padding:.25rem!important}.pt-md-1,.py-md-1{padding-top:.25rem!important}.pr-md-1,.px-md-1{padding-right:.25rem!important}.pb-md-1,.py-md-1{padding-bottom:.25rem!important}.pl-md-1,.px-md-1{padding-left:.25rem!important}.p-md-2{padding:.5rem!important}.pt-md-2,.py-md-2{padding-top:.5rem!important}.pr-md-2,.px-md-2{padding-right:.5rem!important}.pb-md-2,.py-md-2{padding-bottom:.5rem!important}.pl-md-2,.px-md-2{padding-left:.5rem!important}.p-md-3{padding:1rem!important}.pt-md-3,.py-md-3{padding-top:1rem!important}.pr-md-3,.px-md-3{padding-right:1rem!important}.pb-md-3,.py-md-3{padding-bottom:1rem!important}.pl-md-3,.px-md-3{padding-left:1rem!important}.p-md-4{padding:1.5rem!important}.pt-md-4,.py-md-4{padding-top:1.5rem!important}.pr-md-4,.px-md-4{padding-right:1.5rem!important}.pb-md-4,.py-md-4{padding-bottom:1.5rem!important}.pl-md-4,.px-md-4{padding-left:1.5rem!important}.p-md-5{padding:3rem!important}.pt-md-5,.py-md-5{padding-top:3rem!important}.pr-md-5,.px-md-5{padding-right:3rem!important}.pb-md-5,.py-md-5{padding-bottom:3rem!important}.pl-md-5,.px-md-5{padding-left:3rem!important}.m-md-n1{margin:-.25rem!important}.mt-md-n1,.my-md-n1{margin-top:-.25rem!important}.mr-md-n1,.mx-md-n1{margin-right:-.25rem!important}.mb-md-n1,.my-md-n1{margin-bottom:-.25rem!important}.ml-md-n1,.mx-md-n1{margin-left:-.25rem!important}.m-md-n2{margin:-.5rem!important}.mt-md-n2,.my-md-n2{margin-top:-.5rem!important}.mr-md-n2,.mx-md-n2{margin-right:-.5rem!important}.mb-md-n2,.my-md-n2{margin-bottom:-.5rem!important}.ml-md-n2,.mx-md-n2{margin-left:-.5rem!important}.m-md-n3{margin:-1rem!important}.mt-md-n3,.my-md-n3{margin-top:-1rem!important}.mr-md-n3,.mx-md-n3{margin-right:-1rem!important}.mb-md-n3,.my-md-n3{margin-bottom:-1rem!important}.ml-md-n3,.mx-md-n3{margin-left:-1rem!important}.m-md-n4{margin:-1.5rem!important}.mt-md-n4,.my-md-n4{margin-top:-1.5rem!important}.mr-md-n4,.mx-md-n4{margin-right:-1.5rem!important}.mb-md-n4,.my-md-n4{margin-bottom:-1.5rem!important}.ml-md-n4,.mx-md-n4{margin-left:-1.5rem!important}.m-md-n5{margin:-3rem!important}.mt-md-n5,.my-md-n5{margin-top:-3rem!important}.mr-md-n5,.mx-md-n5{margin-right:-3rem!important}.mb-md-n5,.my-md-n5{margin-bottom:-3rem!important}.ml-md-n5,.mx-md-n5{margin-left:-3rem!important}.m-md-auto{margin:auto!important}.mt-md-auto,.my-md-auto{margin-top:auto!important}.mr-md-auto,.mx-md-auto{margin-right:auto!important}.mb-md-auto,.my-md-auto{margin-bottom:auto!important}.ml-md-auto,.mx-md-auto{margin-left:auto!important}}@media (min-width:992px){.m-lg-0{margin:0!important}.mt-lg-0,.my-lg-0{margin-top:0!important}.mr-lg-0,.mx-lg-0{margin-right:0!important}.mb-lg-0,.my-lg-0{margin-bottom:0!important}.ml-lg-0,.mx-lg-0{margin-left:0!important}.m-lg-1{margin:.25rem!important}.mt-lg-1,.my-lg-1{margin-top:.25rem!important}.mr-lg-1,.mx-lg-1{margin-right:.25rem!important}.mb-lg-1,.my-lg-1{margin-bottom:.25rem!important}.ml-lg-1,.mx-lg-1{margin-left:.25rem!important}.m-lg-2{margin:.5rem!important}.mt-lg-2,.my-lg-2{margin-top:.5rem!important}.mr-lg-2,.mx-lg-2{margin-right:.5rem!important}.mb-lg-2,.my-lg-2{margin-bottom:.5rem!important}.ml-lg-2,.mx-lg-2{margin-left:.5rem!important}.m-lg-3{margin:1rem!important}.mt-lg-3,.my-lg-3{margin-top:1rem!important}.mr-lg-3,.mx-lg-3{margin-right:1rem!important}.mb-lg-3,.my-lg-3{margin-bottom:1rem!important}.ml-lg-3,.mx-lg-3{margin-left:1rem!important}.m-lg-4{margin:1.5rem!important}.mt-lg-4,.my-lg-4{margin-top:1.5rem!important}.mr-lg-4,.mx-lg-4{margin-right:1.5rem!important}.mb-lg-4,.my-lg-4{margin-bottom:1.5rem!important}.ml-lg-4,.mx-lg-4{margin-left:1.5rem!important}.m-lg-5{margin:3rem!important}.mt-lg-5,.my-lg-5{margin-top:3rem!important}.mr-lg-5,.mx-lg-5{margin-right:3rem!important}.mb-lg-5,.my-lg-5{margin-bottom:3rem!important}.ml-lg-5,.mx-lg-5{margin-left:3rem!important}.p-lg-0{padding:0!important}.pt-lg-0,.py-lg-0{padding-top:0!important}.pr-lg-0,.px-lg-0{padding-right:0!important}.pb-lg-0,.py-lg-0{padding-bottom:0!important}.pl-lg-0,.px-lg-0{padding-left:0!important}.p-lg-1{padding:.25rem!important}.pt-lg-1,.py-lg-1{padding-top:.25rem!important}.pr-lg-1,.px-lg-1{padding-right:.25rem!important}.pb-lg-1,.py-lg-1{padding-bottom:.25rem!important}.pl-lg-1,.px-lg-1{padding-left:.25rem!important}.p-lg-2{padding:.5rem!important}.pt-lg-2,.py-lg-2{padding-top:.5rem!important}.pr-lg-2,.px-lg-2{padding-right:.5rem!important}.pb-lg-2,.py-lg-2{padding-bottom:.5rem!important}.pl-lg-2,.px-lg-2{padding-left:.5rem!important}.p-lg-3{padding:1rem!important}.pt-lg-3,.py-lg-3{padding-top:1rem!important}.pr-lg-3,.px-lg-3{padding-right:1rem!important}.pb-lg-3,.py-lg-3{padding-bottom:1rem!important}.pl-lg-3,.px-lg-3{padding-left:1rem!important}.p-lg-4{padding:1.5rem!important}.pt-lg-4,.py-lg-4{padding-top:1.5rem!important}.pr-lg-4,.px-lg-4{padding-right:1.5rem!important}.pb-lg-4,.py-lg-4{padding-bottom:1.5rem!important}.pl-lg-4,.px-lg-4{padding-left:1.5rem!important}.p-lg-5{padding:3rem!important}.pt-lg-5,.py-lg-5{padding-top:3rem!important}.pr-lg-5,.px-lg-5{padding-right:3rem!important}.pb-lg-5,.py-lg-5{padding-bottom:3rem!important}.pl-lg-5,.px-lg-5{padding-left:3rem!important}.m-lg-n1{margin:-.25rem!important}.mt-lg-n1,.my-lg-n1{margin-top:-.25rem!important}.mr-lg-n1,.mx-lg-n1{margin-right:-.25rem!important}.mb-lg-n1,.my-lg-n1{margin-bottom:-.25rem!important}.ml-lg-n1,.mx-lg-n1{margin-left:-.25rem!important}.m-lg-n2{margin:-.5rem!important}.mt-lg-n2,.my-lg-n2{margin-top:-.5rem!important}.mr-lg-n2,.mx-lg-n2{margin-right:-.5rem!important}.mb-lg-n2,.my-lg-n2{margin-bottom:-.5rem!important}.ml-lg-n2,.mx-lg-n2{margin-left:-.5rem!important}.m-lg-n3{margin:-1rem!important}.mt-lg-n3,.my-lg-n3{margin-top:-1rem!important}.mr-lg-n3,.mx-lg-n3{margin-right:-1rem!important}.mb-lg-n3,.my-lg-n3{margin-bottom:-1rem!important}.ml-lg-n3,.mx-lg-n3{margin-left:-1rem!important}.m-lg-n4{margin:-1.5rem!important}.mt-lg-n4,.my-lg-n4{margin-top:-1.5rem!important}.mr-lg-n4,.mx-lg-n4{margin-right:-1.5rem!important}.mb-lg-n4,.my-lg-n4{margin-bottom:-1.5rem!important}.ml-lg-n4,.mx-lg-n4{margin-left:-1.5rem!important}.m-lg-n5{margin:-3rem!important}.mt-lg-n5,.my-lg-n5{margin-top:-3rem!important}.mr-lg-n5,.mx-lg-n5{margin-right:-3rem!important}.mb-lg-n5,.my-lg-n5{margin-bottom:-3rem!important}.ml-lg-n5,.mx-lg-n5{margin-left:-3rem!important}.m-lg-auto{margin:auto!important}.mt-lg-auto,.my-lg-auto{margin-top:auto!important}.mr-lg-auto,.mx-lg-auto{margin-right:auto!important}.mb-lg-auto,.my-lg-auto{margin-bottom:auto!important}.ml-lg-auto,.mx-lg-auto{margin-left:auto!important}}@media (min-width:1200px){.m-xl-0{margin:0!important}.mt-xl-0,.my-xl-0{margin-top:0!important}.mr-xl-0,.mx-xl-0{margin-right:0!important}.mb-xl-0,.my-xl-0{margin-bottom:0!important}.ml-xl-0,.mx-xl-0{margin-left:0!important}.m-xl-1{margin:.25rem!important}.mt-xl-1,.my-xl-1{margin-top:.25rem!important}.mr-xl-1,.mx-xl-1{margin-right:.25rem!important}.mb-xl-1,.my-xl-1{margin-bottom:.25rem!important}.ml-xl-1,.mx-xl-1{margin-left:.25rem!important}.m-xl-2{margin:.5rem!important}.mt-xl-2,.my-xl-2{margin-top:.5rem!important}.mr-xl-2,.mx-xl-2{margin-right:.5rem!important}.mb-xl-2,.my-xl-2{margin-bottom:.5rem!important}.ml-xl-2,.mx-xl-2{margin-left:.5rem!important}.m-xl-3{margin:1rem!important}.mt-xl-3,.my-xl-3{margin-top:1rem!important}.mr-xl-3,.mx-xl-3{margin-right:1rem!important}.mb-xl-3,.my-xl-3{margin-bottom:1rem!important}.ml-xl-3,.mx-xl-3{margin-left:1rem!important}.m-xl-4{margin:1.5rem!important}.mt-xl-4,.my-xl-4{margin-top:1.5rem!important}.mr-xl-4,.mx-xl-4{margin-right:1.5rem!important}.mb-xl-4,.my-xl-4{margin-bottom:1.5rem!important}.ml-xl-4,.mx-xl-4{margin-left:1.5rem!important}.m-xl-5{margin:3rem!important}.mt-xl-5,.my-xl-5{margin-top:3rem!important}.mr-xl-5,.mx-xl-5{margin-right:3rem!important}.mb-xl-5,.my-xl-5{margin-bottom:3rem!important}.ml-xl-5,.mx-xl-5{margin-left:3rem!important}.p-xl-0{padding:0!important}.pt-xl-0,.py-xl-0{padding-top:0!important}.pr-xl-0,.px-xl-0{padding-right:0!important}.pb-xl-0,.py-xl-0{padding-bottom:0!important}.pl-xl-0,.px-xl-0{padding-left:0!important}.p-xl-1{padding:.25rem!important}.pt-xl-1,.py-xl-1{padding-top:.25rem!important}.pr-xl-1,.px-xl-1{padding-right:.25rem!important}.pb-xl-1,.py-xl-1{padding-bottom:.25rem!important}.pl-xl-1,.px-xl-1{padding-left:.25rem!important}.p-xl-2{padding:.5rem!important}.pt-xl-2,.py-xl-2{padding-top:.5rem!important}.pr-xl-2,.px-xl-2{padding-right:.5rem!important}.pb-xl-2,.py-xl-2{padding-bottom:.5rem!important}.pl-xl-2,.px-xl-2{padding-left:.5rem!important}.p-xl-3{padding:1rem!important}.pt-xl-3,.py-xl-3{padding-top:1rem!important}.pr-xl-3,.px-xl-3{padding-right:1rem!important}.pb-xl-3,.py-xl-3{padding-bottom:1rem!important}.pl-xl-3,.px-xl-3{padding-left:1rem!important}.p-xl-4{padding:1.5rem!important}.pt-xl-4,.py-xl-4{padding-top:1.5rem!important}.pr-xl-4,.px-xl-4{padding-right:1.5rem!important}.pb-xl-4,.py-xl-4{padding-bottom:1.5rem!important}.pl-xl-4,.px-xl-4{padding-left:1.5rem!important}.p-xl-5{padding:3rem!important}.pt-xl-5,.py-xl-5{padding-top:3rem!important}.pr-xl-5,.px-xl-5{padding-right:3rem!important}.pb-xl-5,.py-xl-5{padding-bottom:3rem!important}.pl-xl-5,.px-xl-5{padding-left:3rem!important}.m-xl-n1{margin:-.25rem!important}.mt-xl-n1,.my-xl-n1{margin-top:-.25rem!important}.mr-xl-n1,.mx-xl-n1{margin-right:-.25rem!important}.mb-xl-n1,.my-xl-n1{margin-bottom:-.25rem!important}.ml-xl-n1,.mx-xl-n1{margin-left:-.25rem!important}.m-xl-n2{margin:-.5rem!important}.mt-xl-n2,.my-xl-n2{margin-top:-.5rem!important}.mr-xl-n2,.mx-xl-n2{margin-right:-.5rem!important}.mb-xl-n2,.my-xl-n2{margin-bottom:-.5rem!important}.ml-xl-n2,.mx-xl-n2{margin-left:-.5rem!important}.m-xl-n3{margin:-1rem!important}.mt-xl-n3,.my-xl-n3{margin-top:-1rem!important}.mr-xl-n3,.mx-xl-n3{margin-right:-1rem!important}.mb-xl-n3,.my-xl-n3{margin-bottom:-1rem!important}.ml-xl-n3,.mx-xl-n3{margin-left:-1rem!important}.m-xl-n4{margin:-1.5rem!important}.mt-xl-n4,.my-xl-n4{margin-top:-1.5rem!important}.mr-xl-n4,.mx-xl-n4{margin-right:-1.5rem!important}.mb-xl-n4,.my-xl-n4{margin-bottom:-1.5rem!important}.ml-xl-n4,.mx-xl-n4{margin-left:-1.5rem!important}.m-xl-n5{margin:-3rem!important}.mt-xl-n5,.my-xl-n5{margin-top:-3rem!important}.mr-xl-n5,.mx-xl-n5{margin-right:-3rem!important}.mb-xl-n5,.my-xl-n5{margin-bottom:-3rem!important}.ml-xl-n5,.mx-xl-n5{margin-left:-3rem!important}.m-xl-auto{margin:auto!important}.mt-xl-auto,.my-xl-auto{margin-top:auto!important}.mr-xl-auto,.mx-xl-auto{margin-right:auto!important}.mb-xl-auto,.my-xl-auto{margin-bottom:auto!important}.ml-xl-auto,.mx-xl-auto{margin-left:auto!important}}.text-monospace{font-family:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace!important}.text-justify{text-align:justify!important}.text-wrap{white-space:normal!important}.text-nowrap{white-space:nowrap!important}.text-truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.text-left{text-align:left!important}.text-right{text-align:right!important}.text-center{text-align:center!important}@media (min-width:576px){.text-sm-left{text-align:left!important}.text-sm-right{text-align:right!important}.text-sm-center{text-align:center!important}}@media (min-width:768px){.text-md-left{text-align:left!important}.text-md-right{text-align:right!important}.text-md-center{text-align:center!important}}@media (min-width:992px){.text-lg-left{text-align:left!important}.text-lg-right{text-align:right!important}.text-lg-center{text-align:center!important}}@media (min-width:1200px){.text-xl-left{text-align:left!important}.text-xl-right{text-align:right!important}.text-xl-center{text-align:center!important}}.text-lowercase{text-transform:lowercase!important}.text-uppercase{text-transform:uppercase!important}.text-capitalize{text-transform:capitalize!important}.font-weight-light{font-weight:300!important}.font-weight-lighter{font-weight:lighter!important}.font-weight-normal{font-weight:400!important}.font-weight-bold{font-weight:700!important}.font-weight-bolder{font-weight:bolder!important}.font-italic{font-style:italic!important}.text-white{color:#fff!important}.text-primary{color:#007bff!important}a.text-primary:focus,a.text-primary:hover{color:#0056b3!important}.text-secondary{color:#6c757d!important}a.text-secondary:focus,a.text-secondary:hover{color:#494f54!important}.text-success{color:#28a745!important}a.text-success:focus,a.text-success:hover{color:#19692c!important}.text-info{color:#17a2b8!important}a.text-info:focus,a.text-info:hover{color:#0f6674!important}.text-warning{color:#ffc107!important}a.text-warning:focus,a.text-warning:hover{color:#ba8b00!important}.text-danger{color:#dc3545!important}a.text-danger:focus,a.text-danger:hover{color:#a71d2a!important}.text-light{color:#f8f9fa!important}a.text-light:focus,a.text-light:hover{color:#cbd3da!important}.text-dark{color:#343a40!important}a.text-dark:focus,a.text-dark:hover{color:#121416!important}.text-body{color:#212529!important}.text-muted{color:#6c757d!important}.text-black-50{color:rgba(0,0,0,.5)!important}.text-white-50{color:rgba(255,255,255,.5)!important}.text-hide{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.text-decoration-none{text-decoration:none!important}.text-break{word-break:break-word!important;overflow-wrap:break-word!important}.text-reset{color:inherit!important}.visible{visibility:visible!important}.invisible{visibility:hidden!important}@media print{*,::after,::before{text-shadow:none!important;box-shadow:none!important}a:not(.btn){text-decoration:underline}abbr[title]::after{content:" (" attr(title) ")"}pre{white-space:pre-wrap!important}blockquote,pre{border:1px solid #adb5bd;page-break-inside:avoid}thead{display:table-header-group}img,tr{page-break-inside:avoid}h2,h3,p{orphans:3;widows:3}h2,h3{page-break-after:avoid}@page{size:a3}body{min-width:992px!important}.container{min-width:992px!important}.navbar{display:none}.badge{border:1px solid #000}.table{border-collapse:collapse!important}.table td,.table th{background-color:#fff!important}.table-bordered td,.table-bordered th{border:1px solid #dee2e6!important}.table-dark{color:inherit}.table-dark tbody+tbody,.table-dark td,.table-dark th,.table-dark thead th{border-color:#dee2e6}.table .thead-dark th{color:inherit;border-color:#dee2e6}}
  22908. /*# sourceMappingURL=bootstrap.min.css.map */body {
  22909. padding-top: 10px;
  22910. }
  22911. .popover {
  22912. max-width: none;
  22913. }
  22914. .octicon {
  22915. margin-right:.25em;
  22916. }
  22917. .table-bordered>thead>tr>td {
  22918. border-bottom-width: 1px;
  22919. }
  22920. .table tbody>tr>td, .table thead>tr>td {
  22921. padding-top: 3px;
  22922. padding-bottom: 3px;
  22923. }
  22924. .table-condensed tbody>tr>td {
  22925. padding-top: 0;
  22926. padding-bottom: 0;
  22927. }
  22928. .table .progress {
  22929. margin-bottom: inherit;
  22930. }
  22931. .table-borderless th, .table-borderless td {
  22932. border: 0 !important;
  22933. }
  22934. .table tbody tr.covered-by-large-tests, li.covered-by-large-tests, tr.success, td.success, li.success, span.success {
  22935. background-color: #dff0d8;
  22936. }
  22937. .table tbody tr.covered-by-medium-tests, li.covered-by-medium-tests {
  22938. background-color: #c3e3b5;
  22939. }
  22940. .table tbody tr.covered-by-small-tests, li.covered-by-small-tests {
  22941. background-color: #99cb84;
  22942. }
  22943. .table tbody tr.danger, .table tbody td.danger, li.danger, span.danger {
  22944. background-color: #f2dede;
  22945. }
  22946. .table tbody tr.warning, .table tbody td.warning, li.warning, span.warning {
  22947. background-color: #fcf8e3;
  22948. }
  22949. .table tbody td.info {
  22950. background-color: #d9edf7;
  22951. }
  22952. td.big {
  22953. width: 117px;
  22954. }
  22955. td.small {
  22956. }
  22957. td.codeLine {
  22958. font-family: "Source Code Pro", "SFMono-Regular", Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
  22959. white-space: pre;
  22960. }
  22961. td span.comment {
  22962. color: #888a85;
  22963. }
  22964. td span.default {
  22965. color: #2e3436;
  22966. }
  22967. td span.html {
  22968. color: #888a85;
  22969. }
  22970. td span.keyword {
  22971. color: #2e3436;
  22972. font-weight: bold;
  22973. }
  22974. pre span.string {
  22975. color: #2e3436;
  22976. }
  22977. span.success, span.warning, span.danger {
  22978. margin-right: 2px;
  22979. padding-left: 10px;
  22980. padding-right: 10px;
  22981. text-align: center;
  22982. }
  22983. #classCoverageDistribution, #classComplexity {
  22984. height: 200px;
  22985. width: 475px;
  22986. }
  22987. #toplink {
  22988. position: fixed;
  22989. left: 5px;
  22990. bottom: 5px;
  22991. outline: 0;
  22992. }
  22993. svg text {
  22994. font-family: "Lucida Grande", "Lucida Sans Unicode", Verdana, Arial, Helvetica, sans-serif;
  22995. font-size: 11px;
  22996. color: #666;
  22997. fill: #666;
  22998. }
  22999. .scrollbox {
  23000. height:245px;
  23001. overflow-x:hidden;
  23002. overflow-y:scroll;
  23003. }
  23004. .octicon {
  23005. display: inline-block;
  23006. vertical-align: text-top;
  23007. fill: currentColor;
  23008. }
  23009. .nvd3 .nv-axis{pointer-events:none;opacity:1}.nvd3 .nv-axis path{fill:none;stroke:#000;stroke-opacity:.75;shape-rendering:crispEdges}.nvd3 .nv-axis path.domain{stroke-opacity:.75}.nvd3 .nv-axis.nv-x path.domain{stroke-opacity:0}.nvd3 .nv-axis line{fill:none;stroke:#e5e5e5;shape-rendering:crispEdges}.nvd3 .nv-axis .zero line,.nvd3 .nv-axis line.zero{stroke-opacity:.75}.nvd3 .nv-axis .nv-axisMaxMin text{font-weight:700}.nvd3 .x .nv-axis .nv-axisMaxMin text,.nvd3 .x2 .nv-axis .nv-axisMaxMin text,.nvd3 .x3 .nv-axis .nv-axisMaxMin text{text-anchor:middle}.nvd3 .nv-axis.nv-disabled{opacity:0}.nvd3 .nv-bars rect{fill-opacity:.75;transition:fill-opacity 250ms linear;-moz-transition:fill-opacity 250ms linear;-webkit-transition:fill-opacity 250ms linear}.nvd3 .nv-bars rect.hover{fill-opacity:1}.nvd3 .nv-bars .hover rect{fill:#add8e6}.nvd3 .nv-bars text{fill:rgba(0,0,0,0)}.nvd3 .nv-bars .hover text{fill:rgba(0,0,0,1)}.nvd3 .nv-multibar .nv-groups rect,.nvd3 .nv-multibarHorizontal .nv-groups rect,.nvd3 .nv-discretebar .nv-groups rect{stroke-opacity:0;transition:fill-opacity 250ms linear;-moz-transition:fill-opacity 250ms linear;-webkit-transition:fill-opacity 250ms linear}.nvd3 .nv-multibar .nv-groups rect:hover,.nvd3 .nv-multibarHorizontal .nv-groups rect:hover,.nvd3 .nv-candlestickBar .nv-ticks rect:hover,.nvd3 .nv-discretebar .nv-groups rect:hover{fill-opacity:1}.nvd3 .nv-discretebar .nv-groups text,.nvd3 .nv-multibarHorizontal .nv-groups text{font-weight:700;fill:rgba(0,0,0,1);stroke:rgba(0,0,0,0)}.nvd3 .nv-boxplot circle{fill-opacity:.5}.nvd3 .nv-boxplot circle:hover{fill-opacity:1}.nvd3 .nv-boxplot rect:hover{fill-opacity:1}.nvd3 line.nv-boxplot-median{stroke:#000}.nv-boxplot-tick:hover{stroke-width:2.5px}.nvd3.nv-bullet{font:10px sans-serif}.nvd3.nv-bullet .nv-measure{fill-opacity:.8}.nvd3.nv-bullet .nv-measure:hover{fill-opacity:1}.nvd3.nv-bullet .nv-marker{stroke:#000;stroke-width:2px}.nvd3.nv-bullet .nv-markerTriangle{stroke:#000;fill:#fff;stroke-width:1.5px}.nvd3.nv-bullet .nv-tick line{stroke:#666;stroke-width:.5px}.nvd3.nv-bullet .nv-range.nv-s0{fill:#eee}.nvd3.nv-bullet .nv-range.nv-s1{fill:#ddd}.nvd3.nv-bullet .nv-range.nv-s2{fill:#ccc}.nvd3.nv-bullet .nv-title{font-size:14px;font-weight:700}.nvd3.nv-bullet .nv-subtitle{fill:#999}.nvd3.nv-bullet .nv-range{fill:#bababa;fill-opacity:.4}.nvd3.nv-bullet .nv-range:hover{fill-opacity:.7}.nvd3.nv-candlestickBar .nv-ticks .nv-tick{stroke-width:1px}.nvd3.nv-candlestickBar .nv-ticks .nv-tick.hover{stroke-width:2px}.nvd3.nv-candlestickBar .nv-ticks .nv-tick.positive rect{stroke:#2ca02c;fill:#2ca02c}.nvd3.nv-candlestickBar .nv-ticks .nv-tick.negative rect{stroke:#d62728;fill:#d62728}.with-transitions .nv-candlestickBar .nv-ticks .nv-tick{transition:stroke-width 250ms linear,stroke-opacity 250ms linear;-moz-transition:stroke-width 250ms linear,stroke-opacity 250ms linear;-webkit-transition:stroke-width 250ms linear,stroke-opacity 250ms linear}.nvd3.nv-candlestickBar .nv-ticks line{stroke:#333}.nvd3 .nv-legend .nv-disabled rect{}.nvd3 .nv-check-box .nv-box{fill-opacity:0;stroke-width:2}.nvd3 .nv-check-box .nv-check{fill-opacity:0;stroke-width:4}.nvd3 .nv-series.nv-disabled .nv-check-box .nv-check{fill-opacity:0;stroke-opacity:0}.nvd3 .nv-controlsWrap .nv-legend .nv-check-box .nv-check{opacity:0}.nvd3.nv-linePlusBar .nv-bar rect{fill-opacity:.75}.nvd3.nv-linePlusBar .nv-bar rect:hover{fill-opacity:1}.nvd3 .nv-groups path.nv-line{fill:none}.nvd3 .nv-groups path.nv-area{stroke:none}.nvd3.nv-line .nvd3.nv-scatter .nv-groups .nv-point{fill-opacity:0;stroke-opacity:0}.nvd3.nv-scatter.nv-single-point .nv-groups .nv-point{fill-opacity:.5!important;stroke-opacity:.5!important}.with-transitions .nvd3 .nv-groups .nv-point{transition:stroke-width 250ms linear,stroke-opacity 250ms linear;-moz-transition:stroke-width 250ms linear,stroke-opacity 250ms linear;-webkit-transition:stroke-width 250ms linear,stroke-opacity 250ms linear}.nvd3.nv-scatter .nv-groups .nv-point.hover,.nvd3 .nv-groups .nv-point.hover{stroke-width:7px;fill-opacity:.95!important;stroke-opacity:.95!important}.nvd3 .nv-point-paths path{stroke:#aaa;stroke-opacity:0;fill:#eee;fill-opacity:0}.nvd3 .nv-indexLine{cursor:ew-resize}svg.nvd3-svg{-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-ms-user-select:none;-moz-user-select:none;user-select:none;display:block;width:100%;height:100%}.nvtooltip.with-3d-shadow,.with-3d-shadow .nvtooltip{-moz-box-shadow:0 5px 10px rgba(0,0,0,.2);-webkit-box-shadow:0 5px 10px rgba(0,0,0,.2);box-shadow:0 5px 10px rgba(0,0,0,.2);-webkit-border-radius:5px;-moz-border-radius:5px;border-radius:5px}.nvd3 text{font:400 12px Arial}.nvd3 .title{font:700 14px Arial}.nvd3 .nv-background{fill:#fff;fill-opacity:0}.nvd3.nv-noData{font-size:18px;font-weight:700}.nv-brush .extent{fill-opacity:.125;shape-rendering:crispEdges}.nv-brush .resize path{fill:#eee;stroke:#666}.nvd3 .nv-legend .nv-series{cursor:pointer}.nvd3 .nv-legend .nv-disabled circle{fill-opacity:0}.nvd3 .nv-brush .extent{fill-opacity:0!important}.nvd3 .nv-brushBackground rect{stroke:#000;stroke-width:.4;fill:#fff;fill-opacity:.7}.nvd3.nv-ohlcBar .nv-ticks .nv-tick{stroke-width:1px}.nvd3.nv-ohlcBar .nv-ticks .nv-tick.hover{stroke-width:2px}.nvd3.nv-ohlcBar .nv-ticks .nv-tick.positive{stroke:#2ca02c}.nvd3.nv-ohlcBar .nv-ticks .nv-tick.negative{stroke:#d62728}.nvd3 .background path{fill:none;stroke:#EEE;stroke-opacity:.4;shape-rendering:crispEdges}.nvd3 .foreground path{fill:none;stroke-opacity:.7}.nvd3 .nv-parallelCoordinates-brush .extent{fill:#fff;fill-opacity:.6;stroke:gray;shape-rendering:crispEdges}.nvd3 .nv-parallelCoordinates .hover{fill-opacity:1;stroke-width:3px}.nvd3 .missingValuesline line{fill:none;stroke:#000;stroke-width:1;stroke-opacity:1;stroke-dasharray:5,5}.nvd3.nv-pie path{stroke-opacity:0;transition:fill-opacity 250ms linear,stroke-width 250ms linear,stroke-opacity 250ms linear;-moz-transition:fill-opacity 250ms linear,stroke-width 250ms linear,stroke-opacity 250ms linear;-webkit-transition:fill-opacity 250ms linear,stroke-width 250ms linear,stroke-opacity 250ms linear}.nvd3.nv-pie .nv-pie-title{font-size:24px;fill:rgba(19,196,249,.59)}.nvd3.nv-pie .nv-slice text{stroke:#000;stroke-width:0}.nvd3.nv-pie path{stroke:#fff;stroke-width:1px;stroke-opacity:1}.nvd3.nv-pie .hover path{fill-opacity:.7}.nvd3.nv-pie .nv-label{pointer-events:none}.nvd3.nv-pie .nv-label rect{fill-opacity:0;stroke-opacity:0}.nvd3 .nv-groups .nv-point.hover{stroke-width:20px;stroke-opacity:.5}.nvd3 .nv-scatter .nv-point.hover{fill-opacity:1}.nv-noninteractive{pointer-events:none}.nv-distx,.nv-disty{pointer-events:none}.nvd3.nv-sparkline path{fill:none}.nvd3.nv-sparklineplus g.nv-hoverValue{pointer-events:none}.nvd3.nv-sparklineplus .nv-hoverValue line{stroke:#333;stroke-width:1.5px}.nvd3.nv-sparklineplus,.nvd3.nv-sparklineplus g{pointer-events:all}.nvd3 .nv-hoverArea{fill-opacity:0;stroke-opacity:0}.nvd3.nv-sparklineplus .nv-xValue,.nvd3.nv-sparklineplus .nv-yValue{stroke-width:0;font-size:.9em;font-weight:400}.nvd3.nv-sparklineplus .nv-yValue{stroke:#f66}.nvd3.nv-sparklineplus .nv-maxValue{stroke:#2ca02c;fill:#2ca02c}.nvd3.nv-sparklineplus .nv-minValue{stroke:#d62728;fill:#d62728}.nvd3.nv-sparklineplus .nv-currentValue{font-weight:700;font-size:1.1em}.nvd3.nv-stackedarea path.nv-area{fill-opacity:.7;stroke-opacity:0;transition:fill-opacity 250ms linear,stroke-opacity 250ms linear;-moz-transition:fill-opacity 250ms linear,stroke-opacity 250ms linear;-webkit-transition:fill-opacity 250ms linear,stroke-opacity 250ms linear}.nvd3.nv-stackedarea path.nv-area.hover{fill-opacity:.9}.nvd3.nv-stackedarea .nv-groups .nv-point{stroke-opacity:0;fill-opacity:0}.nvtooltip{position:absolute;background-color:rgba(255,255,255,1);color:rgba(0,0,0,1);padding:1px;border:1px solid rgba(0,0,0,.2);z-index:10000;display:block;font-family:Arial;font-size:13px;text-align:left;pointer-events:none;white-space:nowrap;-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.nvtooltip{background:rgba(255,255,255,.8);border:1px solid rgba(0,0,0,.5);border-radius:4px}.nvtooltip.with-transitions,.with-transitions .nvtooltip{transition:opacity 50ms linear;-moz-transition:opacity 50ms linear;-webkit-transition:opacity 50ms linear;transition-delay:200ms;-moz-transition-delay:200ms;-webkit-transition-delay:200ms}.nvtooltip.x-nvtooltip,.nvtooltip.y-nvtooltip{padding:8px}.nvtooltip h3{margin:0;padding:4px 14px;line-height:18px;font-weight:400;background-color:rgba(247,247,247,.75);color:rgba(0,0,0,1);text-align:center;border-bottom:1px solid #ebebeb;-webkit-border-radius:5px 5px 0 0;-moz-border-radius:5px 5px 0 0;border-radius:5px 5px 0 0}.nvtooltip p{margin:0;padding:5px 14px;text-align:center}.nvtooltip span{display:inline-block;margin:2px 0}.nvtooltip table{margin:6px;border-spacing:0}.nvtooltip table td{padding:2px 9px 2px 0;vertical-align:middle}.nvtooltip table td.key{font-weight:400}.nvtooltip table td.value{text-align:right;font-weight:700}.nvtooltip table tr.highlight td{padding:1px 9px 1px 0;border-bottom-style:solid;border-bottom-width:1px;border-top-style:solid;border-top-width:1px}.nvtooltip table td.legend-color-guide div{width:8px;height:8px;vertical-align:middle}.nvtooltip table td.legend-color-guide div{width:12px;height:12px;border:1px solid #999}.nvtooltip .footer{padding:3px;text-align:center}.nvtooltip-pending-removal{pointer-events:none;display:none}.nvd3 .nv-interactiveGuideLine{pointer-events:none}.nvd3 line.nv-guideline{stroke:#ccc} <tr>
  23010. <td class="{{classes_level}}">{{name}}</td>
  23011. <td class="{{classes_level}} big">{{classes_bar}}</td>
  23012. <td class="{{classes_level}} small"><div align="right">{{classes_tested_percent}}</div></td>
  23013. <td class="{{classes_level}} small"><div align="right">{{classes_number}}</div></td>
  23014. <td class="{{methods_level}} big">{{methods_bar}}</td>
  23015. <td class="{{methods_level}} small"><div align="right">{{methods_tested_percent}}</div></td>
  23016. <td class="{{methods_level}} small"><div align="right">{{methods_number}}</div></td>
  23017. <td class="{{methods_level}} small">{{crap}}</td>
  23018. <td class="{{lines_level}} big">{{lines_bar}}</td>
  23019. <td class="{{lines_level}} small"><div align="right">{{lines_executed_percent}}</div></td>
  23020. <td class="{{lines_level}} small"><div align="right">{{lines_number}}</div></td>
  23021. </tr>
  23022. <svg xmlns="http://www.w3.org/2000/svg" width="12" height="16" viewBox="0 0 12 16"><path fill-rule="evenodd" d="M8.5 1H1c-.55 0-1 .45-1 1v12c0 .55.45 1 1 1h10c.55 0 1-.45 1-1V4.5L8.5 1zM11 14H1V2h7l3 3v9zM5 6.98L3.5 8.5 5 10l-.5 1L2 8.5 4.5 6l.5.98zM7.5 6L10 8.5 7.5 11l-.5-.98L8.5 8.5 7 7l.5-1z"/></svg><svg xmlns="http://www.w3.org/2000/svg" width="14" height="16" viewBox="0 0 14 16"><path fill-rule="evenodd" d="M13 4H7V3c0-.66-.31-1-1-1H1c-.55 0-1 .45-1 1v10c0 .55.45 1 1 1h12c.55 0 1-.45 1-1V5c0-.55-.45-1-1-1zM6 4H1V3h5v1z"/></svg><?php
  23023. declare (strict_types=1);
  23024. /*
  23025. * This file is part of phpunit/php-code-coverage.
  23026. *
  23027. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  23028. *
  23029. * For the full copyright and license information, please view the LICENSE
  23030. * file that was distributed with this source code.
  23031. */
  23032. namespace PHPUnit\SebastianBergmann\CodeCoverage\Report\Html;
  23033. use PHPUnit\SebastianBergmann\CodeCoverage\Node\File as FileNode;
  23034. use PHPUnit\SebastianBergmann\CodeCoverage\Percentage;
  23035. use PHPUnit\SebastianBergmann\Template\Template;
  23036. /**
  23037. * Renders a file node.
  23038. */
  23039. final class File extends \PHPUnit\SebastianBergmann\CodeCoverage\Report\Html\Renderer
  23040. {
  23041. /**
  23042. * @var int
  23043. */
  23044. private $htmlSpecialCharsFlags = \ENT_COMPAT | \ENT_HTML401 | \ENT_SUBSTITUTE;
  23045. /**
  23046. * @throws \RuntimeException
  23047. */
  23048. public function render(\PHPUnit\SebastianBergmann\CodeCoverage\Node\File $node, string $file) : void
  23049. {
  23050. $template = new \PHPUnit\SebastianBergmann\Template\Template($this->templatePath . 'file.html', '{{', '}}');
  23051. $template->setVar(['items' => $this->renderItems($node), 'lines' => $this->renderSource($node)]);
  23052. $this->setCommonTemplateVariables($template, $node);
  23053. $template->renderTo($file);
  23054. }
  23055. protected function renderItems(\PHPUnit\SebastianBergmann\CodeCoverage\Node\File $node) : string
  23056. {
  23057. $template = new \PHPUnit\SebastianBergmann\Template\Template($this->templatePath . 'file_item.html', '{{', '}}');
  23058. $methodItemTemplate = new \PHPUnit\SebastianBergmann\Template\Template($this->templatePath . 'method_item.html', '{{', '}}');
  23059. $items = $this->renderItemTemplate($template, ['name' => 'Total', 'numClasses' => $node->getNumClassesAndTraits(), 'numTestedClasses' => $node->getNumTestedClassesAndTraits(), 'numMethods' => $node->getNumFunctionsAndMethods(), 'numTestedMethods' => $node->getNumTestedFunctionsAndMethods(), 'linesExecutedPercent' => $node->getLineExecutedPercent(\false), 'linesExecutedPercentAsString' => $node->getLineExecutedPercent(), 'numExecutedLines' => $node->getNumExecutedLines(), 'numExecutableLines' => $node->getNumExecutableLines(), 'testedMethodsPercent' => $node->getTestedFunctionsAndMethodsPercent(\false), 'testedMethodsPercentAsString' => $node->getTestedFunctionsAndMethodsPercent(), 'testedClassesPercent' => $node->getTestedClassesAndTraitsPercent(\false), 'testedClassesPercentAsString' => $node->getTestedClassesAndTraitsPercent(), 'crap' => '<abbr title="Change Risk Anti-Patterns (CRAP) Index">CRAP</abbr>']);
  23060. $items .= $this->renderFunctionItems($node->getFunctions(), $methodItemTemplate);
  23061. $items .= $this->renderTraitOrClassItems($node->getTraits(), $template, $methodItemTemplate);
  23062. $items .= $this->renderTraitOrClassItems($node->getClasses(), $template, $methodItemTemplate);
  23063. return $items;
  23064. }
  23065. protected function renderTraitOrClassItems(array $items, \PHPUnit\SebastianBergmann\Template\Template $template, \PHPUnit\SebastianBergmann\Template\Template $methodItemTemplate) : string
  23066. {
  23067. $buffer = '';
  23068. if (empty($items)) {
  23069. return $buffer;
  23070. }
  23071. foreach ($items as $name => $item) {
  23072. $numMethods = 0;
  23073. $numTestedMethods = 0;
  23074. foreach ($item['methods'] as $method) {
  23075. if ($method['executableLines'] > 0) {
  23076. $numMethods++;
  23077. if ($method['executedLines'] === $method['executableLines']) {
  23078. $numTestedMethods++;
  23079. }
  23080. }
  23081. }
  23082. if ($item['executableLines'] > 0) {
  23083. $numClasses = 1;
  23084. $numTestedClasses = $numTestedMethods == $numMethods ? 1 : 0;
  23085. $linesExecutedPercentAsString = \PHPUnit\SebastianBergmann\CodeCoverage\Percentage::fromFractionAndTotal($item['executedLines'], $item['executableLines'])->asString();
  23086. } else {
  23087. $numClasses = 'n/a';
  23088. $numTestedClasses = 'n/a';
  23089. $linesExecutedPercentAsString = 'n/a';
  23090. }
  23091. $testedMethodsPercentage = \PHPUnit\SebastianBergmann\CodeCoverage\Percentage::fromFractionAndTotal($numTestedMethods, $numMethods);
  23092. $testedClassesPercentage = \PHPUnit\SebastianBergmann\CodeCoverage\Percentage::fromFractionAndTotal($numTestedMethods === $numMethods ? 1 : 0, 1);
  23093. $buffer .= $this->renderItemTemplate($template, ['name' => $this->abbreviateClassName($name), 'numClasses' => $numClasses, 'numTestedClasses' => $numTestedClasses, 'numMethods' => $numMethods, 'numTestedMethods' => $numTestedMethods, 'linesExecutedPercent' => \PHPUnit\SebastianBergmann\CodeCoverage\Percentage::fromFractionAndTotal($item['executedLines'], $item['executableLines'])->asFloat(), 'linesExecutedPercentAsString' => $linesExecutedPercentAsString, 'numExecutedLines' => $item['executedLines'], 'numExecutableLines' => $item['executableLines'], 'testedMethodsPercent' => $testedMethodsPercentage->asFloat(), 'testedMethodsPercentAsString' => $testedMethodsPercentage->asString(), 'testedClassesPercent' => $testedClassesPercentage->asFloat(), 'testedClassesPercentAsString' => $testedClassesPercentage->asString(), 'crap' => $item['crap']]);
  23094. foreach ($item['methods'] as $method) {
  23095. $buffer .= $this->renderFunctionOrMethodItem($methodItemTemplate, $method, '&nbsp;');
  23096. }
  23097. }
  23098. return $buffer;
  23099. }
  23100. protected function renderFunctionItems(array $functions, \PHPUnit\SebastianBergmann\Template\Template $template) : string
  23101. {
  23102. if (empty($functions)) {
  23103. return '';
  23104. }
  23105. $buffer = '';
  23106. foreach ($functions as $function) {
  23107. $buffer .= $this->renderFunctionOrMethodItem($template, $function);
  23108. }
  23109. return $buffer;
  23110. }
  23111. protected function renderFunctionOrMethodItem(\PHPUnit\SebastianBergmann\Template\Template $template, array $item, string $indent = '') : string
  23112. {
  23113. $numMethods = 0;
  23114. $numTestedMethods = 0;
  23115. if ($item['executableLines'] > 0) {
  23116. $numMethods = 1;
  23117. if ($item['executedLines'] === $item['executableLines']) {
  23118. $numTestedMethods = 1;
  23119. }
  23120. }
  23121. $executedLinesPercentage = \PHPUnit\SebastianBergmann\CodeCoverage\Percentage::fromFractionAndTotal($item['executedLines'], $item['executableLines']);
  23122. $testedMethodsPercentage = \PHPUnit\SebastianBergmann\CodeCoverage\Percentage::fromFractionAndTotal($numTestedMethods, 1);
  23123. return $this->renderItemTemplate($template, ['name' => \sprintf('%s<a href="#%d"><abbr title="%s">%s</abbr></a>', $indent, $item['startLine'], \htmlspecialchars($item['signature'], $this->htmlSpecialCharsFlags), $item['functionName'] ?? $item['methodName']), 'numMethods' => $numMethods, 'numTestedMethods' => $numTestedMethods, 'linesExecutedPercent' => $executedLinesPercentage->asFloat(), 'linesExecutedPercentAsString' => $executedLinesPercentage->asString(), 'numExecutedLines' => $item['executedLines'], 'numExecutableLines' => $item['executableLines'], 'testedMethodsPercent' => $testedMethodsPercentage->asFloat(), 'testedMethodsPercentAsString' => $testedMethodsPercentage->asString(), 'crap' => $item['crap']]);
  23124. }
  23125. protected function renderSource(\PHPUnit\SebastianBergmann\CodeCoverage\Node\File $node) : string
  23126. {
  23127. $coverageData = $node->getCoverageData();
  23128. $testData = $node->getTestData();
  23129. $codeLines = $this->loadFile($node->getPath());
  23130. $lines = '';
  23131. $i = 1;
  23132. foreach ($codeLines as $line) {
  23133. $trClass = '';
  23134. $popoverContent = '';
  23135. $popoverTitle = '';
  23136. if (\array_key_exists($i, $coverageData)) {
  23137. $numTests = $coverageData[$i] ? \count($coverageData[$i]) : 0;
  23138. if ($coverageData[$i] === null) {
  23139. $trClass = ' class="warning"';
  23140. } elseif ($numTests == 0) {
  23141. $trClass = ' class="danger"';
  23142. } else {
  23143. $lineCss = 'covered-by-large-tests';
  23144. $popoverContent = '<ul>';
  23145. if ($numTests > 1) {
  23146. $popoverTitle = $numTests . ' tests cover line ' . $i;
  23147. } else {
  23148. $popoverTitle = '1 test covers line ' . $i;
  23149. }
  23150. foreach ($coverageData[$i] as $test) {
  23151. if ($lineCss == 'covered-by-large-tests' && $testData[$test]['size'] == 'medium') {
  23152. $lineCss = 'covered-by-medium-tests';
  23153. } elseif ($testData[$test]['size'] == 'small') {
  23154. $lineCss = 'covered-by-small-tests';
  23155. }
  23156. switch ($testData[$test]['status']) {
  23157. case 0:
  23158. switch ($testData[$test]['size']) {
  23159. case 'small':
  23160. $testCSS = ' class="covered-by-small-tests"';
  23161. break;
  23162. case 'medium':
  23163. $testCSS = ' class="covered-by-medium-tests"';
  23164. break;
  23165. default:
  23166. $testCSS = ' class="covered-by-large-tests"';
  23167. break;
  23168. }
  23169. break;
  23170. case 1:
  23171. case 2:
  23172. $testCSS = ' class="warning"';
  23173. break;
  23174. case 3:
  23175. $testCSS = ' class="danger"';
  23176. break;
  23177. case 4:
  23178. $testCSS = ' class="danger"';
  23179. break;
  23180. default:
  23181. $testCSS = '';
  23182. }
  23183. $popoverContent .= \sprintf('<li%s>%s</li>', $testCSS, \htmlspecialchars($test, $this->htmlSpecialCharsFlags));
  23184. }
  23185. $popoverContent .= '</ul>';
  23186. $trClass = ' class="' . $lineCss . ' popin"';
  23187. }
  23188. }
  23189. $popover = '';
  23190. if (!empty($popoverTitle)) {
  23191. $popover = \sprintf(' data-title="%s" data-content="%s" data-placement="top" data-html="true"', $popoverTitle, \htmlspecialchars($popoverContent, $this->htmlSpecialCharsFlags));
  23192. }
  23193. $lines .= \sprintf(' <tr%s><td%s><div align="right"><a name="%d"></a><a href="#%d">%d</a></div></td><td class="codeLine">%s</td></tr>' . "\n", $trClass, $popover, $i, $i, $i, $line);
  23194. $i++;
  23195. }
  23196. return $lines;
  23197. }
  23198. /**
  23199. * @param string $file
  23200. */
  23201. protected function loadFile($file) : array
  23202. {
  23203. $buffer = \file_get_contents($file);
  23204. $tokens = \token_get_all($buffer);
  23205. $result = [''];
  23206. $i = 0;
  23207. $stringFlag = \false;
  23208. $fileEndsWithNewLine = \substr($buffer, -1) == "\n";
  23209. unset($buffer);
  23210. foreach ($tokens as $j => $token) {
  23211. if (\is_string($token)) {
  23212. if ($token === '"' && $tokens[$j - 1] !== '\\') {
  23213. $result[$i] .= \sprintf('<span class="string">%s</span>', \htmlspecialchars($token, $this->htmlSpecialCharsFlags));
  23214. $stringFlag = !$stringFlag;
  23215. } else {
  23216. $result[$i] .= \sprintf('<span class="keyword">%s</span>', \htmlspecialchars($token, $this->htmlSpecialCharsFlags));
  23217. }
  23218. continue;
  23219. }
  23220. [$token, $value] = $token;
  23221. $value = \str_replace(["\t", ' '], ['&nbsp;&nbsp;&nbsp;&nbsp;', '&nbsp;'], \htmlspecialchars($value, $this->htmlSpecialCharsFlags));
  23222. if ($value === "\n") {
  23223. $result[++$i] = '';
  23224. } else {
  23225. $lines = \explode("\n", $value);
  23226. foreach ($lines as $jj => $line) {
  23227. $line = \trim($line);
  23228. if ($line !== '') {
  23229. if ($stringFlag) {
  23230. $colour = 'string';
  23231. } else {
  23232. switch ($token) {
  23233. case \T_INLINE_HTML:
  23234. $colour = 'html';
  23235. break;
  23236. case \T_COMMENT:
  23237. case \T_DOC_COMMENT:
  23238. $colour = 'comment';
  23239. break;
  23240. case \T_ABSTRACT:
  23241. case \T_ARRAY:
  23242. case \T_AS:
  23243. case \T_BREAK:
  23244. case \T_CALLABLE:
  23245. case \T_CASE:
  23246. case \T_CATCH:
  23247. case \T_CLASS:
  23248. case \T_CLONE:
  23249. case \T_CONTINUE:
  23250. case \T_DEFAULT:
  23251. case \T_ECHO:
  23252. case \T_ELSE:
  23253. case \T_ELSEIF:
  23254. case \T_EMPTY:
  23255. case \T_ENDDECLARE:
  23256. case \T_ENDFOR:
  23257. case \T_ENDFOREACH:
  23258. case \T_ENDIF:
  23259. case \T_ENDSWITCH:
  23260. case \T_ENDWHILE:
  23261. case \T_EXIT:
  23262. case \T_EXTENDS:
  23263. case \T_FINAL:
  23264. case \T_FINALLY:
  23265. case \T_FOREACH:
  23266. case \T_FUNCTION:
  23267. case \T_GLOBAL:
  23268. case \T_IF:
  23269. case \T_IMPLEMENTS:
  23270. case \T_INCLUDE:
  23271. case \T_INCLUDE_ONCE:
  23272. case \T_INSTANCEOF:
  23273. case \T_INSTEADOF:
  23274. case \T_INTERFACE:
  23275. case \T_ISSET:
  23276. case \T_LOGICAL_AND:
  23277. case \T_LOGICAL_OR:
  23278. case \T_LOGICAL_XOR:
  23279. case \T_NAMESPACE:
  23280. case \T_NEW:
  23281. case \T_PRIVATE:
  23282. case \T_PROTECTED:
  23283. case \T_PUBLIC:
  23284. case \T_REQUIRE:
  23285. case \T_REQUIRE_ONCE:
  23286. case \T_RETURN:
  23287. case \T_STATIC:
  23288. case \T_THROW:
  23289. case \T_TRAIT:
  23290. case \T_TRY:
  23291. case \T_UNSET:
  23292. case \T_USE:
  23293. case \T_VAR:
  23294. case \T_WHILE:
  23295. case \T_YIELD:
  23296. $colour = 'keyword';
  23297. break;
  23298. default:
  23299. $colour = 'default';
  23300. }
  23301. }
  23302. $result[$i] .= \sprintf('<span class="%s">%s</span>', $colour, $line);
  23303. }
  23304. if (isset($lines[$jj + 1])) {
  23305. $result[++$i] = '';
  23306. }
  23307. }
  23308. }
  23309. }
  23310. if ($fileEndsWithNewLine) {
  23311. unset($result[\count($result) - 1]);
  23312. }
  23313. return $result;
  23314. }
  23315. private function abbreviateClassName(string $className) : string
  23316. {
  23317. $tmp = \explode('\\', $className);
  23318. if (\count($tmp) > 1) {
  23319. $className = \sprintf('<abbr title="%s">%s</abbr>', $className, \array_pop($tmp));
  23320. }
  23321. return $className;
  23322. }
  23323. }
  23324. <?php
  23325. declare (strict_types=1);
  23326. /*
  23327. * This file is part of phpunit/php-code-coverage.
  23328. *
  23329. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  23330. *
  23331. * For the full copyright and license information, please view the LICENSE
  23332. * file that was distributed with this source code.
  23333. */
  23334. namespace PHPUnit\SebastianBergmann\CodeCoverage\Report\Html;
  23335. use PHPUnit\SebastianBergmann\CodeCoverage\Node\AbstractNode;
  23336. use PHPUnit\SebastianBergmann\CodeCoverage\Node\Directory as DirectoryNode;
  23337. use PHPUnit\SebastianBergmann\Template\Template;
  23338. /**
  23339. * Renders the dashboard for a directory node.
  23340. */
  23341. final class Dashboard extends \PHPUnit\SebastianBergmann\CodeCoverage\Report\Html\Renderer
  23342. {
  23343. /**
  23344. * @throws \InvalidArgumentException
  23345. * @throws \RuntimeException
  23346. */
  23347. public function render(\PHPUnit\SebastianBergmann\CodeCoverage\Node\Directory $node, string $file) : void
  23348. {
  23349. $classes = $node->getClassesAndTraits();
  23350. $template = new \PHPUnit\SebastianBergmann\Template\Template($this->templatePath . 'dashboard.html', '{{', '}}');
  23351. $this->setCommonTemplateVariables($template, $node);
  23352. $baseLink = $node->getId() . '/';
  23353. $complexity = $this->complexity($classes, $baseLink);
  23354. $coverageDistribution = $this->coverageDistribution($classes);
  23355. $insufficientCoverage = $this->insufficientCoverage($classes, $baseLink);
  23356. $projectRisks = $this->projectRisks($classes, $baseLink);
  23357. $template->setVar(['insufficient_coverage_classes' => $insufficientCoverage['class'], 'insufficient_coverage_methods' => $insufficientCoverage['method'], 'project_risks_classes' => $projectRisks['class'], 'project_risks_methods' => $projectRisks['method'], 'complexity_class' => $complexity['class'], 'complexity_method' => $complexity['method'], 'class_coverage_distribution' => $coverageDistribution['class'], 'method_coverage_distribution' => $coverageDistribution['method']]);
  23358. $template->renderTo($file);
  23359. }
  23360. /**
  23361. * Returns the data for the Class/Method Complexity charts.
  23362. */
  23363. protected function complexity(array $classes, string $baseLink) : array
  23364. {
  23365. $result = ['class' => [], 'method' => []];
  23366. foreach ($classes as $className => $class) {
  23367. foreach ($class['methods'] as $methodName => $method) {
  23368. if ($className !== '*') {
  23369. $methodName = $className . '::' . $methodName;
  23370. }
  23371. $result['method'][] = [$method['coverage'], $method['ccn'], \sprintf('<a href="%s">%s</a>', \str_replace($baseLink, '', $method['link']), $methodName)];
  23372. }
  23373. $result['class'][] = [$class['coverage'], $class['ccn'], \sprintf('<a href="%s">%s</a>', \str_replace($baseLink, '', $class['link']), $className)];
  23374. }
  23375. return ['class' => \json_encode($result['class']), 'method' => \json_encode($result['method'])];
  23376. }
  23377. /**
  23378. * Returns the data for the Class / Method Coverage Distribution chart.
  23379. */
  23380. protected function coverageDistribution(array $classes) : array
  23381. {
  23382. $result = ['class' => ['0%' => 0, '0-10%' => 0, '10-20%' => 0, '20-30%' => 0, '30-40%' => 0, '40-50%' => 0, '50-60%' => 0, '60-70%' => 0, '70-80%' => 0, '80-90%' => 0, '90-100%' => 0, '100%' => 0], 'method' => ['0%' => 0, '0-10%' => 0, '10-20%' => 0, '20-30%' => 0, '30-40%' => 0, '40-50%' => 0, '50-60%' => 0, '60-70%' => 0, '70-80%' => 0, '80-90%' => 0, '90-100%' => 0, '100%' => 0]];
  23383. foreach ($classes as $class) {
  23384. foreach ($class['methods'] as $methodName => $method) {
  23385. if ($method['coverage'] === 0) {
  23386. $result['method']['0%']++;
  23387. } elseif ($method['coverage'] === 100) {
  23388. $result['method']['100%']++;
  23389. } else {
  23390. $key = \floor($method['coverage'] / 10) * 10;
  23391. $key = $key . '-' . ($key + 10) . '%';
  23392. $result['method'][$key]++;
  23393. }
  23394. }
  23395. if ($class['coverage'] === 0) {
  23396. $result['class']['0%']++;
  23397. } elseif ($class['coverage'] === 100) {
  23398. $result['class']['100%']++;
  23399. } else {
  23400. $key = \floor($class['coverage'] / 10) * 10;
  23401. $key = $key . '-' . ($key + 10) . '%';
  23402. $result['class'][$key]++;
  23403. }
  23404. }
  23405. return ['class' => \json_encode(\array_values($result['class'])), 'method' => \json_encode(\array_values($result['method']))];
  23406. }
  23407. /**
  23408. * Returns the classes / methods with insufficient coverage.
  23409. */
  23410. protected function insufficientCoverage(array $classes, string $baseLink) : array
  23411. {
  23412. $leastTestedClasses = [];
  23413. $leastTestedMethods = [];
  23414. $result = ['class' => '', 'method' => ''];
  23415. foreach ($classes as $className => $class) {
  23416. foreach ($class['methods'] as $methodName => $method) {
  23417. if ($method['coverage'] < $this->highLowerBound) {
  23418. $key = $methodName;
  23419. if ($className !== '*') {
  23420. $key = $className . '::' . $methodName;
  23421. }
  23422. $leastTestedMethods[$key] = $method['coverage'];
  23423. }
  23424. }
  23425. if ($class['coverage'] < $this->highLowerBound) {
  23426. $leastTestedClasses[$className] = $class['coverage'];
  23427. }
  23428. }
  23429. \asort($leastTestedClasses);
  23430. \asort($leastTestedMethods);
  23431. foreach ($leastTestedClasses as $className => $coverage) {
  23432. $result['class'] .= \sprintf(' <tr><td><a href="%s">%s</a></td><td class="text-right">%d%%</td></tr>' . "\n", \str_replace($baseLink, '', $classes[$className]['link']), $className, $coverage);
  23433. }
  23434. foreach ($leastTestedMethods as $methodName => $coverage) {
  23435. [$class, $method] = \explode('::', $methodName);
  23436. $result['method'] .= \sprintf(' <tr><td><a href="%s"><abbr title="%s">%s</abbr></a></td><td class="text-right">%d%%</td></tr>' . "\n", \str_replace($baseLink, '', $classes[$class]['methods'][$method]['link']), $methodName, $method, $coverage);
  23437. }
  23438. return $result;
  23439. }
  23440. /**
  23441. * Returns the project risks according to the CRAP index.
  23442. */
  23443. protected function projectRisks(array $classes, string $baseLink) : array
  23444. {
  23445. $classRisks = [];
  23446. $methodRisks = [];
  23447. $result = ['class' => '', 'method' => ''];
  23448. foreach ($classes as $className => $class) {
  23449. foreach ($class['methods'] as $methodName => $method) {
  23450. if ($method['coverage'] < $this->highLowerBound && $method['ccn'] > 1) {
  23451. $key = $methodName;
  23452. if ($className !== '*') {
  23453. $key = $className . '::' . $methodName;
  23454. }
  23455. $methodRisks[$key] = $method['crap'];
  23456. }
  23457. }
  23458. if ($class['coverage'] < $this->highLowerBound && $class['ccn'] > \count($class['methods'])) {
  23459. $classRisks[$className] = $class['crap'];
  23460. }
  23461. }
  23462. \arsort($classRisks);
  23463. \arsort($methodRisks);
  23464. foreach ($classRisks as $className => $crap) {
  23465. $result['class'] .= \sprintf(' <tr><td><a href="%s">%s</a></td><td class="text-right">%d</td></tr>' . "\n", \str_replace($baseLink, '', $classes[$className]['link']), $className, $crap);
  23466. }
  23467. foreach ($methodRisks as $methodName => $crap) {
  23468. [$class, $method] = \explode('::', $methodName);
  23469. $result['method'] .= \sprintf(' <tr><td><a href="%s"><abbr title="%s">%s</abbr></a></td><td class="text-right">%d</td></tr>' . "\n", \str_replace($baseLink, '', $classes[$class]['methods'][$method]['link']), $methodName, $method, $crap);
  23470. }
  23471. return $result;
  23472. }
  23473. protected function getActiveBreadcrumb(\PHPUnit\SebastianBergmann\CodeCoverage\Node\AbstractNode $node) : string
  23474. {
  23475. return \sprintf(' <li class="breadcrumb-item"><a href="index.html">%s</a></li>' . "\n" . ' <li class="breadcrumb-item active">(Dashboard)</li>' . "\n", $node->getName());
  23476. }
  23477. }
  23478. <?php
  23479. declare (strict_types=1);
  23480. /*
  23481. * This file is part of phpunit/php-code-coverage.
  23482. *
  23483. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  23484. *
  23485. * For the full copyright and license information, please view the LICENSE
  23486. * file that was distributed with this source code.
  23487. */
  23488. namespace PHPUnit\SebastianBergmann\CodeCoverage\Report\Html;
  23489. use PHPUnit\SebastianBergmann\CodeCoverage\Node\AbstractNode as Node;
  23490. use PHPUnit\SebastianBergmann\CodeCoverage\Node\Directory as DirectoryNode;
  23491. use PHPUnit\SebastianBergmann\Template\Template;
  23492. /**
  23493. * Renders a directory node.
  23494. */
  23495. final class Directory extends \PHPUnit\SebastianBergmann\CodeCoverage\Report\Html\Renderer
  23496. {
  23497. /**
  23498. * @throws \InvalidArgumentException
  23499. * @throws \RuntimeException
  23500. */
  23501. public function render(\PHPUnit\SebastianBergmann\CodeCoverage\Node\Directory $node, string $file) : void
  23502. {
  23503. $template = new \PHPUnit\SebastianBergmann\Template\Template($this->templatePath . 'directory.html', '{{', '}}');
  23504. $this->setCommonTemplateVariables($template, $node);
  23505. $items = $this->renderItem($node, \true);
  23506. foreach ($node->getDirectories() as $item) {
  23507. $items .= $this->renderItem($item);
  23508. }
  23509. foreach ($node->getFiles() as $item) {
  23510. $items .= $this->renderItem($item);
  23511. }
  23512. $template->setVar(['id' => $node->getId(), 'items' => $items]);
  23513. $template->renderTo($file);
  23514. }
  23515. protected function renderItem(\PHPUnit\SebastianBergmann\CodeCoverage\Node\AbstractNode $node, bool $total = \false) : string
  23516. {
  23517. $data = ['numClasses' => $node->getNumClassesAndTraits(), 'numTestedClasses' => $node->getNumTestedClassesAndTraits(), 'numMethods' => $node->getNumFunctionsAndMethods(), 'numTestedMethods' => $node->getNumTestedFunctionsAndMethods(), 'linesExecutedPercent' => $node->getLineExecutedPercent(\false), 'linesExecutedPercentAsString' => $node->getLineExecutedPercent(), 'numExecutedLines' => $node->getNumExecutedLines(), 'numExecutableLines' => $node->getNumExecutableLines(), 'testedMethodsPercent' => $node->getTestedFunctionsAndMethodsPercent(\false), 'testedMethodsPercentAsString' => $node->getTestedFunctionsAndMethodsPercent(), 'testedClassesPercent' => $node->getTestedClassesAndTraitsPercent(\false), 'testedClassesPercentAsString' => $node->getTestedClassesAndTraitsPercent()];
  23518. if ($total) {
  23519. $data['name'] = 'Total';
  23520. } else {
  23521. if ($node instanceof \PHPUnit\SebastianBergmann\CodeCoverage\Node\Directory) {
  23522. $data['name'] = \sprintf('<a href="%s/index.html">%s</a>', $node->getName(), $node->getName());
  23523. $up = \str_repeat('../', \count($node->getPathAsArray()) - 2);
  23524. $data['icon'] = \sprintf('<img src="%s_icons/file-directory.svg" class="octicon" />', $up);
  23525. } else {
  23526. $data['name'] = \sprintf('<a href="%s.html">%s</a>', $node->getName(), $node->getName());
  23527. $up = \str_repeat('../', \count($node->getPathAsArray()) - 2);
  23528. $data['icon'] = \sprintf('<img src="%s_icons/file-code.svg" class="octicon" />', $up);
  23529. }
  23530. }
  23531. return $this->renderItemTemplate(new \PHPUnit\SebastianBergmann\Template\Template($this->templatePath . 'directory_item.html', '{{', '}}'), $data);
  23532. }
  23533. }
  23534. <?php
  23535. declare (strict_types=1);
  23536. /*
  23537. * This file is part of phpunit/php-code-coverage.
  23538. *
  23539. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  23540. *
  23541. * For the full copyright and license information, please view the LICENSE
  23542. * file that was distributed with this source code.
  23543. */
  23544. namespace PHPUnit\SebastianBergmann\CodeCoverage\Report;
  23545. use PHPUnit\SebastianBergmann\CodeCoverage\CodeCoverage;
  23546. use PHPUnit\SebastianBergmann\CodeCoverage\Directory;
  23547. use PHPUnit\SebastianBergmann\CodeCoverage\RuntimeException;
  23548. /**
  23549. * Uses var_export() to write a SebastianBergmann\CodeCoverage\CodeCoverage object to a file.
  23550. */
  23551. final class PHP
  23552. {
  23553. /**
  23554. * @throws \SebastianBergmann\CodeCoverage\RuntimeException
  23555. */
  23556. public function process(\PHPUnit\SebastianBergmann\CodeCoverage\CodeCoverage $coverage, ?string $target = null) : string
  23557. {
  23558. $filter = $coverage->filter();
  23559. $buffer = \sprintf('<?php
  23560. $coverage = new SebastianBergmann\\CodeCoverage\\CodeCoverage;
  23561. $coverage->setData(%s);
  23562. $coverage->setTests(%s);
  23563. $filter = $coverage->filter();
  23564. $filter->setWhitelistedFiles(%s);
  23565. return $coverage;', \var_export($coverage->getData(\true), \true), \var_export($coverage->getTests(), \true), \var_export($filter->getWhitelistedFiles(), \true));
  23566. if ($target !== null) {
  23567. \PHPUnit\SebastianBergmann\CodeCoverage\Directory::create(\dirname($target));
  23568. if (@\file_put_contents($target, $buffer) === \false) {
  23569. throw new \PHPUnit\SebastianBergmann\CodeCoverage\RuntimeException(\sprintf('Could not write to "%s', $target));
  23570. }
  23571. }
  23572. return $buffer;
  23573. }
  23574. }
  23575. <?php
  23576. declare (strict_types=1);
  23577. /*
  23578. * This file is part of phpunit/php-code-coverage.
  23579. *
  23580. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  23581. *
  23582. * For the full copyright and license information, please view the LICENSE
  23583. * file that was distributed with this source code.
  23584. */
  23585. namespace PHPUnit\SebastianBergmann\CodeCoverage\Report\Xml;
  23586. use PHPUnit\SebastianBergmann\Environment\Runtime;
  23587. final class BuildInformation
  23588. {
  23589. /**
  23590. * @var \DOMElement
  23591. */
  23592. private $contextNode;
  23593. public function __construct(\DOMElement $contextNode)
  23594. {
  23595. $this->contextNode = $contextNode;
  23596. }
  23597. public function setRuntimeInformation(\PHPUnit\SebastianBergmann\Environment\Runtime $runtime) : void
  23598. {
  23599. $runtimeNode = $this->getNodeByName('runtime');
  23600. $runtimeNode->setAttribute('name', $runtime->getName());
  23601. $runtimeNode->setAttribute('version', $runtime->getVersion());
  23602. $runtimeNode->setAttribute('url', $runtime->getVendorUrl());
  23603. $driverNode = $this->getNodeByName('driver');
  23604. if ($runtime->hasPHPDBGCodeCoverage()) {
  23605. $driverNode->setAttribute('name', 'phpdbg');
  23606. $driverNode->setAttribute('version', \constant('PHPDBG_VERSION'));
  23607. }
  23608. if ($runtime->hasXdebug()) {
  23609. $driverNode->setAttribute('name', 'xdebug');
  23610. $driverNode->setAttribute('version', \phpversion('xdebug'));
  23611. }
  23612. if ($runtime->hasPCOV()) {
  23613. $driverNode->setAttribute('name', 'pcov');
  23614. $driverNode->setAttribute('version', \phpversion('pcov'));
  23615. }
  23616. }
  23617. public function setBuildTime(\DateTimeImmutable $date) : void
  23618. {
  23619. $this->contextNode->setAttribute('time', $date->format('D M j G:i:s T Y'));
  23620. }
  23621. public function setGeneratorVersions(string $phpUnitVersion, string $coverageVersion) : void
  23622. {
  23623. $this->contextNode->setAttribute('phpunit', $phpUnitVersion);
  23624. $this->contextNode->setAttribute('coverage', $coverageVersion);
  23625. }
  23626. private function getNodeByName(string $name) : \DOMElement
  23627. {
  23628. $node = $this->contextNode->getElementsByTagNameNS('https://schema.phpunit.de/coverage/1.0', $name)->item(0);
  23629. if (!$node) {
  23630. $node = $this->contextNode->appendChild($this->contextNode->ownerDocument->createElementNS('https://schema.phpunit.de/coverage/1.0', $name));
  23631. }
  23632. return $node;
  23633. }
  23634. }
  23635. <?php
  23636. declare (strict_types=1);
  23637. /*
  23638. * This file is part of phpunit/php-code-coverage.
  23639. *
  23640. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  23641. *
  23642. * For the full copyright and license information, please view the LICENSE
  23643. * file that was distributed with this source code.
  23644. */
  23645. namespace PHPUnit\SebastianBergmann\CodeCoverage\Report\Xml;
  23646. use PHPUnit\TheSeer\Tokenizer\NamespaceUri;
  23647. use PHPUnit\TheSeer\Tokenizer\Tokenizer;
  23648. use PHPUnit\TheSeer\Tokenizer\XMLSerializer;
  23649. final class Source
  23650. {
  23651. /** @var \DOMElement */
  23652. private $context;
  23653. public function __construct(\DOMElement $context)
  23654. {
  23655. $this->context = $context;
  23656. }
  23657. public function setSourceCode(string $source) : void
  23658. {
  23659. $context = $this->context;
  23660. $tokens = (new \PHPUnit\TheSeer\Tokenizer\Tokenizer())->parse($source);
  23661. $srcDom = (new \PHPUnit\TheSeer\Tokenizer\XMLSerializer(new \PHPUnit\TheSeer\Tokenizer\NamespaceUri($context->namespaceURI)))->toDom($tokens);
  23662. $context->parentNode->replaceChild($context->ownerDocument->importNode($srcDom->documentElement, \true), $context);
  23663. }
  23664. }
  23665. <?php
  23666. declare (strict_types=1);
  23667. /*
  23668. * This file is part of phpunit/php-code-coverage.
  23669. *
  23670. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  23671. *
  23672. * For the full copyright and license information, please view the LICENSE
  23673. * file that was distributed with this source code.
  23674. */
  23675. namespace PHPUnit\SebastianBergmann\CodeCoverage\Report\Xml;
  23676. use PHPUnit\SebastianBergmann\CodeCoverage\CodeCoverage;
  23677. use PHPUnit\SebastianBergmann\CodeCoverage\Directory as DirectoryUtil;
  23678. use PHPUnit\SebastianBergmann\CodeCoverage\Node\AbstractNode;
  23679. use PHPUnit\SebastianBergmann\CodeCoverage\Node\Directory as DirectoryNode;
  23680. use PHPUnit\SebastianBergmann\CodeCoverage\Node\File as FileNode;
  23681. use PHPUnit\SebastianBergmann\CodeCoverage\RuntimeException;
  23682. use PHPUnit\SebastianBergmann\CodeCoverage\Version;
  23683. use PHPUnit\SebastianBergmann\Environment\Runtime;
  23684. final class Facade
  23685. {
  23686. /**
  23687. * @var string
  23688. */
  23689. private $target;
  23690. /**
  23691. * @var Project
  23692. */
  23693. private $project;
  23694. /**
  23695. * @var string
  23696. */
  23697. private $phpUnitVersion;
  23698. public function __construct(string $version)
  23699. {
  23700. $this->phpUnitVersion = $version;
  23701. }
  23702. /**
  23703. * @throws RuntimeException
  23704. */
  23705. public function process(\PHPUnit\SebastianBergmann\CodeCoverage\CodeCoverage $coverage, string $target) : void
  23706. {
  23707. if (\substr($target, -1, 1) !== \DIRECTORY_SEPARATOR) {
  23708. $target .= \DIRECTORY_SEPARATOR;
  23709. }
  23710. $this->target = $target;
  23711. $this->initTargetDirectory($target);
  23712. $report = $coverage->getReport();
  23713. $this->project = new \PHPUnit\SebastianBergmann\CodeCoverage\Report\Xml\Project($coverage->getReport()->getName());
  23714. $this->setBuildInformation();
  23715. $this->processTests($coverage->getTests());
  23716. $this->processDirectory($report, $this->project);
  23717. $this->saveDocument($this->project->asDom(), 'index');
  23718. }
  23719. private function setBuildInformation() : void
  23720. {
  23721. $buildNode = $this->project->getBuildInformation();
  23722. $buildNode->setRuntimeInformation(new \PHPUnit\SebastianBergmann\Environment\Runtime());
  23723. $buildNode->setBuildTime(new \DateTimeImmutable());
  23724. $buildNode->setGeneratorVersions($this->phpUnitVersion, \PHPUnit\SebastianBergmann\CodeCoverage\Version::id());
  23725. }
  23726. /**
  23727. * @throws RuntimeException
  23728. */
  23729. private function initTargetDirectory(string $directory) : void
  23730. {
  23731. if (\file_exists($directory)) {
  23732. if (!\is_dir($directory)) {
  23733. throw new \PHPUnit\SebastianBergmann\CodeCoverage\RuntimeException("'{$directory}' exists but is not a directory.");
  23734. }
  23735. if (!\is_writable($directory)) {
  23736. throw new \PHPUnit\SebastianBergmann\CodeCoverage\RuntimeException("'{$directory}' exists but is not writable.");
  23737. }
  23738. }
  23739. \PHPUnit\SebastianBergmann\CodeCoverage\Directory::create($directory);
  23740. }
  23741. private function processDirectory(\PHPUnit\SebastianBergmann\CodeCoverage\Node\Directory $directory, \PHPUnit\SebastianBergmann\CodeCoverage\Report\Xml\Node $context) : void
  23742. {
  23743. $directoryName = $directory->getName();
  23744. if ($this->project->getProjectSourceDirectory() === $directoryName) {
  23745. $directoryName = '/';
  23746. }
  23747. $directoryObject = $context->addDirectory($directoryName);
  23748. $this->setTotals($directory, $directoryObject->getTotals());
  23749. foreach ($directory->getDirectories() as $node) {
  23750. $this->processDirectory($node, $directoryObject);
  23751. }
  23752. foreach ($directory->getFiles() as $node) {
  23753. $this->processFile($node, $directoryObject);
  23754. }
  23755. }
  23756. /**
  23757. * @throws RuntimeException
  23758. */
  23759. private function processFile(\PHPUnit\SebastianBergmann\CodeCoverage\Node\File $file, \PHPUnit\SebastianBergmann\CodeCoverage\Report\Xml\Directory $context) : void
  23760. {
  23761. $fileObject = $context->addFile($file->getName(), $file->getId() . '.xml');
  23762. $this->setTotals($file, $fileObject->getTotals());
  23763. $path = \substr($file->getPath(), \strlen($this->project->getProjectSourceDirectory()));
  23764. $fileReport = new \PHPUnit\SebastianBergmann\CodeCoverage\Report\Xml\Report($path);
  23765. $this->setTotals($file, $fileReport->getTotals());
  23766. foreach ($file->getClassesAndTraits() as $unit) {
  23767. $this->processUnit($unit, $fileReport);
  23768. }
  23769. foreach ($file->getFunctions() as $function) {
  23770. $this->processFunction($function, $fileReport);
  23771. }
  23772. foreach ($file->getCoverageData() as $line => $tests) {
  23773. if (!\is_array($tests) || \count($tests) === 0) {
  23774. continue;
  23775. }
  23776. $coverage = $fileReport->getLineCoverage((string) $line);
  23777. foreach ($tests as $test) {
  23778. $coverage->addTest($test);
  23779. }
  23780. $coverage->finalize();
  23781. }
  23782. $fileReport->getSource()->setSourceCode(\file_get_contents($file->getPath()));
  23783. $this->saveDocument($fileReport->asDom(), $file->getId());
  23784. }
  23785. private function processUnit(array $unit, \PHPUnit\SebastianBergmann\CodeCoverage\Report\Xml\Report $report) : void
  23786. {
  23787. if (isset($unit['className'])) {
  23788. $unitObject = $report->getClassObject($unit['className']);
  23789. } else {
  23790. $unitObject = $report->getTraitObject($unit['traitName']);
  23791. }
  23792. $unitObject->setLines($unit['startLine'], $unit['executableLines'], $unit['executedLines']);
  23793. $unitObject->setCrap((float) $unit['crap']);
  23794. $unitObject->setPackage($unit['package']['fullPackage'], $unit['package']['package'], $unit['package']['subpackage'], $unit['package']['category']);
  23795. $unitObject->setNamespace($unit['package']['namespace']);
  23796. foreach ($unit['methods'] as $method) {
  23797. $methodObject = $unitObject->addMethod($method['methodName']);
  23798. $methodObject->setSignature($method['signature']);
  23799. $methodObject->setLines((string) $method['startLine'], (string) $method['endLine']);
  23800. $methodObject->setCrap($method['crap']);
  23801. $methodObject->setTotals((string) $method['executableLines'], (string) $method['executedLines'], (string) $method['coverage']);
  23802. }
  23803. }
  23804. private function processFunction(array $function, \PHPUnit\SebastianBergmann\CodeCoverage\Report\Xml\Report $report) : void
  23805. {
  23806. $functionObject = $report->getFunctionObject($function['functionName']);
  23807. $functionObject->setSignature($function['signature']);
  23808. $functionObject->setLines((string) $function['startLine']);
  23809. $functionObject->setCrap($function['crap']);
  23810. $functionObject->setTotals((string) $function['executableLines'], (string) $function['executedLines'], (string) $function['coverage']);
  23811. }
  23812. private function processTests(array $tests) : void
  23813. {
  23814. $testsObject = $this->project->getTests();
  23815. foreach ($tests as $test => $result) {
  23816. if ($test === 'UNCOVERED_FILES_FROM_WHITELIST') {
  23817. continue;
  23818. }
  23819. $testsObject->addTest($test, $result);
  23820. }
  23821. }
  23822. private function setTotals(\PHPUnit\SebastianBergmann\CodeCoverage\Node\AbstractNode $node, \PHPUnit\SebastianBergmann\CodeCoverage\Report\Xml\Totals $totals) : void
  23823. {
  23824. $loc = $node->getLinesOfCode();
  23825. $totals->setNumLines($loc['loc'], $loc['cloc'], $loc['ncloc'], $node->getNumExecutableLines(), $node->getNumExecutedLines());
  23826. $totals->setNumClasses($node->getNumClasses(), $node->getNumTestedClasses());
  23827. $totals->setNumTraits($node->getNumTraits(), $node->getNumTestedTraits());
  23828. $totals->setNumMethods($node->getNumMethods(), $node->getNumTestedMethods());
  23829. $totals->setNumFunctions($node->getNumFunctions(), $node->getNumTestedFunctions());
  23830. }
  23831. private function getTargetDirectory() : string
  23832. {
  23833. return $this->target;
  23834. }
  23835. /**
  23836. * @throws RuntimeException
  23837. */
  23838. private function saveDocument(\DOMDocument $document, string $name) : void
  23839. {
  23840. $filename = \sprintf('%s/%s.xml', $this->getTargetDirectory(), $name);
  23841. $document->formatOutput = \true;
  23842. $document->preserveWhiteSpace = \false;
  23843. $this->initTargetDirectory(\dirname($filename));
  23844. /* @see https://bugs.php.net/bug.php?id=79191 */
  23845. \file_put_contents($filename, $document->saveXML());
  23846. }
  23847. }
  23848. <?php
  23849. declare (strict_types=1);
  23850. /*
  23851. * This file is part of phpunit/php-code-coverage.
  23852. *
  23853. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  23854. *
  23855. * For the full copyright and license information, please view the LICENSE
  23856. * file that was distributed with this source code.
  23857. */
  23858. namespace PHPUnit\SebastianBergmann\CodeCoverage\Report\Xml;
  23859. final class Method
  23860. {
  23861. /**
  23862. * @var \DOMElement
  23863. */
  23864. private $contextNode;
  23865. public function __construct(\DOMElement $context, string $name)
  23866. {
  23867. $this->contextNode = $context;
  23868. $this->setName($name);
  23869. }
  23870. public function setSignature(string $signature) : void
  23871. {
  23872. $this->contextNode->setAttribute('signature', $signature);
  23873. }
  23874. public function setLines(string $start, ?string $end = null) : void
  23875. {
  23876. $this->contextNode->setAttribute('start', $start);
  23877. if ($end !== null) {
  23878. $this->contextNode->setAttribute('end', $end);
  23879. }
  23880. }
  23881. public function setTotals(string $executable, string $executed, string $coverage) : void
  23882. {
  23883. $this->contextNode->setAttribute('executable', $executable);
  23884. $this->contextNode->setAttribute('executed', $executed);
  23885. $this->contextNode->setAttribute('coverage', $coverage);
  23886. }
  23887. public function setCrap(string $crap) : void
  23888. {
  23889. $this->contextNode->setAttribute('crap', $crap);
  23890. }
  23891. private function setName(string $name) : void
  23892. {
  23893. $this->contextNode->setAttribute('name', $name);
  23894. }
  23895. }
  23896. <?php
  23897. declare (strict_types=1);
  23898. /*
  23899. * This file is part of phpunit/php-code-coverage.
  23900. *
  23901. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  23902. *
  23903. * For the full copyright and license information, please view the LICENSE
  23904. * file that was distributed with this source code.
  23905. */
  23906. namespace PHPUnit\SebastianBergmann\CodeCoverage\Report\Xml;
  23907. final class Report extends \PHPUnit\SebastianBergmann\CodeCoverage\Report\Xml\File
  23908. {
  23909. public function __construct(string $name)
  23910. {
  23911. $dom = new \DOMDocument();
  23912. $dom->loadXML('<?xml version="1.0" ?><phpunit xmlns="https://schema.phpunit.de/coverage/1.0"><file /></phpunit>');
  23913. $contextNode = $dom->getElementsByTagNameNS('https://schema.phpunit.de/coverage/1.0', 'file')->item(0);
  23914. parent::__construct($contextNode);
  23915. $this->setName($name);
  23916. }
  23917. public function asDom() : \DOMDocument
  23918. {
  23919. return $this->getDomDocument();
  23920. }
  23921. public function getFunctionObject($name) : \PHPUnit\SebastianBergmann\CodeCoverage\Report\Xml\Method
  23922. {
  23923. $node = $this->getContextNode()->appendChild($this->getDomDocument()->createElementNS('https://schema.phpunit.de/coverage/1.0', 'function'));
  23924. return new \PHPUnit\SebastianBergmann\CodeCoverage\Report\Xml\Method($node, $name);
  23925. }
  23926. public function getClassObject($name) : \PHPUnit\SebastianBergmann\CodeCoverage\Report\Xml\Unit
  23927. {
  23928. return $this->getUnitObject('class', $name);
  23929. }
  23930. public function getTraitObject($name) : \PHPUnit\SebastianBergmann\CodeCoverage\Report\Xml\Unit
  23931. {
  23932. return $this->getUnitObject('trait', $name);
  23933. }
  23934. public function getSource() : \PHPUnit\SebastianBergmann\CodeCoverage\Report\Xml\Source
  23935. {
  23936. $source = $this->getContextNode()->getElementsByTagNameNS('https://schema.phpunit.de/coverage/1.0', 'source')->item(0);
  23937. if (!$source) {
  23938. $source = $this->getContextNode()->appendChild($this->getDomDocument()->createElementNS('https://schema.phpunit.de/coverage/1.0', 'source'));
  23939. }
  23940. return new \PHPUnit\SebastianBergmann\CodeCoverage\Report\Xml\Source($source);
  23941. }
  23942. private function setName(string $name) : void
  23943. {
  23944. $this->getContextNode()->setAttribute('name', \basename($name));
  23945. $this->getContextNode()->setAttribute('path', \dirname($name));
  23946. }
  23947. private function getUnitObject(string $tagName, $name) : \PHPUnit\SebastianBergmann\CodeCoverage\Report\Xml\Unit
  23948. {
  23949. $node = $this->getContextNode()->appendChild($this->getDomDocument()->createElementNS('https://schema.phpunit.de/coverage/1.0', $tagName));
  23950. return new \PHPUnit\SebastianBergmann\CodeCoverage\Report\Xml\Unit($node, $name);
  23951. }
  23952. }
  23953. <?php
  23954. declare (strict_types=1);
  23955. /*
  23956. * This file is part of phpunit/php-code-coverage.
  23957. *
  23958. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  23959. *
  23960. * For the full copyright and license information, please view the LICENSE
  23961. * file that was distributed with this source code.
  23962. */
  23963. namespace PHPUnit\SebastianBergmann\CodeCoverage\Report\Xml;
  23964. class File
  23965. {
  23966. /**
  23967. * @var \DOMDocument
  23968. */
  23969. private $dom;
  23970. /**
  23971. * @var \DOMElement
  23972. */
  23973. private $contextNode;
  23974. public function __construct(\DOMElement $context)
  23975. {
  23976. $this->dom = $context->ownerDocument;
  23977. $this->contextNode = $context;
  23978. }
  23979. public function getTotals() : \PHPUnit\SebastianBergmann\CodeCoverage\Report\Xml\Totals
  23980. {
  23981. $totalsContainer = $this->contextNode->firstChild;
  23982. if (!$totalsContainer) {
  23983. $totalsContainer = $this->contextNode->appendChild($this->dom->createElementNS('https://schema.phpunit.de/coverage/1.0', 'totals'));
  23984. }
  23985. return new \PHPUnit\SebastianBergmann\CodeCoverage\Report\Xml\Totals($totalsContainer);
  23986. }
  23987. public function getLineCoverage(string $line) : \PHPUnit\SebastianBergmann\CodeCoverage\Report\Xml\Coverage
  23988. {
  23989. $coverage = $this->contextNode->getElementsByTagNameNS('https://schema.phpunit.de/coverage/1.0', 'coverage')->item(0);
  23990. if (!$coverage) {
  23991. $coverage = $this->contextNode->appendChild($this->dom->createElementNS('https://schema.phpunit.de/coverage/1.0', 'coverage'));
  23992. }
  23993. $lineNode = $coverage->appendChild($this->dom->createElementNS('https://schema.phpunit.de/coverage/1.0', 'line'));
  23994. return new \PHPUnit\SebastianBergmann\CodeCoverage\Report\Xml\Coverage($lineNode, $line);
  23995. }
  23996. protected function getContextNode() : \DOMElement
  23997. {
  23998. return $this->contextNode;
  23999. }
  24000. protected function getDomDocument() : \DOMDocument
  24001. {
  24002. return $this->dom;
  24003. }
  24004. }
  24005. <?php
  24006. declare (strict_types=1);
  24007. /*
  24008. * This file is part of phpunit/php-code-coverage.
  24009. *
  24010. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  24011. *
  24012. * For the full copyright and license information, please view the LICENSE
  24013. * file that was distributed with this source code.
  24014. */
  24015. namespace PHPUnit\SebastianBergmann\CodeCoverage\Report\Xml;
  24016. use PHPUnit\SebastianBergmann\CodeCoverage\Percentage;
  24017. final class Totals
  24018. {
  24019. /**
  24020. * @var \DOMNode
  24021. */
  24022. private $container;
  24023. /**
  24024. * @var \DOMElement
  24025. */
  24026. private $linesNode;
  24027. /**
  24028. * @var \DOMElement
  24029. */
  24030. private $methodsNode;
  24031. /**
  24032. * @var \DOMElement
  24033. */
  24034. private $functionsNode;
  24035. /**
  24036. * @var \DOMElement
  24037. */
  24038. private $classesNode;
  24039. /**
  24040. * @var \DOMElement
  24041. */
  24042. private $traitsNode;
  24043. public function __construct(\DOMElement $container)
  24044. {
  24045. $this->container = $container;
  24046. $dom = $container->ownerDocument;
  24047. $this->linesNode = $dom->createElementNS('https://schema.phpunit.de/coverage/1.0', 'lines');
  24048. $this->methodsNode = $dom->createElementNS('https://schema.phpunit.de/coverage/1.0', 'methods');
  24049. $this->functionsNode = $dom->createElementNS('https://schema.phpunit.de/coverage/1.0', 'functions');
  24050. $this->classesNode = $dom->createElementNS('https://schema.phpunit.de/coverage/1.0', 'classes');
  24051. $this->traitsNode = $dom->createElementNS('https://schema.phpunit.de/coverage/1.0', 'traits');
  24052. $container->appendChild($this->linesNode);
  24053. $container->appendChild($this->methodsNode);
  24054. $container->appendChild($this->functionsNode);
  24055. $container->appendChild($this->classesNode);
  24056. $container->appendChild($this->traitsNode);
  24057. }
  24058. public function getContainer() : \DOMNode
  24059. {
  24060. return $this->container;
  24061. }
  24062. public function setNumLines(int $loc, int $cloc, int $ncloc, int $executable, int $executed) : void
  24063. {
  24064. $this->linesNode->setAttribute('total', (string) $loc);
  24065. $this->linesNode->setAttribute('comments', (string) $cloc);
  24066. $this->linesNode->setAttribute('code', (string) $ncloc);
  24067. $this->linesNode->setAttribute('executable', (string) $executable);
  24068. $this->linesNode->setAttribute('executed', (string) $executed);
  24069. $this->linesNode->setAttribute('percent', $executable === 0 ? '0' : \sprintf('%01.2F', \PHPUnit\SebastianBergmann\CodeCoverage\Percentage::fromFractionAndTotal($executed, $executable)->asFloat()));
  24070. }
  24071. public function setNumClasses(int $count, int $tested) : void
  24072. {
  24073. $this->classesNode->setAttribute('count', (string) $count);
  24074. $this->classesNode->setAttribute('tested', (string) $tested);
  24075. $this->classesNode->setAttribute('percent', $count === 0 ? '0' : \sprintf('%01.2F', \PHPUnit\SebastianBergmann\CodeCoverage\Percentage::fromFractionAndTotal($tested, $count)->asFloat()));
  24076. }
  24077. public function setNumTraits(int $count, int $tested) : void
  24078. {
  24079. $this->traitsNode->setAttribute('count', (string) $count);
  24080. $this->traitsNode->setAttribute('tested', (string) $tested);
  24081. $this->traitsNode->setAttribute('percent', $count === 0 ? '0' : \sprintf('%01.2F', \PHPUnit\SebastianBergmann\CodeCoverage\Percentage::fromFractionAndTotal($tested, $count)->asFloat()));
  24082. }
  24083. public function setNumMethods(int $count, int $tested) : void
  24084. {
  24085. $this->methodsNode->setAttribute('count', (string) $count);
  24086. $this->methodsNode->setAttribute('tested', (string) $tested);
  24087. $this->methodsNode->setAttribute('percent', $count === 0 ? '0' : \sprintf('%01.2F', \PHPUnit\SebastianBergmann\CodeCoverage\Percentage::fromFractionAndTotal($tested, $count)->asFloat()));
  24088. }
  24089. public function setNumFunctions(int $count, int $tested) : void
  24090. {
  24091. $this->functionsNode->setAttribute('count', (string) $count);
  24092. $this->functionsNode->setAttribute('tested', (string) $tested);
  24093. $this->functionsNode->setAttribute('percent', $count === 0 ? '0' : \sprintf('%01.2F', \PHPUnit\SebastianBergmann\CodeCoverage\Percentage::fromFractionAndTotal($tested, $count)->asFloat()));
  24094. }
  24095. }
  24096. <?php
  24097. declare (strict_types=1);
  24098. /*
  24099. * This file is part of phpunit/php-code-coverage.
  24100. *
  24101. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  24102. *
  24103. * For the full copyright and license information, please view the LICENSE
  24104. * file that was distributed with this source code.
  24105. */
  24106. namespace PHPUnit\SebastianBergmann\CodeCoverage\Report\Xml;
  24107. final class Tests
  24108. {
  24109. private $contextNode;
  24110. private $codeMap = [
  24111. -1 => 'UNKNOWN',
  24112. // PHPUnit_Runner_BaseTestRunner::STATUS_UNKNOWN
  24113. 0 => 'PASSED',
  24114. // PHPUnit_Runner_BaseTestRunner::STATUS_PASSED
  24115. 1 => 'SKIPPED',
  24116. // PHPUnit_Runner_BaseTestRunner::STATUS_SKIPPED
  24117. 2 => 'INCOMPLETE',
  24118. // PHPUnit_Runner_BaseTestRunner::STATUS_INCOMPLETE
  24119. 3 => 'FAILURE',
  24120. // PHPUnit_Runner_BaseTestRunner::STATUS_FAILURE
  24121. 4 => 'ERROR',
  24122. // PHPUnit_Runner_BaseTestRunner::STATUS_ERROR
  24123. 5 => 'RISKY',
  24124. // PHPUnit_Runner_BaseTestRunner::STATUS_RISKY
  24125. 6 => 'WARNING',
  24126. ];
  24127. public function __construct(\DOMElement $context)
  24128. {
  24129. $this->contextNode = $context;
  24130. }
  24131. public function addTest(string $test, array $result) : void
  24132. {
  24133. $node = $this->contextNode->appendChild($this->contextNode->ownerDocument->createElementNS('https://schema.phpunit.de/coverage/1.0', 'test'));
  24134. $node->setAttribute('name', $test);
  24135. $node->setAttribute('size', $result['size']);
  24136. $node->setAttribute('result', (string) $result['status']);
  24137. $node->setAttribute('status', $this->codeMap[(int) $result['status']]);
  24138. }
  24139. }
  24140. <?php
  24141. declare (strict_types=1);
  24142. /*
  24143. * This file is part of phpunit/php-code-coverage.
  24144. *
  24145. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  24146. *
  24147. * For the full copyright and license information, please view the LICENSE
  24148. * file that was distributed with this source code.
  24149. */
  24150. namespace PHPUnit\SebastianBergmann\CodeCoverage\Report\Xml;
  24151. abstract class Node
  24152. {
  24153. /**
  24154. * @var \DOMDocument
  24155. */
  24156. private $dom;
  24157. /**
  24158. * @var \DOMElement
  24159. */
  24160. private $contextNode;
  24161. public function __construct(\DOMElement $context)
  24162. {
  24163. $this->setContextNode($context);
  24164. }
  24165. public function getDom() : \DOMDocument
  24166. {
  24167. return $this->dom;
  24168. }
  24169. public function getTotals() : \PHPUnit\SebastianBergmann\CodeCoverage\Report\Xml\Totals
  24170. {
  24171. $totalsContainer = $this->getContextNode()->firstChild;
  24172. if (!$totalsContainer) {
  24173. $totalsContainer = $this->getContextNode()->appendChild($this->dom->createElementNS('https://schema.phpunit.de/coverage/1.0', 'totals'));
  24174. }
  24175. return new \PHPUnit\SebastianBergmann\CodeCoverage\Report\Xml\Totals($totalsContainer);
  24176. }
  24177. public function addDirectory(string $name) : \PHPUnit\SebastianBergmann\CodeCoverage\Report\Xml\Directory
  24178. {
  24179. $dirNode = $this->getDom()->createElementNS('https://schema.phpunit.de/coverage/1.0', 'directory');
  24180. $dirNode->setAttribute('name', $name);
  24181. $this->getContextNode()->appendChild($dirNode);
  24182. return new \PHPUnit\SebastianBergmann\CodeCoverage\Report\Xml\Directory($dirNode);
  24183. }
  24184. public function addFile(string $name, string $href) : \PHPUnit\SebastianBergmann\CodeCoverage\Report\Xml\File
  24185. {
  24186. $fileNode = $this->getDom()->createElementNS('https://schema.phpunit.de/coverage/1.0', 'file');
  24187. $fileNode->setAttribute('name', $name);
  24188. $fileNode->setAttribute('href', $href);
  24189. $this->getContextNode()->appendChild($fileNode);
  24190. return new \PHPUnit\SebastianBergmann\CodeCoverage\Report\Xml\File($fileNode);
  24191. }
  24192. protected function setContextNode(\DOMElement $context) : void
  24193. {
  24194. $this->dom = $context->ownerDocument;
  24195. $this->contextNode = $context;
  24196. }
  24197. protected function getContextNode() : \DOMElement
  24198. {
  24199. return $this->contextNode;
  24200. }
  24201. }
  24202. <?php
  24203. declare (strict_types=1);
  24204. /*
  24205. * This file is part of phpunit/php-code-coverage.
  24206. *
  24207. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  24208. *
  24209. * For the full copyright and license information, please view the LICENSE
  24210. * file that was distributed with this source code.
  24211. */
  24212. namespace PHPUnit\SebastianBergmann\CodeCoverage\Report\Xml;
  24213. final class Project extends \PHPUnit\SebastianBergmann\CodeCoverage\Report\Xml\Node
  24214. {
  24215. public function __construct(string $directory)
  24216. {
  24217. $this->init();
  24218. $this->setProjectSourceDirectory($directory);
  24219. }
  24220. public function getProjectSourceDirectory() : string
  24221. {
  24222. return $this->getContextNode()->getAttribute('source');
  24223. }
  24224. public function getBuildInformation() : \PHPUnit\SebastianBergmann\CodeCoverage\Report\Xml\BuildInformation
  24225. {
  24226. $buildNode = $this->getDom()->getElementsByTagNameNS('https://schema.phpunit.de/coverage/1.0', 'build')->item(0);
  24227. if (!$buildNode) {
  24228. $buildNode = $this->getDom()->documentElement->appendChild($this->getDom()->createElementNS('https://schema.phpunit.de/coverage/1.0', 'build'));
  24229. }
  24230. return new \PHPUnit\SebastianBergmann\CodeCoverage\Report\Xml\BuildInformation($buildNode);
  24231. }
  24232. public function getTests() : \PHPUnit\SebastianBergmann\CodeCoverage\Report\Xml\Tests
  24233. {
  24234. $testsNode = $this->getContextNode()->getElementsByTagNameNS('https://schema.phpunit.de/coverage/1.0', 'tests')->item(0);
  24235. if (!$testsNode) {
  24236. $testsNode = $this->getContextNode()->appendChild($this->getDom()->createElementNS('https://schema.phpunit.de/coverage/1.0', 'tests'));
  24237. }
  24238. return new \PHPUnit\SebastianBergmann\CodeCoverage\Report\Xml\Tests($testsNode);
  24239. }
  24240. public function asDom() : \DOMDocument
  24241. {
  24242. return $this->getDom();
  24243. }
  24244. private function init() : void
  24245. {
  24246. $dom = new \DOMDocument();
  24247. $dom->loadXML('<?xml version="1.0" ?><phpunit xmlns="https://schema.phpunit.de/coverage/1.0"><build/><project/></phpunit>');
  24248. $this->setContextNode($dom->getElementsByTagNameNS('https://schema.phpunit.de/coverage/1.0', 'project')->item(0));
  24249. }
  24250. private function setProjectSourceDirectory(string $name) : void
  24251. {
  24252. $this->getContextNode()->setAttribute('source', $name);
  24253. }
  24254. }
  24255. <?php
  24256. declare (strict_types=1);
  24257. /*
  24258. * This file is part of phpunit/php-code-coverage.
  24259. *
  24260. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  24261. *
  24262. * For the full copyright and license information, please view the LICENSE
  24263. * file that was distributed with this source code.
  24264. */
  24265. namespace PHPUnit\SebastianBergmann\CodeCoverage\Report\Xml;
  24266. use PHPUnit\SebastianBergmann\CodeCoverage\RuntimeException;
  24267. final class Coverage
  24268. {
  24269. /**
  24270. * @var \XMLWriter
  24271. */
  24272. private $writer;
  24273. /**
  24274. * @var \DOMElement
  24275. */
  24276. private $contextNode;
  24277. /**
  24278. * @var bool
  24279. */
  24280. private $finalized = \false;
  24281. public function __construct(\DOMElement $context, string $line)
  24282. {
  24283. $this->contextNode = $context;
  24284. $this->writer = new \XMLWriter();
  24285. $this->writer->openMemory();
  24286. $this->writer->startElementNS(null, $context->nodeName, 'https://schema.phpunit.de/coverage/1.0');
  24287. $this->writer->writeAttribute('nr', $line);
  24288. }
  24289. /**
  24290. * @throws RuntimeException
  24291. */
  24292. public function addTest(string $test) : void
  24293. {
  24294. if ($this->finalized) {
  24295. throw new \PHPUnit\SebastianBergmann\CodeCoverage\RuntimeException('Coverage Report already finalized');
  24296. }
  24297. $this->writer->startElement('covered');
  24298. $this->writer->writeAttribute('by', $test);
  24299. $this->writer->endElement();
  24300. }
  24301. public function finalize() : void
  24302. {
  24303. $this->writer->endElement();
  24304. $fragment = $this->contextNode->ownerDocument->createDocumentFragment();
  24305. $fragment->appendXML($this->writer->outputMemory());
  24306. $this->contextNode->parentNode->replaceChild($fragment, $this->contextNode);
  24307. $this->finalized = \true;
  24308. }
  24309. }
  24310. <?php
  24311. declare (strict_types=1);
  24312. /*
  24313. * This file is part of phpunit/php-code-coverage.
  24314. *
  24315. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  24316. *
  24317. * For the full copyright and license information, please view the LICENSE
  24318. * file that was distributed with this source code.
  24319. */
  24320. namespace PHPUnit\SebastianBergmann\CodeCoverage\Report\Xml;
  24321. final class Directory extends \PHPUnit\SebastianBergmann\CodeCoverage\Report\Xml\Node
  24322. {
  24323. }
  24324. <?php
  24325. declare (strict_types=1);
  24326. /*
  24327. * This file is part of phpunit/php-code-coverage.
  24328. *
  24329. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  24330. *
  24331. * For the full copyright and license information, please view the LICENSE
  24332. * file that was distributed with this source code.
  24333. */
  24334. namespace PHPUnit\SebastianBergmann\CodeCoverage\Report\Xml;
  24335. final class Unit
  24336. {
  24337. /**
  24338. * @var \DOMElement
  24339. */
  24340. private $contextNode;
  24341. public function __construct(\DOMElement $context, string $name)
  24342. {
  24343. $this->contextNode = $context;
  24344. $this->setName($name);
  24345. }
  24346. public function setLines(int $start, int $executable, int $executed) : void
  24347. {
  24348. $this->contextNode->setAttribute('start', (string) $start);
  24349. $this->contextNode->setAttribute('executable', (string) $executable);
  24350. $this->contextNode->setAttribute('executed', (string) $executed);
  24351. }
  24352. public function setCrap(float $crap) : void
  24353. {
  24354. $this->contextNode->setAttribute('crap', (string) $crap);
  24355. }
  24356. public function setPackage(string $full, string $package, string $sub, string $category) : void
  24357. {
  24358. $node = $this->contextNode->getElementsByTagNameNS('https://schema.phpunit.de/coverage/1.0', 'package')->item(0);
  24359. if (!$node) {
  24360. $node = $this->contextNode->appendChild($this->contextNode->ownerDocument->createElementNS('https://schema.phpunit.de/coverage/1.0', 'package'));
  24361. }
  24362. $node->setAttribute('full', $full);
  24363. $node->setAttribute('name', $package);
  24364. $node->setAttribute('sub', $sub);
  24365. $node->setAttribute('category', $category);
  24366. }
  24367. public function setNamespace(string $namespace) : void
  24368. {
  24369. $node = $this->contextNode->getElementsByTagNameNS('https://schema.phpunit.de/coverage/1.0', 'namespace')->item(0);
  24370. if (!$node) {
  24371. $node = $this->contextNode->appendChild($this->contextNode->ownerDocument->createElementNS('https://schema.phpunit.de/coverage/1.0', 'namespace'));
  24372. }
  24373. $node->setAttribute('name', $namespace);
  24374. }
  24375. public function addMethod(string $name) : \PHPUnit\SebastianBergmann\CodeCoverage\Report\Xml\Method
  24376. {
  24377. $node = $this->contextNode->appendChild($this->contextNode->ownerDocument->createElementNS('https://schema.phpunit.de/coverage/1.0', 'method'));
  24378. return new \PHPUnit\SebastianBergmann\CodeCoverage\Report\Xml\Method($node, $name);
  24379. }
  24380. private function setName(string $name) : void
  24381. {
  24382. $this->contextNode->setAttribute('name', $name);
  24383. }
  24384. }
  24385. <?php
  24386. declare (strict_types=1);
  24387. /*
  24388. * This file is part of phpunit/php-code-coverage.
  24389. *
  24390. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  24391. *
  24392. * For the full copyright and license information, please view the LICENSE
  24393. * file that was distributed with this source code.
  24394. */
  24395. namespace PHPUnit\SebastianBergmann\CodeCoverage\Report;
  24396. use PHPUnit\SebastianBergmann\CodeCoverage\CodeCoverage;
  24397. use PHPUnit\SebastianBergmann\CodeCoverage\Directory;
  24398. use PHPUnit\SebastianBergmann\CodeCoverage\Node\File;
  24399. use PHPUnit\SebastianBergmann\CodeCoverage\RuntimeException;
  24400. /**
  24401. * Generates a Clover XML logfile from a code coverage object.
  24402. */
  24403. final class Clover
  24404. {
  24405. /**
  24406. * @throws \RuntimeException
  24407. */
  24408. public function process(\PHPUnit\SebastianBergmann\CodeCoverage\CodeCoverage $coverage, ?string $target = null, ?string $name = null) : string
  24409. {
  24410. $time = (string) \time();
  24411. $xmlDocument = new \DOMDocument('1.0', 'UTF-8');
  24412. $xmlDocument->formatOutput = \true;
  24413. $xmlCoverage = $xmlDocument->createElement('coverage');
  24414. $xmlCoverage->setAttribute('generated', $time);
  24415. $xmlDocument->appendChild($xmlCoverage);
  24416. $xmlProject = $xmlDocument->createElement('project');
  24417. $xmlProject->setAttribute('timestamp', $time);
  24418. if (\is_string($name)) {
  24419. $xmlProject->setAttribute('name', $name);
  24420. }
  24421. $xmlCoverage->appendChild($xmlProject);
  24422. $packages = [];
  24423. $report = $coverage->getReport();
  24424. foreach ($report as $item) {
  24425. if (!$item instanceof \PHPUnit\SebastianBergmann\CodeCoverage\Node\File) {
  24426. continue;
  24427. }
  24428. /* @var File $item */
  24429. $xmlFile = $xmlDocument->createElement('file');
  24430. $xmlFile->setAttribute('name', $item->getPath());
  24431. $classes = $item->getClassesAndTraits();
  24432. $coverageData = $item->getCoverageData();
  24433. $lines = [];
  24434. $namespace = 'global';
  24435. foreach ($classes as $className => $class) {
  24436. $classStatements = 0;
  24437. $coveredClassStatements = 0;
  24438. $coveredMethods = 0;
  24439. $classMethods = 0;
  24440. foreach ($class['methods'] as $methodName => $method) {
  24441. if ($method['executableLines'] == 0) {
  24442. continue;
  24443. }
  24444. $classMethods++;
  24445. $classStatements += $method['executableLines'];
  24446. $coveredClassStatements += $method['executedLines'];
  24447. if ($method['coverage'] == 100) {
  24448. $coveredMethods++;
  24449. }
  24450. $methodCount = 0;
  24451. foreach (\range($method['startLine'], $method['endLine']) as $line) {
  24452. if (isset($coverageData[$line]) && $coverageData[$line] !== null) {
  24453. $methodCount = \max($methodCount, \count($coverageData[$line]));
  24454. }
  24455. }
  24456. $lines[$method['startLine']] = ['ccn' => $method['ccn'], 'count' => $methodCount, 'crap' => $method['crap'], 'type' => 'method', 'visibility' => $method['visibility'], 'name' => $methodName];
  24457. }
  24458. if (!empty($class['package']['namespace'])) {
  24459. $namespace = $class['package']['namespace'];
  24460. }
  24461. $xmlClass = $xmlDocument->createElement('class');
  24462. $xmlClass->setAttribute('name', $className);
  24463. $xmlClass->setAttribute('namespace', $namespace);
  24464. if (!empty($class['package']['fullPackage'])) {
  24465. $xmlClass->setAttribute('fullPackage', $class['package']['fullPackage']);
  24466. }
  24467. if (!empty($class['package']['category'])) {
  24468. $xmlClass->setAttribute('category', $class['package']['category']);
  24469. }
  24470. if (!empty($class['package']['package'])) {
  24471. $xmlClass->setAttribute('package', $class['package']['package']);
  24472. }
  24473. if (!empty($class['package']['subpackage'])) {
  24474. $xmlClass->setAttribute('subpackage', $class['package']['subpackage']);
  24475. }
  24476. $xmlFile->appendChild($xmlClass);
  24477. $xmlMetrics = $xmlDocument->createElement('metrics');
  24478. $xmlMetrics->setAttribute('complexity', (string) $class['ccn']);
  24479. $xmlMetrics->setAttribute('methods', (string) $classMethods);
  24480. $xmlMetrics->setAttribute('coveredmethods', (string) $coveredMethods);
  24481. $xmlMetrics->setAttribute('conditionals', '0');
  24482. $xmlMetrics->setAttribute('coveredconditionals', '0');
  24483. $xmlMetrics->setAttribute('statements', (string) $classStatements);
  24484. $xmlMetrics->setAttribute('coveredstatements', (string) $coveredClassStatements);
  24485. $xmlMetrics->setAttribute('elements', (string) ($classMethods + $classStatements));
  24486. $xmlMetrics->setAttribute('coveredelements', (string) ($coveredMethods + $coveredClassStatements));
  24487. $xmlClass->appendChild($xmlMetrics);
  24488. }
  24489. foreach ($coverageData as $line => $data) {
  24490. if ($data === null || isset($lines[$line])) {
  24491. continue;
  24492. }
  24493. $lines[$line] = ['count' => \count($data), 'type' => 'stmt'];
  24494. }
  24495. \ksort($lines);
  24496. foreach ($lines as $line => $data) {
  24497. $xmlLine = $xmlDocument->createElement('line');
  24498. $xmlLine->setAttribute('num', (string) $line);
  24499. $xmlLine->setAttribute('type', $data['type']);
  24500. if (isset($data['name'])) {
  24501. $xmlLine->setAttribute('name', $data['name']);
  24502. }
  24503. if (isset($data['visibility'])) {
  24504. $xmlLine->setAttribute('visibility', $data['visibility']);
  24505. }
  24506. if (isset($data['ccn'])) {
  24507. $xmlLine->setAttribute('complexity', (string) $data['ccn']);
  24508. }
  24509. if (isset($data['crap'])) {
  24510. $xmlLine->setAttribute('crap', (string) $data['crap']);
  24511. }
  24512. $xmlLine->setAttribute('count', (string) $data['count']);
  24513. $xmlFile->appendChild($xmlLine);
  24514. }
  24515. $linesOfCode = $item->getLinesOfCode();
  24516. $xmlMetrics = $xmlDocument->createElement('metrics');
  24517. $xmlMetrics->setAttribute('loc', (string) $linesOfCode['loc']);
  24518. $xmlMetrics->setAttribute('ncloc', (string) $linesOfCode['ncloc']);
  24519. $xmlMetrics->setAttribute('classes', (string) $item->getNumClassesAndTraits());
  24520. $xmlMetrics->setAttribute('methods', (string) $item->getNumMethods());
  24521. $xmlMetrics->setAttribute('coveredmethods', (string) $item->getNumTestedMethods());
  24522. $xmlMetrics->setAttribute('conditionals', '0');
  24523. $xmlMetrics->setAttribute('coveredconditionals', '0');
  24524. $xmlMetrics->setAttribute('statements', (string) $item->getNumExecutableLines());
  24525. $xmlMetrics->setAttribute('coveredstatements', (string) $item->getNumExecutedLines());
  24526. $xmlMetrics->setAttribute('elements', (string) ($item->getNumMethods() + $item->getNumExecutableLines()));
  24527. $xmlMetrics->setAttribute('coveredelements', (string) ($item->getNumTestedMethods() + $item->getNumExecutedLines()));
  24528. $xmlFile->appendChild($xmlMetrics);
  24529. if ($namespace === 'global') {
  24530. $xmlProject->appendChild($xmlFile);
  24531. } else {
  24532. if (!isset($packages[$namespace])) {
  24533. $packages[$namespace] = $xmlDocument->createElement('package');
  24534. $packages[$namespace]->setAttribute('name', $namespace);
  24535. $xmlProject->appendChild($packages[$namespace]);
  24536. }
  24537. $packages[$namespace]->appendChild($xmlFile);
  24538. }
  24539. }
  24540. $linesOfCode = $report->getLinesOfCode();
  24541. $xmlMetrics = $xmlDocument->createElement('metrics');
  24542. $xmlMetrics->setAttribute('files', (string) \count($report));
  24543. $xmlMetrics->setAttribute('loc', (string) $linesOfCode['loc']);
  24544. $xmlMetrics->setAttribute('ncloc', (string) $linesOfCode['ncloc']);
  24545. $xmlMetrics->setAttribute('classes', (string) $report->getNumClassesAndTraits());
  24546. $xmlMetrics->setAttribute('methods', (string) $report->getNumMethods());
  24547. $xmlMetrics->setAttribute('coveredmethods', (string) $report->getNumTestedMethods());
  24548. $xmlMetrics->setAttribute('conditionals', '0');
  24549. $xmlMetrics->setAttribute('coveredconditionals', '0');
  24550. $xmlMetrics->setAttribute('statements', (string) $report->getNumExecutableLines());
  24551. $xmlMetrics->setAttribute('coveredstatements', (string) $report->getNumExecutedLines());
  24552. $xmlMetrics->setAttribute('elements', (string) ($report->getNumMethods() + $report->getNumExecutableLines()));
  24553. $xmlMetrics->setAttribute('coveredelements', (string) ($report->getNumTestedMethods() + $report->getNumExecutedLines()));
  24554. $xmlProject->appendChild($xmlMetrics);
  24555. $buffer = $xmlDocument->saveXML();
  24556. if ($target !== null) {
  24557. \PHPUnit\SebastianBergmann\CodeCoverage\Directory::create(\dirname($target));
  24558. if (@\file_put_contents($target, $buffer) === \false) {
  24559. throw new \PHPUnit\SebastianBergmann\CodeCoverage\RuntimeException(\sprintf('Could not write to "%s', $target));
  24560. }
  24561. }
  24562. return $buffer;
  24563. }
  24564. }
  24565. <?php
  24566. declare (strict_types=1);
  24567. /*
  24568. * This file is part of phpunit/php-code-coverage.
  24569. *
  24570. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  24571. *
  24572. * For the full copyright and license information, please view the LICENSE
  24573. * file that was distributed with this source code.
  24574. */
  24575. namespace PHPUnit\SebastianBergmann\CodeCoverage\Node;
  24576. /**
  24577. * Represents a file in the code coverage information tree.
  24578. */
  24579. final class File extends \PHPUnit\SebastianBergmann\CodeCoverage\Node\AbstractNode
  24580. {
  24581. /**
  24582. * @var array
  24583. */
  24584. private $coverageData;
  24585. /**
  24586. * @var array
  24587. */
  24588. private $testData;
  24589. /**
  24590. * @var int
  24591. */
  24592. private $numExecutableLines = 0;
  24593. /**
  24594. * @var int
  24595. */
  24596. private $numExecutedLines = 0;
  24597. /**
  24598. * @var array
  24599. */
  24600. private $classes = [];
  24601. /**
  24602. * @var array
  24603. */
  24604. private $traits = [];
  24605. /**
  24606. * @var array
  24607. */
  24608. private $functions = [];
  24609. /**
  24610. * @var array
  24611. */
  24612. private $linesOfCode = [];
  24613. /**
  24614. * @var int
  24615. */
  24616. private $numClasses;
  24617. /**
  24618. * @var int
  24619. */
  24620. private $numTestedClasses = 0;
  24621. /**
  24622. * @var int
  24623. */
  24624. private $numTraits;
  24625. /**
  24626. * @var int
  24627. */
  24628. private $numTestedTraits = 0;
  24629. /**
  24630. * @var int
  24631. */
  24632. private $numMethods;
  24633. /**
  24634. * @var int
  24635. */
  24636. private $numTestedMethods;
  24637. /**
  24638. * @var int
  24639. */
  24640. private $numTestedFunctions;
  24641. /**
  24642. * @var bool
  24643. */
  24644. private $cacheTokens;
  24645. /**
  24646. * @var array
  24647. */
  24648. private $codeUnitsByLine = [];
  24649. public function __construct(string $name, \PHPUnit\SebastianBergmann\CodeCoverage\Node\AbstractNode $parent, array $coverageData, array $testData, bool $cacheTokens)
  24650. {
  24651. parent::__construct($name, $parent);
  24652. $this->coverageData = $coverageData;
  24653. $this->testData = $testData;
  24654. $this->cacheTokens = $cacheTokens;
  24655. $this->calculateStatistics();
  24656. }
  24657. /**
  24658. * Returns the number of files in/under this node.
  24659. */
  24660. public function count() : int
  24661. {
  24662. return 1;
  24663. }
  24664. /**
  24665. * Returns the code coverage data of this node.
  24666. */
  24667. public function getCoverageData() : array
  24668. {
  24669. return $this->coverageData;
  24670. }
  24671. /**
  24672. * Returns the test data of this node.
  24673. */
  24674. public function getTestData() : array
  24675. {
  24676. return $this->testData;
  24677. }
  24678. /**
  24679. * Returns the classes of this node.
  24680. */
  24681. public function getClasses() : array
  24682. {
  24683. return $this->classes;
  24684. }
  24685. /**
  24686. * Returns the traits of this node.
  24687. */
  24688. public function getTraits() : array
  24689. {
  24690. return $this->traits;
  24691. }
  24692. /**
  24693. * Returns the functions of this node.
  24694. */
  24695. public function getFunctions() : array
  24696. {
  24697. return $this->functions;
  24698. }
  24699. /**
  24700. * Returns the LOC/CLOC/NCLOC of this node.
  24701. */
  24702. public function getLinesOfCode() : array
  24703. {
  24704. return $this->linesOfCode;
  24705. }
  24706. /**
  24707. * Returns the number of executable lines.
  24708. */
  24709. public function getNumExecutableLines() : int
  24710. {
  24711. return $this->numExecutableLines;
  24712. }
  24713. /**
  24714. * Returns the number of executed lines.
  24715. */
  24716. public function getNumExecutedLines() : int
  24717. {
  24718. return $this->numExecutedLines;
  24719. }
  24720. /**
  24721. * Returns the number of classes.
  24722. */
  24723. public function getNumClasses() : int
  24724. {
  24725. if ($this->numClasses === null) {
  24726. $this->numClasses = 0;
  24727. foreach ($this->classes as $class) {
  24728. foreach ($class['methods'] as $method) {
  24729. if ($method['executableLines'] > 0) {
  24730. $this->numClasses++;
  24731. continue 2;
  24732. }
  24733. }
  24734. }
  24735. }
  24736. return $this->numClasses;
  24737. }
  24738. /**
  24739. * Returns the number of tested classes.
  24740. */
  24741. public function getNumTestedClasses() : int
  24742. {
  24743. return $this->numTestedClasses;
  24744. }
  24745. /**
  24746. * Returns the number of traits.
  24747. */
  24748. public function getNumTraits() : int
  24749. {
  24750. if ($this->numTraits === null) {
  24751. $this->numTraits = 0;
  24752. foreach ($this->traits as $trait) {
  24753. foreach ($trait['methods'] as $method) {
  24754. if ($method['executableLines'] > 0) {
  24755. $this->numTraits++;
  24756. continue 2;
  24757. }
  24758. }
  24759. }
  24760. }
  24761. return $this->numTraits;
  24762. }
  24763. /**
  24764. * Returns the number of tested traits.
  24765. */
  24766. public function getNumTestedTraits() : int
  24767. {
  24768. return $this->numTestedTraits;
  24769. }
  24770. /**
  24771. * Returns the number of methods.
  24772. */
  24773. public function getNumMethods() : int
  24774. {
  24775. if ($this->numMethods === null) {
  24776. $this->numMethods = 0;
  24777. foreach ($this->classes as $class) {
  24778. foreach ($class['methods'] as $method) {
  24779. if ($method['executableLines'] > 0) {
  24780. $this->numMethods++;
  24781. }
  24782. }
  24783. }
  24784. foreach ($this->traits as $trait) {
  24785. foreach ($trait['methods'] as $method) {
  24786. if ($method['executableLines'] > 0) {
  24787. $this->numMethods++;
  24788. }
  24789. }
  24790. }
  24791. }
  24792. return $this->numMethods;
  24793. }
  24794. /**
  24795. * Returns the number of tested methods.
  24796. */
  24797. public function getNumTestedMethods() : int
  24798. {
  24799. if ($this->numTestedMethods === null) {
  24800. $this->numTestedMethods = 0;
  24801. foreach ($this->classes as $class) {
  24802. foreach ($class['methods'] as $method) {
  24803. if ($method['executableLines'] > 0 && $method['coverage'] === 100) {
  24804. $this->numTestedMethods++;
  24805. }
  24806. }
  24807. }
  24808. foreach ($this->traits as $trait) {
  24809. foreach ($trait['methods'] as $method) {
  24810. if ($method['executableLines'] > 0 && $method['coverage'] === 100) {
  24811. $this->numTestedMethods++;
  24812. }
  24813. }
  24814. }
  24815. }
  24816. return $this->numTestedMethods;
  24817. }
  24818. /**
  24819. * Returns the number of functions.
  24820. */
  24821. public function getNumFunctions() : int
  24822. {
  24823. return \count($this->functions);
  24824. }
  24825. /**
  24826. * Returns the number of tested functions.
  24827. */
  24828. public function getNumTestedFunctions() : int
  24829. {
  24830. if ($this->numTestedFunctions === null) {
  24831. $this->numTestedFunctions = 0;
  24832. foreach ($this->functions as $function) {
  24833. if ($function['executableLines'] > 0 && $function['coverage'] === 100) {
  24834. $this->numTestedFunctions++;
  24835. }
  24836. }
  24837. }
  24838. return $this->numTestedFunctions;
  24839. }
  24840. private function calculateStatistics() : void
  24841. {
  24842. if ($this->cacheTokens) {
  24843. $tokens = \PHPUnit\PHP_Token_Stream_CachingFactory::get($this->getPath());
  24844. } else {
  24845. $tokens = new \PHPUnit\PHP_Token_Stream($this->getPath());
  24846. }
  24847. $this->linesOfCode = $tokens->getLinesOfCode();
  24848. foreach (\range(1, $this->linesOfCode['loc']) as $lineNumber) {
  24849. $this->codeUnitsByLine[$lineNumber] = [];
  24850. }
  24851. try {
  24852. $this->processClasses($tokens);
  24853. $this->processTraits($tokens);
  24854. $this->processFunctions($tokens);
  24855. } catch (\OutOfBoundsException $e) {
  24856. // This can happen with PHP_Token_Stream if the file is syntactically invalid,
  24857. // and probably affects a file that wasn't executed.
  24858. }
  24859. unset($tokens);
  24860. foreach (\range(1, $this->linesOfCode['loc']) as $lineNumber) {
  24861. if (isset($this->coverageData[$lineNumber])) {
  24862. foreach ($this->codeUnitsByLine[$lineNumber] as &$codeUnit) {
  24863. $codeUnit['executableLines']++;
  24864. }
  24865. unset($codeUnit);
  24866. $this->numExecutableLines++;
  24867. if (\count($this->coverageData[$lineNumber]) > 0) {
  24868. foreach ($this->codeUnitsByLine[$lineNumber] as &$codeUnit) {
  24869. $codeUnit['executedLines']++;
  24870. }
  24871. unset($codeUnit);
  24872. $this->numExecutedLines++;
  24873. }
  24874. }
  24875. }
  24876. foreach ($this->traits as &$trait) {
  24877. foreach ($trait['methods'] as &$method) {
  24878. if ($method['executableLines'] > 0) {
  24879. $method['coverage'] = $method['executedLines'] / $method['executableLines'] * 100;
  24880. } else {
  24881. $method['coverage'] = 100;
  24882. }
  24883. $method['crap'] = $this->crap($method['ccn'], $method['coverage']);
  24884. $trait['ccn'] += $method['ccn'];
  24885. }
  24886. unset($method);
  24887. if ($trait['executableLines'] > 0) {
  24888. $trait['coverage'] = $trait['executedLines'] / $trait['executableLines'] * 100;
  24889. if ($trait['coverage'] === 100) {
  24890. $this->numTestedClasses++;
  24891. }
  24892. } else {
  24893. $trait['coverage'] = 100;
  24894. }
  24895. $trait['crap'] = $this->crap($trait['ccn'], $trait['coverage']);
  24896. }
  24897. unset($trait);
  24898. foreach ($this->classes as &$class) {
  24899. foreach ($class['methods'] as &$method) {
  24900. if ($method['executableLines'] > 0) {
  24901. $method['coverage'] = $method['executedLines'] / $method['executableLines'] * 100;
  24902. } else {
  24903. $method['coverage'] = 100;
  24904. }
  24905. $method['crap'] = $this->crap($method['ccn'], $method['coverage']);
  24906. $class['ccn'] += $method['ccn'];
  24907. }
  24908. unset($method);
  24909. if ($class['executableLines'] > 0) {
  24910. $class['coverage'] = $class['executedLines'] / $class['executableLines'] * 100;
  24911. if ($class['coverage'] === 100) {
  24912. $this->numTestedClasses++;
  24913. }
  24914. } else {
  24915. $class['coverage'] = 100;
  24916. }
  24917. $class['crap'] = $this->crap($class['ccn'], $class['coverage']);
  24918. }
  24919. unset($class);
  24920. foreach ($this->functions as &$function) {
  24921. if ($function['executableLines'] > 0) {
  24922. $function['coverage'] = $function['executedLines'] / $function['executableLines'] * 100;
  24923. } else {
  24924. $function['coverage'] = 100;
  24925. }
  24926. if ($function['coverage'] === 100) {
  24927. $this->numTestedFunctions++;
  24928. }
  24929. $function['crap'] = $this->crap($function['ccn'], $function['coverage']);
  24930. }
  24931. }
  24932. private function processClasses(\PHPUnit\PHP_Token_Stream $tokens) : void
  24933. {
  24934. $classes = $tokens->getClasses();
  24935. $link = $this->getId() . '.html#';
  24936. foreach ($classes as $className => $class) {
  24937. if (\strpos($className, 'anonymous') === 0) {
  24938. continue;
  24939. }
  24940. if (!empty($class['package']['namespace'])) {
  24941. $className = $class['package']['namespace'] . '\\' . $className;
  24942. }
  24943. $this->classes[$className] = ['className' => $className, 'methods' => [], 'startLine' => $class['startLine'], 'executableLines' => 0, 'executedLines' => 0, 'ccn' => 0, 'coverage' => 0, 'crap' => 0, 'package' => $class['package'], 'link' => $link . $class['startLine']];
  24944. foreach ($class['methods'] as $methodName => $method) {
  24945. if (\strpos($methodName, 'anonymous') === 0) {
  24946. continue;
  24947. }
  24948. $this->classes[$className]['methods'][$methodName] = $this->newMethod($methodName, $method, $link);
  24949. foreach (\range($method['startLine'], $method['endLine']) as $lineNumber) {
  24950. $this->codeUnitsByLine[$lineNumber] = [&$this->classes[$className], &$this->classes[$className]['methods'][$methodName]];
  24951. }
  24952. }
  24953. }
  24954. }
  24955. private function processTraits(\PHPUnit\PHP_Token_Stream $tokens) : void
  24956. {
  24957. $traits = $tokens->getTraits();
  24958. $link = $this->getId() . '.html#';
  24959. foreach ($traits as $traitName => $trait) {
  24960. if (!empty($trait['package']['namespace'])) {
  24961. $traitName = $trait['package']['namespace'] . '\\' . $traitName;
  24962. }
  24963. $this->traits[$traitName] = ['traitName' => $traitName, 'methods' => [], 'startLine' => $trait['startLine'], 'executableLines' => 0, 'executedLines' => 0, 'ccn' => 0, 'coverage' => 0, 'crap' => 0, 'package' => $trait['package'], 'link' => $link . $trait['startLine']];
  24964. foreach ($trait['methods'] as $methodName => $method) {
  24965. if (\strpos($methodName, 'anonymous') === 0) {
  24966. continue;
  24967. }
  24968. $this->traits[$traitName]['methods'][$methodName] = $this->newMethod($methodName, $method, $link);
  24969. foreach (\range($method['startLine'], $method['endLine']) as $lineNumber) {
  24970. $this->codeUnitsByLine[$lineNumber] = [&$this->traits[$traitName], &$this->traits[$traitName]['methods'][$methodName]];
  24971. }
  24972. }
  24973. }
  24974. }
  24975. private function processFunctions(\PHPUnit\PHP_Token_Stream $tokens) : void
  24976. {
  24977. $functions = $tokens->getFunctions();
  24978. $link = $this->getId() . '.html#';
  24979. foreach ($functions as $functionName => $function) {
  24980. if (\strpos($functionName, 'anonymous') === 0) {
  24981. continue;
  24982. }
  24983. $this->functions[$functionName] = ['functionName' => $functionName, 'signature' => $function['signature'], 'startLine' => $function['startLine'], 'executableLines' => 0, 'executedLines' => 0, 'ccn' => $function['ccn'], 'coverage' => 0, 'crap' => 0, 'link' => $link . $function['startLine']];
  24984. foreach (\range($function['startLine'], $function['endLine']) as $lineNumber) {
  24985. $this->codeUnitsByLine[$lineNumber] = [&$this->functions[$functionName]];
  24986. }
  24987. }
  24988. }
  24989. private function crap(int $ccn, float $coverage) : string
  24990. {
  24991. if ($coverage === 0.0) {
  24992. return (string) ($ccn ** 2 + $ccn);
  24993. }
  24994. if ($coverage >= 95) {
  24995. return (string) $ccn;
  24996. }
  24997. return \sprintf('%01.2F', $ccn ** 2 * (1 - $coverage / 100) ** 3 + $ccn);
  24998. }
  24999. private function newMethod(string $methodName, array $method, string $link) : array
  25000. {
  25001. return ['methodName' => $methodName, 'visibility' => $method['visibility'], 'signature' => $method['signature'], 'startLine' => $method['startLine'], 'endLine' => $method['endLine'], 'executableLines' => 0, 'executedLines' => 0, 'ccn' => $method['ccn'], 'coverage' => 0, 'crap' => 0, 'link' => $link . $method['startLine']];
  25002. }
  25003. }
  25004. <?php
  25005. declare (strict_types=1);
  25006. /*
  25007. * This file is part of phpunit/php-code-coverage.
  25008. *
  25009. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  25010. *
  25011. * For the full copyright and license information, please view the LICENSE
  25012. * file that was distributed with this source code.
  25013. */
  25014. namespace PHPUnit\SebastianBergmann\CodeCoverage\Node;
  25015. use PHPUnit\SebastianBergmann\CodeCoverage\CodeCoverage;
  25016. final class Builder
  25017. {
  25018. public function build(\PHPUnit\SebastianBergmann\CodeCoverage\CodeCoverage $coverage) : \PHPUnit\SebastianBergmann\CodeCoverage\Node\Directory
  25019. {
  25020. $files = $coverage->getData();
  25021. $commonPath = $this->reducePaths($files);
  25022. $root = new \PHPUnit\SebastianBergmann\CodeCoverage\Node\Directory($commonPath, null);
  25023. $this->addItems($root, $this->buildDirectoryStructure($files), $coverage->getTests(), $coverage->getCacheTokens());
  25024. return $root;
  25025. }
  25026. private function addItems(\PHPUnit\SebastianBergmann\CodeCoverage\Node\Directory $root, array $items, array $tests, bool $cacheTokens) : void
  25027. {
  25028. foreach ($items as $key => $value) {
  25029. $key = (string) $key;
  25030. if (\substr($key, -2) === '/f') {
  25031. $key = \substr($key, 0, -2);
  25032. if (\file_exists($root->getPath() . \DIRECTORY_SEPARATOR . $key)) {
  25033. $root->addFile($key, $value, $tests, $cacheTokens);
  25034. }
  25035. } else {
  25036. $child = $root->addDirectory($key);
  25037. $this->addItems($child, $value, $tests, $cacheTokens);
  25038. }
  25039. }
  25040. }
  25041. /**
  25042. * Builds an array representation of the directory structure.
  25043. *
  25044. * For instance,
  25045. *
  25046. * <code>
  25047. * Array
  25048. * (
  25049. * [Money.php] => Array
  25050. * (
  25051. * ...
  25052. * )
  25053. *
  25054. * [MoneyBag.php] => Array
  25055. * (
  25056. * ...
  25057. * )
  25058. * )
  25059. * </code>
  25060. *
  25061. * is transformed into
  25062. *
  25063. * <code>
  25064. * Array
  25065. * (
  25066. * [.] => Array
  25067. * (
  25068. * [Money.php] => Array
  25069. * (
  25070. * ...
  25071. * )
  25072. *
  25073. * [MoneyBag.php] => Array
  25074. * (
  25075. * ...
  25076. * )
  25077. * )
  25078. * )
  25079. * </code>
  25080. */
  25081. private function buildDirectoryStructure(array $files) : array
  25082. {
  25083. $result = [];
  25084. foreach ($files as $path => $file) {
  25085. $path = \explode(\DIRECTORY_SEPARATOR, $path);
  25086. $pointer =& $result;
  25087. $max = \count($path);
  25088. for ($i = 0; $i < $max; $i++) {
  25089. $type = '';
  25090. if ($i === $max - 1) {
  25091. $type = '/f';
  25092. }
  25093. $pointer =& $pointer[$path[$i] . $type];
  25094. }
  25095. $pointer = $file;
  25096. }
  25097. return $result;
  25098. }
  25099. /**
  25100. * Reduces the paths by cutting the longest common start path.
  25101. *
  25102. * For instance,
  25103. *
  25104. * <code>
  25105. * Array
  25106. * (
  25107. * [/home/sb/Money/Money.php] => Array
  25108. * (
  25109. * ...
  25110. * )
  25111. *
  25112. * [/home/sb/Money/MoneyBag.php] => Array
  25113. * (
  25114. * ...
  25115. * )
  25116. * )
  25117. * </code>
  25118. *
  25119. * is reduced to
  25120. *
  25121. * <code>
  25122. * Array
  25123. * (
  25124. * [Money.php] => Array
  25125. * (
  25126. * ...
  25127. * )
  25128. *
  25129. * [MoneyBag.php] => Array
  25130. * (
  25131. * ...
  25132. * )
  25133. * )
  25134. * </code>
  25135. */
  25136. private function reducePaths(array &$files) : string
  25137. {
  25138. if (empty($files)) {
  25139. return '.';
  25140. }
  25141. $commonPath = '';
  25142. $paths = \array_keys($files);
  25143. if (\count($files) === 1) {
  25144. $commonPath = \dirname($paths[0]) . \DIRECTORY_SEPARATOR;
  25145. $files[\basename($paths[0])] = $files[$paths[0]];
  25146. unset($files[$paths[0]]);
  25147. return $commonPath;
  25148. }
  25149. $max = \count($paths);
  25150. for ($i = 0; $i < $max; $i++) {
  25151. // strip phar:// prefixes
  25152. if (\strpos($paths[$i], 'phar://') === 0) {
  25153. $paths[$i] = \substr($paths[$i], 7);
  25154. $paths[$i] = \str_replace('/', \DIRECTORY_SEPARATOR, $paths[$i]);
  25155. }
  25156. $paths[$i] = \explode(\DIRECTORY_SEPARATOR, $paths[$i]);
  25157. if (empty($paths[$i][0])) {
  25158. $paths[$i][0] = \DIRECTORY_SEPARATOR;
  25159. }
  25160. }
  25161. $done = \false;
  25162. $max = \count($paths);
  25163. while (!$done) {
  25164. for ($i = 0; $i < $max - 1; $i++) {
  25165. if (!isset($paths[$i][0]) || !isset($paths[$i + 1][0]) || $paths[$i][0] !== $paths[$i + 1][0]) {
  25166. $done = \true;
  25167. break;
  25168. }
  25169. }
  25170. if (!$done) {
  25171. $commonPath .= $paths[0][0];
  25172. if ($paths[0][0] !== \DIRECTORY_SEPARATOR) {
  25173. $commonPath .= \DIRECTORY_SEPARATOR;
  25174. }
  25175. for ($i = 0; $i < $max; $i++) {
  25176. \array_shift($paths[$i]);
  25177. }
  25178. }
  25179. }
  25180. $original = \array_keys($files);
  25181. $max = \count($original);
  25182. for ($i = 0; $i < $max; $i++) {
  25183. $files[\implode(\DIRECTORY_SEPARATOR, $paths[$i])] = $files[$original[$i]];
  25184. unset($files[$original[$i]]);
  25185. }
  25186. \ksort($files);
  25187. return \substr($commonPath, 0, -1);
  25188. }
  25189. }
  25190. <?php
  25191. declare (strict_types=1);
  25192. /*
  25193. * This file is part of phpunit/php-code-coverage.
  25194. *
  25195. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  25196. *
  25197. * For the full copyright and license information, please view the LICENSE
  25198. * file that was distributed with this source code.
  25199. */
  25200. namespace PHPUnit\SebastianBergmann\CodeCoverage\Node;
  25201. /**
  25202. * Recursive iterator for node object graphs.
  25203. */
  25204. final class Iterator implements \RecursiveIterator
  25205. {
  25206. /**
  25207. * @var int
  25208. */
  25209. private $position;
  25210. /**
  25211. * @var AbstractNode[]
  25212. */
  25213. private $nodes;
  25214. public function __construct(\PHPUnit\SebastianBergmann\CodeCoverage\Node\Directory $node)
  25215. {
  25216. $this->nodes = $node->getChildNodes();
  25217. }
  25218. /**
  25219. * Rewinds the Iterator to the first element.
  25220. */
  25221. public function rewind() : void
  25222. {
  25223. $this->position = 0;
  25224. }
  25225. /**
  25226. * Checks if there is a current element after calls to rewind() or next().
  25227. */
  25228. public function valid() : bool
  25229. {
  25230. return $this->position < \count($this->nodes);
  25231. }
  25232. /**
  25233. * Returns the key of the current element.
  25234. */
  25235. public function key() : int
  25236. {
  25237. return $this->position;
  25238. }
  25239. /**
  25240. * Returns the current element.
  25241. */
  25242. public function current() : ?\PHPUnit\SebastianBergmann\CodeCoverage\Node\AbstractNode
  25243. {
  25244. return $this->valid() ? $this->nodes[$this->position] : null;
  25245. }
  25246. /**
  25247. * Moves forward to next element.
  25248. */
  25249. public function next() : void
  25250. {
  25251. $this->position++;
  25252. }
  25253. /**
  25254. * Returns the sub iterator for the current element.
  25255. *
  25256. * @return Iterator
  25257. */
  25258. public function getChildren() : self
  25259. {
  25260. return new self($this->nodes[$this->position]);
  25261. }
  25262. /**
  25263. * Checks whether the current element has children.
  25264. */
  25265. public function hasChildren() : bool
  25266. {
  25267. return $this->nodes[$this->position] instanceof \PHPUnit\SebastianBergmann\CodeCoverage\Node\Directory;
  25268. }
  25269. }
  25270. <?php
  25271. declare (strict_types=1);
  25272. /*
  25273. * This file is part of phpunit/php-code-coverage.
  25274. *
  25275. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  25276. *
  25277. * For the full copyright and license information, please view the LICENSE
  25278. * file that was distributed with this source code.
  25279. */
  25280. namespace PHPUnit\SebastianBergmann\CodeCoverage\Node;
  25281. use PHPUnit\SebastianBergmann\CodeCoverage\InvalidArgumentException;
  25282. /**
  25283. * Represents a directory in the code coverage information tree.
  25284. */
  25285. final class Directory extends \PHPUnit\SebastianBergmann\CodeCoverage\Node\AbstractNode implements \IteratorAggregate
  25286. {
  25287. /**
  25288. * @var AbstractNode[]
  25289. */
  25290. private $children = [];
  25291. /**
  25292. * @var Directory[]
  25293. */
  25294. private $directories = [];
  25295. /**
  25296. * @var File[]
  25297. */
  25298. private $files = [];
  25299. /**
  25300. * @var array
  25301. */
  25302. private $classes;
  25303. /**
  25304. * @var array
  25305. */
  25306. private $traits;
  25307. /**
  25308. * @var array
  25309. */
  25310. private $functions;
  25311. /**
  25312. * @var array
  25313. */
  25314. private $linesOfCode;
  25315. /**
  25316. * @var int
  25317. */
  25318. private $numFiles = -1;
  25319. /**
  25320. * @var int
  25321. */
  25322. private $numExecutableLines = -1;
  25323. /**
  25324. * @var int
  25325. */
  25326. private $numExecutedLines = -1;
  25327. /**
  25328. * @var int
  25329. */
  25330. private $numClasses = -1;
  25331. /**
  25332. * @var int
  25333. */
  25334. private $numTestedClasses = -1;
  25335. /**
  25336. * @var int
  25337. */
  25338. private $numTraits = -1;
  25339. /**
  25340. * @var int
  25341. */
  25342. private $numTestedTraits = -1;
  25343. /**
  25344. * @var int
  25345. */
  25346. private $numMethods = -1;
  25347. /**
  25348. * @var int
  25349. */
  25350. private $numTestedMethods = -1;
  25351. /**
  25352. * @var int
  25353. */
  25354. private $numFunctions = -1;
  25355. /**
  25356. * @var int
  25357. */
  25358. private $numTestedFunctions = -1;
  25359. /**
  25360. * Returns the number of files in/under this node.
  25361. */
  25362. public function count() : int
  25363. {
  25364. if ($this->numFiles === -1) {
  25365. $this->numFiles = 0;
  25366. foreach ($this->children as $child) {
  25367. $this->numFiles += \count($child);
  25368. }
  25369. }
  25370. return $this->numFiles;
  25371. }
  25372. /**
  25373. * Returns an iterator for this node.
  25374. */
  25375. public function getIterator() : \RecursiveIteratorIterator
  25376. {
  25377. return new \RecursiveIteratorIterator(new \PHPUnit\SebastianBergmann\CodeCoverage\Node\Iterator($this), \RecursiveIteratorIterator::SELF_FIRST);
  25378. }
  25379. /**
  25380. * Adds a new directory.
  25381. */
  25382. public function addDirectory(string $name) : self
  25383. {
  25384. $directory = new self($name, $this);
  25385. $this->children[] = $directory;
  25386. $this->directories[] =& $this->children[\count($this->children) - 1];
  25387. return $directory;
  25388. }
  25389. /**
  25390. * Adds a new file.
  25391. *
  25392. * @throws InvalidArgumentException
  25393. */
  25394. public function addFile(string $name, array $coverageData, array $testData, bool $cacheTokens) : \PHPUnit\SebastianBergmann\CodeCoverage\Node\File
  25395. {
  25396. $file = new \PHPUnit\SebastianBergmann\CodeCoverage\Node\File($name, $this, $coverageData, $testData, $cacheTokens);
  25397. $this->children[] = $file;
  25398. $this->files[] =& $this->children[\count($this->children) - 1];
  25399. $this->numExecutableLines = -1;
  25400. $this->numExecutedLines = -1;
  25401. return $file;
  25402. }
  25403. /**
  25404. * Returns the directories in this directory.
  25405. */
  25406. public function getDirectories() : array
  25407. {
  25408. return $this->directories;
  25409. }
  25410. /**
  25411. * Returns the files in this directory.
  25412. */
  25413. public function getFiles() : array
  25414. {
  25415. return $this->files;
  25416. }
  25417. /**
  25418. * Returns the child nodes of this node.
  25419. */
  25420. public function getChildNodes() : array
  25421. {
  25422. return $this->children;
  25423. }
  25424. /**
  25425. * Returns the classes of this node.
  25426. */
  25427. public function getClasses() : array
  25428. {
  25429. if ($this->classes === null) {
  25430. $this->classes = [];
  25431. foreach ($this->children as $child) {
  25432. $this->classes = \array_merge($this->classes, $child->getClasses());
  25433. }
  25434. }
  25435. return $this->classes;
  25436. }
  25437. /**
  25438. * Returns the traits of this node.
  25439. */
  25440. public function getTraits() : array
  25441. {
  25442. if ($this->traits === null) {
  25443. $this->traits = [];
  25444. foreach ($this->children as $child) {
  25445. $this->traits = \array_merge($this->traits, $child->getTraits());
  25446. }
  25447. }
  25448. return $this->traits;
  25449. }
  25450. /**
  25451. * Returns the functions of this node.
  25452. */
  25453. public function getFunctions() : array
  25454. {
  25455. if ($this->functions === null) {
  25456. $this->functions = [];
  25457. foreach ($this->children as $child) {
  25458. $this->functions = \array_merge($this->functions, $child->getFunctions());
  25459. }
  25460. }
  25461. return $this->functions;
  25462. }
  25463. /**
  25464. * Returns the LOC/CLOC/NCLOC of this node.
  25465. */
  25466. public function getLinesOfCode() : array
  25467. {
  25468. if ($this->linesOfCode === null) {
  25469. $this->linesOfCode = ['loc' => 0, 'cloc' => 0, 'ncloc' => 0];
  25470. foreach ($this->children as $child) {
  25471. $linesOfCode = $child->getLinesOfCode();
  25472. $this->linesOfCode['loc'] += $linesOfCode['loc'];
  25473. $this->linesOfCode['cloc'] += $linesOfCode['cloc'];
  25474. $this->linesOfCode['ncloc'] += $linesOfCode['ncloc'];
  25475. }
  25476. }
  25477. return $this->linesOfCode;
  25478. }
  25479. /**
  25480. * Returns the number of executable lines.
  25481. */
  25482. public function getNumExecutableLines() : int
  25483. {
  25484. if ($this->numExecutableLines === -1) {
  25485. $this->numExecutableLines = 0;
  25486. foreach ($this->children as $child) {
  25487. $this->numExecutableLines += $child->getNumExecutableLines();
  25488. }
  25489. }
  25490. return $this->numExecutableLines;
  25491. }
  25492. /**
  25493. * Returns the number of executed lines.
  25494. */
  25495. public function getNumExecutedLines() : int
  25496. {
  25497. if ($this->numExecutedLines === -1) {
  25498. $this->numExecutedLines = 0;
  25499. foreach ($this->children as $child) {
  25500. $this->numExecutedLines += $child->getNumExecutedLines();
  25501. }
  25502. }
  25503. return $this->numExecutedLines;
  25504. }
  25505. /**
  25506. * Returns the number of classes.
  25507. */
  25508. public function getNumClasses() : int
  25509. {
  25510. if ($this->numClasses === -1) {
  25511. $this->numClasses = 0;
  25512. foreach ($this->children as $child) {
  25513. $this->numClasses += $child->getNumClasses();
  25514. }
  25515. }
  25516. return $this->numClasses;
  25517. }
  25518. /**
  25519. * Returns the number of tested classes.
  25520. */
  25521. public function getNumTestedClasses() : int
  25522. {
  25523. if ($this->numTestedClasses === -1) {
  25524. $this->numTestedClasses = 0;
  25525. foreach ($this->children as $child) {
  25526. $this->numTestedClasses += $child->getNumTestedClasses();
  25527. }
  25528. }
  25529. return $this->numTestedClasses;
  25530. }
  25531. /**
  25532. * Returns the number of traits.
  25533. */
  25534. public function getNumTraits() : int
  25535. {
  25536. if ($this->numTraits === -1) {
  25537. $this->numTraits = 0;
  25538. foreach ($this->children as $child) {
  25539. $this->numTraits += $child->getNumTraits();
  25540. }
  25541. }
  25542. return $this->numTraits;
  25543. }
  25544. /**
  25545. * Returns the number of tested traits.
  25546. */
  25547. public function getNumTestedTraits() : int
  25548. {
  25549. if ($this->numTestedTraits === -1) {
  25550. $this->numTestedTraits = 0;
  25551. foreach ($this->children as $child) {
  25552. $this->numTestedTraits += $child->getNumTestedTraits();
  25553. }
  25554. }
  25555. return $this->numTestedTraits;
  25556. }
  25557. /**
  25558. * Returns the number of methods.
  25559. */
  25560. public function getNumMethods() : int
  25561. {
  25562. if ($this->numMethods === -1) {
  25563. $this->numMethods = 0;
  25564. foreach ($this->children as $child) {
  25565. $this->numMethods += $child->getNumMethods();
  25566. }
  25567. }
  25568. return $this->numMethods;
  25569. }
  25570. /**
  25571. * Returns the number of tested methods.
  25572. */
  25573. public function getNumTestedMethods() : int
  25574. {
  25575. if ($this->numTestedMethods === -1) {
  25576. $this->numTestedMethods = 0;
  25577. foreach ($this->children as $child) {
  25578. $this->numTestedMethods += $child->getNumTestedMethods();
  25579. }
  25580. }
  25581. return $this->numTestedMethods;
  25582. }
  25583. /**
  25584. * Returns the number of functions.
  25585. */
  25586. public function getNumFunctions() : int
  25587. {
  25588. if ($this->numFunctions === -1) {
  25589. $this->numFunctions = 0;
  25590. foreach ($this->children as $child) {
  25591. $this->numFunctions += $child->getNumFunctions();
  25592. }
  25593. }
  25594. return $this->numFunctions;
  25595. }
  25596. /**
  25597. * Returns the number of tested functions.
  25598. */
  25599. public function getNumTestedFunctions() : int
  25600. {
  25601. if ($this->numTestedFunctions === -1) {
  25602. $this->numTestedFunctions = 0;
  25603. foreach ($this->children as $child) {
  25604. $this->numTestedFunctions += $child->getNumTestedFunctions();
  25605. }
  25606. }
  25607. return $this->numTestedFunctions;
  25608. }
  25609. }
  25610. <?php
  25611. declare (strict_types=1);
  25612. /*
  25613. * This file is part of phpunit/php-code-coverage.
  25614. *
  25615. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  25616. *
  25617. * For the full copyright and license information, please view the LICENSE
  25618. * file that was distributed with this source code.
  25619. */
  25620. namespace PHPUnit\SebastianBergmann\CodeCoverage\Node;
  25621. use PHPUnit\SebastianBergmann\CodeCoverage\Percentage;
  25622. /**
  25623. * Base class for nodes in the code coverage information tree.
  25624. */
  25625. abstract class AbstractNode implements \Countable
  25626. {
  25627. /**
  25628. * @var string
  25629. */
  25630. private $name;
  25631. /**
  25632. * @var string
  25633. */
  25634. private $path;
  25635. /**
  25636. * @var array
  25637. */
  25638. private $pathArray;
  25639. /**
  25640. * @var AbstractNode
  25641. */
  25642. private $parent;
  25643. /**
  25644. * @var string
  25645. */
  25646. private $id;
  25647. public function __construct(string $name, self $parent = null)
  25648. {
  25649. if (\substr($name, -1) == \DIRECTORY_SEPARATOR) {
  25650. $name = \substr($name, 0, -1);
  25651. }
  25652. $this->name = $name;
  25653. $this->parent = $parent;
  25654. }
  25655. public function getName() : string
  25656. {
  25657. return $this->name;
  25658. }
  25659. public function getId() : string
  25660. {
  25661. if ($this->id === null) {
  25662. $parent = $this->getParent();
  25663. if ($parent === null) {
  25664. $this->id = 'index';
  25665. } else {
  25666. $parentId = $parent->getId();
  25667. if ($parentId === 'index') {
  25668. $this->id = \str_replace(':', '_', $this->name);
  25669. } else {
  25670. $this->id = $parentId . '/' . $this->name;
  25671. }
  25672. }
  25673. }
  25674. return $this->id;
  25675. }
  25676. public function getPath() : string
  25677. {
  25678. if ($this->path === null) {
  25679. if ($this->parent === null || $this->parent->getPath() === null || $this->parent->getPath() === \false) {
  25680. $this->path = $this->name;
  25681. } else {
  25682. $this->path = $this->parent->getPath() . \DIRECTORY_SEPARATOR . $this->name;
  25683. }
  25684. }
  25685. return $this->path;
  25686. }
  25687. public function getPathAsArray() : array
  25688. {
  25689. if ($this->pathArray === null) {
  25690. if ($this->parent === null) {
  25691. $this->pathArray = [];
  25692. } else {
  25693. $this->pathArray = $this->parent->getPathAsArray();
  25694. }
  25695. $this->pathArray[] = $this;
  25696. }
  25697. return $this->pathArray;
  25698. }
  25699. public function getParent() : ?self
  25700. {
  25701. return $this->parent;
  25702. }
  25703. /**
  25704. * Returns the percentage of classes that has been tested.
  25705. *
  25706. * @return int|string
  25707. */
  25708. public function getTestedClassesPercent(bool $asString = \true)
  25709. {
  25710. $percentage = \PHPUnit\SebastianBergmann\CodeCoverage\Percentage::fromFractionAndTotal($this->getNumTestedClasses(), $this->getNumClasses());
  25711. if ($asString) {
  25712. return $percentage->asString();
  25713. }
  25714. return $percentage->asFloat();
  25715. }
  25716. /**
  25717. * Returns the percentage of traits that has been tested.
  25718. *
  25719. * @return int|string
  25720. */
  25721. public function getTestedTraitsPercent(bool $asString = \true)
  25722. {
  25723. $percentage = \PHPUnit\SebastianBergmann\CodeCoverage\Percentage::fromFractionAndTotal($this->getNumTestedTraits(), $this->getNumTraits());
  25724. if ($asString) {
  25725. return $percentage->asString();
  25726. }
  25727. return $percentage->asFloat();
  25728. }
  25729. /**
  25730. * Returns the percentage of classes and traits that has been tested.
  25731. *
  25732. * @return int|string
  25733. */
  25734. public function getTestedClassesAndTraitsPercent(bool $asString = \true)
  25735. {
  25736. $percentage = \PHPUnit\SebastianBergmann\CodeCoverage\Percentage::fromFractionAndTotal($this->getNumTestedClassesAndTraits(), $this->getNumClassesAndTraits());
  25737. if ($asString) {
  25738. return $percentage->asString();
  25739. }
  25740. return $percentage->asFloat();
  25741. }
  25742. /**
  25743. * Returns the percentage of functions that has been tested.
  25744. *
  25745. * @return int|string
  25746. */
  25747. public function getTestedFunctionsPercent(bool $asString = \true)
  25748. {
  25749. $percentage = \PHPUnit\SebastianBergmann\CodeCoverage\Percentage::fromFractionAndTotal($this->getNumTestedFunctions(), $this->getNumFunctions());
  25750. if ($asString) {
  25751. return $percentage->asString();
  25752. }
  25753. return $percentage->asFloat();
  25754. }
  25755. /**
  25756. * Returns the percentage of methods that has been tested.
  25757. *
  25758. * @return int|string
  25759. */
  25760. public function getTestedMethodsPercent(bool $asString = \true)
  25761. {
  25762. $percentage = \PHPUnit\SebastianBergmann\CodeCoverage\Percentage::fromFractionAndTotal($this->getNumTestedMethods(), $this->getNumMethods());
  25763. if ($asString) {
  25764. return $percentage->asString();
  25765. }
  25766. return $percentage->asFloat();
  25767. }
  25768. /**
  25769. * Returns the percentage of functions and methods that has been tested.
  25770. *
  25771. * @return int|string
  25772. */
  25773. public function getTestedFunctionsAndMethodsPercent(bool $asString = \true)
  25774. {
  25775. $percentage = \PHPUnit\SebastianBergmann\CodeCoverage\Percentage::fromFractionAndTotal($this->getNumTestedFunctionsAndMethods(), $this->getNumFunctionsAndMethods());
  25776. if ($asString) {
  25777. return $percentage->asString();
  25778. }
  25779. return $percentage->asFloat();
  25780. }
  25781. /**
  25782. * Returns the percentage of executed lines.
  25783. *
  25784. * @return int|string
  25785. */
  25786. public function getLineExecutedPercent(bool $asString = \true)
  25787. {
  25788. $percentage = \PHPUnit\SebastianBergmann\CodeCoverage\Percentage::fromFractionAndTotal($this->getNumExecutedLines(), $this->getNumExecutableLines());
  25789. if ($asString) {
  25790. return $percentage->asString();
  25791. }
  25792. return $percentage->asFloat();
  25793. }
  25794. /**
  25795. * Returns the number of classes and traits.
  25796. */
  25797. public function getNumClassesAndTraits() : int
  25798. {
  25799. return $this->getNumClasses() + $this->getNumTraits();
  25800. }
  25801. /**
  25802. * Returns the number of tested classes and traits.
  25803. */
  25804. public function getNumTestedClassesAndTraits() : int
  25805. {
  25806. return $this->getNumTestedClasses() + $this->getNumTestedTraits();
  25807. }
  25808. /**
  25809. * Returns the classes and traits of this node.
  25810. */
  25811. public function getClassesAndTraits() : array
  25812. {
  25813. return \array_merge($this->getClasses(), $this->getTraits());
  25814. }
  25815. /**
  25816. * Returns the number of functions and methods.
  25817. */
  25818. public function getNumFunctionsAndMethods() : int
  25819. {
  25820. return $this->getNumFunctions() + $this->getNumMethods();
  25821. }
  25822. /**
  25823. * Returns the number of tested functions and methods.
  25824. */
  25825. public function getNumTestedFunctionsAndMethods() : int
  25826. {
  25827. return $this->getNumTestedFunctions() + $this->getNumTestedMethods();
  25828. }
  25829. /**
  25830. * Returns the functions and methods of this node.
  25831. */
  25832. public function getFunctionsAndMethods() : array
  25833. {
  25834. return \array_merge($this->getFunctions(), $this->getMethods());
  25835. }
  25836. /**
  25837. * Returns the classes of this node.
  25838. */
  25839. public abstract function getClasses() : array;
  25840. /**
  25841. * Returns the traits of this node.
  25842. */
  25843. public abstract function getTraits() : array;
  25844. /**
  25845. * Returns the functions of this node.
  25846. */
  25847. public abstract function getFunctions() : array;
  25848. /**
  25849. * Returns the LOC/CLOC/NCLOC of this node.
  25850. */
  25851. public abstract function getLinesOfCode() : array;
  25852. /**
  25853. * Returns the number of executable lines.
  25854. */
  25855. public abstract function getNumExecutableLines() : int;
  25856. /**
  25857. * Returns the number of executed lines.
  25858. */
  25859. public abstract function getNumExecutedLines() : int;
  25860. /**
  25861. * Returns the number of classes.
  25862. */
  25863. public abstract function getNumClasses() : int;
  25864. /**
  25865. * Returns the number of tested classes.
  25866. */
  25867. public abstract function getNumTestedClasses() : int;
  25868. /**
  25869. * Returns the number of traits.
  25870. */
  25871. public abstract function getNumTraits() : int;
  25872. /**
  25873. * Returns the number of tested traits.
  25874. */
  25875. public abstract function getNumTestedTraits() : int;
  25876. /**
  25877. * Returns the number of methods.
  25878. */
  25879. public abstract function getNumMethods() : int;
  25880. /**
  25881. * Returns the number of tested methods.
  25882. */
  25883. public abstract function getNumTestedMethods() : int;
  25884. /**
  25885. * Returns the number of functions.
  25886. */
  25887. public abstract function getNumFunctions() : int;
  25888. /**
  25889. * Returns the number of tested functions.
  25890. */
  25891. public abstract function getNumTestedFunctions() : int;
  25892. }
  25893. php-code-coverage
  25894. Copyright (c) 2009-2020, Sebastian Bergmann <sebastian@phpunit.de>.
  25895. All rights reserved.
  25896. Redistribution and use in source and binary forms, with or without
  25897. modification, are permitted provided that the following conditions
  25898. are met:
  25899. * Redistributions of source code must retain the above copyright
  25900. notice, this list of conditions and the following disclaimer.
  25901. * Redistributions in binary form must reproduce the above copyright
  25902. notice, this list of conditions and the following disclaimer in
  25903. the documentation and/or other materials provided with the
  25904. distribution.
  25905. * Neither the name of Sebastian Bergmann nor the names of his
  25906. contributors may be used to endorse or promote products derived
  25907. from this software without specific prior written permission.
  25908. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  25909. "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  25910. LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  25911. FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  25912. COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  25913. INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  25914. BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  25915. LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  25916. CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  25917. LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
  25918. ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  25919. POSSIBILITY OF SUCH DAMAGE.
  25920. <?php
  25921. declare (strict_types=1);
  25922. /*
  25923. * This file is part of phpunit/php-code-coverage.
  25924. *
  25925. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  25926. *
  25927. * For the full copyright and license information, please view the LICENSE
  25928. * file that was distributed with this source code.
  25929. */
  25930. namespace PHPUnit\SebastianBergmann\CodeCoverage;
  25931. final class Directory
  25932. {
  25933. /**
  25934. * @throws DirectoryCouldNotBeCreatedException
  25935. */
  25936. public static function create(string $directory) : void
  25937. {
  25938. $success = !(!\is_dir($directory) && !@\mkdir($directory, 0777, \true) && !\is_dir($directory));
  25939. if (!$success) {
  25940. throw new \PHPUnit\SebastianBergmann\CodeCoverage\DirectoryCouldNotBeCreatedException(\sprintf('Directory "%s" could not be created', $directory));
  25941. }
  25942. }
  25943. }
  25944. <?php
  25945. declare (strict_types=1);
  25946. /*
  25947. * This file is part of PHPUnit.
  25948. *
  25949. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  25950. *
  25951. * For the full copyright and license information, please view the LICENSE
  25952. * file that was distributed with this source code.
  25953. */
  25954. namespace PHPUnit\Util;
  25955. use PHPUnit\Framework\Exception;
  25956. /**
  25957. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  25958. */
  25959. final class Xml
  25960. {
  25961. public static function import(\DOMElement $element) : \DOMElement
  25962. {
  25963. return (new \DOMDocument())->importNode($element, \true);
  25964. }
  25965. /**
  25966. * Load an $actual document into a DOMDocument. This is called
  25967. * from the selector assertions.
  25968. *
  25969. * If $actual is already a DOMDocument, it is returned with
  25970. * no changes. Otherwise, $actual is loaded into a new DOMDocument
  25971. * as either HTML or XML, depending on the value of $isHtml. If $isHtml is
  25972. * false and $xinclude is true, xinclude is performed on the loaded
  25973. * DOMDocument.
  25974. *
  25975. * Note: prior to PHPUnit 3.3.0, this method loaded a file and
  25976. * not a string as it currently does. To load a file into a
  25977. * DOMDocument, use loadFile() instead.
  25978. *
  25979. * @param \DOMDocument|string $actual
  25980. *
  25981. * @throws Exception
  25982. */
  25983. public static function load($actual, bool $isHtml = \false, string $filename = '', bool $xinclude = \false, bool $strict = \false) : \DOMDocument
  25984. {
  25985. if ($actual instanceof \DOMDocument) {
  25986. return $actual;
  25987. }
  25988. if (!\is_string($actual)) {
  25989. throw new \PHPUnit\Framework\Exception('Could not load XML from ' . \gettype($actual));
  25990. }
  25991. if ($actual === '') {
  25992. throw new \PHPUnit\Framework\Exception('Could not load XML from empty string');
  25993. }
  25994. // Required for XInclude on Windows.
  25995. if ($xinclude) {
  25996. $cwd = \getcwd();
  25997. @\chdir(\dirname($filename));
  25998. }
  25999. $document = new \DOMDocument();
  26000. $document->preserveWhiteSpace = \false;
  26001. $internal = \libxml_use_internal_errors(\true);
  26002. $message = '';
  26003. $reporting = \error_reporting(0);
  26004. if ($filename !== '') {
  26005. // Required for XInclude
  26006. $document->documentURI = $filename;
  26007. }
  26008. if ($isHtml) {
  26009. $loaded = $document->loadHTML($actual);
  26010. } else {
  26011. $loaded = $document->loadXML($actual);
  26012. }
  26013. if (!$isHtml && $xinclude) {
  26014. $document->xinclude();
  26015. }
  26016. foreach (\libxml_get_errors() as $error) {
  26017. $message .= "\n" . $error->message;
  26018. }
  26019. \libxml_use_internal_errors($internal);
  26020. \error_reporting($reporting);
  26021. if (isset($cwd)) {
  26022. @\chdir($cwd);
  26023. }
  26024. if ($loaded === \false || $strict && $message !== '') {
  26025. if ($filename !== '') {
  26026. throw new \PHPUnit\Framework\Exception(\sprintf('Could not load "%s".%s', $filename, $message !== '' ? "\n" . $message : ''));
  26027. }
  26028. if ($message === '') {
  26029. $message = 'Could not load XML for unknown reason';
  26030. }
  26031. throw new \PHPUnit\Framework\Exception($message);
  26032. }
  26033. return $document;
  26034. }
  26035. /**
  26036. * Loads an XML (or HTML) file into a DOMDocument object.
  26037. *
  26038. * @throws Exception
  26039. */
  26040. public static function loadFile(string $filename, bool $isHtml = \false, bool $xinclude = \false, bool $strict = \false) : \DOMDocument
  26041. {
  26042. $reporting = \error_reporting(0);
  26043. $contents = \file_get_contents($filename);
  26044. \error_reporting($reporting);
  26045. if ($contents === \false) {
  26046. throw new \PHPUnit\Framework\Exception(\sprintf('Could not read "%s".', $filename));
  26047. }
  26048. return self::load($contents, $isHtml, $filename, $xinclude, $strict);
  26049. }
  26050. public static function removeCharacterDataNodes(\DOMNode $node) : void
  26051. {
  26052. if ($node->hasChildNodes()) {
  26053. for ($i = $node->childNodes->length - 1; $i >= 0; $i--) {
  26054. if (($child = $node->childNodes->item($i)) instanceof \DOMCharacterData) {
  26055. $node->removeChild($child);
  26056. }
  26057. }
  26058. }
  26059. }
  26060. /**
  26061. * Escapes a string for the use in XML documents
  26062. *
  26063. * Any Unicode character is allowed, excluding the surrogate blocks, FFFE,
  26064. * and FFFF (not even as character reference).
  26065. *
  26066. * @see https://www.w3.org/TR/xml/#charsets
  26067. */
  26068. public static function prepareString(string $string) : string
  26069. {
  26070. return \preg_replace('/[\\x00-\\x08\\x0b\\x0c\\x0e-\\x1f\\x7f]/', '', \htmlspecialchars(self::convertToUtf8($string), \ENT_QUOTES));
  26071. }
  26072. /**
  26073. * "Convert" a DOMElement object into a PHP variable.
  26074. */
  26075. public static function xmlToVariable(\DOMElement $element)
  26076. {
  26077. $variable = null;
  26078. switch ($element->tagName) {
  26079. case 'array':
  26080. $variable = [];
  26081. foreach ($element->childNodes as $entry) {
  26082. if (!$entry instanceof \DOMElement || $entry->tagName !== 'element') {
  26083. continue;
  26084. }
  26085. $item = $entry->childNodes->item(0);
  26086. if ($item instanceof \DOMText) {
  26087. $item = $entry->childNodes->item(1);
  26088. }
  26089. $value = self::xmlToVariable($item);
  26090. if ($entry->hasAttribute('key')) {
  26091. $variable[(string) $entry->getAttribute('key')] = $value;
  26092. } else {
  26093. $variable[] = $value;
  26094. }
  26095. }
  26096. break;
  26097. case 'object':
  26098. $className = $element->getAttribute('class');
  26099. if ($element->hasChildNodes()) {
  26100. $arguments = $element->childNodes->item(0)->childNodes;
  26101. $constructorArgs = [];
  26102. foreach ($arguments as $argument) {
  26103. if ($argument instanceof \DOMElement) {
  26104. $constructorArgs[] = self::xmlToVariable($argument);
  26105. }
  26106. }
  26107. try {
  26108. \assert(\class_exists($className));
  26109. $variable = (new \ReflectionClass($className))->newInstanceArgs($constructorArgs);
  26110. // @codeCoverageIgnoreStart
  26111. } catch (\ReflectionException $e) {
  26112. throw new \PHPUnit\Framework\Exception($e->getMessage(), (int) $e->getCode(), $e);
  26113. }
  26114. // @codeCoverageIgnoreEnd
  26115. } else {
  26116. $variable = new $className();
  26117. }
  26118. break;
  26119. case 'boolean':
  26120. $variable = $element->textContent === 'true';
  26121. break;
  26122. case 'integer':
  26123. case 'double':
  26124. case 'string':
  26125. $variable = $element->textContent;
  26126. \settype($variable, $element->tagName);
  26127. break;
  26128. }
  26129. return $variable;
  26130. }
  26131. private static function convertToUtf8(string $string) : string
  26132. {
  26133. if (!self::isUtf8($string)) {
  26134. $string = \mb_convert_encoding($string, 'UTF-8');
  26135. }
  26136. return $string;
  26137. }
  26138. private static function isUtf8(string $string) : bool
  26139. {
  26140. $length = \strlen($string);
  26141. for ($i = 0; $i < $length; $i++) {
  26142. if (\ord($string[$i]) < 0x80) {
  26143. $n = 0;
  26144. } elseif ((\ord($string[$i]) & 0xe0) === 0xc0) {
  26145. $n = 1;
  26146. } elseif ((\ord($string[$i]) & 0xf0) === 0xe0) {
  26147. $n = 2;
  26148. } elseif ((\ord($string[$i]) & 0xf0) === 0xf0) {
  26149. $n = 3;
  26150. } else {
  26151. return \false;
  26152. }
  26153. for ($j = 0; $j < $n; $j++) {
  26154. if (++$i === $length || (\ord($string[$i]) & 0xc0) !== 0x80) {
  26155. return \false;
  26156. }
  26157. }
  26158. }
  26159. return \true;
  26160. }
  26161. }
  26162. <?php
  26163. declare (strict_types=1);
  26164. /*
  26165. * This file is part of PHPUnit.
  26166. *
  26167. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  26168. *
  26169. * For the full copyright and license information, please view the LICENSE
  26170. * file that was distributed with this source code.
  26171. */
  26172. namespace PHPUnit\Util;
  26173. /**
  26174. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  26175. */
  26176. final class GlobalState
  26177. {
  26178. /**
  26179. * @var string[]
  26180. */
  26181. private const SUPER_GLOBAL_ARRAYS = ['_ENV', '_POST', '_GET', '_COOKIE', '_SERVER', '_FILES', '_REQUEST'];
  26182. /**
  26183. * @throws Exception
  26184. */
  26185. public static function getIncludedFilesAsString() : string
  26186. {
  26187. return static::processIncludedFilesAsString(\get_included_files());
  26188. }
  26189. /**
  26190. * @param string[] $files
  26191. *
  26192. * @throws Exception
  26193. */
  26194. public static function processIncludedFilesAsString(array $files) : string
  26195. {
  26196. $blacklist = new \PHPUnit\Util\Blacklist();
  26197. $prefix = \false;
  26198. $result = '';
  26199. if (\defined('__PHPUNIT_PHAR__')) {
  26200. $prefix = 'phar://' . __PHPUNIT_PHAR__ . '/';
  26201. }
  26202. for ($i = \count($files) - 1; $i > 0; $i--) {
  26203. $file = $files[$i];
  26204. if (!empty($GLOBALS['__PHPUNIT_ISOLATION_BLACKLIST']) && \in_array($file, $GLOBALS['__PHPUNIT_ISOLATION_BLACKLIST'])) {
  26205. continue;
  26206. }
  26207. if ($prefix !== \false && \strpos($file, $prefix) === 0) {
  26208. continue;
  26209. }
  26210. // Skip virtual file system protocols
  26211. if (\preg_match('/^(vfs|phpvfs[a-z0-9]+):/', $file)) {
  26212. continue;
  26213. }
  26214. if (!$blacklist->isBlacklisted($file) && \is_file($file)) {
  26215. $result = 'require_once \'' . $file . "';\n" . $result;
  26216. }
  26217. }
  26218. return $result;
  26219. }
  26220. public static function getIniSettingsAsString() : string
  26221. {
  26222. $result = '';
  26223. foreach (\ini_get_all(null, \false) as $key => $value) {
  26224. $result .= \sprintf('@ini_set(%s, %s);' . "\n", self::exportVariable($key), self::exportVariable((string) $value));
  26225. }
  26226. return $result;
  26227. }
  26228. public static function getConstantsAsString() : string
  26229. {
  26230. $constants = \get_defined_constants(\true);
  26231. $result = '';
  26232. if (isset($constants['user'])) {
  26233. foreach ($constants['user'] as $name => $value) {
  26234. $result .= \sprintf('if (!defined(\'%s\')) define(\'%s\', %s);' . "\n", $name, $name, self::exportVariable($value));
  26235. }
  26236. }
  26237. return $result;
  26238. }
  26239. public static function getGlobalsAsString() : string
  26240. {
  26241. $result = '';
  26242. foreach (self::SUPER_GLOBAL_ARRAYS as $superGlobalArray) {
  26243. if (isset($GLOBALS[$superGlobalArray]) && \is_array($GLOBALS[$superGlobalArray])) {
  26244. foreach (\array_keys($GLOBALS[$superGlobalArray]) as $key) {
  26245. if ($GLOBALS[$superGlobalArray][$key] instanceof \Closure) {
  26246. continue;
  26247. }
  26248. $result .= \sprintf('$GLOBALS[\'%s\'][\'%s\'] = %s;' . "\n", $superGlobalArray, $key, self::exportVariable($GLOBALS[$superGlobalArray][$key]));
  26249. }
  26250. }
  26251. }
  26252. $blacklist = self::SUPER_GLOBAL_ARRAYS;
  26253. $blacklist[] = 'GLOBALS';
  26254. foreach (\array_keys($GLOBALS) as $key) {
  26255. if (!$GLOBALS[$key] instanceof \Closure && !\in_array($key, $blacklist, \true)) {
  26256. $result .= \sprintf('$GLOBALS[\'%s\'] = %s;' . "\n", $key, self::exportVariable($GLOBALS[$key]));
  26257. }
  26258. }
  26259. return $result;
  26260. }
  26261. private static function exportVariable($variable) : string
  26262. {
  26263. if (\is_scalar($variable) || $variable === null || \is_array($variable) && self::arrayOnlyContainsScalars($variable)) {
  26264. return \var_export($variable, \true);
  26265. }
  26266. return 'unserialize(' . \var_export(\serialize($variable), \true) . ')';
  26267. }
  26268. private static function arrayOnlyContainsScalars(array $array) : bool
  26269. {
  26270. $result = \true;
  26271. foreach ($array as $element) {
  26272. if (\is_array($element)) {
  26273. $result = self::arrayOnlyContainsScalars($element);
  26274. } elseif (!\is_scalar($element) && $element !== null) {
  26275. $result = \false;
  26276. }
  26277. if (!$result) {
  26278. break;
  26279. }
  26280. }
  26281. return $result;
  26282. }
  26283. }
  26284. <?php
  26285. declare (strict_types=1);
  26286. /*
  26287. * This file is part of PHPUnit.
  26288. *
  26289. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  26290. *
  26291. * For the full copyright and license information, please view the LICENSE
  26292. * file that was distributed with this source code.
  26293. */
  26294. namespace PHPUnit\Util;
  26295. /**
  26296. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  26297. */
  26298. final class InvalidDataSetException extends \RuntimeException implements \PHPUnit\Exception
  26299. {
  26300. }
  26301. <?php
  26302. declare (strict_types=1);
  26303. /*
  26304. * This file is part of PHPUnit.
  26305. *
  26306. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  26307. *
  26308. * For the full copyright and license information, please view the LICENSE
  26309. * file that was distributed with this source code.
  26310. */
  26311. namespace PHPUnit\Util\Log;
  26312. use PHPUnit\Framework\AssertionFailedError;
  26313. use PHPUnit\Framework\ExceptionWrapper;
  26314. use PHPUnit\Framework\SelfDescribing;
  26315. use PHPUnit\Framework\Test;
  26316. use PHPUnit\Framework\TestFailure;
  26317. use PHPUnit\Framework\TestListener;
  26318. use PHPUnit\Framework\TestSuite;
  26319. use PHPUnit\Framework\Warning;
  26320. use PHPUnit\Util\Exception;
  26321. use PHPUnit\Util\Filter;
  26322. use PHPUnit\Util\Printer;
  26323. use PHPUnit\Util\Xml;
  26324. /**
  26325. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  26326. */
  26327. final class JUnit extends \PHPUnit\Util\Printer implements \PHPUnit\Framework\TestListener
  26328. {
  26329. /**
  26330. * @var \DOMDocument
  26331. */
  26332. private $document;
  26333. /**
  26334. * @var \DOMElement
  26335. */
  26336. private $root;
  26337. /**
  26338. * @var bool
  26339. */
  26340. private $reportRiskyTests = \false;
  26341. /**
  26342. * @var \DOMElement[]
  26343. */
  26344. private $testSuites = [];
  26345. /**
  26346. * @var int[]
  26347. */
  26348. private $testSuiteTests = [0];
  26349. /**
  26350. * @var int[]
  26351. */
  26352. private $testSuiteAssertions = [0];
  26353. /**
  26354. * @var int[]
  26355. */
  26356. private $testSuiteErrors = [0];
  26357. /**
  26358. * @var int[]
  26359. */
  26360. private $testSuiteWarnings = [0];
  26361. /**
  26362. * @var int[]
  26363. */
  26364. private $testSuiteFailures = [0];
  26365. /**
  26366. * @var int[]
  26367. */
  26368. private $testSuiteSkipped = [0];
  26369. /**
  26370. * @var int[]
  26371. */
  26372. private $testSuiteTimes = [0];
  26373. /**
  26374. * @var int
  26375. */
  26376. private $testSuiteLevel = 0;
  26377. /**
  26378. * @var \DOMElement
  26379. */
  26380. private $currentTestCase;
  26381. /**
  26382. * @param null|mixed $out
  26383. */
  26384. public function __construct($out = null, bool $reportRiskyTests = \false)
  26385. {
  26386. $this->document = new \DOMDocument('1.0', 'UTF-8');
  26387. $this->document->formatOutput = \true;
  26388. $this->root = $this->document->createElement('testsuites');
  26389. $this->document->appendChild($this->root);
  26390. parent::__construct($out);
  26391. $this->reportRiskyTests = $reportRiskyTests;
  26392. }
  26393. /**
  26394. * Flush buffer and close output.
  26395. */
  26396. public function flush() : void
  26397. {
  26398. $this->write($this->getXML());
  26399. parent::flush();
  26400. }
  26401. /**
  26402. * An error occurred.
  26403. */
  26404. public function addError(\PHPUnit\Framework\Test $test, \Throwable $t, float $time) : void
  26405. {
  26406. $this->doAddFault($test, $t, 'error');
  26407. $this->testSuiteErrors[$this->testSuiteLevel]++;
  26408. }
  26409. /**
  26410. * A warning occurred.
  26411. */
  26412. public function addWarning(\PHPUnit\Framework\Test $test, \PHPUnit\Framework\Warning $e, float $time) : void
  26413. {
  26414. $this->doAddFault($test, $e, 'warning');
  26415. $this->testSuiteWarnings[$this->testSuiteLevel]++;
  26416. }
  26417. /**
  26418. * A failure occurred.
  26419. */
  26420. public function addFailure(\PHPUnit\Framework\Test $test, \PHPUnit\Framework\AssertionFailedError $e, float $time) : void
  26421. {
  26422. $this->doAddFault($test, $e, 'failure');
  26423. $this->testSuiteFailures[$this->testSuiteLevel]++;
  26424. }
  26425. /**
  26426. * Incomplete test.
  26427. */
  26428. public function addIncompleteTest(\PHPUnit\Framework\Test $test, \Throwable $t, float $time) : void
  26429. {
  26430. $this->doAddSkipped();
  26431. }
  26432. /**
  26433. * Risky test.
  26434. */
  26435. public function addRiskyTest(\PHPUnit\Framework\Test $test, \Throwable $t, float $time) : void
  26436. {
  26437. if (!$this->reportRiskyTests || $this->currentTestCase === null) {
  26438. return;
  26439. }
  26440. $error = $this->document->createElement('error', \PHPUnit\Util\Xml::prepareString("Risky Test\n" . \PHPUnit\Util\Filter::getFilteredStacktrace($t)));
  26441. $error->setAttribute('type', \get_class($t));
  26442. $this->currentTestCase->appendChild($error);
  26443. $this->testSuiteErrors[$this->testSuiteLevel]++;
  26444. }
  26445. /**
  26446. * Skipped test.
  26447. */
  26448. public function addSkippedTest(\PHPUnit\Framework\Test $test, \Throwable $t, float $time) : void
  26449. {
  26450. $this->doAddSkipped();
  26451. }
  26452. /**
  26453. * A testsuite started.
  26454. */
  26455. public function startTestSuite(\PHPUnit\Framework\TestSuite $suite) : void
  26456. {
  26457. $testSuite = $this->document->createElement('testsuite');
  26458. $testSuite->setAttribute('name', $suite->getName());
  26459. if (\class_exists($suite->getName(), \false)) {
  26460. try {
  26461. $class = new \ReflectionClass($suite->getName());
  26462. $testSuite->setAttribute('file', $class->getFileName());
  26463. } catch (\ReflectionException $e) {
  26464. }
  26465. }
  26466. if ($this->testSuiteLevel > 0) {
  26467. $this->testSuites[$this->testSuiteLevel]->appendChild($testSuite);
  26468. } else {
  26469. $this->root->appendChild($testSuite);
  26470. }
  26471. $this->testSuiteLevel++;
  26472. $this->testSuites[$this->testSuiteLevel] = $testSuite;
  26473. $this->testSuiteTests[$this->testSuiteLevel] = 0;
  26474. $this->testSuiteAssertions[$this->testSuiteLevel] = 0;
  26475. $this->testSuiteErrors[$this->testSuiteLevel] = 0;
  26476. $this->testSuiteWarnings[$this->testSuiteLevel] = 0;
  26477. $this->testSuiteFailures[$this->testSuiteLevel] = 0;
  26478. $this->testSuiteSkipped[$this->testSuiteLevel] = 0;
  26479. $this->testSuiteTimes[$this->testSuiteLevel] = 0;
  26480. }
  26481. /**
  26482. * A testsuite ended.
  26483. */
  26484. public function endTestSuite(\PHPUnit\Framework\TestSuite $suite) : void
  26485. {
  26486. $this->testSuites[$this->testSuiteLevel]->setAttribute('tests', (string) $this->testSuiteTests[$this->testSuiteLevel]);
  26487. $this->testSuites[$this->testSuiteLevel]->setAttribute('assertions', (string) $this->testSuiteAssertions[$this->testSuiteLevel]);
  26488. $this->testSuites[$this->testSuiteLevel]->setAttribute('errors', (string) $this->testSuiteErrors[$this->testSuiteLevel]);
  26489. $this->testSuites[$this->testSuiteLevel]->setAttribute('warnings', (string) $this->testSuiteWarnings[$this->testSuiteLevel]);
  26490. $this->testSuites[$this->testSuiteLevel]->setAttribute('failures', (string) $this->testSuiteFailures[$this->testSuiteLevel]);
  26491. $this->testSuites[$this->testSuiteLevel]->setAttribute('skipped', (string) $this->testSuiteSkipped[$this->testSuiteLevel]);
  26492. $this->testSuites[$this->testSuiteLevel]->setAttribute('time', \sprintf('%F', $this->testSuiteTimes[$this->testSuiteLevel]));
  26493. if ($this->testSuiteLevel > 1) {
  26494. $this->testSuiteTests[$this->testSuiteLevel - 1] += $this->testSuiteTests[$this->testSuiteLevel];
  26495. $this->testSuiteAssertions[$this->testSuiteLevel - 1] += $this->testSuiteAssertions[$this->testSuiteLevel];
  26496. $this->testSuiteErrors[$this->testSuiteLevel - 1] += $this->testSuiteErrors[$this->testSuiteLevel];
  26497. $this->testSuiteWarnings[$this->testSuiteLevel - 1] += $this->testSuiteWarnings[$this->testSuiteLevel];
  26498. $this->testSuiteFailures[$this->testSuiteLevel - 1] += $this->testSuiteFailures[$this->testSuiteLevel];
  26499. $this->testSuiteSkipped[$this->testSuiteLevel - 1] += $this->testSuiteSkipped[$this->testSuiteLevel];
  26500. $this->testSuiteTimes[$this->testSuiteLevel - 1] += $this->testSuiteTimes[$this->testSuiteLevel];
  26501. }
  26502. $this->testSuiteLevel--;
  26503. }
  26504. /**
  26505. * A test started.
  26506. */
  26507. public function startTest(\PHPUnit\Framework\Test $test) : void
  26508. {
  26509. $usesDataprovider = \false;
  26510. if (\method_exists($test, 'usesDataProvider')) {
  26511. $usesDataprovider = $test->usesDataProvider();
  26512. }
  26513. $testCase = $this->document->createElement('testcase');
  26514. $testCase->setAttribute('name', $test->getName());
  26515. try {
  26516. $class = new \ReflectionClass($test);
  26517. // @codeCoverageIgnoreStart
  26518. } catch (\ReflectionException $e) {
  26519. throw new \PHPUnit\Util\Exception($e->getMessage(), (int) $e->getCode(), $e);
  26520. }
  26521. // @codeCoverageIgnoreEnd
  26522. $methodName = $test->getName(!$usesDataprovider);
  26523. if ($class->hasMethod($methodName)) {
  26524. try {
  26525. $method = $class->getMethod($methodName);
  26526. // @codeCoverageIgnoreStart
  26527. } catch (\ReflectionException $e) {
  26528. throw new \PHPUnit\Util\Exception($e->getMessage(), (int) $e->getCode(), $e);
  26529. }
  26530. // @codeCoverageIgnoreEnd
  26531. $testCase->setAttribute('class', $class->getName());
  26532. $testCase->setAttribute('classname', \str_replace('\\', '.', $class->getName()));
  26533. $testCase->setAttribute('file', $class->getFileName());
  26534. $testCase->setAttribute('line', (string) $method->getStartLine());
  26535. }
  26536. $this->currentTestCase = $testCase;
  26537. }
  26538. /**
  26539. * A test ended.
  26540. */
  26541. public function endTest(\PHPUnit\Framework\Test $test, float $time) : void
  26542. {
  26543. $numAssertions = 0;
  26544. if (\method_exists($test, 'getNumAssertions')) {
  26545. $numAssertions = $test->getNumAssertions();
  26546. }
  26547. $this->testSuiteAssertions[$this->testSuiteLevel] += $numAssertions;
  26548. $this->currentTestCase->setAttribute('assertions', (string) $numAssertions);
  26549. $this->currentTestCase->setAttribute('time', \sprintf('%F', $time));
  26550. $this->testSuites[$this->testSuiteLevel]->appendChild($this->currentTestCase);
  26551. $this->testSuiteTests[$this->testSuiteLevel]++;
  26552. $this->testSuiteTimes[$this->testSuiteLevel] += $time;
  26553. $testOutput = '';
  26554. if (\method_exists($test, 'hasOutput') && \method_exists($test, 'getActualOutput')) {
  26555. $testOutput = $test->hasOutput() ? $test->getActualOutput() : '';
  26556. }
  26557. if (!empty($testOutput)) {
  26558. $systemOut = $this->document->createElement('system-out', \PHPUnit\Util\Xml::prepareString($testOutput));
  26559. $this->currentTestCase->appendChild($systemOut);
  26560. }
  26561. $this->currentTestCase = null;
  26562. }
  26563. /**
  26564. * Returns the XML as a string.
  26565. */
  26566. public function getXML() : string
  26567. {
  26568. return $this->document->saveXML();
  26569. }
  26570. private function doAddFault(\PHPUnit\Framework\Test $test, \Throwable $t, string $type) : void
  26571. {
  26572. if ($this->currentTestCase === null) {
  26573. return;
  26574. }
  26575. if ($test instanceof \PHPUnit\Framework\SelfDescribing) {
  26576. $buffer = $test->toString() . "\n";
  26577. } else {
  26578. $buffer = '';
  26579. }
  26580. $buffer .= \PHPUnit\Framework\TestFailure::exceptionToString($t) . "\n" . \PHPUnit\Util\Filter::getFilteredStacktrace($t);
  26581. $fault = $this->document->createElement($type, \PHPUnit\Util\Xml::prepareString($buffer));
  26582. if ($t instanceof \PHPUnit\Framework\ExceptionWrapper) {
  26583. $fault->setAttribute('type', $t->getClassName());
  26584. } else {
  26585. $fault->setAttribute('type', \get_class($t));
  26586. }
  26587. $this->currentTestCase->appendChild($fault);
  26588. }
  26589. private function doAddSkipped() : void
  26590. {
  26591. if ($this->currentTestCase === null) {
  26592. return;
  26593. }
  26594. $skipped = $this->document->createElement('skipped');
  26595. $this->currentTestCase->appendChild($skipped);
  26596. $this->testSuiteSkipped[$this->testSuiteLevel]++;
  26597. }
  26598. }
  26599. <?php
  26600. declare (strict_types=1);
  26601. /*
  26602. * This file is part of PHPUnit.
  26603. *
  26604. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  26605. *
  26606. * For the full copyright and license information, please view the LICENSE
  26607. * file that was distributed with this source code.
  26608. */
  26609. namespace PHPUnit\Util\Log;
  26610. use PHPUnit\Framework\AssertionFailedError;
  26611. use PHPUnit\Framework\ExceptionWrapper;
  26612. use PHPUnit\Framework\ExpectationFailedException;
  26613. use PHPUnit\Framework\Test;
  26614. use PHPUnit\Framework\TestCase;
  26615. use PHPUnit\Framework\TestFailure;
  26616. use PHPUnit\Framework\TestResult;
  26617. use PHPUnit\Framework\TestSuite;
  26618. use PHPUnit\Framework\Warning;
  26619. use PHPUnit\TextUI\DefaultResultPrinter;
  26620. use PHPUnit\Util\Exception;
  26621. use PHPUnit\Util\Filter;
  26622. use PHPUnit\SebastianBergmann\Comparator\ComparisonFailure;
  26623. /**
  26624. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  26625. */
  26626. final class TeamCity extends \PHPUnit\TextUI\DefaultResultPrinter
  26627. {
  26628. /**
  26629. * @var bool
  26630. */
  26631. private $isSummaryTestCountPrinted = \false;
  26632. /**
  26633. * @var string
  26634. */
  26635. private $startedTestName;
  26636. /**
  26637. * @var false|int
  26638. */
  26639. private $flowId;
  26640. public function printResult(\PHPUnit\Framework\TestResult $result) : void
  26641. {
  26642. $this->printHeader($result);
  26643. $this->printFooter($result);
  26644. }
  26645. /**
  26646. * An error occurred.
  26647. */
  26648. public function addError(\PHPUnit\Framework\Test $test, \Throwable $t, float $time) : void
  26649. {
  26650. $this->printEvent('testFailed', ['name' => $test->getName(), 'message' => self::getMessage($t), 'details' => self::getDetails($t), 'duration' => self::toMilliseconds($time)]);
  26651. }
  26652. /**
  26653. * A warning occurred.
  26654. */
  26655. public function addWarning(\PHPUnit\Framework\Test $test, \PHPUnit\Framework\Warning $e, float $time) : void
  26656. {
  26657. $this->printEvent('testFailed', ['name' => $test->getName(), 'message' => self::getMessage($e), 'details' => self::getDetails($e), 'duration' => self::toMilliseconds($time)]);
  26658. }
  26659. /**
  26660. * A failure occurred.
  26661. */
  26662. public function addFailure(\PHPUnit\Framework\Test $test, \PHPUnit\Framework\AssertionFailedError $e, float $time) : void
  26663. {
  26664. $parameters = ['name' => $test->getName(), 'message' => self::getMessage($e), 'details' => self::getDetails($e), 'duration' => self::toMilliseconds($time)];
  26665. if ($e instanceof \PHPUnit\Framework\ExpectationFailedException) {
  26666. $comparisonFailure = $e->getComparisonFailure();
  26667. if ($comparisonFailure instanceof \PHPUnit\SebastianBergmann\Comparator\ComparisonFailure) {
  26668. $expectedString = $comparisonFailure->getExpectedAsString();
  26669. if ($expectedString === null || empty($expectedString)) {
  26670. $expectedString = self::getPrimitiveValueAsString($comparisonFailure->getExpected());
  26671. }
  26672. $actualString = $comparisonFailure->getActualAsString();
  26673. if ($actualString === null || empty($actualString)) {
  26674. $actualString = self::getPrimitiveValueAsString($comparisonFailure->getActual());
  26675. }
  26676. if ($actualString !== null && $expectedString !== null) {
  26677. $parameters['type'] = 'comparisonFailure';
  26678. $parameters['actual'] = $actualString;
  26679. $parameters['expected'] = $expectedString;
  26680. }
  26681. }
  26682. }
  26683. $this->printEvent('testFailed', $parameters);
  26684. }
  26685. /**
  26686. * Incomplete test.
  26687. */
  26688. public function addIncompleteTest(\PHPUnit\Framework\Test $test, \Throwable $t, float $time) : void
  26689. {
  26690. $this->printIgnoredTest($test->getName(), $t, $time);
  26691. }
  26692. /**
  26693. * Risky test.
  26694. */
  26695. public function addRiskyTest(\PHPUnit\Framework\Test $test, \Throwable $t, float $time) : void
  26696. {
  26697. $this->addError($test, $t, $time);
  26698. }
  26699. /**
  26700. * Skipped test.
  26701. */
  26702. public function addSkippedTest(\PHPUnit\Framework\Test $test, \Throwable $t, float $time) : void
  26703. {
  26704. $testName = $test->getName();
  26705. if ($this->startedTestName !== $testName) {
  26706. $this->startTest($test);
  26707. $this->printIgnoredTest($testName, $t, $time);
  26708. $this->endTest($test, $time);
  26709. } else {
  26710. $this->printIgnoredTest($testName, $t, $time);
  26711. }
  26712. }
  26713. public function printIgnoredTest(string $testName, \Throwable $t, float $time) : void
  26714. {
  26715. $this->printEvent('testIgnored', ['name' => $testName, 'message' => self::getMessage($t), 'details' => self::getDetails($t), 'duration' => self::toMilliseconds($time)]);
  26716. }
  26717. /**
  26718. * A testsuite started.
  26719. */
  26720. public function startTestSuite(\PHPUnit\Framework\TestSuite $suite) : void
  26721. {
  26722. if (\stripos(\ini_get('disable_functions'), 'getmypid') === \false) {
  26723. $this->flowId = \getmypid();
  26724. } else {
  26725. $this->flowId = \false;
  26726. }
  26727. if (!$this->isSummaryTestCountPrinted) {
  26728. $this->isSummaryTestCountPrinted = \true;
  26729. $this->printEvent('testCount', ['count' => \count($suite)]);
  26730. }
  26731. $suiteName = $suite->getName();
  26732. if (empty($suiteName)) {
  26733. return;
  26734. }
  26735. $parameters = ['name' => $suiteName];
  26736. if (\class_exists($suiteName, \false)) {
  26737. $fileName = self::getFileName($suiteName);
  26738. $parameters['locationHint'] = "php_qn://{$fileName}::\\{$suiteName}";
  26739. } else {
  26740. $split = \explode('::', $suiteName);
  26741. if (\count($split) === 2 && \class_exists($split[0]) && \method_exists($split[0], $split[1])) {
  26742. $fileName = self::getFileName($split[0]);
  26743. $parameters['locationHint'] = "php_qn://{$fileName}::\\{$suiteName}";
  26744. $parameters['name'] = $split[1];
  26745. }
  26746. }
  26747. $this->printEvent('testSuiteStarted', $parameters);
  26748. }
  26749. /**
  26750. * A testsuite ended.
  26751. */
  26752. public function endTestSuite(\PHPUnit\Framework\TestSuite $suite) : void
  26753. {
  26754. $suiteName = $suite->getName();
  26755. if (empty($suiteName)) {
  26756. return;
  26757. }
  26758. $parameters = ['name' => $suiteName];
  26759. if (!\class_exists($suiteName, \false)) {
  26760. $split = \explode('::', $suiteName);
  26761. if (\count($split) === 2 && \class_exists($split[0]) && \method_exists($split[0], $split[1])) {
  26762. $parameters['name'] = $split[1];
  26763. }
  26764. }
  26765. $this->printEvent('testSuiteFinished', $parameters);
  26766. }
  26767. /**
  26768. * A test started.
  26769. */
  26770. public function startTest(\PHPUnit\Framework\Test $test) : void
  26771. {
  26772. $testName = $test->getName();
  26773. $this->startedTestName = $testName;
  26774. $params = ['name' => $testName];
  26775. if ($test instanceof \PHPUnit\Framework\TestCase) {
  26776. $className = \get_class($test);
  26777. $fileName = self::getFileName($className);
  26778. $params['locationHint'] = "php_qn://{$fileName}::\\{$className}::{$testName}";
  26779. }
  26780. $this->printEvent('testStarted', $params);
  26781. }
  26782. /**
  26783. * A test ended.
  26784. */
  26785. public function endTest(\PHPUnit\Framework\Test $test, float $time) : void
  26786. {
  26787. parent::endTest($test, $time);
  26788. $this->printEvent('testFinished', ['name' => $test->getName(), 'duration' => self::toMilliseconds($time)]);
  26789. }
  26790. protected function writeProgress(string $progress) : void
  26791. {
  26792. }
  26793. private function printEvent(string $eventName, array $params = []) : void
  26794. {
  26795. $this->write("\n##teamcity[{$eventName}");
  26796. if ($this->flowId) {
  26797. $params['flowId'] = $this->flowId;
  26798. }
  26799. foreach ($params as $key => $value) {
  26800. $escapedValue = self::escapeValue((string) $value);
  26801. $this->write(" {$key}='{$escapedValue}'");
  26802. }
  26803. $this->write("]\n");
  26804. }
  26805. private static function getMessage(\Throwable $t) : string
  26806. {
  26807. $message = '';
  26808. if ($t instanceof \PHPUnit\Framework\ExceptionWrapper) {
  26809. if ($t->getClassName() !== '') {
  26810. $message .= $t->getClassName();
  26811. }
  26812. if ($message !== '' && $t->getMessage() !== '') {
  26813. $message .= ' : ';
  26814. }
  26815. }
  26816. return $message . $t->getMessage();
  26817. }
  26818. private static function getDetails(\Throwable $t) : string
  26819. {
  26820. $stackTrace = \PHPUnit\Util\Filter::getFilteredStacktrace($t);
  26821. $previous = $t instanceof \PHPUnit\Framework\ExceptionWrapper ? $t->getPreviousWrapped() : $t->getPrevious();
  26822. while ($previous) {
  26823. $stackTrace .= "\nCaused by\n" . \PHPUnit\Framework\TestFailure::exceptionToString($previous) . "\n" . \PHPUnit\Util\Filter::getFilteredStacktrace($previous);
  26824. $previous = $previous instanceof \PHPUnit\Framework\ExceptionWrapper ? $previous->getPreviousWrapped() : $previous->getPrevious();
  26825. }
  26826. return ' ' . \str_replace("\n", "\n ", $stackTrace);
  26827. }
  26828. private static function getPrimitiveValueAsString($value) : ?string
  26829. {
  26830. if ($value === null) {
  26831. return 'null';
  26832. }
  26833. if (\is_bool($value)) {
  26834. return $value ? 'true' : 'false';
  26835. }
  26836. if (\is_scalar($value)) {
  26837. return \print_r($value, \true);
  26838. }
  26839. return null;
  26840. }
  26841. private static function escapeValue(string $text) : string
  26842. {
  26843. return \str_replace(['|', "'", "\n", "\r", ']', '['], ['||', "|'", '|n', '|r', '|]', '|['], $text);
  26844. }
  26845. /**
  26846. * @param string $className
  26847. */
  26848. private static function getFileName($className) : string
  26849. {
  26850. try {
  26851. return (new \ReflectionClass($className))->getFileName();
  26852. // @codeCoverageIgnoreStart
  26853. } catch (\ReflectionException $e) {
  26854. throw new \PHPUnit\Util\Exception($e->getMessage(), (int) $e->getCode(), $e);
  26855. }
  26856. // @codeCoverageIgnoreEnd
  26857. }
  26858. /**
  26859. * @param float $time microseconds
  26860. */
  26861. private static function toMilliseconds(float $time) : int
  26862. {
  26863. return (int) \round($time * 1000);
  26864. }
  26865. }
  26866. <?php
  26867. declare (strict_types=1);
  26868. /*
  26869. * This file is part of PHPUnit.
  26870. *
  26871. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  26872. *
  26873. * For the full copyright and license information, please view the LICENSE
  26874. * file that was distributed with this source code.
  26875. */
  26876. namespace PHPUnit\Util;
  26877. use PHPUnit\Composer\Autoload\ClassLoader;
  26878. use PHPUnit\DeepCopy\DeepCopy;
  26879. use PHPUnit\Doctrine\Instantiator\Instantiator;
  26880. use PHPUnit\PharIo\Manifest\Manifest;
  26881. use PHPUnit\PharIo\Version\Version as PharIoVersion;
  26882. use PHPUnit\PHP_Token;
  26883. use PHPUnit\phpDocumentor\Reflection\DocBlock;
  26884. use PHPUnit\phpDocumentor\Reflection\Project;
  26885. use PHPUnit\phpDocumentor\Reflection\Type;
  26886. use PHPUnit\Framework\TestCase;
  26887. use Prophecy\Prophet;
  26888. use PHPUnit\SebastianBergmann\CodeCoverage\CodeCoverage;
  26889. use PHPUnit\SebastianBergmann\CodeUnit\CodeUnit;
  26890. use PHPUnit\SebastianBergmann\CodeUnitReverseLookup\Wizard;
  26891. use PHPUnit\SebastianBergmann\Comparator\Comparator;
  26892. use PHPUnit\SebastianBergmann\Diff\Diff;
  26893. use PHPUnit\SebastianBergmann\Environment\Runtime;
  26894. use PHPUnit\SebastianBergmann\Exporter\Exporter;
  26895. use PHPUnit\SebastianBergmann\FileIterator\Facade as FileIteratorFacade;
  26896. use PHPUnit\SebastianBergmann\GlobalState\Snapshot;
  26897. use PHPUnit\SebastianBergmann\Invoker\Invoker;
  26898. use PHPUnit\SebastianBergmann\ObjectEnumerator\Enumerator;
  26899. use PHPUnit\SebastianBergmann\RecursionContext\Context;
  26900. use PHPUnit\SebastianBergmann\ResourceOperations\ResourceOperations;
  26901. use PHPUnit\SebastianBergmann\Template\Template;
  26902. use PHPUnit\SebastianBergmann\Timer\Timer;
  26903. use PHPUnit\SebastianBergmann\Type\TypeName;
  26904. use PHPUnit\SebastianBergmann\Version;
  26905. use PHPUnit\TheSeer\Tokenizer\Tokenizer;
  26906. use PHPUnit\Webmozart\Assert\Assert;
  26907. final class Blacklist
  26908. {
  26909. /**
  26910. * @var array<string,int>
  26911. */
  26912. private const BLACKLISTED_CLASS_NAMES = [
  26913. // composer
  26914. \PHPUnit\Composer\Autoload\ClassLoader::class => 1,
  26915. // doctrine/instantiator
  26916. \PHPUnit\Doctrine\Instantiator\Instantiator::class => 1,
  26917. // myclabs/deepcopy
  26918. \PHPUnit\DeepCopy\DeepCopy::class => 1,
  26919. // phar-io/manifest
  26920. \PHPUnit\PharIo\Manifest\Manifest::class => 1,
  26921. // phar-io/version
  26922. \PHPUnit\PharIo\Version\Version::class => 1,
  26923. // phpdocumentor/reflection-common
  26924. \PHPUnit\phpDocumentor\Reflection\Project::class => 1,
  26925. // phpdocumentor/reflection-docblock
  26926. \PHPUnit\phpDocumentor\Reflection\DocBlock::class => 1,
  26927. // phpdocumentor/type-resolver
  26928. \PHPUnit\phpDocumentor\Reflection\Type::class => 1,
  26929. // phpspec/prophecy
  26930. \Prophecy\Prophet::class => 1,
  26931. // phpunit/phpunit
  26932. \PHPUnit\Framework\TestCase::class => 2,
  26933. // phpunit/php-code-coverage
  26934. \PHPUnit\SebastianBergmann\CodeCoverage\CodeCoverage::class => 1,
  26935. // phpunit/php-file-iterator
  26936. \PHPUnit\SebastianBergmann\FileIterator\Facade::class => 1,
  26937. // phpunit/php-invoker
  26938. \PHPUnit\SebastianBergmann\Invoker\Invoker::class => 1,
  26939. // phpunit/php-text-template
  26940. \PHPUnit\SebastianBergmann\Template\Template::class => 1,
  26941. // phpunit/php-timer
  26942. \PHPUnit\SebastianBergmann\Timer\Timer::class => 1,
  26943. // phpunit/php-token-stream
  26944. \PHPUnit\PHP_Token::class => 1,
  26945. // sebastian/code-unit
  26946. \PHPUnit\SebastianBergmann\CodeUnit\CodeUnit::class => 1,
  26947. // sebastian/code-unit-reverse-lookup
  26948. \PHPUnit\SebastianBergmann\CodeUnitReverseLookup\Wizard::class => 1,
  26949. // sebastian/comparator
  26950. \PHPUnit\SebastianBergmann\Comparator\Comparator::class => 1,
  26951. // sebastian/diff
  26952. \PHPUnit\SebastianBergmann\Diff\Diff::class => 1,
  26953. // sebastian/environment
  26954. \PHPUnit\SebastianBergmann\Environment\Runtime::class => 1,
  26955. // sebastian/exporter
  26956. \PHPUnit\SebastianBergmann\Exporter\Exporter::class => 1,
  26957. // sebastian/global-state
  26958. \PHPUnit\SebastianBergmann\GlobalState\Snapshot::class => 1,
  26959. // sebastian/object-enumerator
  26960. \PHPUnit\SebastianBergmann\ObjectEnumerator\Enumerator::class => 1,
  26961. // sebastian/recursion-context
  26962. \PHPUnit\SebastianBergmann\RecursionContext\Context::class => 1,
  26963. // sebastian/resource-operations
  26964. \PHPUnit\SebastianBergmann\ResourceOperations\ResourceOperations::class => 1,
  26965. // sebastian/type
  26966. \PHPUnit\SebastianBergmann\Type\TypeName::class => 1,
  26967. // sebastian/version
  26968. \PHPUnit\SebastianBergmann\Version::class => 1,
  26969. // theseer/tokenizer
  26970. \PHPUnit\TheSeer\Tokenizer\Tokenizer::class => 1,
  26971. // webmozart/assert
  26972. \PHPUnit\Webmozart\Assert\Assert::class => 1,
  26973. ];
  26974. /**
  26975. * @var string[]
  26976. */
  26977. private static $directories;
  26978. public static function addDirectory(string $directory) : void
  26979. {
  26980. if (!\is_dir($directory)) {
  26981. throw new \PHPUnit\Util\Exception(\sprintf('"%s" is not a directory', $directory));
  26982. }
  26983. self::$directories[] = \realpath($directory);
  26984. }
  26985. /**
  26986. * @throws Exception
  26987. *
  26988. * @return string[]
  26989. */
  26990. public function getBlacklistedDirectories() : array
  26991. {
  26992. $this->initialize();
  26993. return self::$directories;
  26994. }
  26995. /**
  26996. * @throws Exception
  26997. */
  26998. public function isBlacklisted(string $file) : bool
  26999. {
  27000. if (\defined('PHPUNIT_TESTSUITE')) {
  27001. return \false;
  27002. }
  27003. $this->initialize();
  27004. foreach (self::$directories as $directory) {
  27005. if (\strpos($file, $directory) === 0) {
  27006. return \true;
  27007. }
  27008. }
  27009. return \false;
  27010. }
  27011. /**
  27012. * @throws Exception
  27013. */
  27014. private function initialize() : void
  27015. {
  27016. if (self::$directories === null) {
  27017. self::$directories = [];
  27018. foreach (self::BLACKLISTED_CLASS_NAMES as $className => $parent) {
  27019. if (!\class_exists($className)) {
  27020. continue;
  27021. }
  27022. try {
  27023. $directory = (new \ReflectionClass($className))->getFileName();
  27024. // @codeCoverageIgnoreStart
  27025. } catch (\ReflectionException $e) {
  27026. throw new \PHPUnit\Util\Exception($e->getMessage(), (int) $e->getCode(), $e);
  27027. }
  27028. // @codeCoverageIgnoreEnd
  27029. for ($i = 0; $i < $parent; $i++) {
  27030. $directory = \dirname($directory);
  27031. }
  27032. self::$directories[] = $directory;
  27033. }
  27034. // Hide process isolation workaround on Windows.
  27035. if (\DIRECTORY_SEPARATOR === '\\') {
  27036. // tempnam() prefix is limited to first 3 chars.
  27037. // @see https://php.net/manual/en/function.tempnam.php
  27038. self::$directories[] = \sys_get_temp_dir() . '\\PHP';
  27039. }
  27040. }
  27041. }
  27042. }
  27043. <?php
  27044. declare (strict_types=1);
  27045. /*
  27046. * This file is part of PHPUnit.
  27047. *
  27048. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  27049. *
  27050. * For the full copyright and license information, please view the LICENSE
  27051. * file that was distributed with this source code.
  27052. */
  27053. namespace PHPUnit\Util;
  27054. use PHPUnit\Framework\Exception;
  27055. use PHPUnit\Framework\SyntheticError;
  27056. /**
  27057. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  27058. */
  27059. final class Filter
  27060. {
  27061. /**
  27062. * @throws Exception
  27063. */
  27064. public static function getFilteredStacktrace(\Throwable $t) : string
  27065. {
  27066. $filteredStacktrace = '';
  27067. if ($t instanceof \PHPUnit\Framework\SyntheticError) {
  27068. $eTrace = $t->getSyntheticTrace();
  27069. $eFile = $t->getSyntheticFile();
  27070. $eLine = $t->getSyntheticLine();
  27071. } elseif ($t instanceof \PHPUnit\Framework\Exception) {
  27072. $eTrace = $t->getSerializableTrace();
  27073. $eFile = $t->getFile();
  27074. $eLine = $t->getLine();
  27075. } else {
  27076. if ($t->getPrevious()) {
  27077. $t = $t->getPrevious();
  27078. }
  27079. $eTrace = $t->getTrace();
  27080. $eFile = $t->getFile();
  27081. $eLine = $t->getLine();
  27082. }
  27083. if (!self::frameExists($eTrace, $eFile, $eLine)) {
  27084. \array_unshift($eTrace, ['file' => $eFile, 'line' => $eLine]);
  27085. }
  27086. $prefix = \defined('__PHPUNIT_PHAR_ROOT__') ? __PHPUNIT_PHAR_ROOT__ : \false;
  27087. $blacklist = new \PHPUnit\Util\Blacklist();
  27088. foreach ($eTrace as $frame) {
  27089. if (self::shouldPrintFrame($frame, $prefix, $blacklist)) {
  27090. $filteredStacktrace .= \sprintf("%s:%s\n", $frame['file'], $frame['line'] ?? '?');
  27091. }
  27092. }
  27093. return $filteredStacktrace;
  27094. }
  27095. /**
  27096. * @param false|string $prefix
  27097. */
  27098. private static function shouldPrintFrame(array $frame, $prefix, \PHPUnit\Util\Blacklist $blacklist) : bool
  27099. {
  27100. if (!isset($frame['file'])) {
  27101. return \false;
  27102. }
  27103. $file = $frame['file'];
  27104. $fileIsNotPrefixed = $prefix === \false || \strpos($file, $prefix) !== 0;
  27105. // @see https://github.com/sebastianbergmann/phpunit/issues/4033
  27106. if (isset($GLOBALS['_SERVER']['SCRIPT_NAME'])) {
  27107. $script = \realpath($GLOBALS['_SERVER']['SCRIPT_NAME']);
  27108. } else {
  27109. $script = '';
  27110. }
  27111. return \is_file($file) && self::fileIsBlacklisted($file, $blacklist) && $fileIsNotPrefixed && $file !== $script;
  27112. }
  27113. private static function fileIsBlacklisted(string $file, \PHPUnit\Util\Blacklist $blacklist) : bool
  27114. {
  27115. return (empty($GLOBALS['__PHPUNIT_ISOLATION_BLACKLIST']) || !\in_array($file, $GLOBALS['__PHPUNIT_ISOLATION_BLACKLIST'], \true)) && !$blacklist->isBlacklisted($file);
  27116. }
  27117. private static function frameExists(array $trace, string $file, int $line) : bool
  27118. {
  27119. foreach ($trace as $frame) {
  27120. if (isset($frame['file'], $frame['line']) && $frame['file'] === $file && $frame['line'] === $line) {
  27121. return \true;
  27122. }
  27123. }
  27124. return \false;
  27125. }
  27126. }
  27127. <?php
  27128. declare (strict_types=1);
  27129. /*
  27130. * This file is part of PHPUnit.
  27131. *
  27132. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  27133. *
  27134. * For the full copyright and license information, please view the LICENSE
  27135. * file that was distributed with this source code.
  27136. */
  27137. namespace PHPUnit\Util;
  27138. use PHPUnit\Framework\Assert;
  27139. use PHPUnit\Framework\CodeCoverageException;
  27140. use PHPUnit\Framework\InvalidCoversTargetException;
  27141. use PHPUnit\Framework\SelfDescribing;
  27142. use PHPUnit\Framework\TestCase;
  27143. use PHPUnit\Framework\Warning;
  27144. use PHPUnit\Runner\Version;
  27145. use PHPUnit\Util\Annotation\Registry;
  27146. use PHPUnit\SebastianBergmann\CodeUnit\CodeUnitCollection;
  27147. use PHPUnit\SebastianBergmann\CodeUnit\InvalidCodeUnitException;
  27148. use PHPUnit\SebastianBergmann\CodeUnit\Mapper;
  27149. use PHPUnit\SebastianBergmann\Environment\OperatingSystem;
  27150. /**
  27151. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  27152. */
  27153. final class Test
  27154. {
  27155. /**
  27156. * @var int
  27157. */
  27158. public const UNKNOWN = -1;
  27159. /**
  27160. * @var int
  27161. */
  27162. public const SMALL = 0;
  27163. /**
  27164. * @var int
  27165. */
  27166. public const MEDIUM = 1;
  27167. /**
  27168. * @var int
  27169. */
  27170. public const LARGE = 2;
  27171. /**
  27172. * @var array
  27173. */
  27174. private static $hookMethods = [];
  27175. /**
  27176. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  27177. */
  27178. public static function describe(\PHPUnit\Framework\Test $test) : array
  27179. {
  27180. if ($test instanceof \PHPUnit\Framework\TestCase) {
  27181. return [\get_class($test), $test->getName()];
  27182. }
  27183. if ($test instanceof \PHPUnit\Framework\SelfDescribing) {
  27184. return ['', $test->toString()];
  27185. }
  27186. return ['', \get_class($test)];
  27187. }
  27188. public static function describeAsString(\PHPUnit\Framework\Test $test) : string
  27189. {
  27190. if ($test instanceof \PHPUnit\Framework\SelfDescribing) {
  27191. return $test->toString();
  27192. }
  27193. return \get_class($test);
  27194. }
  27195. /**
  27196. * @throws CodeCoverageException
  27197. *
  27198. * @return array|bool
  27199. * @psalm-param class-string $className
  27200. */
  27201. public static function getLinesToBeCovered(string $className, string $methodName)
  27202. {
  27203. $annotations = self::parseTestMethodAnnotations($className, $methodName);
  27204. if (!self::shouldCoversAnnotationBeUsed($annotations)) {
  27205. return \false;
  27206. }
  27207. return self::getLinesToBeCoveredOrUsed($className, $methodName, 'covers');
  27208. }
  27209. /**
  27210. * Returns lines of code specified with the @uses annotation.
  27211. *
  27212. * @throws CodeCoverageException
  27213. * @psalm-param class-string $className
  27214. */
  27215. public static function getLinesToBeUsed(string $className, string $methodName) : array
  27216. {
  27217. return self::getLinesToBeCoveredOrUsed($className, $methodName, 'uses');
  27218. }
  27219. public static function requiresCodeCoverageDataCollection(\PHPUnit\Framework\TestCase $test) : bool
  27220. {
  27221. $annotations = $test->getAnnotations();
  27222. // If there is no @covers annotation but a @coversNothing annotation on
  27223. // the test method then code coverage data does not need to be collected
  27224. if (isset($annotations['method']['coversNothing'])) {
  27225. return \false;
  27226. }
  27227. // If there is at least one @covers annotation then
  27228. // code coverage data needs to be collected
  27229. if (isset($annotations['method']['covers'])) {
  27230. return \true;
  27231. }
  27232. // If there is no @covers annotation but a @coversNothing annotation
  27233. // then code coverage data does not need to be collected
  27234. if (isset($annotations['class']['coversNothing'])) {
  27235. return \false;
  27236. }
  27237. // If there is no @coversNothing annotation then
  27238. // code coverage data may be collected
  27239. return \true;
  27240. }
  27241. /**
  27242. * @throws Exception
  27243. * @psalm-param class-string $className
  27244. */
  27245. public static function getRequirements(string $className, string $methodName) : array
  27246. {
  27247. return self::mergeArraysRecursively(\PHPUnit\Util\Annotation\Registry::getInstance()->forClassName($className)->requirements(), \PHPUnit\Util\Annotation\Registry::getInstance()->forMethod($className, $methodName)->requirements());
  27248. }
  27249. /**
  27250. * Returns the missing requirements for a test.
  27251. *
  27252. * @throws Exception
  27253. * @throws Warning
  27254. * @psalm-param class-string $className
  27255. */
  27256. public static function getMissingRequirements(string $className, string $methodName) : array
  27257. {
  27258. $required = static::getRequirements($className, $methodName);
  27259. $missing = [];
  27260. $hint = null;
  27261. if (!empty($required['PHP'])) {
  27262. $operator = new \PHPUnit\Util\VersionComparisonOperator(empty($required['PHP']['operator']) ? '>=' : $required['PHP']['operator']);
  27263. if (!\version_compare(\PHP_VERSION, $required['PHP']['version'], $operator->asString())) {
  27264. $missing[] = \sprintf('PHP %s %s is required.', $operator->asString(), $required['PHP']['version']);
  27265. $hint = 'PHP';
  27266. }
  27267. } elseif (!empty($required['PHP_constraint'])) {
  27268. $version = new \PHPUnit\PharIo\Version\Version(self::sanitizeVersionNumber(\PHP_VERSION));
  27269. if (!$required['PHP_constraint']['constraint']->complies($version)) {
  27270. $missing[] = \sprintf('PHP version does not match the required constraint %s.', $required['PHP_constraint']['constraint']->asString());
  27271. $hint = 'PHP_constraint';
  27272. }
  27273. }
  27274. if (!empty($required['PHPUnit'])) {
  27275. $phpunitVersion = \PHPUnit\Runner\Version::id();
  27276. $operator = new \PHPUnit\Util\VersionComparisonOperator(empty($required['PHPUnit']['operator']) ? '>=' : $required['PHPUnit']['operator']);
  27277. if (!\version_compare($phpunitVersion, $required['PHPUnit']['version'], $operator->asString())) {
  27278. $missing[] = \sprintf('PHPUnit %s %s is required.', $operator->asString(), $required['PHPUnit']['version']);
  27279. $hint = $hint ?? 'PHPUnit';
  27280. }
  27281. } elseif (!empty($required['PHPUnit_constraint'])) {
  27282. $phpunitVersion = new \PHPUnit\PharIo\Version\Version(self::sanitizeVersionNumber(\PHPUnit\Runner\Version::id()));
  27283. if (!$required['PHPUnit_constraint']['constraint']->complies($phpunitVersion)) {
  27284. $missing[] = \sprintf('PHPUnit version does not match the required constraint %s.', $required['PHPUnit_constraint']['constraint']->asString());
  27285. $hint = $hint ?? 'PHPUnit_constraint';
  27286. }
  27287. }
  27288. if (!empty($required['OSFAMILY']) && $required['OSFAMILY'] !== (new \PHPUnit\SebastianBergmann\Environment\OperatingSystem())->getFamily()) {
  27289. $missing[] = \sprintf('Operating system %s is required.', $required['OSFAMILY']);
  27290. $hint = $hint ?? 'OSFAMILY';
  27291. }
  27292. if (!empty($required['OS'])) {
  27293. $requiredOsPattern = \sprintf('/%s/i', \addcslashes($required['OS'], '/'));
  27294. if (!\preg_match($requiredOsPattern, \PHP_OS)) {
  27295. $missing[] = \sprintf('Operating system matching %s is required.', $requiredOsPattern);
  27296. $hint = $hint ?? 'OS';
  27297. }
  27298. }
  27299. if (!empty($required['functions'])) {
  27300. foreach ($required['functions'] as $function) {
  27301. $pieces = \explode('::', $function);
  27302. if (\count($pieces) === 2 && \class_exists($pieces[0]) && \method_exists($pieces[0], $pieces[1])) {
  27303. continue;
  27304. }
  27305. if (\function_exists($function)) {
  27306. continue;
  27307. }
  27308. $missing[] = \sprintf('Function %s is required.', $function);
  27309. $hint = $hint ?? 'function_' . $function;
  27310. }
  27311. }
  27312. if (!empty($required['setting'])) {
  27313. foreach ($required['setting'] as $setting => $value) {
  27314. if (\ini_get($setting) !== $value) {
  27315. $missing[] = \sprintf('Setting "%s" must be "%s".', $setting, $value);
  27316. $hint = $hint ?? '__SETTING_' . $setting;
  27317. }
  27318. }
  27319. }
  27320. if (!empty($required['extensions'])) {
  27321. foreach ($required['extensions'] as $extension) {
  27322. if (isset($required['extension_versions'][$extension])) {
  27323. continue;
  27324. }
  27325. if (!\extension_loaded($extension)) {
  27326. $missing[] = \sprintf('Extension %s is required.', $extension);
  27327. $hint = $hint ?? 'extension_' . $extension;
  27328. }
  27329. }
  27330. }
  27331. if (!empty($required['extension_versions'])) {
  27332. foreach ($required['extension_versions'] as $extension => $req) {
  27333. $actualVersion = \phpversion($extension);
  27334. $operator = new \PHPUnit\Util\VersionComparisonOperator(empty($req['operator']) ? '>=' : $req['operator']);
  27335. if ($actualVersion === \false || !\version_compare($actualVersion, $req['version'], $operator->asString())) {
  27336. $missing[] = \sprintf('Extension %s %s %s is required.', $extension, $operator->asString(), $req['version']);
  27337. $hint = $hint ?? 'extension_' . $extension;
  27338. }
  27339. }
  27340. }
  27341. if ($hint && isset($required['__OFFSET'])) {
  27342. \array_unshift($missing, '__OFFSET_FILE=' . $required['__OFFSET']['__FILE']);
  27343. \array_unshift($missing, '__OFFSET_LINE=' . ($required['__OFFSET'][$hint] ?? 1));
  27344. }
  27345. return $missing;
  27346. }
  27347. /**
  27348. * Returns the provided data for a method.
  27349. *
  27350. * @throws Exception
  27351. * @psalm-param class-string $className
  27352. */
  27353. public static function getProvidedData(string $className, string $methodName) : ?array
  27354. {
  27355. return \PHPUnit\Util\Annotation\Registry::getInstance()->forMethod($className, $methodName)->getProvidedData();
  27356. }
  27357. /**
  27358. * @psalm-param class-string $className
  27359. */
  27360. public static function parseTestMethodAnnotations(string $className, ?string $methodName = '') : array
  27361. {
  27362. $registry = \PHPUnit\Util\Annotation\Registry::getInstance();
  27363. if ($methodName !== null) {
  27364. try {
  27365. return ['method' => $registry->forMethod($className, $methodName)->symbolAnnotations(), 'class' => $registry->forClassName($className)->symbolAnnotations()];
  27366. } catch (\PHPUnit\Util\Exception $methodNotFound) {
  27367. // ignored
  27368. }
  27369. }
  27370. return ['method' => null, 'class' => $registry->forClassName($className)->symbolAnnotations()];
  27371. }
  27372. /**
  27373. * @psalm-param class-string $className
  27374. */
  27375. public static function getInlineAnnotations(string $className, string $methodName) : array
  27376. {
  27377. return \PHPUnit\Util\Annotation\Registry::getInstance()->forMethod($className, $methodName)->getInlineAnnotations();
  27378. }
  27379. /** @psalm-param class-string $className */
  27380. public static function getBackupSettings(string $className, string $methodName) : array
  27381. {
  27382. return ['backupGlobals' => self::getBooleanAnnotationSetting($className, $methodName, 'backupGlobals'), 'backupStaticAttributes' => self::getBooleanAnnotationSetting($className, $methodName, 'backupStaticAttributes')];
  27383. }
  27384. /** @psalm-param class-string $className */
  27385. public static function getDependencies(string $className, string $methodName) : array
  27386. {
  27387. $annotations = self::parseTestMethodAnnotations($className, $methodName);
  27388. $dependencies = $annotations['class']['depends'] ?? [];
  27389. if (isset($annotations['method']['depends'])) {
  27390. $dependencies = \array_merge($dependencies, $annotations['method']['depends']);
  27391. }
  27392. return \array_unique($dependencies);
  27393. }
  27394. /** @psalm-param class-string $className */
  27395. public static function getGroups(string $className, ?string $methodName = '') : array
  27396. {
  27397. $annotations = self::parseTestMethodAnnotations($className, $methodName);
  27398. $groups = [];
  27399. if (isset($annotations['method']['author'])) {
  27400. $groups[] = $annotations['method']['author'];
  27401. } elseif (isset($annotations['class']['author'])) {
  27402. $groups[] = $annotations['class']['author'];
  27403. }
  27404. if (isset($annotations['class']['group'])) {
  27405. $groups[] = $annotations['class']['group'];
  27406. }
  27407. if (isset($annotations['method']['group'])) {
  27408. $groups[] = $annotations['method']['group'];
  27409. }
  27410. if (isset($annotations['class']['ticket'])) {
  27411. $groups[] = $annotations['class']['ticket'];
  27412. }
  27413. if (isset($annotations['method']['ticket'])) {
  27414. $groups[] = $annotations['method']['ticket'];
  27415. }
  27416. foreach (['method', 'class'] as $element) {
  27417. foreach (['small', 'medium', 'large'] as $size) {
  27418. if (isset($annotations[$element][$size])) {
  27419. $groups[] = [$size];
  27420. break 2;
  27421. }
  27422. }
  27423. }
  27424. return \array_unique(\array_merge([], ...$groups));
  27425. }
  27426. /** @psalm-param class-string $className */
  27427. public static function getSize(string $className, ?string $methodName) : int
  27428. {
  27429. $groups = \array_flip(self::getGroups($className, $methodName));
  27430. if (isset($groups['large'])) {
  27431. return self::LARGE;
  27432. }
  27433. if (isset($groups['medium'])) {
  27434. return self::MEDIUM;
  27435. }
  27436. if (isset($groups['small'])) {
  27437. return self::SMALL;
  27438. }
  27439. return self::UNKNOWN;
  27440. }
  27441. /** @psalm-param class-string $className */
  27442. public static function getProcessIsolationSettings(string $className, string $methodName) : bool
  27443. {
  27444. $annotations = self::parseTestMethodAnnotations($className, $methodName);
  27445. return isset($annotations['class']['runTestsInSeparateProcesses']) || isset($annotations['method']['runInSeparateProcess']);
  27446. }
  27447. /** @psalm-param class-string $className */
  27448. public static function getClassProcessIsolationSettings(string $className, string $methodName) : bool
  27449. {
  27450. $annotations = self::parseTestMethodAnnotations($className, $methodName);
  27451. return isset($annotations['class']['runClassInSeparateProcess']);
  27452. }
  27453. /** @psalm-param class-string $className */
  27454. public static function getPreserveGlobalStateSettings(string $className, string $methodName) : ?bool
  27455. {
  27456. return self::getBooleanAnnotationSetting($className, $methodName, 'preserveGlobalState');
  27457. }
  27458. /** @psalm-param class-string $className */
  27459. public static function getHookMethods(string $className) : array
  27460. {
  27461. if (!\class_exists($className, \false)) {
  27462. return self::emptyHookMethodsArray();
  27463. }
  27464. if (!isset(self::$hookMethods[$className])) {
  27465. self::$hookMethods[$className] = self::emptyHookMethodsArray();
  27466. try {
  27467. foreach ((new \ReflectionClass($className))->getMethods() as $method) {
  27468. if ($method->getDeclaringClass()->getName() === \PHPUnit\Framework\Assert::class) {
  27469. continue;
  27470. }
  27471. if ($method->getDeclaringClass()->getName() === \PHPUnit\Framework\TestCase::class) {
  27472. continue;
  27473. }
  27474. $docBlock = \PHPUnit\Util\Annotation\Registry::getInstance()->forMethod($className, $method->getName());
  27475. if ($method->isStatic()) {
  27476. if ($docBlock->isHookToBeExecutedBeforeClass()) {
  27477. \array_unshift(self::$hookMethods[$className]['beforeClass'], $method->getName());
  27478. }
  27479. if ($docBlock->isHookToBeExecutedAfterClass()) {
  27480. self::$hookMethods[$className]['afterClass'][] = $method->getName();
  27481. }
  27482. }
  27483. if ($docBlock->isToBeExecutedBeforeTest()) {
  27484. \array_unshift(self::$hookMethods[$className]['before'], $method->getName());
  27485. }
  27486. if ($docBlock->isToBeExecutedAsPreCondition()) {
  27487. \array_unshift(self::$hookMethods[$className]['preCondition'], $method->getName());
  27488. }
  27489. if ($docBlock->isToBeExecutedAsPostCondition()) {
  27490. self::$hookMethods[$className]['postCondition'][] = $method->getName();
  27491. }
  27492. if ($docBlock->isToBeExecutedAfterTest()) {
  27493. self::$hookMethods[$className]['after'][] = $method->getName();
  27494. }
  27495. }
  27496. } catch (\ReflectionException $e) {
  27497. }
  27498. }
  27499. return self::$hookMethods[$className];
  27500. }
  27501. public static function isTestMethod(\ReflectionMethod $method) : bool
  27502. {
  27503. if (\strpos($method->getName(), 'test') === 0) {
  27504. return \true;
  27505. }
  27506. return \array_key_exists('test', \PHPUnit\Util\Annotation\Registry::getInstance()->forMethod($method->getDeclaringClass()->getName(), $method->getName())->symbolAnnotations());
  27507. }
  27508. /**
  27509. * @throws CodeCoverageException
  27510. * @psalm-param class-string $className
  27511. */
  27512. private static function getLinesToBeCoveredOrUsed(string $className, string $methodName, string $mode) : array
  27513. {
  27514. $annotations = self::parseTestMethodAnnotations($className, $methodName);
  27515. $classShortcut = null;
  27516. if (!empty($annotations['class'][$mode . 'DefaultClass'])) {
  27517. if (\count($annotations['class'][$mode . 'DefaultClass']) > 1) {
  27518. throw new \PHPUnit\Framework\CodeCoverageException(\sprintf('More than one @%sClass annotation in class or interface "%s".', $mode, $className));
  27519. }
  27520. $classShortcut = $annotations['class'][$mode . 'DefaultClass'][0];
  27521. }
  27522. $list = $annotations['class'][$mode] ?? [];
  27523. if (isset($annotations['method'][$mode])) {
  27524. $list = \array_merge($list, $annotations['method'][$mode]);
  27525. }
  27526. $codeUnits = \PHPUnit\SebastianBergmann\CodeUnit\CodeUnitCollection::fromArray([]);
  27527. $mapper = new \PHPUnit\SebastianBergmann\CodeUnit\Mapper();
  27528. foreach (\array_unique($list) as $element) {
  27529. if ($classShortcut && \strncmp($element, '::', 2) === 0) {
  27530. $element = $classShortcut . $element;
  27531. }
  27532. $element = \preg_replace('/[\\s()]+$/', '', $element);
  27533. $element = \explode(' ', $element);
  27534. $element = $element[0];
  27535. if ($mode === 'covers' && \interface_exists($element)) {
  27536. throw new \PHPUnit\Framework\InvalidCoversTargetException(\sprintf('Trying to @cover interface "%s".', $element));
  27537. }
  27538. try {
  27539. $codeUnits = $codeUnits->mergeWith($mapper->stringToCodeUnits($element));
  27540. } catch (\PHPUnit\SebastianBergmann\CodeUnit\InvalidCodeUnitException $e) {
  27541. throw new \PHPUnit\Framework\InvalidCoversTargetException(\sprintf('"@%s %s" is invalid', $mode, $element), (int) $e->getCode(), $e);
  27542. }
  27543. }
  27544. return $mapper->codeUnitsToSourceLines($codeUnits);
  27545. }
  27546. private static function emptyHookMethodsArray() : array
  27547. {
  27548. return ['beforeClass' => ['setUpBeforeClass'], 'before' => ['setUp'], 'preCondition' => ['assertPreConditions'], 'postCondition' => ['assertPostConditions'], 'after' => ['tearDown'], 'afterClass' => ['tearDownAfterClass']];
  27549. }
  27550. /** @psalm-param class-string $className */
  27551. private static function getBooleanAnnotationSetting(string $className, ?string $methodName, string $settingName) : ?bool
  27552. {
  27553. $annotations = self::parseTestMethodAnnotations($className, $methodName);
  27554. if (isset($annotations['method'][$settingName])) {
  27555. if ($annotations['method'][$settingName][0] === 'enabled') {
  27556. return \true;
  27557. }
  27558. if ($annotations['method'][$settingName][0] === 'disabled') {
  27559. return \false;
  27560. }
  27561. }
  27562. if (isset($annotations['class'][$settingName])) {
  27563. if ($annotations['class'][$settingName][0] === 'enabled') {
  27564. return \true;
  27565. }
  27566. if ($annotations['class'][$settingName][0] === 'disabled') {
  27567. return \false;
  27568. }
  27569. }
  27570. return null;
  27571. }
  27572. /**
  27573. * Trims any extensions from version string that follows after
  27574. * the <major>.<minor>[.<patch>] format
  27575. */
  27576. private static function sanitizeVersionNumber(string $version)
  27577. {
  27578. return \preg_replace('/^(\\d+\\.\\d+(?:.\\d+)?).*$/', '$1', $version);
  27579. }
  27580. private static function shouldCoversAnnotationBeUsed(array $annotations) : bool
  27581. {
  27582. if (isset($annotations['method']['coversNothing'])) {
  27583. return \false;
  27584. }
  27585. if (isset($annotations['method']['covers'])) {
  27586. return \true;
  27587. }
  27588. if (isset($annotations['class']['coversNothing'])) {
  27589. return \false;
  27590. }
  27591. return \true;
  27592. }
  27593. /**
  27594. * Merge two arrays together.
  27595. *
  27596. * If an integer key exists in both arrays and preserveNumericKeys is false, the value
  27597. * from the second array will be appended to the first array. If both values are arrays, they
  27598. * are merged together, else the value of the second array overwrites the one of the first array.
  27599. *
  27600. * This implementation is copied from https://github.com/zendframework/zend-stdlib/blob/76b653c5e99b40eccf5966e3122c90615134ae46/src/ArrayUtils.php
  27601. *
  27602. * Zend Framework (http://framework.zend.com/)
  27603. *
  27604. * @link http://github.com/zendframework/zf2 for the canonical source repository
  27605. *
  27606. * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
  27607. * @license http://framework.zend.com/license/new-bsd New BSD License
  27608. */
  27609. private static function mergeArraysRecursively(array $a, array $b) : array
  27610. {
  27611. foreach ($b as $key => $value) {
  27612. if (\array_key_exists($key, $a)) {
  27613. if (\is_int($key)) {
  27614. $a[] = $value;
  27615. } elseif (\is_array($value) && \is_array($a[$key])) {
  27616. $a[$key] = self::mergeArraysRecursively($a[$key], $value);
  27617. } else {
  27618. $a[$key] = $value;
  27619. }
  27620. } else {
  27621. $a[$key] = $value;
  27622. }
  27623. }
  27624. return $a;
  27625. }
  27626. }
  27627. <?php
  27628. declare (strict_types=1);
  27629. /*
  27630. * This file is part of PHPUnit.
  27631. *
  27632. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  27633. *
  27634. * For the full copyright and license information, please view the LICENSE
  27635. * file that was distributed with this source code.
  27636. */
  27637. namespace PHPUnit\Util;
  27638. use PHPUnit\Framework\Exception;
  27639. /**
  27640. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  27641. */
  27642. final class FileLoader
  27643. {
  27644. /**
  27645. * Checks if a PHP sourcecode file is readable. The sourcecode file is loaded through the load() method.
  27646. *
  27647. * As a fallback, PHP looks in the directory of the file executing the stream_resolve_include_path function.
  27648. * We do not want to load the Test.php file here, so skip it if it found that.
  27649. * PHP prioritizes the include_path setting, so if the current directory is in there, it will first look in the
  27650. * current working directory.
  27651. *
  27652. * @throws Exception
  27653. */
  27654. public static function checkAndLoad(string $filename) : string
  27655. {
  27656. $includePathFilename = \stream_resolve_include_path($filename);
  27657. $localFile = __DIR__ . \DIRECTORY_SEPARATOR . $filename;
  27658. if (!$includePathFilename || $includePathFilename === $localFile || !self::isReadable($includePathFilename)) {
  27659. throw new \PHPUnit\Framework\Exception(\sprintf('Cannot open file "%s".' . "\n", $filename));
  27660. }
  27661. self::load($includePathFilename);
  27662. return $includePathFilename;
  27663. }
  27664. /**
  27665. * Loads a PHP sourcefile.
  27666. */
  27667. public static function load(string $filename) : void
  27668. {
  27669. $oldVariableNames = \array_keys(\get_defined_vars());
  27670. include_once $filename;
  27671. $newVariables = \get_defined_vars();
  27672. foreach (\array_diff(\array_keys($newVariables), $oldVariableNames) as $variableName) {
  27673. if ($variableName !== 'oldVariableNames') {
  27674. $GLOBALS[$variableName] = $newVariables[$variableName];
  27675. }
  27676. }
  27677. }
  27678. /**
  27679. * @see https://github.com/sebastianbergmann/phpunit/pull/2751
  27680. */
  27681. private static function isReadable(string $filename) : bool
  27682. {
  27683. return @\fopen($filename, 'r') !== \false;
  27684. }
  27685. }
  27686. <?php
  27687. declare (strict_types=1);
  27688. /*
  27689. * This file is part of PHPUnit.
  27690. *
  27691. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  27692. *
  27693. * For the full copyright and license information, please view the LICENSE
  27694. * file that was distributed with this source code.
  27695. */
  27696. namespace PHPUnit\Util;
  27697. /**
  27698. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  27699. */
  27700. final class Getopt
  27701. {
  27702. /**
  27703. * @throws Exception
  27704. */
  27705. public static function getopt(array $args, string $short_options, array $long_options = null) : array
  27706. {
  27707. if (empty($args)) {
  27708. return [[], []];
  27709. }
  27710. $opts = [];
  27711. $non_opts = [];
  27712. if ($long_options) {
  27713. \sort($long_options);
  27714. }
  27715. if (isset($args[0][0]) && $args[0][0] !== '-') {
  27716. \array_shift($args);
  27717. }
  27718. \reset($args);
  27719. $args = \array_map('trim', $args);
  27720. /* @noinspection ComparisonOperandsOrderInspection */
  27721. while (\false !== ($arg = \current($args))) {
  27722. $i = \key($args);
  27723. \next($args);
  27724. if ($arg === '') {
  27725. continue;
  27726. }
  27727. if ($arg === '--') {
  27728. $non_opts = \array_merge($non_opts, \array_slice($args, $i + 1));
  27729. break;
  27730. }
  27731. if ($arg[0] !== '-' || \strlen($arg) > 1 && $arg[1] === '-' && !$long_options) {
  27732. $non_opts[] = $args[$i];
  27733. continue;
  27734. }
  27735. if (\strlen($arg) > 1 && $arg[1] === '-') {
  27736. self::parseLongOption(\substr($arg, 2), $long_options, $opts, $args);
  27737. } else {
  27738. self::parseShortOption(\substr($arg, 1), $short_options, $opts, $args);
  27739. }
  27740. }
  27741. return [$opts, $non_opts];
  27742. }
  27743. /**
  27744. * @throws Exception
  27745. */
  27746. private static function parseShortOption(string $arg, string $short_options, array &$opts, array &$args) : void
  27747. {
  27748. $argLen = \strlen($arg);
  27749. for ($i = 0; $i < $argLen; $i++) {
  27750. $opt = $arg[$i];
  27751. $opt_arg = null;
  27752. if ($arg[$i] === ':' || ($spec = \strstr($short_options, $opt)) === \false) {
  27753. throw new \PHPUnit\Util\Exception("unrecognized option -- {$opt}");
  27754. }
  27755. if (\strlen($spec) > 1 && $spec[1] === ':') {
  27756. if ($i + 1 < $argLen) {
  27757. $opts[] = [$opt, \substr($arg, $i + 1)];
  27758. break;
  27759. }
  27760. if (!(\strlen($spec) > 2 && $spec[2] === ':')) {
  27761. /* @noinspection ComparisonOperandsOrderInspection */
  27762. if (\false === ($opt_arg = \current($args))) {
  27763. throw new \PHPUnit\Util\Exception("option requires an argument -- {$opt}");
  27764. }
  27765. \next($args);
  27766. }
  27767. }
  27768. $opts[] = [$opt, $opt_arg];
  27769. }
  27770. }
  27771. /**
  27772. * @throws Exception
  27773. */
  27774. private static function parseLongOption(string $arg, array $long_options, array &$opts, array &$args) : void
  27775. {
  27776. $count = \count($long_options);
  27777. $list = \explode('=', $arg);
  27778. $opt = $list[0];
  27779. $opt_arg = null;
  27780. if (\count($list) > 1) {
  27781. $opt_arg = $list[1];
  27782. }
  27783. $opt_len = \strlen($opt);
  27784. foreach ($long_options as $i => $long_opt) {
  27785. $opt_start = \substr($long_opt, 0, $opt_len);
  27786. if ($opt_start !== $opt) {
  27787. continue;
  27788. }
  27789. $opt_rest = \substr($long_opt, $opt_len);
  27790. if ($opt_rest !== '' && $i + 1 < $count && $opt[0] !== '=' && \strpos($long_options[$i + 1], $opt) === 0) {
  27791. throw new \PHPUnit\Util\Exception("option --{$opt} is ambiguous");
  27792. }
  27793. if (\substr($long_opt, -1) === '=') {
  27794. /* @noinspection StrlenInEmptyStringCheckContextInspection */
  27795. if (\substr($long_opt, -2) !== '==' && !\strlen((string) $opt_arg)) {
  27796. /* @noinspection ComparisonOperandsOrderInspection */
  27797. if (\false === ($opt_arg = \current($args))) {
  27798. throw new \PHPUnit\Util\Exception("option --{$opt} requires an argument");
  27799. }
  27800. \next($args);
  27801. }
  27802. } elseif ($opt_arg) {
  27803. throw new \PHPUnit\Util\Exception("option --{$opt} doesn't allow an argument");
  27804. }
  27805. $full_option = '--' . \preg_replace('/={1,2}$/', '', $long_opt);
  27806. $opts[] = [$full_option, $opt_arg];
  27807. return;
  27808. }
  27809. throw new \PHPUnit\Util\Exception("unrecognized option --{$opt}");
  27810. }
  27811. }
  27812. <?php
  27813. declare (strict_types=1);
  27814. /*
  27815. * This file is part of PHPUnit.
  27816. *
  27817. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  27818. *
  27819. * For the full copyright and license information, please view the LICENSE
  27820. * file that was distributed with this source code.
  27821. */
  27822. namespace PHPUnit\Util;
  27823. use PHPUnit\Framework\TestCase;
  27824. use PHPUnit\Framework\TestSuite;
  27825. use PHPUnit\Runner\PhptTestCase;
  27826. /**
  27827. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  27828. */
  27829. final class XmlTestListRenderer
  27830. {
  27831. /**
  27832. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  27833. */
  27834. public function render(\PHPUnit\Framework\TestSuite $suite) : string
  27835. {
  27836. $writer = new \XMLWriter();
  27837. $writer->openMemory();
  27838. $writer->setIndent(\true);
  27839. $writer->startDocument();
  27840. $writer->startElement('tests');
  27841. $currentTestCase = null;
  27842. foreach (new \RecursiveIteratorIterator($suite->getIterator()) as $test) {
  27843. if ($test instanceof \PHPUnit\Framework\TestCase) {
  27844. if (\get_class($test) !== $currentTestCase) {
  27845. if ($currentTestCase !== null) {
  27846. $writer->endElement();
  27847. }
  27848. $writer->startElement('testCaseClass');
  27849. $writer->writeAttribute('name', \get_class($test));
  27850. $currentTestCase = \get_class($test);
  27851. }
  27852. $writer->startElement('testCaseMethod');
  27853. $writer->writeAttribute('name', $test->getName(\false));
  27854. $writer->writeAttribute('groups', \implode(',', $test->getGroups()));
  27855. if (!empty($test->getDataSetAsString(\false))) {
  27856. $writer->writeAttribute('dataSet', \str_replace(' with data set ', '', $test->getDataSetAsString(\false)));
  27857. }
  27858. $writer->endElement();
  27859. } elseif ($test instanceof \PHPUnit\Runner\PhptTestCase) {
  27860. if ($currentTestCase !== null) {
  27861. $writer->endElement();
  27862. $currentTestCase = null;
  27863. }
  27864. $writer->startElement('phptFile');
  27865. $writer->writeAttribute('path', $test->getName());
  27866. $writer->endElement();
  27867. }
  27868. }
  27869. if ($currentTestCase !== null) {
  27870. $writer->endElement();
  27871. }
  27872. $writer->endElement();
  27873. return $writer->outputMemory();
  27874. }
  27875. }
  27876. <?php
  27877. declare (strict_types=1);
  27878. /*
  27879. * This file is part of PHPUnit.
  27880. *
  27881. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  27882. *
  27883. * For the full copyright and license information, please view the LICENSE
  27884. * file that was distributed with this source code.
  27885. */
  27886. namespace PHPUnit\Util;
  27887. use PHPUnit\TextUI\Configuration\Filter as FilterConfiguration;
  27888. /**
  27889. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  27890. */
  27891. final class XdebugFilterScriptGenerator
  27892. {
  27893. public function generate(\PHPUnit\TextUI\Configuration\Filter $filter) : string
  27894. {
  27895. $files = \array_map(static function ($item) {
  27896. return \sprintf(" '%s'", $item);
  27897. }, $this->getWhitelistItems($filter));
  27898. $files = \implode(",\n", $files);
  27899. return <<<EOF
  27900. <?php declare(strict_types=1);
  27901. if (!\\function_exists('xdebug_set_filter')) {
  27902. return;
  27903. }
  27904. \\xdebug_set_filter(
  27905. \\XDEBUG_FILTER_CODE_COVERAGE,
  27906. \\XDEBUG_PATH_WHITELIST,
  27907. [
  27908. {$files}
  27909. ]
  27910. );
  27911. EOF;
  27912. }
  27913. private function getWhitelistItems(\PHPUnit\TextUI\Configuration\Filter $filter) : array
  27914. {
  27915. $files = [];
  27916. foreach ($filter->directories() as $directory) {
  27917. $path = \realpath($directory->path());
  27918. if (\is_string($path)) {
  27919. $files[] = \sprintf(\addslashes('%s' . \DIRECTORY_SEPARATOR), $path);
  27920. }
  27921. }
  27922. foreach ($filter->files() as $file) {
  27923. $files[] = $file->path();
  27924. }
  27925. return $files;
  27926. }
  27927. }
  27928. <?php
  27929. declare (strict_types=1);
  27930. /*
  27931. * This file is part of PHPUnit.
  27932. *
  27933. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  27934. *
  27935. * For the full copyright and license information, please view the LICENSE
  27936. * file that was distributed with this source code.
  27937. */
  27938. namespace PHPUnit\Util;
  27939. /**
  27940. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  27941. */
  27942. final class Filesystem
  27943. {
  27944. /**
  27945. * Maps class names to source file names:
  27946. * - PEAR CS: Foo_Bar_Baz -> Foo/Bar/Baz.php
  27947. * - Namespace: Foo\Bar\Baz -> Foo/Bar/Baz.php
  27948. */
  27949. public static function classNameToFilename(string $className) : string
  27950. {
  27951. return \str_replace(['_', '\\'], \DIRECTORY_SEPARATOR, $className) . '.php';
  27952. }
  27953. public static function createDirectory(string $directory) : bool
  27954. {
  27955. return !(!\is_dir($directory) && !@\mkdir($directory, 0777, \true) && !\is_dir($directory));
  27956. }
  27957. }
  27958. <?php
  27959. declare (strict_types=1);
  27960. /*
  27961. * This file is part of PHPUnit.
  27962. *
  27963. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  27964. *
  27965. * For the full copyright and license information, please view the LICENSE
  27966. * file that was distributed with this source code.
  27967. */
  27968. namespace PHPUnit\Util;
  27969. /**
  27970. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  27971. * @psalm-immutable
  27972. */
  27973. final class VersionComparisonOperator
  27974. {
  27975. /**
  27976. * @psalm-var '<'|'lt'|'<='|'le'|'>'|'gt'|'>='|'ge'|'=='|'='|'eq'|'!='|'<>'|'ne'
  27977. */
  27978. private $operator;
  27979. public function __construct(string $operator)
  27980. {
  27981. $this->ensureOperatorIsValid($operator);
  27982. $this->operator = $operator;
  27983. }
  27984. /**
  27985. * @return '<'|'lt'|'<='|'le'|'>'|'gt'|'>='|'ge'|'=='|'='|'eq'|'!='|'<>'|'ne'
  27986. */
  27987. public function asString() : string
  27988. {
  27989. return $this->operator;
  27990. }
  27991. /**
  27992. * @throws Exception
  27993. *
  27994. * @psalm-assert '<'|'lt'|'<='|'le'|'>'|'gt'|'>='|'ge'|'=='|'='|'eq'|'!='|'<>'|'ne' $operator
  27995. */
  27996. private function ensureOperatorIsValid(string $operator) : void
  27997. {
  27998. if (!\in_array($operator, ['<', 'lt', '<=', 'le', '>', 'gt', '>=', 'ge', '==', '=', 'eq', '!=', '<>', 'ne'])) {
  27999. throw new \PHPUnit\Util\Exception(\sprintf('"%s" is not a valid version_compare() operator', $operator));
  28000. }
  28001. }
  28002. }
  28003. <?php
  28004. declare (strict_types=1);
  28005. /*
  28006. * This file is part of PHPUnit.
  28007. *
  28008. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  28009. *
  28010. * For the full copyright and license information, please view the LICENSE
  28011. * file that was distributed with this source code.
  28012. */
  28013. namespace PHPUnit\Util;
  28014. /**
  28015. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  28016. */
  28017. final class Color
  28018. {
  28019. /**
  28020. * @var array<string,string>
  28021. */
  28022. private const WHITESPACE_MAP = [' ' => '·', "\t" => '⇥'];
  28023. /**
  28024. * @var array<string,string>
  28025. */
  28026. private const WHITESPACE_EOL_MAP = [' ' => '·', "\t" => '⇥', "\n" => '↵', "\r" => '⟵'];
  28027. /**
  28028. * @var array<string,string>
  28029. */
  28030. private static $ansiCodes = ['reset' => '0', 'bold' => '1', 'dim' => '2', 'dim-reset' => '22', 'underlined' => '4', 'fg-default' => '39', 'fg-black' => '30', 'fg-red' => '31', 'fg-green' => '32', 'fg-yellow' => '33', 'fg-blue' => '34', 'fg-magenta' => '35', 'fg-cyan' => '36', 'fg-white' => '37', 'bg-default' => '49', 'bg-black' => '40', 'bg-red' => '41', 'bg-green' => '42', 'bg-yellow' => '43', 'bg-blue' => '44', 'bg-magenta' => '45', 'bg-cyan' => '46', 'bg-white' => '47'];
  28031. public static function colorize(string $color, string $buffer) : string
  28032. {
  28033. if (\trim($buffer) === '') {
  28034. return $buffer;
  28035. }
  28036. $codes = \array_map('\\trim', \explode(',', $color));
  28037. $styles = [];
  28038. foreach ($codes as $code) {
  28039. if (isset(self::$ansiCodes[$code])) {
  28040. $styles[] = self::$ansiCodes[$code] ?? '';
  28041. }
  28042. }
  28043. if (empty($styles)) {
  28044. return $buffer;
  28045. }
  28046. return self::optimizeColor(\sprintf("\33[%sm", \implode(';', $styles)) . $buffer . "\33[0m");
  28047. }
  28048. public static function colorizePath(string $path, ?string $prevPath = null, bool $colorizeFilename = \false) : string
  28049. {
  28050. if ($prevPath === null) {
  28051. $prevPath = '';
  28052. }
  28053. $path = \explode(\DIRECTORY_SEPARATOR, $path);
  28054. $prevPath = \explode(\DIRECTORY_SEPARATOR, $prevPath);
  28055. for ($i = 0; $i < \min(\count($path), \count($prevPath)); $i++) {
  28056. if ($path[$i] == $prevPath[$i]) {
  28057. $path[$i] = self::dim($path[$i]);
  28058. }
  28059. }
  28060. if ($colorizeFilename) {
  28061. $last = \count($path) - 1;
  28062. $path[$last] = \preg_replace_callback('/([\\-_\\.]+|phpt$)/', static function ($matches) {
  28063. return self::dim($matches[0]);
  28064. }, $path[$last]);
  28065. }
  28066. return self::optimizeColor(\implode(self::dim(\DIRECTORY_SEPARATOR), $path));
  28067. }
  28068. public static function dim(string $buffer) : string
  28069. {
  28070. if (\trim($buffer) === '') {
  28071. return $buffer;
  28072. }
  28073. return "\33[2m{$buffer}\33[22m";
  28074. }
  28075. public static function visualizeWhitespace(string $buffer, bool $visualizeEOL = \false) : string
  28076. {
  28077. $replaceMap = $visualizeEOL ? self::WHITESPACE_EOL_MAP : self::WHITESPACE_MAP;
  28078. return \preg_replace_callback('/\\s+/', static function ($matches) use($replaceMap) {
  28079. return self::dim(\strtr($matches[0], $replaceMap));
  28080. }, $buffer);
  28081. }
  28082. private static function optimizeColor(string $buffer) : string
  28083. {
  28084. $patterns = ["/\33\\[22m\33\\[2m/" => '', "/\33\\[([^m]*)m\33\\[([1-9][0-9;]*)m/" => "\33[\$1;\$2m", "/(\33\\[[^m]*m)+(\33\\[0m)/" => '$2'];
  28085. return \preg_replace(\array_keys($patterns), \array_values($patterns), $buffer);
  28086. }
  28087. }
  28088. <?php
  28089. declare (strict_types=1);
  28090. /*
  28091. * This file is part of PHPUnit.
  28092. *
  28093. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  28094. *
  28095. * For the full copyright and license information, please view the LICENSE
  28096. * file that was distributed with this source code.
  28097. */
  28098. namespace PHPUnit\Util;
  28099. use PHPUnit\Framework\TestCase;
  28100. use PHPUnit\Framework\TestSuite;
  28101. use PHPUnit\Runner\PhptTestCase;
  28102. /**
  28103. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  28104. */
  28105. final class TextTestListRenderer
  28106. {
  28107. /**
  28108. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  28109. */
  28110. public function render(\PHPUnit\Framework\TestSuite $suite) : string
  28111. {
  28112. $buffer = 'Available test(s):' . \PHP_EOL;
  28113. foreach (new \RecursiveIteratorIterator($suite->getIterator()) as $test) {
  28114. if ($test instanceof \PHPUnit\Framework\TestCase) {
  28115. $name = \sprintf('%s::%s', \get_class($test), \str_replace(' with data set ', '', $test->getName()));
  28116. } elseif ($test instanceof \PHPUnit\Runner\PhptTestCase) {
  28117. $name = $test->getName();
  28118. } else {
  28119. continue;
  28120. }
  28121. $buffer .= \sprintf(' - %s' . \PHP_EOL, $name);
  28122. }
  28123. return $buffer;
  28124. }
  28125. }
  28126. <?php
  28127. declare (strict_types=1);
  28128. /*
  28129. * This file is part of PHPUnit.
  28130. *
  28131. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  28132. *
  28133. * For the full copyright and license information, please view the LICENSE
  28134. * file that was distributed with this source code.
  28135. */
  28136. namespace PHPUnit\Util;
  28137. /**
  28138. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  28139. */
  28140. final class RegularExpression
  28141. {
  28142. /**
  28143. * @return false|int
  28144. */
  28145. public static function safeMatch(string $pattern, string $subject, ?array $matches = null, int $flags = 0, int $offset = 0)
  28146. {
  28147. return \PHPUnit\Util\ErrorHandler::invokeIgnoringWarnings(static function () use($pattern, $subject, $matches, $flags, $offset) {
  28148. return \preg_match($pattern, $subject, $matches, $flags, $offset);
  28149. });
  28150. }
  28151. }
  28152. <?php
  28153. declare (strict_types=1);
  28154. /*
  28155. * This file is part of PHPUnit.
  28156. *
  28157. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  28158. *
  28159. * For the full copyright and license information, please view the LICENSE
  28160. * file that was distributed with this source code.
  28161. */
  28162. namespace PHPUnit\Util;
  28163. use PHPUnit\Framework\Error\Deprecated;
  28164. use PHPUnit\Framework\Error\Error;
  28165. use PHPUnit\Framework\Error\Notice;
  28166. use PHPUnit\Framework\Error\Warning;
  28167. /**
  28168. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  28169. */
  28170. final class ErrorHandler
  28171. {
  28172. /**
  28173. * @var bool
  28174. */
  28175. private $convertDeprecationsToExceptions;
  28176. /**
  28177. * @var bool
  28178. */
  28179. private $convertErrorsToExceptions;
  28180. /**
  28181. * @var bool
  28182. */
  28183. private $convertNoticesToExceptions;
  28184. /**
  28185. * @var bool
  28186. */
  28187. private $convertWarningsToExceptions;
  28188. /**
  28189. * @var bool
  28190. */
  28191. private $registered = \false;
  28192. public static function invokeIgnoringWarnings(callable $callable)
  28193. {
  28194. \set_error_handler(static function ($errorNumber, $errorString) {
  28195. if ($errorNumber === \E_WARNING) {
  28196. return;
  28197. }
  28198. return \false;
  28199. });
  28200. $result = $callable();
  28201. \restore_error_handler();
  28202. return $result;
  28203. }
  28204. public function __construct(bool $convertDeprecationsToExceptions, bool $convertErrorsToExceptions, bool $convertNoticesToExceptions, bool $convertWarningsToExceptions)
  28205. {
  28206. $this->convertDeprecationsToExceptions = $convertDeprecationsToExceptions;
  28207. $this->convertErrorsToExceptions = $convertErrorsToExceptions;
  28208. $this->convertNoticesToExceptions = $convertNoticesToExceptions;
  28209. $this->convertWarningsToExceptions = $convertWarningsToExceptions;
  28210. }
  28211. public function __invoke(int $errorNumber, string $errorString, string $errorFile, int $errorLine) : bool
  28212. {
  28213. /*
  28214. * Do not raise an exception when the error suppression operator (@) was used.
  28215. *
  28216. * @see https://github.com/sebastianbergmann/phpunit/issues/3739
  28217. */
  28218. if (!($errorNumber & \error_reporting())) {
  28219. return \false;
  28220. }
  28221. switch ($errorNumber) {
  28222. case \E_NOTICE:
  28223. case \E_USER_NOTICE:
  28224. case \E_STRICT:
  28225. if (!$this->convertNoticesToExceptions) {
  28226. return \false;
  28227. }
  28228. throw new \PHPUnit\Framework\Error\Notice($errorString, $errorNumber, $errorFile, $errorLine);
  28229. case \E_WARNING:
  28230. case \E_USER_WARNING:
  28231. if (!$this->convertWarningsToExceptions) {
  28232. return \false;
  28233. }
  28234. throw new \PHPUnit\Framework\Error\Warning($errorString, $errorNumber, $errorFile, $errorLine);
  28235. case \E_DEPRECATED:
  28236. case \E_USER_DEPRECATED:
  28237. if (!$this->convertDeprecationsToExceptions) {
  28238. return \false;
  28239. }
  28240. throw new \PHPUnit\Framework\Error\Deprecated($errorString, $errorNumber, $errorFile, $errorLine);
  28241. default:
  28242. if (!$this->convertErrorsToExceptions) {
  28243. return \false;
  28244. }
  28245. throw new \PHPUnit\Framework\Error\Error($errorString, $errorNumber, $errorFile, $errorLine);
  28246. }
  28247. }
  28248. public function register() : void
  28249. {
  28250. if ($this->registered) {
  28251. return;
  28252. }
  28253. $oldErrorHandler = \set_error_handler($this);
  28254. if ($oldErrorHandler !== null) {
  28255. \restore_error_handler();
  28256. return;
  28257. }
  28258. $this->registered = \true;
  28259. }
  28260. public function unregister() : void
  28261. {
  28262. if (!$this->registered) {
  28263. return;
  28264. }
  28265. \restore_error_handler();
  28266. }
  28267. }
  28268. <?php
  28269. declare (strict_types=1);
  28270. /*
  28271. * This file is part of PHPUnit.
  28272. *
  28273. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  28274. *
  28275. * For the full copyright and license information, please view the LICENSE
  28276. * file that was distributed with this source code.
  28277. */
  28278. namespace PHPUnit\Util;
  28279. /**
  28280. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  28281. */
  28282. final class Exception extends \RuntimeException implements \PHPUnit\Exception
  28283. {
  28284. }
  28285. <?php
  28286. use PHPUnit\Framework\TestCase;
  28287. use PHPUnit\SebastianBergmann\CodeCoverage\CodeCoverage;
  28288. use PHPUnit\TextUI\Configuration\Registry;
  28289. use PHPUnit\TextUI\Configuration\PhpHandler;
  28290. if (!defined('STDOUT')) {
  28291. // php://stdout does not obey output buffering. Any output would break
  28292. // unserialization of child process results in the parent process.
  28293. define('STDOUT', fopen('php://temp', 'w+b'));
  28294. define('STDERR', fopen('php://stderr', 'wb'));
  28295. }
  28296. {iniSettings}
  28297. ini_set('display_errors', 'stderr');
  28298. set_include_path('{include_path}');
  28299. $composerAutoload = {composerAutoload};
  28300. $phar = {phar};
  28301. ob_start();
  28302. if ($composerAutoload) {
  28303. require_once $composerAutoload;
  28304. define('PHPUNIT_COMPOSER_INSTALL', $composerAutoload);
  28305. } else if ($phar) {
  28306. require $phar;
  28307. }
  28308. function __phpunit_run_isolated_test()
  28309. {
  28310. if (!class_exists('{className}')) {
  28311. require_once '{filename}';
  28312. }
  28313. $result = new PHPUnit\Framework\TestResult;
  28314. if ({collectCodeCoverageInformation}) {
  28315. $result->setCodeCoverage(
  28316. new CodeCoverage(
  28317. null,
  28318. unserialize('{codeCoverageFilter}')
  28319. )
  28320. );
  28321. }
  28322. $result->beStrictAboutTestsThatDoNotTestAnything({isStrictAboutTestsThatDoNotTestAnything});
  28323. $result->beStrictAboutOutputDuringTests({isStrictAboutOutputDuringTests});
  28324. $result->enforceTimeLimit({enforcesTimeLimit});
  28325. $result->beStrictAboutTodoAnnotatedTests({isStrictAboutTodoAnnotatedTests});
  28326. $result->beStrictAboutResourceUsageDuringSmallTests({isStrictAboutResourceUsageDuringSmallTests});
  28327. $test = new {className}('{methodName}', unserialize('{data}'), '{dataName}');
  28328. \assert($test instanceof TestCase);
  28329. $test->setDependencyInput(unserialize('{dependencyInput}'));
  28330. $test->setInIsolation(true);
  28331. ob_end_clean();
  28332. $test->run($result);
  28333. $output = '';
  28334. if (!$test->hasExpectationOnOutput()) {
  28335. $output = $test->getActualOutput();
  28336. }
  28337. ini_set('xdebug.scream', '0');
  28338. @rewind(STDOUT); /* @ as not every STDOUT target stream is rewindable */
  28339. if ($stdout = stream_get_contents(STDOUT)) {
  28340. $output = $stdout . $output;
  28341. $streamMetaData = stream_get_meta_data(STDOUT);
  28342. if (!empty($streamMetaData['stream_type']) && 'STDIO' === $streamMetaData['stream_type']) {
  28343. @ftruncate(STDOUT, 0);
  28344. @rewind(STDOUT);
  28345. }
  28346. }
  28347. print serialize(
  28348. [
  28349. 'testResult' => $test->getResult(),
  28350. 'numAssertions' => $test->getNumAssertions(),
  28351. 'result' => $result,
  28352. 'output' => $output
  28353. ]
  28354. );
  28355. }
  28356. $configurationFilePath = '{configurationFilePath}';
  28357. if ('' !== $configurationFilePath) {
  28358. $configuration = Registry::getInstance()->get($configurationFilePath);
  28359. (new PhpHandler)->handle($configuration->php());
  28360. unset($configuration);
  28361. }
  28362. function __phpunit_error_handler($errno, $errstr, $errfile, $errline)
  28363. {
  28364. return true;
  28365. }
  28366. set_error_handler('__phpunit_error_handler');
  28367. {constants}
  28368. {included_files}
  28369. {globals}
  28370. restore_error_handler();
  28371. if (isset($GLOBALS['__PHPUNIT_BOOTSTRAP'])) {
  28372. require_once $GLOBALS['__PHPUNIT_BOOTSTRAP'];
  28373. unset($GLOBALS['__PHPUNIT_BOOTSTRAP']);
  28374. }
  28375. __phpunit_run_isolated_test();
  28376. <?php
  28377. use PHPUnit\SebastianBergmann\CodeCoverage\CodeCoverage;
  28378. use PHPUnit\TextUI\Configuration\Registry;
  28379. use PHPUnit\TextUI\Configuration\PhpHandler;
  28380. if (!defined('STDOUT')) {
  28381. // php://stdout does not obey output buffering. Any output would break
  28382. // unserialization of child process results in the parent process.
  28383. define('STDOUT', fopen('php://temp', 'w+b'));
  28384. define('STDERR', fopen('php://stderr', 'wb'));
  28385. }
  28386. {iniSettings}
  28387. ini_set('display_errors', 'stderr');
  28388. set_include_path('{include_path}');
  28389. $composerAutoload = {composerAutoload};
  28390. $phar = {phar};
  28391. ob_start();
  28392. if ($composerAutoload) {
  28393. require_once $composerAutoload;
  28394. define('PHPUNIT_COMPOSER_INSTALL', $composerAutoload);
  28395. } else if ($phar) {
  28396. require $phar;
  28397. }
  28398. function __phpunit_run_isolated_test()
  28399. {
  28400. if (!class_exists('{className}')) {
  28401. require_once '{filename}';
  28402. }
  28403. $result = new PHPUnit\Framework\TestResult;
  28404. if ({collectCodeCoverageInformation}) {
  28405. $result->setCodeCoverage(
  28406. new CodeCoverage(
  28407. null,
  28408. unserialize('{codeCoverageFilter}')
  28409. )
  28410. );
  28411. }
  28412. $result->beStrictAboutTestsThatDoNotTestAnything({isStrictAboutTestsThatDoNotTestAnything});
  28413. $result->beStrictAboutOutputDuringTests({isStrictAboutOutputDuringTests});
  28414. $result->enforceTimeLimit({enforcesTimeLimit});
  28415. $result->beStrictAboutTodoAnnotatedTests({isStrictAboutTodoAnnotatedTests});
  28416. $result->beStrictAboutResourceUsageDuringSmallTests({isStrictAboutResourceUsageDuringSmallTests});
  28417. $test = new {className}('{name}', unserialize('{data}'), '{dataName}');
  28418. $test->setDependencyInput(unserialize('{dependencyInput}'));
  28419. $test->setInIsolation(TRUE);
  28420. ob_end_clean();
  28421. $test->run($result);
  28422. $output = '';
  28423. if (!$test->hasExpectationOnOutput()) {
  28424. $output = $test->getActualOutput();
  28425. }
  28426. ini_set('xdebug.scream', '0');
  28427. @rewind(STDOUT); /* @ as not every STDOUT target stream is rewindable */
  28428. if ($stdout = stream_get_contents(STDOUT)) {
  28429. $output = $stdout . $output;
  28430. $streamMetaData = stream_get_meta_data(STDOUT);
  28431. if (!empty($streamMetaData['stream_type']) && 'STDIO' === $streamMetaData['stream_type']) {
  28432. @ftruncate(STDOUT, 0);
  28433. @rewind(STDOUT);
  28434. }
  28435. }
  28436. print serialize(
  28437. [
  28438. 'testResult' => $test->getResult(),
  28439. 'numAssertions' => $test->getNumAssertions(),
  28440. 'result' => $result,
  28441. 'output' => $output
  28442. ]
  28443. );
  28444. }
  28445. $configurationFilePath = '{configurationFilePath}';
  28446. if ('' !== $configurationFilePath) {
  28447. $configuration = Registry::getInstance()->get($configurationFilePath);
  28448. (new PhpHandler)->handle($configuration->php());
  28449. unset($configuration);
  28450. }
  28451. function __phpunit_error_handler($errno, $errstr, $errfile, $errline)
  28452. {
  28453. return true;
  28454. }
  28455. set_error_handler('__phpunit_error_handler');
  28456. {constants}
  28457. {included_files}
  28458. {globals}
  28459. restore_error_handler();
  28460. if (isset($GLOBALS['__PHPUNIT_BOOTSTRAP'])) {
  28461. require_once $GLOBALS['__PHPUNIT_BOOTSTRAP'];
  28462. unset($GLOBALS['__PHPUNIT_BOOTSTRAP']);
  28463. }
  28464. __phpunit_run_isolated_test();
  28465. <?php
  28466. use PHPUnit\SebastianBergmann\CodeCoverage\CodeCoverage;
  28467. $composerAutoload = {composerAutoload};
  28468. $phar = {phar};
  28469. ob_start();
  28470. $GLOBALS['__PHPUNIT_ISOLATION_BLACKLIST'][] = '{job}';
  28471. if ($composerAutoload) {
  28472. require_once $composerAutoload;
  28473. define('PHPUNIT_COMPOSER_INSTALL', $composerAutoload);
  28474. } else if ($phar) {
  28475. require $phar;
  28476. }
  28477. {globals}
  28478. $coverage = null;
  28479. if (isset($GLOBALS['__PHPUNIT_BOOTSTRAP'])) {
  28480. require_once $GLOBALS['__PHPUNIT_BOOTSTRAP'];
  28481. }
  28482. if (class_exists('PHPUnit\SebastianBergmann\CodeCoverage\CodeCoverage')) {
  28483. $coverage = new CodeCoverage(null);
  28484. $coverage->start(__FILE__);
  28485. }
  28486. register_shutdown_function(function() use ($coverage) {
  28487. $output = null;
  28488. if ($coverage) {
  28489. $output = $coverage->stop();
  28490. }
  28491. file_put_contents('{coverageFile}', serialize($output));
  28492. });
  28493. ob_end_clean();
  28494. require '{job}';
  28495. <?php
  28496. declare (strict_types=1);
  28497. /*
  28498. * This file is part of PHPUnit.
  28499. *
  28500. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  28501. *
  28502. * For the full copyright and license information, please view the LICENSE
  28503. * file that was distributed with this source code.
  28504. */
  28505. namespace PHPUnit\Util\PHP;
  28506. use PHPUnit\Framework\Exception;
  28507. /**
  28508. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  28509. *
  28510. * @see https://bugs.php.net/bug.php?id=51800
  28511. */
  28512. final class WindowsPhpProcess extends \PHPUnit\Util\PHP\DefaultPhpProcess
  28513. {
  28514. public function getCommand(array $settings, string $file = null) : string
  28515. {
  28516. return '"' . parent::getCommand($settings, $file) . '"';
  28517. }
  28518. /**
  28519. * @throws Exception
  28520. */
  28521. protected function getHandles() : array
  28522. {
  28523. if (\false === ($stdout_handle = \tmpfile())) {
  28524. throw new \PHPUnit\Framework\Exception('A temporary file could not be created; verify that your TEMP environment variable is writable');
  28525. }
  28526. return [1 => $stdout_handle];
  28527. }
  28528. protected function useTemporaryFile() : bool
  28529. {
  28530. return \true;
  28531. }
  28532. }
  28533. <?php
  28534. declare (strict_types=1);
  28535. /*
  28536. * This file is part of PHPUnit.
  28537. *
  28538. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  28539. *
  28540. * For the full copyright and license information, please view the LICENSE
  28541. * file that was distributed with this source code.
  28542. */
  28543. namespace PHPUnit\Util\PHP;
  28544. use PHPUnit\Framework\Exception;
  28545. /**
  28546. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  28547. */
  28548. class DefaultPhpProcess extends \PHPUnit\Util\PHP\AbstractPhpProcess
  28549. {
  28550. /**
  28551. * @var string
  28552. */
  28553. protected $tempFile;
  28554. /**
  28555. * Runs a single job (PHP code) using a separate PHP process.
  28556. *
  28557. * @throws Exception
  28558. */
  28559. public function runJob(string $job, array $settings = []) : array
  28560. {
  28561. if ($this->stdin || $this->useTemporaryFile()) {
  28562. if (!($this->tempFile = \tempnam(\sys_get_temp_dir(), 'PHPUnit')) || \file_put_contents($this->tempFile, $job) === \false) {
  28563. throw new \PHPUnit\Framework\Exception('Unable to write temporary file');
  28564. }
  28565. $job = $this->stdin;
  28566. }
  28567. return $this->runProcess($job, $settings);
  28568. }
  28569. /**
  28570. * Returns an array of file handles to be used in place of pipes
  28571. */
  28572. protected function getHandles() : array
  28573. {
  28574. return [];
  28575. }
  28576. /**
  28577. * Handles creating the child process and returning the STDOUT and STDERR
  28578. *
  28579. * @throws Exception
  28580. */
  28581. protected function runProcess(string $job, array $settings) : array
  28582. {
  28583. $handles = $this->getHandles();
  28584. $env = null;
  28585. if ($this->env) {
  28586. $env = $_SERVER ?? [];
  28587. unset($env['argv'], $env['argc']);
  28588. $env = \array_merge($env, $this->env);
  28589. foreach ($env as $envKey => $envVar) {
  28590. if (\is_array($envVar)) {
  28591. unset($env[$envKey]);
  28592. }
  28593. }
  28594. }
  28595. $pipeSpec = [0 => $handles[0] ?? ['pipe', 'r'], 1 => $handles[1] ?? ['pipe', 'w'], 2 => $handles[2] ?? ['pipe', 'w']];
  28596. $process = \proc_open($this->getCommand($settings, $this->tempFile), $pipeSpec, $pipes, null, $env);
  28597. if (!\is_resource($process)) {
  28598. throw new \PHPUnit\Framework\Exception('Unable to spawn worker process');
  28599. }
  28600. if ($job) {
  28601. $this->process($pipes[0], $job);
  28602. }
  28603. \fclose($pipes[0]);
  28604. $stderr = $stdout = '';
  28605. if ($this->timeout) {
  28606. unset($pipes[0]);
  28607. while (\true) {
  28608. $r = $pipes;
  28609. $w = null;
  28610. $e = null;
  28611. $n = @\stream_select($r, $w, $e, $this->timeout);
  28612. if ($n === \false) {
  28613. break;
  28614. }
  28615. if ($n === 0) {
  28616. \proc_terminate($process, 9);
  28617. throw new \PHPUnit\Framework\Exception(\sprintf('Job execution aborted after %d seconds', $this->timeout));
  28618. }
  28619. if ($n > 0) {
  28620. foreach ($r as $pipe) {
  28621. $pipeOffset = 0;
  28622. foreach ($pipes as $i => $origPipe) {
  28623. if ($pipe === $origPipe) {
  28624. $pipeOffset = $i;
  28625. break;
  28626. }
  28627. }
  28628. if (!$pipeOffset) {
  28629. break;
  28630. }
  28631. $line = \fread($pipe, 8192);
  28632. if ($line === '' || $line === \false) {
  28633. \fclose($pipes[$pipeOffset]);
  28634. unset($pipes[$pipeOffset]);
  28635. } elseif ($pipeOffset === 1) {
  28636. $stdout .= $line;
  28637. } else {
  28638. $stderr .= $line;
  28639. }
  28640. }
  28641. if (empty($pipes)) {
  28642. break;
  28643. }
  28644. }
  28645. }
  28646. } else {
  28647. if (isset($pipes[1])) {
  28648. $stdout = \stream_get_contents($pipes[1]);
  28649. \fclose($pipes[1]);
  28650. }
  28651. if (isset($pipes[2])) {
  28652. $stderr = \stream_get_contents($pipes[2]);
  28653. \fclose($pipes[2]);
  28654. }
  28655. }
  28656. if (isset($handles[1])) {
  28657. \rewind($handles[1]);
  28658. $stdout = \stream_get_contents($handles[1]);
  28659. \fclose($handles[1]);
  28660. }
  28661. if (isset($handles[2])) {
  28662. \rewind($handles[2]);
  28663. $stderr = \stream_get_contents($handles[2]);
  28664. \fclose($handles[2]);
  28665. }
  28666. \proc_close($process);
  28667. $this->cleanup();
  28668. return ['stdout' => $stdout, 'stderr' => $stderr];
  28669. }
  28670. /**
  28671. * @param resource $pipe
  28672. */
  28673. protected function process($pipe, string $job) : void
  28674. {
  28675. \fwrite($pipe, $job);
  28676. }
  28677. protected function cleanup() : void
  28678. {
  28679. if ($this->tempFile) {
  28680. \unlink($this->tempFile);
  28681. }
  28682. }
  28683. protected function useTemporaryFile() : bool
  28684. {
  28685. return \false;
  28686. }
  28687. }
  28688. <?php
  28689. declare (strict_types=1);
  28690. /*
  28691. * This file is part of PHPUnit.
  28692. *
  28693. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  28694. *
  28695. * For the full copyright and license information, please view the LICENSE
  28696. * file that was distributed with this source code.
  28697. */
  28698. namespace PHPUnit\Util\PHP;
  28699. use PHPUnit\Framework\AssertionFailedError;
  28700. use PHPUnit\Framework\Exception;
  28701. use PHPUnit\Framework\SyntheticError;
  28702. use PHPUnit\Framework\Test;
  28703. use PHPUnit\Framework\TestCase;
  28704. use PHPUnit\Framework\TestFailure;
  28705. use PHPUnit\Framework\TestResult;
  28706. use PHPUnit\SebastianBergmann\Environment\Runtime;
  28707. /**
  28708. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  28709. */
  28710. abstract class AbstractPhpProcess
  28711. {
  28712. /**
  28713. * @var Runtime
  28714. */
  28715. protected $runtime;
  28716. /**
  28717. * @var bool
  28718. */
  28719. protected $stderrRedirection = \false;
  28720. /**
  28721. * @var string
  28722. */
  28723. protected $stdin = '';
  28724. /**
  28725. * @var string
  28726. */
  28727. protected $args = '';
  28728. /**
  28729. * @var array<string, string>
  28730. */
  28731. protected $env = [];
  28732. /**
  28733. * @var int
  28734. */
  28735. protected $timeout = 0;
  28736. public static function factory() : self
  28737. {
  28738. if (\DIRECTORY_SEPARATOR === '\\') {
  28739. return new \PHPUnit\Util\PHP\WindowsPhpProcess();
  28740. }
  28741. return new \PHPUnit\Util\PHP\DefaultPhpProcess();
  28742. }
  28743. public function __construct()
  28744. {
  28745. $this->runtime = new \PHPUnit\SebastianBergmann\Environment\Runtime();
  28746. }
  28747. /**
  28748. * Defines if should use STDERR redirection or not.
  28749. *
  28750. * Then $stderrRedirection is TRUE, STDERR is redirected to STDOUT.
  28751. */
  28752. public function setUseStderrRedirection(bool $stderrRedirection) : void
  28753. {
  28754. $this->stderrRedirection = $stderrRedirection;
  28755. }
  28756. /**
  28757. * Returns TRUE if uses STDERR redirection or FALSE if not.
  28758. */
  28759. public function useStderrRedirection() : bool
  28760. {
  28761. return $this->stderrRedirection;
  28762. }
  28763. /**
  28764. * Sets the input string to be sent via STDIN
  28765. */
  28766. public function setStdin(string $stdin) : void
  28767. {
  28768. $this->stdin = $stdin;
  28769. }
  28770. /**
  28771. * Returns the input string to be sent via STDIN
  28772. */
  28773. public function getStdin() : string
  28774. {
  28775. return $this->stdin;
  28776. }
  28777. /**
  28778. * Sets the string of arguments to pass to the php job
  28779. */
  28780. public function setArgs(string $args) : void
  28781. {
  28782. $this->args = $args;
  28783. }
  28784. /**
  28785. * Returns the string of arguments to pass to the php job
  28786. */
  28787. public function getArgs() : string
  28788. {
  28789. return $this->args;
  28790. }
  28791. /**
  28792. * Sets the array of environment variables to start the child process with
  28793. *
  28794. * @param array<string, string> $env
  28795. */
  28796. public function setEnv(array $env) : void
  28797. {
  28798. $this->env = $env;
  28799. }
  28800. /**
  28801. * Returns the array of environment variables to start the child process with
  28802. */
  28803. public function getEnv() : array
  28804. {
  28805. return $this->env;
  28806. }
  28807. /**
  28808. * Sets the amount of seconds to wait before timing out
  28809. */
  28810. public function setTimeout(int $timeout) : void
  28811. {
  28812. $this->timeout = $timeout;
  28813. }
  28814. /**
  28815. * Returns the amount of seconds to wait before timing out
  28816. */
  28817. public function getTimeout() : int
  28818. {
  28819. return $this->timeout;
  28820. }
  28821. /**
  28822. * Runs a single test in a separate PHP process.
  28823. *
  28824. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  28825. */
  28826. public function runTestJob(string $job, \PHPUnit\Framework\Test $test, \PHPUnit\Framework\TestResult $result) : void
  28827. {
  28828. $result->startTest($test);
  28829. $_result = $this->runJob($job);
  28830. $this->processChildResult($test, $result, $_result['stdout'], $_result['stderr']);
  28831. }
  28832. /**
  28833. * Returns the command based into the configurations.
  28834. */
  28835. public function getCommand(array $settings, string $file = null) : string
  28836. {
  28837. $command = $this->runtime->getBinary();
  28838. if ($this->runtime->hasPCOV()) {
  28839. $settings = \array_merge($settings, $this->runtime->getCurrentSettings(\array_keys(\ini_get_all('pcov'))));
  28840. } elseif ($this->runtime->hasXdebug()) {
  28841. $settings = \array_merge($settings, $this->runtime->getCurrentSettings(\array_keys(\ini_get_all('xdebug'))));
  28842. }
  28843. $command .= $this->settingsToParameters($settings);
  28844. if (\PHP_SAPI === 'phpdbg') {
  28845. $command .= ' -qrr';
  28846. if (!$file) {
  28847. $command .= 's=';
  28848. }
  28849. }
  28850. if ($file) {
  28851. $command .= ' ' . \escapeshellarg($file);
  28852. }
  28853. if ($this->args) {
  28854. if (!$file) {
  28855. $command .= ' --';
  28856. }
  28857. $command .= ' ' . $this->args;
  28858. }
  28859. if ($this->stderrRedirection) {
  28860. $command .= ' 2>&1';
  28861. }
  28862. return $command;
  28863. }
  28864. /**
  28865. * Runs a single job (PHP code) using a separate PHP process.
  28866. */
  28867. public abstract function runJob(string $job, array $settings = []) : array;
  28868. protected function settingsToParameters(array $settings) : string
  28869. {
  28870. $buffer = '';
  28871. foreach ($settings as $setting) {
  28872. $buffer .= ' -d ' . \escapeshellarg($setting);
  28873. }
  28874. return $buffer;
  28875. }
  28876. /**
  28877. * Processes the TestResult object from an isolated process.
  28878. *
  28879. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  28880. */
  28881. private function processChildResult(\PHPUnit\Framework\Test $test, \PHPUnit\Framework\TestResult $result, string $stdout, string $stderr) : void
  28882. {
  28883. $time = 0;
  28884. if (!empty($stderr)) {
  28885. $result->addError($test, new \PHPUnit\Framework\Exception(\trim($stderr)), $time);
  28886. } else {
  28887. \set_error_handler(
  28888. /**
  28889. * @throws \ErrorException
  28890. */
  28891. static function ($errno, $errstr, $errfile, $errline) : void {
  28892. throw new \ErrorException($errstr, $errno, $errno, $errfile, $errline);
  28893. }
  28894. );
  28895. try {
  28896. if (\strpos($stdout, "#!/usr/bin/env php\n") === 0) {
  28897. $stdout = \substr($stdout, 19);
  28898. }
  28899. $childResult = \unserialize(\str_replace("#!/usr/bin/env php\n", '', $stdout));
  28900. \restore_error_handler();
  28901. if ($childResult === \false) {
  28902. $result->addFailure($test, new \PHPUnit\Framework\AssertionFailedError('Test was run in child process and ended unexpectedly'), $time);
  28903. }
  28904. } catch (\ErrorException $e) {
  28905. \restore_error_handler();
  28906. $childResult = \false;
  28907. $result->addError($test, new \PHPUnit\Framework\Exception(\trim($stdout), 0, $e), $time);
  28908. }
  28909. if ($childResult !== \false) {
  28910. if (!empty($childResult['output'])) {
  28911. $output = $childResult['output'];
  28912. }
  28913. /* @var TestCase $test */
  28914. $test->setResult($childResult['testResult']);
  28915. $test->addToAssertionCount($childResult['numAssertions']);
  28916. $childResult = $childResult['result'];
  28917. \assert($childResult instanceof \PHPUnit\Framework\TestResult);
  28918. if ($result->getCollectCodeCoverageInformation()) {
  28919. $result->getCodeCoverage()->merge($childResult->getCodeCoverage());
  28920. }
  28921. $time = $childResult->time();
  28922. $notImplemented = $childResult->notImplemented();
  28923. $risky = $childResult->risky();
  28924. $skipped = $childResult->skipped();
  28925. $errors = $childResult->errors();
  28926. $warnings = $childResult->warnings();
  28927. $failures = $childResult->failures();
  28928. if (!empty($notImplemented)) {
  28929. $result->addError($test, $this->getException($notImplemented[0]), $time);
  28930. } elseif (!empty($risky)) {
  28931. $result->addError($test, $this->getException($risky[0]), $time);
  28932. } elseif (!empty($skipped)) {
  28933. $result->addError($test, $this->getException($skipped[0]), $time);
  28934. } elseif (!empty($errors)) {
  28935. $result->addError($test, $this->getException($errors[0]), $time);
  28936. } elseif (!empty($warnings)) {
  28937. $result->addWarning($test, $this->getException($warnings[0]), $time);
  28938. } elseif (!empty($failures)) {
  28939. $result->addFailure($test, $this->getException($failures[0]), $time);
  28940. }
  28941. }
  28942. }
  28943. $result->endTest($test, $time);
  28944. if (!empty($output)) {
  28945. print $output;
  28946. }
  28947. }
  28948. /**
  28949. * Gets the thrown exception from a PHPUnit\Framework\TestFailure.
  28950. *
  28951. * @see https://github.com/sebastianbergmann/phpunit/issues/74
  28952. */
  28953. private function getException(\PHPUnit\Framework\TestFailure $error) : \PHPUnit\Framework\Exception
  28954. {
  28955. $exception = $error->thrownException();
  28956. if ($exception instanceof \__PHP_Incomplete_Class) {
  28957. $exceptionArray = [];
  28958. foreach ((array) $exception as $key => $value) {
  28959. $key = \substr($key, \strrpos($key, "\0") + 1);
  28960. $exceptionArray[$key] = $value;
  28961. }
  28962. $exception = new \PHPUnit\Framework\SyntheticError(\sprintf('%s: %s', $exceptionArray['_PHP_Incomplete_Class_Name'], $exceptionArray['message']), $exceptionArray['code'], $exceptionArray['file'], $exceptionArray['line'], $exceptionArray['trace']);
  28963. }
  28964. return $exception;
  28965. }
  28966. }
  28967. <?php
  28968. declare (strict_types=1);
  28969. /*
  28970. * This file is part of PHPUnit.
  28971. *
  28972. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  28973. *
  28974. * For the full copyright and license information, please view the LICENSE
  28975. * file that was distributed with this source code.
  28976. */
  28977. namespace PHPUnit\Util;
  28978. /**
  28979. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  28980. */
  28981. class Printer
  28982. {
  28983. /**
  28984. * @psalm-var closed-resource|resource
  28985. */
  28986. private $stream;
  28987. /**
  28988. * @var bool
  28989. */
  28990. private $isPhpStream;
  28991. /**
  28992. * @param null|resource|string $out
  28993. *
  28994. * @throws Exception
  28995. */
  28996. public function __construct($out = null)
  28997. {
  28998. if (\is_resource($out)) {
  28999. $this->stream = $out;
  29000. return;
  29001. }
  29002. if (!\is_string($out)) {
  29003. return;
  29004. }
  29005. if (\strpos($out, 'socket://') === 0) {
  29006. $tmp = \explode(':', \str_replace('socket://', '', $out));
  29007. if (\count($tmp) !== 2) {
  29008. throw new \PHPUnit\Util\Exception(\sprintf('"%s" does not match "socket://hostname:port" format', $out));
  29009. }
  29010. $this->stream = \fsockopen($tmp[0], (int) $tmp[1]);
  29011. return;
  29012. }
  29013. if (\strpos($out, 'php://') === \false && !\PHPUnit\Util\Filesystem::createDirectory(\dirname($out))) {
  29014. throw new \PHPUnit\Util\Exception(\sprintf('Directory "%s" was not created', \dirname($out)));
  29015. }
  29016. $this->stream = \fopen($out, 'wb');
  29017. $this->isPhpStream = \strncmp($out, 'php://', 6) !== 0;
  29018. }
  29019. public function write(string $buffer) : void
  29020. {
  29021. if ($this->stream) {
  29022. \assert(\is_resource($this->stream));
  29023. \fwrite($this->stream, $buffer);
  29024. } else {
  29025. if (\PHP_SAPI !== 'cli' && \PHP_SAPI !== 'phpdbg') {
  29026. $buffer = \htmlspecialchars($buffer, \ENT_COMPAT | \ENT_SUBSTITUTE);
  29027. }
  29028. print $buffer;
  29029. }
  29030. }
  29031. public function flush() : void
  29032. {
  29033. if ($this->stream && $this->isPhpStream) {
  29034. \assert(\is_resource($this->stream));
  29035. \fclose($this->stream);
  29036. }
  29037. }
  29038. }
  29039. <?php
  29040. declare (strict_types=1);
  29041. /*
  29042. * This file is part of PHPUnit.
  29043. *
  29044. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  29045. *
  29046. * For the full copyright and license information, please view the LICENSE
  29047. * file that was distributed with this source code.
  29048. */
  29049. namespace PHPUnit\Util;
  29050. /**
  29051. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  29052. */
  29053. final class Type
  29054. {
  29055. public static function isType(string $type) : bool
  29056. {
  29057. switch ($type) {
  29058. case 'numeric':
  29059. case 'integer':
  29060. case 'int':
  29061. case 'iterable':
  29062. case 'float':
  29063. case 'string':
  29064. case 'boolean':
  29065. case 'bool':
  29066. case 'null':
  29067. case 'array':
  29068. case 'object':
  29069. case 'resource':
  29070. case 'scalar':
  29071. return \true;
  29072. default:
  29073. return \false;
  29074. }
  29075. }
  29076. public static function isCloneable(object $object) : bool
  29077. {
  29078. try {
  29079. $clone = clone $object;
  29080. } catch (\Throwable $t) {
  29081. return \false;
  29082. }
  29083. return $clone instanceof $object;
  29084. }
  29085. }
  29086. <?php
  29087. declare (strict_types=1);
  29088. /*
  29089. * This file is part of PHPUnit.
  29090. *
  29091. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  29092. *
  29093. * For the full copyright and license information, please view the LICENSE
  29094. * file that was distributed with this source code.
  29095. */
  29096. namespace PHPUnit\Util;
  29097. use PHPUnit\Framework\Exception;
  29098. /**
  29099. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  29100. */
  29101. final class Json
  29102. {
  29103. /**
  29104. * Prettify json string
  29105. *
  29106. * @throws \PHPUnit\Framework\Exception
  29107. */
  29108. public static function prettify(string $json) : string
  29109. {
  29110. $decodedJson = \json_decode($json, \false);
  29111. if (\json_last_error()) {
  29112. throw new \PHPUnit\Framework\Exception('Cannot prettify invalid json');
  29113. }
  29114. return \json_encode($decodedJson, \JSON_PRETTY_PRINT | \JSON_UNESCAPED_SLASHES | \JSON_UNESCAPED_UNICODE);
  29115. }
  29116. /*
  29117. * To allow comparison of JSON strings, first process them into a consistent
  29118. * format so that they can be compared as strings.
  29119. * @return array ($error, $canonicalized_json) The $error parameter is used
  29120. * to indicate an error decoding the json. This is used to avoid ambiguity
  29121. * with JSON strings consisting entirely of 'null' or 'false'.
  29122. */
  29123. public static function canonicalize(string $json) : array
  29124. {
  29125. $decodedJson = \json_decode($json);
  29126. if (\json_last_error()) {
  29127. return [\true, null];
  29128. }
  29129. self::recursiveSort($decodedJson);
  29130. $reencodedJson = \json_encode($decodedJson);
  29131. return [\false, $reencodedJson];
  29132. }
  29133. /*
  29134. * JSON object keys are unordered while PHP array keys are ordered.
  29135. * Sort all array keys to ensure both the expected and actual values have
  29136. * their keys in the same order.
  29137. */
  29138. private static function recursiveSort(&$json) : void
  29139. {
  29140. if (!\is_array($json)) {
  29141. // If the object is not empty, change it to an associative array
  29142. // so we can sort the keys (and we will still re-encode it
  29143. // correctly, since PHP encodes associative arrays as JSON objects.)
  29144. // But EMPTY objects MUST remain empty objects. (Otherwise we will
  29145. // re-encode it as a JSON array rather than a JSON object.)
  29146. // See #2919.
  29147. if (\is_object($json) && \count((array) $json) > 0) {
  29148. $json = (array) $json;
  29149. } else {
  29150. return;
  29151. }
  29152. }
  29153. \ksort($json);
  29154. foreach ($json as $key => &$value) {
  29155. self::recursiveSort($value);
  29156. }
  29157. }
  29158. }
  29159. <?php
  29160. declare (strict_types=1);
  29161. /*
  29162. * This file is part of PHPUnit.
  29163. *
  29164. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  29165. *
  29166. * For the full copyright and license information, please view the LICENSE
  29167. * file that was distributed with this source code.
  29168. */
  29169. namespace PHPUnit\Util\Annotation;
  29170. use PHPUnit\PharIo\Version\VersionConstraintParser;
  29171. use PHPUnit\Framework\InvalidDataProviderException;
  29172. use PHPUnit\Framework\SkippedTestError;
  29173. use PHPUnit\Framework\Warning;
  29174. use PHPUnit\Util\Exception;
  29175. use PHPUnit\Util\InvalidDataSetException;
  29176. /**
  29177. * This is an abstraction around a PHPUnit-specific docBlock,
  29178. * allowing us to ask meaningful questions about a specific
  29179. * reflection symbol.
  29180. *
  29181. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  29182. */
  29183. final class DocBlock
  29184. {
  29185. /**
  29186. * @todo This constant should be private (it's public because of TestTest::testGetProvidedDataRegEx)
  29187. */
  29188. public const REGEX_DATA_PROVIDER = '/@dataProvider\\s+([a-zA-Z0-9._:-\\\\x7f-\\xff]+)/';
  29189. private const REGEX_REQUIRES_VERSION = '/@requires\\s+(?P<name>PHP(?:Unit)?)\\s+(?P<operator>[<>=!]{0,2})\\s*(?P<version>[\\d\\.-]+(dev|(RC|alpha|beta)[\\d\\.])?)[ \\t]*\\r?$/m';
  29190. private const REGEX_REQUIRES_VERSION_CONSTRAINT = '/@requires\\s+(?P<name>PHP(?:Unit)?)\\s+(?P<constraint>[\\d\\t \\-.|~^]+)[ \\t]*\\r?$/m';
  29191. private const REGEX_REQUIRES_OS = '/@requires\\s+(?P<name>OS(?:FAMILY)?)\\s+(?P<value>.+?)[ \\t]*\\r?$/m';
  29192. private const REGEX_REQUIRES_SETTING = '/@requires\\s+(?P<name>setting)\\s+(?P<setting>([^ ]+?))\\s*(?P<value>[\\w\\.-]+[\\w\\.]?)?[ \\t]*\\r?$/m';
  29193. private const REGEX_REQUIRES = '/@requires\\s+(?P<name>function|extension)\\s+(?P<value>([^\\s<>=!]+))\\s*(?P<operator>[<>=!]{0,2})\\s*(?P<version>[\\d\\.-]+[\\d\\.]?)?[ \\t]*\\r?$/m';
  29194. private const REGEX_TEST_WITH = '/@testWith\\s+/';
  29195. /** @var string */
  29196. private $docComment;
  29197. /** @var bool */
  29198. private $isMethod;
  29199. /** @var array<string, array<int, string>> pre-parsed annotations indexed by name and occurrence index */
  29200. private $symbolAnnotations;
  29201. /**
  29202. * @var null|array<string, mixed>
  29203. *
  29204. * @psalm-var null|(array{
  29205. * __OFFSET: array<string, int>&array{__FILE: string},
  29206. * setting?: array<string, string>,
  29207. * extension_versions?: array<string, array{version: string, operator: string}>
  29208. * }&array<
  29209. * string,
  29210. * string|array{version: string, operator: string}|array{constraint: string}|array<int|string, string>
  29211. * >)
  29212. */
  29213. private $parsedRequirements;
  29214. /** @var int */
  29215. private $startLine;
  29216. /** @var int */
  29217. private $endLine;
  29218. /** @var string */
  29219. private $fileName;
  29220. /** @var string */
  29221. private $name;
  29222. /**
  29223. * @var string
  29224. *
  29225. * @psalm-var class-string
  29226. */
  29227. private $className;
  29228. public static function ofClass(\ReflectionClass $class) : self
  29229. {
  29230. $className = $class->getName();
  29231. return new self((string) $class->getDocComment(), \false, self::extractAnnotationsFromReflector($class), $class->getStartLine(), $class->getEndLine(), $class->getFileName(), $className, $className);
  29232. }
  29233. /**
  29234. * @psalm-param class-string $classNameInHierarchy
  29235. */
  29236. public static function ofMethod(\ReflectionMethod $method, string $classNameInHierarchy) : self
  29237. {
  29238. return new self((string) $method->getDocComment(), \true, self::extractAnnotationsFromReflector($method), $method->getStartLine(), $method->getEndLine(), $method->getFileName(), $method->getName(), $classNameInHierarchy);
  29239. }
  29240. /**
  29241. * Note: we do not preserve an instance of the reflection object, since it cannot be safely (de-)serialized.
  29242. *
  29243. * @param array<string, array<int, string>> $symbolAnnotations
  29244. *
  29245. * @psalm-param class-string $className
  29246. */
  29247. private function __construct(string $docComment, bool $isMethod, array $symbolAnnotations, int $startLine, int $endLine, string $fileName, string $name, string $className)
  29248. {
  29249. $this->docComment = $docComment;
  29250. $this->isMethod = $isMethod;
  29251. $this->symbolAnnotations = $symbolAnnotations;
  29252. $this->startLine = $startLine;
  29253. $this->endLine = $endLine;
  29254. $this->fileName = $fileName;
  29255. $this->name = $name;
  29256. $this->className = $className;
  29257. }
  29258. /**
  29259. * @psalm-return array{
  29260. * __OFFSET: array<string, int>&array{__FILE: string},
  29261. * setting?: array<string, string>,
  29262. * extension_versions?: array<string, array{version: string, operator: string}>
  29263. * }&array<
  29264. * string,
  29265. * string|array{version: string, operator: string}|array{constraint: string}|array<int|string, string>
  29266. * >
  29267. *
  29268. * @throws Warning if the requirements version constraint is not well-formed
  29269. */
  29270. public function requirements() : array
  29271. {
  29272. if ($this->parsedRequirements !== null) {
  29273. return $this->parsedRequirements;
  29274. }
  29275. $offset = $this->startLine;
  29276. $requires = [];
  29277. $recordedSettings = [];
  29278. $extensionVersions = [];
  29279. $recordedOffsets = ['__FILE' => \realpath($this->fileName)];
  29280. // Split docblock into lines and rewind offset to start of docblock
  29281. $lines = \preg_split('/\\r\\n|\\r|\\n/', $this->docComment);
  29282. $offset -= \count($lines);
  29283. foreach ($lines as $line) {
  29284. if (\preg_match(self::REGEX_REQUIRES_OS, $line, $matches)) {
  29285. $requires[$matches['name']] = $matches['value'];
  29286. $recordedOffsets[$matches['name']] = $offset;
  29287. }
  29288. if (\preg_match(self::REGEX_REQUIRES_VERSION, $line, $matches)) {
  29289. $requires[$matches['name']] = ['version' => $matches['version'], 'operator' => $matches['operator']];
  29290. $recordedOffsets[$matches['name']] = $offset;
  29291. }
  29292. if (\preg_match(self::REGEX_REQUIRES_VERSION_CONSTRAINT, $line, $matches)) {
  29293. if (!empty($requires[$matches['name']])) {
  29294. $offset++;
  29295. continue;
  29296. }
  29297. try {
  29298. $versionConstraintParser = new \PHPUnit\PharIo\Version\VersionConstraintParser();
  29299. $requires[$matches['name'] . '_constraint'] = ['constraint' => $versionConstraintParser->parse(\trim($matches['constraint']))];
  29300. $recordedOffsets[$matches['name'] . '_constraint'] = $offset;
  29301. } catch (\PHPUnit\PharIo\Version\Exception $e) {
  29302. /* @TODO this catch is currently not valid, see https://github.com/phar-io/version/issues/16 */
  29303. throw new \PHPUnit\Framework\Warning($e->getMessage(), $e->getCode(), $e);
  29304. }
  29305. }
  29306. if (\preg_match(self::REGEX_REQUIRES_SETTING, $line, $matches)) {
  29307. $recordedSettings[$matches['setting']] = $matches['value'];
  29308. $recordedOffsets['__SETTING_' . $matches['setting']] = $offset;
  29309. }
  29310. if (\preg_match(self::REGEX_REQUIRES, $line, $matches)) {
  29311. $name = $matches['name'] . 's';
  29312. if (!isset($requires[$name])) {
  29313. $requires[$name] = [];
  29314. }
  29315. $requires[$name][] = $matches['value'];
  29316. $recordedOffsets[$matches['name'] . '_' . $matches['value']] = $offset;
  29317. if ($name === 'extensions' && !empty($matches['version'])) {
  29318. $extensionVersions[$matches['value']] = ['version' => $matches['version'], 'operator' => $matches['operator']];
  29319. }
  29320. }
  29321. $offset++;
  29322. }
  29323. return $this->parsedRequirements = \array_merge($requires, ['__OFFSET' => $recordedOffsets], \array_filter(['setting' => $recordedSettings, 'extension_versions' => $extensionVersions]));
  29324. }
  29325. /**
  29326. * Returns the provided data for a method.
  29327. *
  29328. * @throws Exception
  29329. */
  29330. public function getProvidedData() : ?array
  29331. {
  29332. /** @noinspection SuspiciousBinaryOperationInspection */
  29333. $data = $this->getDataFromDataProviderAnnotation($this->docComment) ?? $this->getDataFromTestWithAnnotation($this->docComment);
  29334. if ($data === null) {
  29335. return null;
  29336. }
  29337. if ($data === []) {
  29338. throw new \PHPUnit\Framework\SkippedTestError();
  29339. }
  29340. foreach ($data as $key => $value) {
  29341. if (!\is_array($value)) {
  29342. throw new \PHPUnit\Util\InvalidDataSetException(\sprintf('Data set %s is invalid.', \is_int($key) ? '#' . $key : '"' . $key . '"'));
  29343. }
  29344. }
  29345. return $data;
  29346. }
  29347. /**
  29348. * @psalm-return array<string, array{line: int, value: string}>
  29349. */
  29350. public function getInlineAnnotations() : array
  29351. {
  29352. $code = \file($this->fileName);
  29353. $lineNumber = $this->startLine;
  29354. $startLine = $this->startLine - 1;
  29355. $endLine = $this->endLine - 1;
  29356. $codeLines = \array_slice($code, $startLine, $endLine - $startLine + 1);
  29357. $annotations = [];
  29358. foreach ($codeLines as $line) {
  29359. if (\preg_match('#/\\*\\*?\\s*@(?P<name>[A-Za-z_-]+)(?:[ \\t]+(?P<value>.*?))?[ \\t]*\\r?\\*/$#m', $line, $matches)) {
  29360. $annotations[\strtolower($matches['name'])] = ['line' => $lineNumber, 'value' => $matches['value']];
  29361. }
  29362. $lineNumber++;
  29363. }
  29364. return $annotations;
  29365. }
  29366. public function symbolAnnotations() : array
  29367. {
  29368. return $this->symbolAnnotations;
  29369. }
  29370. public function isHookToBeExecutedBeforeClass() : bool
  29371. {
  29372. return $this->isMethod && \false !== \strpos($this->docComment, '@beforeClass');
  29373. }
  29374. public function isHookToBeExecutedAfterClass() : bool
  29375. {
  29376. return $this->isMethod && \false !== \strpos($this->docComment, '@afterClass');
  29377. }
  29378. public function isToBeExecutedBeforeTest() : bool
  29379. {
  29380. return 1 === \preg_match('/@before\\b/', $this->docComment);
  29381. }
  29382. public function isToBeExecutedAfterTest() : bool
  29383. {
  29384. return 1 === \preg_match('/@after\\b/', $this->docComment);
  29385. }
  29386. public function isToBeExecutedAsPreCondition() : bool
  29387. {
  29388. return 1 === \preg_match('/@preCondition\\b/', $this->docComment);
  29389. }
  29390. public function isToBeExecutedAsPostCondition() : bool
  29391. {
  29392. return 1 === \preg_match('/@postCondition\\b/', $this->docComment);
  29393. }
  29394. /**
  29395. * Parse annotation content to use constant/class constant values
  29396. *
  29397. * Constants are specified using a starting '@'. For example: @ClassName::CONST_NAME
  29398. *
  29399. * If the constant is not found the string is used as is to ensure maximum BC.
  29400. */
  29401. private function parseAnnotationContent(string $message) : string
  29402. {
  29403. if (\defined($message) && (\strpos($message, '::') !== \false && \substr_count($message, '::') + 1 === 2)) {
  29404. return \constant($message);
  29405. }
  29406. return $message;
  29407. }
  29408. private function getDataFromDataProviderAnnotation(string $docComment) : ?array
  29409. {
  29410. $methodName = null;
  29411. $className = $this->className;
  29412. if ($this->isMethod) {
  29413. $methodName = $this->name;
  29414. }
  29415. if (!\preg_match_all(self::REGEX_DATA_PROVIDER, $docComment, $matches)) {
  29416. return null;
  29417. }
  29418. $result = [];
  29419. foreach ($matches[1] as $match) {
  29420. $dataProviderMethodNameNamespace = \explode('\\', $match);
  29421. $leaf = \explode('::', \array_pop($dataProviderMethodNameNamespace));
  29422. $dataProviderMethodName = \array_pop($leaf);
  29423. if (empty($dataProviderMethodNameNamespace)) {
  29424. $dataProviderMethodNameNamespace = '';
  29425. } else {
  29426. $dataProviderMethodNameNamespace = \implode('\\', $dataProviderMethodNameNamespace) . '\\';
  29427. }
  29428. if (empty($leaf)) {
  29429. $dataProviderClassName = $className;
  29430. } else {
  29431. /** @psalm-var class-string $dataProviderClassName */
  29432. $dataProviderClassName = $dataProviderMethodNameNamespace . \array_pop($leaf);
  29433. }
  29434. try {
  29435. $dataProviderClass = new \ReflectionClass($dataProviderClassName);
  29436. $dataProviderMethod = $dataProviderClass->getMethod($dataProviderMethodName);
  29437. // @codeCoverageIgnoreStart
  29438. } catch (\ReflectionException $e) {
  29439. throw new \PHPUnit\Util\Exception($e->getMessage(), (int) $e->getCode(), $e);
  29440. // @codeCoverageIgnoreEnd
  29441. }
  29442. if ($dataProviderMethod->isStatic()) {
  29443. $object = null;
  29444. } else {
  29445. $object = $dataProviderClass->newInstance();
  29446. }
  29447. if ($dataProviderMethod->getNumberOfParameters() === 0) {
  29448. $data = $dataProviderMethod->invoke($object);
  29449. } else {
  29450. $data = $dataProviderMethod->invoke($object, $methodName);
  29451. }
  29452. if ($data instanceof \Traversable) {
  29453. $origData = $data;
  29454. $data = [];
  29455. foreach ($origData as $key => $value) {
  29456. if (\is_int($key)) {
  29457. $data[] = $value;
  29458. } elseif (\array_key_exists($key, $data)) {
  29459. throw new \PHPUnit\Framework\InvalidDataProviderException(\sprintf('The key "%s" has already been defined in the data provider "%s".', $key, $match));
  29460. } else {
  29461. $data[$key] = $value;
  29462. }
  29463. }
  29464. }
  29465. if (\is_array($data)) {
  29466. $result = \array_merge($result, $data);
  29467. }
  29468. }
  29469. return $result;
  29470. }
  29471. /**
  29472. * @throws Exception
  29473. */
  29474. private function getDataFromTestWithAnnotation(string $docComment) : ?array
  29475. {
  29476. $docComment = $this->cleanUpMultiLineAnnotation($docComment);
  29477. if (!\preg_match(self::REGEX_TEST_WITH, $docComment, $matches, \PREG_OFFSET_CAPTURE)) {
  29478. return null;
  29479. }
  29480. $offset = \strlen($matches[0][0]) + $matches[0][1];
  29481. $annotationContent = \substr($docComment, $offset);
  29482. $data = [];
  29483. foreach (\explode("\n", $annotationContent) as $candidateRow) {
  29484. $candidateRow = \trim($candidateRow);
  29485. if ($candidateRow[0] !== '[') {
  29486. break;
  29487. }
  29488. $dataSet = \json_decode($candidateRow, \true);
  29489. if (\json_last_error() !== \JSON_ERROR_NONE) {
  29490. throw new \PHPUnit\Util\Exception('The data set for the @testWith annotation cannot be parsed: ' . \json_last_error_msg());
  29491. }
  29492. $data[] = $dataSet;
  29493. }
  29494. if (!$data) {
  29495. throw new \PHPUnit\Util\Exception('The data set for the @testWith annotation cannot be parsed.');
  29496. }
  29497. return $data;
  29498. }
  29499. private function cleanUpMultiLineAnnotation(string $docComment) : string
  29500. {
  29501. //removing initial ' * ' for docComment
  29502. $docComment = \str_replace("\r\n", "\n", $docComment);
  29503. $docComment = \preg_replace('/' . '\\n' . '\\s*' . '\\*' . '\\s?' . '/', "\n", $docComment);
  29504. $docComment = (string) \substr($docComment, 0, -1);
  29505. return \rtrim($docComment, "\n");
  29506. }
  29507. /** @return array<string, array<int, string>> */
  29508. private static function parseDocBlock(string $docBlock) : array
  29509. {
  29510. // Strip away the docblock header and footer to ease parsing of one line annotations
  29511. $docBlock = (string) \substr($docBlock, 3, -2);
  29512. $annotations = [];
  29513. if (\preg_match_all('/@(?P<name>[A-Za-z_-]+)(?:[ \\t]+(?P<value>.*?))?[ \\t]*\\r?$/m', $docBlock, $matches)) {
  29514. $numMatches = \count($matches[0]);
  29515. for ($i = 0; $i < $numMatches; ++$i) {
  29516. $annotations[$matches['name'][$i]][] = (string) $matches['value'][$i];
  29517. }
  29518. }
  29519. return $annotations;
  29520. }
  29521. /** @param \ReflectionClass|\ReflectionFunctionAbstract $reflector */
  29522. private static function extractAnnotationsFromReflector(\Reflector $reflector) : array
  29523. {
  29524. $annotations = [];
  29525. if ($reflector instanceof \ReflectionClass) {
  29526. $annotations = \array_merge($annotations, ...\array_map(function (\ReflectionClass $trait) : array {
  29527. return self::parseDocBlock((string) $trait->getDocComment());
  29528. }, \array_values($reflector->getTraits())));
  29529. }
  29530. return \array_merge($annotations, self::parseDocBlock((string) $reflector->getDocComment()));
  29531. }
  29532. }
  29533. <?php
  29534. declare (strict_types=1);
  29535. /*
  29536. * This file is part of PHPUnit.
  29537. *
  29538. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  29539. *
  29540. * For the full copyright and license information, please view the LICENSE
  29541. * file that was distributed with this source code.
  29542. */
  29543. namespace PHPUnit\Util\Annotation;
  29544. use PHPUnit\Util\Exception;
  29545. /**
  29546. * Reflection information, and therefore DocBlock information, is static within
  29547. * a single PHP process. It is therefore okay to use a Singleton registry here.
  29548. *
  29549. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  29550. */
  29551. final class Registry
  29552. {
  29553. /** @var null|self */
  29554. private static $instance;
  29555. /** @var array<string, DocBlock> indexed by class name */
  29556. private $classDocBlocks = [];
  29557. /** @var array<string, array<string, DocBlock>> indexed by class name and method name */
  29558. private $methodDocBlocks = [];
  29559. public static function getInstance() : self
  29560. {
  29561. return self::$instance ?? (self::$instance = new self());
  29562. }
  29563. private function __construct()
  29564. {
  29565. }
  29566. /**
  29567. * @throws Exception
  29568. * @psalm-param class-string $class
  29569. */
  29570. public function forClassName(string $class) : \PHPUnit\Util\Annotation\DocBlock
  29571. {
  29572. if (\array_key_exists($class, $this->classDocBlocks)) {
  29573. return $this->classDocBlocks[$class];
  29574. }
  29575. try {
  29576. $reflection = new \ReflectionClass($class);
  29577. // @codeCoverageIgnoreStart
  29578. } catch (\ReflectionException $e) {
  29579. throw new \PHPUnit\Util\Exception($e->getMessage(), (int) $e->getCode(), $e);
  29580. }
  29581. // @codeCoverageIgnoreEnd
  29582. return $this->classDocBlocks[$class] = \PHPUnit\Util\Annotation\DocBlock::ofClass($reflection);
  29583. }
  29584. /**
  29585. * @throws Exception
  29586. * @psalm-param class-string $classInHierarchy
  29587. */
  29588. public function forMethod(string $classInHierarchy, string $method) : \PHPUnit\Util\Annotation\DocBlock
  29589. {
  29590. if (isset($this->methodDocBlocks[$classInHierarchy][$method])) {
  29591. return $this->methodDocBlocks[$classInHierarchy][$method];
  29592. }
  29593. try {
  29594. $reflection = new \ReflectionMethod($classInHierarchy, $method);
  29595. // @codeCoverageIgnoreStart
  29596. } catch (\ReflectionException $e) {
  29597. throw new \PHPUnit\Util\Exception($e->getMessage(), (int) $e->getCode(), $e);
  29598. }
  29599. // @codeCoverageIgnoreEnd
  29600. return $this->methodDocBlocks[$classInHierarchy][$method] = \PHPUnit\Util\Annotation\DocBlock::ofMethod($reflection, $classInHierarchy);
  29601. }
  29602. }
  29603. <?php
  29604. declare (strict_types=1);
  29605. /*
  29606. * This file is part of PHPUnit.
  29607. *
  29608. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  29609. *
  29610. * For the full copyright and license information, please view the LICENSE
  29611. * file that was distributed with this source code.
  29612. */
  29613. namespace PHPUnit\Util\TestDox;
  29614. use PHPUnit\Framework\TestResult;
  29615. /**
  29616. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  29617. */
  29618. final class TextResultPrinter extends \PHPUnit\Util\TestDox\ResultPrinter
  29619. {
  29620. public function printResult(\PHPUnit\Framework\TestResult $result) : void
  29621. {
  29622. }
  29623. /**
  29624. * Handler for 'start class' event.
  29625. */
  29626. protected function startClass(string $name) : void
  29627. {
  29628. $this->write($this->currentTestClassPrettified . "\n");
  29629. }
  29630. /**
  29631. * Handler for 'on test' event.
  29632. */
  29633. protected function onTest(string $name, bool $success = \true) : void
  29634. {
  29635. if ($success) {
  29636. $this->write(' [x] ');
  29637. } else {
  29638. $this->write(' [ ] ');
  29639. }
  29640. $this->write($name . "\n");
  29641. }
  29642. /**
  29643. * Handler for 'end class' event.
  29644. */
  29645. protected function endClass(string $name) : void
  29646. {
  29647. $this->write("\n");
  29648. }
  29649. }
  29650. <?php
  29651. declare (strict_types=1);
  29652. /*
  29653. * This file is part of PHPUnit.
  29654. *
  29655. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  29656. *
  29657. * For the full copyright and license information, please view the LICENSE
  29658. * file that was distributed with this source code.
  29659. */
  29660. namespace PHPUnit\Util\TestDox;
  29661. use PHPUnit\Framework\TestCase;
  29662. use PHPUnit\Util\Color;
  29663. use PHPUnit\Util\Exception as UtilException;
  29664. use PHPUnit\Util\Test;
  29665. use PHPUnit\SebastianBergmann\Exporter\Exporter;
  29666. /**
  29667. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  29668. */
  29669. final class NamePrettifier
  29670. {
  29671. /**
  29672. * @var string[]
  29673. */
  29674. private $strings = [];
  29675. /**
  29676. * @var bool
  29677. */
  29678. private $useColor;
  29679. public function __construct(bool $useColor = \false)
  29680. {
  29681. $this->useColor = $useColor;
  29682. }
  29683. /**
  29684. * Prettifies the name of a test class.
  29685. *
  29686. * @psalm-param class-string $className
  29687. */
  29688. public function prettifyTestClass(string $className) : string
  29689. {
  29690. try {
  29691. $annotations = \PHPUnit\Util\Test::parseTestMethodAnnotations($className);
  29692. if (isset($annotations['class']['testdox'][0])) {
  29693. return $annotations['class']['testdox'][0];
  29694. }
  29695. } catch (\PHPUnit\Util\Exception $e) {
  29696. // ignore, determine className by parsing the provided name
  29697. }
  29698. $parts = \explode('\\', $className);
  29699. $className = \array_pop($parts);
  29700. if (\substr($className, -1 * \strlen('Test')) === 'Test') {
  29701. $className = \substr($className, 0, \strlen($className) - \strlen('Test'));
  29702. }
  29703. if (\strpos($className, 'Tests') === 0) {
  29704. $className = \substr($className, \strlen('Tests'));
  29705. } elseif (\strpos($className, 'Test') === 0) {
  29706. $className = \substr($className, \strlen('Test'));
  29707. }
  29708. if (empty($className)) {
  29709. $className = 'UnnamedTests';
  29710. }
  29711. if (!empty($parts)) {
  29712. $parts[] = $className;
  29713. $fullyQualifiedName = \implode('\\', $parts);
  29714. } else {
  29715. $fullyQualifiedName = $className;
  29716. }
  29717. $result = '';
  29718. $wasLowerCase = \false;
  29719. foreach (\range(0, \strlen($className) - 1) as $i) {
  29720. $isLowerCase = \mb_strtolower($className[$i], 'UTF-8') === $className[$i];
  29721. if ($wasLowerCase && !$isLowerCase) {
  29722. $result .= ' ';
  29723. }
  29724. $result .= $className[$i];
  29725. if ($isLowerCase) {
  29726. $wasLowerCase = \true;
  29727. } else {
  29728. $wasLowerCase = \false;
  29729. }
  29730. }
  29731. if ($fullyQualifiedName !== $className) {
  29732. return $result . ' (' . $fullyQualifiedName . ')';
  29733. }
  29734. return $result;
  29735. }
  29736. /**
  29737. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  29738. */
  29739. public function prettifyTestCase(\PHPUnit\Framework\TestCase $test) : string
  29740. {
  29741. $annotations = $test->getAnnotations();
  29742. $annotationWithPlaceholders = \false;
  29743. $callback = static function (string $variable) : string {
  29744. return \sprintf('/%s(?=\\b)/', \preg_quote($variable, '/'));
  29745. };
  29746. if (isset($annotations['method']['testdox'][0])) {
  29747. $result = $annotations['method']['testdox'][0];
  29748. if (\strpos($result, '$') !== \false) {
  29749. $annotation = $annotations['method']['testdox'][0];
  29750. $providedData = $this->mapTestMethodParameterNamesToProvidedDataValues($test);
  29751. $variables = \array_map($callback, \array_keys($providedData));
  29752. $result = \trim(\preg_replace($variables, $providedData, $annotation));
  29753. $annotationWithPlaceholders = \true;
  29754. }
  29755. } else {
  29756. $result = $this->prettifyTestMethod($test->getName(\false));
  29757. }
  29758. if (!$annotationWithPlaceholders && $test->usesDataProvider()) {
  29759. $result .= $this->prettifyDataSet($test);
  29760. }
  29761. return $result;
  29762. }
  29763. public function prettifyDataSet(\PHPUnit\Framework\TestCase $test) : string
  29764. {
  29765. if (!$this->useColor) {
  29766. return $test->getDataSetAsString(\false);
  29767. }
  29768. if (\is_int($test->dataName())) {
  29769. $data = \PHPUnit\Util\Color::dim(' with data set ') . \PHPUnit\Util\Color::colorize('fg-cyan', (string) $test->dataName());
  29770. } else {
  29771. $data = \PHPUnit\Util\Color::dim(' with ') . \PHPUnit\Util\Color::colorize('fg-cyan', \PHPUnit\Util\Color::visualizeWhitespace((string) $test->dataName()));
  29772. }
  29773. return $data;
  29774. }
  29775. /**
  29776. * Prettifies the name of a test method.
  29777. */
  29778. public function prettifyTestMethod(string $name) : string
  29779. {
  29780. $buffer = '';
  29781. if ($name === '') {
  29782. return $buffer;
  29783. }
  29784. $string = (string) \preg_replace('#\\d+$#', '', $name, -1, $count);
  29785. if (\in_array($string, $this->strings)) {
  29786. $name = $string;
  29787. } elseif ($count === 0) {
  29788. $this->strings[] = $string;
  29789. }
  29790. if (\strpos($name, 'test_') === 0) {
  29791. $name = \substr($name, 5);
  29792. } elseif (\strpos($name, 'test') === 0) {
  29793. $name = \substr($name, 4);
  29794. }
  29795. if ($name === '') {
  29796. return $buffer;
  29797. }
  29798. $name[0] = \strtoupper($name[0]);
  29799. if (\strpos($name, '_') !== \false) {
  29800. return \trim(\str_replace('_', ' ', $name));
  29801. }
  29802. $wasNumeric = \false;
  29803. foreach (\range(0, \strlen($name) - 1) as $i) {
  29804. if ($i > 0 && \ord($name[$i]) >= 65 && \ord($name[$i]) <= 90) {
  29805. $buffer .= ' ' . \strtolower($name[$i]);
  29806. } else {
  29807. $isNumeric = \is_numeric($name[$i]);
  29808. if (!$wasNumeric && $isNumeric) {
  29809. $buffer .= ' ';
  29810. $wasNumeric = \true;
  29811. }
  29812. if ($wasNumeric && !$isNumeric) {
  29813. $wasNumeric = \false;
  29814. }
  29815. $buffer .= $name[$i];
  29816. }
  29817. }
  29818. return $buffer;
  29819. }
  29820. /**
  29821. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  29822. */
  29823. private function mapTestMethodParameterNamesToProvidedDataValues(\PHPUnit\Framework\TestCase $test) : array
  29824. {
  29825. try {
  29826. $reflector = new \ReflectionMethod(\get_class($test), $test->getName(\false));
  29827. // @codeCoverageIgnoreStart
  29828. } catch (\ReflectionException $e) {
  29829. throw new \PHPUnit\Util\Exception($e->getMessage(), (int) $e->getCode(), $e);
  29830. }
  29831. // @codeCoverageIgnoreEnd
  29832. $providedData = [];
  29833. $providedDataValues = \array_values($test->getProvidedData());
  29834. $i = 0;
  29835. $providedData['$_dataName'] = $test->dataName();
  29836. foreach ($reflector->getParameters() as $parameter) {
  29837. if (!\array_key_exists($i, $providedDataValues) && $parameter->isDefaultValueAvailable()) {
  29838. try {
  29839. $providedDataValues[$i] = $parameter->getDefaultValue();
  29840. // @codeCoverageIgnoreStart
  29841. } catch (\ReflectionException $e) {
  29842. throw new \PHPUnit\Util\Exception($e->getMessage(), (int) $e->getCode(), $e);
  29843. }
  29844. // @codeCoverageIgnoreEnd
  29845. }
  29846. $value = $providedDataValues[$i++] ?? null;
  29847. if (\is_object($value)) {
  29848. $reflector = new \ReflectionObject($value);
  29849. if ($reflector->hasMethod('__toString')) {
  29850. $value = (string) $value;
  29851. } else {
  29852. $value = \get_class($value);
  29853. }
  29854. }
  29855. if (!\is_scalar($value)) {
  29856. $value = \gettype($value);
  29857. }
  29858. if (\is_bool($value) || \is_int($value) || \is_float($value)) {
  29859. $value = (new \PHPUnit\SebastianBergmann\Exporter\Exporter())->export($value);
  29860. }
  29861. if (\is_string($value) && $value === '') {
  29862. if ($this->useColor) {
  29863. $value = \PHPUnit\Util\Color::colorize('dim,underlined', 'empty');
  29864. } else {
  29865. $value = "''";
  29866. }
  29867. }
  29868. $providedData['$' . $parameter->getName()] = $value;
  29869. }
  29870. if ($this->useColor) {
  29871. $providedData = \array_map(static function ($value) {
  29872. return \PHPUnit\Util\Color::colorize('fg-cyan', \PHPUnit\Util\Color::visualizeWhitespace((string) $value, \true));
  29873. }, $providedData);
  29874. }
  29875. return $providedData;
  29876. }
  29877. }
  29878. <?php
  29879. declare (strict_types=1);
  29880. /*
  29881. * This file is part of PHPUnit.
  29882. *
  29883. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  29884. *
  29885. * For the full copyright and license information, please view the LICENSE
  29886. * file that was distributed with this source code.
  29887. */
  29888. namespace PHPUnit\Util\TestDox;
  29889. use PHPUnit\Framework\Test;
  29890. use PHPUnit\Framework\TestCase;
  29891. use PHPUnit\Framework\TestResult;
  29892. use PHPUnit\Runner\BaseTestRunner;
  29893. use PHPUnit\Runner\PhptTestCase;
  29894. use PHPUnit\Util\Color;
  29895. use PHPUnit\SebastianBergmann\Timer\ResourceUsageFormatter;
  29896. use PHPUnit\SebastianBergmann\Timer\Timer;
  29897. /**
  29898. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  29899. */
  29900. class CliTestDoxPrinter extends \PHPUnit\Util\TestDox\TestDoxPrinter
  29901. {
  29902. /**
  29903. * The default Testdox left margin for messages is a vertical line
  29904. */
  29905. private const PREFIX_SIMPLE = ['default' => '│', 'start' => '│', 'message' => '│', 'diff' => '│', 'trace' => '│', 'last' => '│'];
  29906. /**
  29907. * Colored Testdox use box-drawing for a more textured map of the message
  29908. */
  29909. private const PREFIX_DECORATED = ['default' => '│', 'start' => '�', 'message' => '├', 'diff' => '┊', 'trace' => '╵', 'last' => '┴'];
  29910. private const SPINNER_ICONS = [" \33[36mâ—�\33[0m running tests", " \33[36mâ—“\33[0m running tests", " \33[36mâ—‘\33[0m running tests", " \33[36mâ—’\33[0m running tests"];
  29911. private const STATUS_STYLES = [\PHPUnit\Runner\BaseTestRunner::STATUS_PASSED => ['symbol' => '✔', 'color' => 'fg-green'], \PHPUnit\Runner\BaseTestRunner::STATUS_ERROR => ['symbol' => '✘', 'color' => 'fg-yellow', 'message' => 'bg-yellow,fg-black'], \PHPUnit\Runner\BaseTestRunner::STATUS_FAILURE => ['symbol' => '✘', 'color' => 'fg-red', 'message' => 'bg-red,fg-white'], \PHPUnit\Runner\BaseTestRunner::STATUS_SKIPPED => ['symbol' => '↩', 'color' => 'fg-cyan', 'message' => 'fg-cyan'], \PHPUnit\Runner\BaseTestRunner::STATUS_RISKY => ['symbol' => '☢', 'color' => 'fg-yellow', 'message' => 'fg-yellow'], \PHPUnit\Runner\BaseTestRunner::STATUS_INCOMPLETE => ['symbol' => '∅', 'color' => 'fg-yellow', 'message' => 'fg-yellow'], \PHPUnit\Runner\BaseTestRunner::STATUS_WARNING => ['symbol' => '⚠', 'color' => 'fg-yellow', 'message' => 'fg-yellow'], \PHPUnit\Runner\BaseTestRunner::STATUS_UNKNOWN => ['symbol' => '?', 'color' => 'fg-blue', 'message' => 'fg-white,bg-blue']];
  29912. /**
  29913. * @var int[]
  29914. */
  29915. private $nonSuccessfulTestResults = [];
  29916. /**
  29917. * @var Timer
  29918. */
  29919. private $timer;
  29920. /**
  29921. * @param null|resource|string $out
  29922. * @param int|string $numberOfColumns
  29923. *
  29924. * @throws \PHPUnit\Framework\Exception
  29925. */
  29926. public function __construct($out = null, bool $verbose = \false, string $colors = self::COLOR_DEFAULT, bool $debug = \false, $numberOfColumns = 80, bool $reverse = \false)
  29927. {
  29928. parent::__construct($out, $verbose, $colors, $debug, $numberOfColumns, $reverse);
  29929. $this->timer = new \PHPUnit\SebastianBergmann\Timer\Timer();
  29930. $this->timer->start();
  29931. }
  29932. public function printResult(\PHPUnit\Framework\TestResult $result) : void
  29933. {
  29934. $this->printHeader($result);
  29935. $this->printNonSuccessfulTestsSummary($result->count());
  29936. $this->printFooter($result);
  29937. }
  29938. protected function printHeader(\PHPUnit\Framework\TestResult $result) : void
  29939. {
  29940. $this->write("\n" . (new \PHPUnit\SebastianBergmann\Timer\ResourceUsageFormatter())->resourceUsage($this->timer->stop()) . "\n\n");
  29941. }
  29942. protected function formatClassName(\PHPUnit\Framework\Test $test) : string
  29943. {
  29944. if ($test instanceof \PHPUnit\Framework\TestCase) {
  29945. return $this->prettifier->prettifyTestClass(\get_class($test));
  29946. }
  29947. return \get_class($test);
  29948. }
  29949. /**
  29950. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  29951. */
  29952. protected function registerTestResult(\PHPUnit\Framework\Test $test, ?\Throwable $t, int $status, float $time, bool $verbose) : void
  29953. {
  29954. if ($status !== \PHPUnit\Runner\BaseTestRunner::STATUS_PASSED) {
  29955. $this->nonSuccessfulTestResults[] = $this->testIndex;
  29956. }
  29957. parent::registerTestResult($test, $t, $status, $time, $verbose);
  29958. }
  29959. /**
  29960. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  29961. */
  29962. protected function formatTestName(\PHPUnit\Framework\Test $test) : string
  29963. {
  29964. if ($test instanceof \PHPUnit\Framework\TestCase) {
  29965. return $this->prettifier->prettifyTestCase($test);
  29966. }
  29967. return parent::formatTestName($test);
  29968. }
  29969. protected function writeTestResult(array $prevResult, array $result) : void
  29970. {
  29971. // spacer line for new suite headers and after verbose messages
  29972. if ($prevResult['testName'] !== '' && (!empty($prevResult['message']) || $prevResult['className'] !== $result['className'])) {
  29973. $this->write(\PHP_EOL);
  29974. }
  29975. // suite header
  29976. if ($prevResult['className'] !== $result['className']) {
  29977. $this->write($this->colorizeTextBox('underlined', $result['className']) . \PHP_EOL);
  29978. }
  29979. // test result line
  29980. if ($this->colors && $result['className'] === \PHPUnit\Runner\PhptTestCase::class) {
  29981. $testName = \PHPUnit\Util\Color::colorizePath($result['testName'], $prevResult['testName'], \true);
  29982. } else {
  29983. $testName = $result['testMethod'];
  29984. }
  29985. $style = self::STATUS_STYLES[$result['status']];
  29986. $line = \sprintf(' %s %s%s' . \PHP_EOL, $this->colorizeTextBox($style['color'], $style['symbol']), $testName, $this->verbose ? ' ' . $this->formatRuntime($result['time'], $style['color']) : '');
  29987. $this->write($line);
  29988. // additional information when verbose
  29989. $this->write($result['message']);
  29990. }
  29991. protected function formatThrowable(\Throwable $t, ?int $status = null) : string
  29992. {
  29993. return \trim(\PHPUnit\Framework\TestFailure::exceptionToString($t));
  29994. }
  29995. protected function colorizeMessageAndDiff(string $style, string $buffer) : array
  29996. {
  29997. $lines = $buffer ? \array_map('\\rtrim', \explode(\PHP_EOL, $buffer)) : [];
  29998. $message = [];
  29999. $diff = [];
  30000. $insideDiff = \false;
  30001. foreach ($lines as $line) {
  30002. if ($line === '--- Expected') {
  30003. $insideDiff = \true;
  30004. }
  30005. if (!$insideDiff) {
  30006. $message[] = $line;
  30007. } else {
  30008. if (\strpos($line, '-') === 0) {
  30009. $line = \PHPUnit\Util\Color::colorize('fg-red', \PHPUnit\Util\Color::visualizeWhitespace($line, \true));
  30010. } elseif (\strpos($line, '+') === 0) {
  30011. $line = \PHPUnit\Util\Color::colorize('fg-green', \PHPUnit\Util\Color::visualizeWhitespace($line, \true));
  30012. } elseif ($line === '@@ @@') {
  30013. $line = \PHPUnit\Util\Color::colorize('fg-cyan', $line);
  30014. }
  30015. $diff[] = $line;
  30016. }
  30017. }
  30018. $diff = \implode(\PHP_EOL, $diff);
  30019. if (!empty($message)) {
  30020. $message = $this->colorizeTextBox($style, \implode(\PHP_EOL, $message));
  30021. }
  30022. return [$message, $diff];
  30023. }
  30024. protected function formatStacktrace(\Throwable $t) : string
  30025. {
  30026. $trace = \PHPUnit\Util\Filter::getFilteredStacktrace($t);
  30027. if (!$this->colors) {
  30028. return $trace;
  30029. }
  30030. $lines = [];
  30031. $prevPath = '';
  30032. foreach (\explode(\PHP_EOL, $trace) as $line) {
  30033. if (\preg_match('/^(.*):(\\d+)$/', $line, $matches)) {
  30034. $lines[] = \PHPUnit\Util\Color::colorizePath($matches[1], $prevPath) . \PHPUnit\Util\Color::dim(':') . \PHPUnit\Util\Color::colorize('fg-blue', $matches[2]) . "\n";
  30035. $prevPath = $matches[1];
  30036. } else {
  30037. $lines[] = $line;
  30038. $prevPath = '';
  30039. }
  30040. }
  30041. return \implode('', $lines);
  30042. }
  30043. protected function formatTestResultMessage(\Throwable $t, array $result, ?string $prefix = null) : string
  30044. {
  30045. $message = $this->formatThrowable($t, $result['status']);
  30046. $diff = '';
  30047. if (!($this->verbose || $result['verbose'])) {
  30048. return '';
  30049. }
  30050. if ($message && $this->colors) {
  30051. $style = self::STATUS_STYLES[$result['status']]['message'] ?? '';
  30052. [$message, $diff] = $this->colorizeMessageAndDiff($style, $message);
  30053. }
  30054. if ($prefix === null || !$this->colors) {
  30055. $prefix = self::PREFIX_SIMPLE;
  30056. }
  30057. if ($this->colors) {
  30058. $color = self::STATUS_STYLES[$result['status']]['color'] ?? '';
  30059. $prefix = \array_map(static function ($p) use($color) {
  30060. return \PHPUnit\Util\Color::colorize($color, $p);
  30061. }, self::PREFIX_DECORATED);
  30062. }
  30063. $trace = $this->formatStacktrace($t);
  30064. $out = $this->prefixLines($prefix['start'], \PHP_EOL) . \PHP_EOL;
  30065. if ($message) {
  30066. $out .= $this->prefixLines($prefix['message'], $message . \PHP_EOL) . \PHP_EOL;
  30067. }
  30068. if ($diff) {
  30069. $out .= $this->prefixLines($prefix['diff'], $diff . \PHP_EOL) . \PHP_EOL;
  30070. }
  30071. if ($trace) {
  30072. if ($message || $diff) {
  30073. $out .= $this->prefixLines($prefix['default'], \PHP_EOL) . \PHP_EOL;
  30074. }
  30075. $out .= $this->prefixLines($prefix['trace'], $trace . \PHP_EOL) . \PHP_EOL;
  30076. }
  30077. $out .= $this->prefixLines($prefix['last'], \PHP_EOL) . \PHP_EOL;
  30078. return $out;
  30079. }
  30080. protected function drawSpinner() : void
  30081. {
  30082. if ($this->colors) {
  30083. $id = $this->spinState % \count(self::SPINNER_ICONS);
  30084. $this->write(self::SPINNER_ICONS[$id]);
  30085. }
  30086. }
  30087. protected function undrawSpinner() : void
  30088. {
  30089. if ($this->colors) {
  30090. $id = $this->spinState % \count(self::SPINNER_ICONS);
  30091. $this->write("\33[1K\33[" . \strlen(self::SPINNER_ICONS[$id]) . 'D');
  30092. }
  30093. }
  30094. private function formatRuntime(float $time, string $color = '') : string
  30095. {
  30096. if (!$this->colors) {
  30097. return \sprintf('[%.2f ms]', $time * 1000);
  30098. }
  30099. if ($time > 1) {
  30100. $color = 'fg-magenta';
  30101. }
  30102. return \PHPUnit\Util\Color::colorize($color, ' ' . (int) \ceil($time * 1000) . ' ' . \PHPUnit\Util\Color::dim('ms'));
  30103. }
  30104. private function printNonSuccessfulTestsSummary(int $numberOfExecutedTests) : void
  30105. {
  30106. if (empty($this->nonSuccessfulTestResults)) {
  30107. return;
  30108. }
  30109. if (\count($this->nonSuccessfulTestResults) / $numberOfExecutedTests >= 0.7) {
  30110. return;
  30111. }
  30112. $this->write("Summary of non-successful tests:\n\n");
  30113. $prevResult = $this->getEmptyTestResult();
  30114. foreach ($this->nonSuccessfulTestResults as $testIndex) {
  30115. $result = $this->testResults[$testIndex];
  30116. $this->writeTestResult($prevResult, $result);
  30117. $prevResult = $result;
  30118. }
  30119. }
  30120. }
  30121. <?php
  30122. declare (strict_types=1);
  30123. /*
  30124. * This file is part of PHPUnit.
  30125. *
  30126. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  30127. *
  30128. * For the full copyright and license information, please view the LICENSE
  30129. * file that was distributed with this source code.
  30130. */
  30131. namespace PHPUnit\Util\TestDox;
  30132. use PHPUnit\Framework\AssertionFailedError;
  30133. use PHPUnit\Framework\Test;
  30134. use PHPUnit\Framework\TestCase;
  30135. use PHPUnit\Framework\TestSuite;
  30136. use PHPUnit\Framework\Warning;
  30137. use PHPUnit\Framework\WarningTestCase;
  30138. use PHPUnit\Runner\BaseTestRunner;
  30139. use PHPUnit\TextUI\ResultPrinter as ResultPrinterInterface;
  30140. use PHPUnit\Util\Printer;
  30141. /**
  30142. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  30143. */
  30144. abstract class ResultPrinter extends \PHPUnit\Util\Printer implements \PHPUnit\TextUI\ResultPrinter
  30145. {
  30146. /**
  30147. * @var NamePrettifier
  30148. */
  30149. protected $prettifier;
  30150. /**
  30151. * @var string
  30152. */
  30153. protected $testClass = '';
  30154. /**
  30155. * @var int
  30156. */
  30157. protected $testStatus;
  30158. /**
  30159. * @var array
  30160. */
  30161. protected $tests = [];
  30162. /**
  30163. * @var int
  30164. */
  30165. protected $successful = 0;
  30166. /**
  30167. * @var int
  30168. */
  30169. protected $warned = 0;
  30170. /**
  30171. * @var int
  30172. */
  30173. protected $failed = 0;
  30174. /**
  30175. * @var int
  30176. */
  30177. protected $risky = 0;
  30178. /**
  30179. * @var int
  30180. */
  30181. protected $skipped = 0;
  30182. /**
  30183. * @var int
  30184. */
  30185. protected $incomplete = 0;
  30186. /**
  30187. * @var null|string
  30188. */
  30189. protected $currentTestClassPrettified;
  30190. /**
  30191. * @var null|string
  30192. */
  30193. protected $currentTestMethodPrettified;
  30194. /**
  30195. * @var array
  30196. */
  30197. private $groups;
  30198. /**
  30199. * @var array
  30200. */
  30201. private $excludeGroups;
  30202. /**
  30203. * @param resource $out
  30204. *
  30205. * @throws \PHPUnit\Framework\Exception
  30206. */
  30207. public function __construct($out = null, array $groups = [], array $excludeGroups = [])
  30208. {
  30209. parent::__construct($out);
  30210. $this->groups = $groups;
  30211. $this->excludeGroups = $excludeGroups;
  30212. $this->prettifier = new \PHPUnit\Util\TestDox\NamePrettifier();
  30213. $this->startRun();
  30214. }
  30215. /**
  30216. * Flush buffer and close output.
  30217. */
  30218. public function flush() : void
  30219. {
  30220. $this->doEndClass();
  30221. $this->endRun();
  30222. parent::flush();
  30223. }
  30224. /**
  30225. * An error occurred.
  30226. */
  30227. public function addError(\PHPUnit\Framework\Test $test, \Throwable $t, float $time) : void
  30228. {
  30229. if (!$this->isOfInterest($test)) {
  30230. return;
  30231. }
  30232. $this->testStatus = \PHPUnit\Runner\BaseTestRunner::STATUS_ERROR;
  30233. $this->failed++;
  30234. }
  30235. /**
  30236. * A warning occurred.
  30237. */
  30238. public function addWarning(\PHPUnit\Framework\Test $test, \PHPUnit\Framework\Warning $e, float $time) : void
  30239. {
  30240. if (!$this->isOfInterest($test)) {
  30241. return;
  30242. }
  30243. $this->testStatus = \PHPUnit\Runner\BaseTestRunner::STATUS_WARNING;
  30244. $this->warned++;
  30245. }
  30246. /**
  30247. * A failure occurred.
  30248. */
  30249. public function addFailure(\PHPUnit\Framework\Test $test, \PHPUnit\Framework\AssertionFailedError $e, float $time) : void
  30250. {
  30251. if (!$this->isOfInterest($test)) {
  30252. return;
  30253. }
  30254. $this->testStatus = \PHPUnit\Runner\BaseTestRunner::STATUS_FAILURE;
  30255. $this->failed++;
  30256. }
  30257. /**
  30258. * Incomplete test.
  30259. */
  30260. public function addIncompleteTest(\PHPUnit\Framework\Test $test, \Throwable $t, float $time) : void
  30261. {
  30262. if (!$this->isOfInterest($test)) {
  30263. return;
  30264. }
  30265. $this->testStatus = \PHPUnit\Runner\BaseTestRunner::STATUS_INCOMPLETE;
  30266. $this->incomplete++;
  30267. }
  30268. /**
  30269. * Risky test.
  30270. */
  30271. public function addRiskyTest(\PHPUnit\Framework\Test $test, \Throwable $t, float $time) : void
  30272. {
  30273. if (!$this->isOfInterest($test)) {
  30274. return;
  30275. }
  30276. $this->testStatus = \PHPUnit\Runner\BaseTestRunner::STATUS_RISKY;
  30277. $this->risky++;
  30278. }
  30279. /**
  30280. * Skipped test.
  30281. */
  30282. public function addSkippedTest(\PHPUnit\Framework\Test $test, \Throwable $t, float $time) : void
  30283. {
  30284. if (!$this->isOfInterest($test)) {
  30285. return;
  30286. }
  30287. $this->testStatus = \PHPUnit\Runner\BaseTestRunner::STATUS_SKIPPED;
  30288. $this->skipped++;
  30289. }
  30290. /**
  30291. * A testsuite started.
  30292. */
  30293. public function startTestSuite(\PHPUnit\Framework\TestSuite $suite) : void
  30294. {
  30295. }
  30296. /**
  30297. * A testsuite ended.
  30298. */
  30299. public function endTestSuite(\PHPUnit\Framework\TestSuite $suite) : void
  30300. {
  30301. }
  30302. /**
  30303. * A test started.
  30304. *
  30305. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  30306. */
  30307. public function startTest(\PHPUnit\Framework\Test $test) : void
  30308. {
  30309. if (!$this->isOfInterest($test)) {
  30310. return;
  30311. }
  30312. $class = \get_class($test);
  30313. if ($this->testClass !== $class) {
  30314. if ($this->testClass !== '') {
  30315. $this->doEndClass();
  30316. }
  30317. $this->currentTestClassPrettified = $this->prettifier->prettifyTestClass($class);
  30318. $this->testClass = $class;
  30319. $this->tests = [];
  30320. $this->startClass($class);
  30321. }
  30322. if ($test instanceof \PHPUnit\Framework\TestCase) {
  30323. $this->currentTestMethodPrettified = $this->prettifier->prettifyTestCase($test);
  30324. }
  30325. $this->testStatus = \PHPUnit\Runner\BaseTestRunner::STATUS_PASSED;
  30326. }
  30327. /**
  30328. * A test ended.
  30329. */
  30330. public function endTest(\PHPUnit\Framework\Test $test, float $time) : void
  30331. {
  30332. if (!$this->isOfInterest($test)) {
  30333. return;
  30334. }
  30335. $this->tests[] = [$this->currentTestMethodPrettified, $this->testStatus];
  30336. $this->currentTestClassPrettified = null;
  30337. $this->currentTestMethodPrettified = null;
  30338. }
  30339. protected function doEndClass() : void
  30340. {
  30341. foreach ($this->tests as $test) {
  30342. $this->onTest($test[0], $test[1] === \PHPUnit\Runner\BaseTestRunner::STATUS_PASSED);
  30343. }
  30344. $this->endClass($this->testClass);
  30345. }
  30346. /**
  30347. * Handler for 'start run' event.
  30348. */
  30349. protected function startRun() : void
  30350. {
  30351. }
  30352. /**
  30353. * Handler for 'start class' event.
  30354. */
  30355. protected function startClass(string $name) : void
  30356. {
  30357. }
  30358. /**
  30359. * Handler for 'on test' event.
  30360. */
  30361. protected function onTest(string $name, bool $success = \true) : void
  30362. {
  30363. }
  30364. /**
  30365. * Handler for 'end class' event.
  30366. */
  30367. protected function endClass(string $name) : void
  30368. {
  30369. }
  30370. /**
  30371. * Handler for 'end run' event.
  30372. */
  30373. protected function endRun() : void
  30374. {
  30375. }
  30376. private function isOfInterest(\PHPUnit\Framework\Test $test) : bool
  30377. {
  30378. if (!$test instanceof \PHPUnit\Framework\TestCase) {
  30379. return \false;
  30380. }
  30381. if ($test instanceof \PHPUnit\Framework\WarningTestCase) {
  30382. return \false;
  30383. }
  30384. if (!empty($this->groups)) {
  30385. foreach ($test->getGroups() as $group) {
  30386. if (\in_array($group, $this->groups)) {
  30387. return \true;
  30388. }
  30389. }
  30390. return \false;
  30391. }
  30392. if (!empty($this->excludeGroups)) {
  30393. foreach ($test->getGroups() as $group) {
  30394. if (\in_array($group, $this->excludeGroups)) {
  30395. return \false;
  30396. }
  30397. }
  30398. return \true;
  30399. }
  30400. return \true;
  30401. }
  30402. }
  30403. <?php
  30404. declare (strict_types=1);
  30405. /*
  30406. * This file is part of PHPUnit.
  30407. *
  30408. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  30409. *
  30410. * For the full copyright and license information, please view the LICENSE
  30411. * file that was distributed with this source code.
  30412. */
  30413. namespace PHPUnit\Util\TestDox;
  30414. use PHPUnit\Framework\AssertionFailedError;
  30415. use PHPUnit\Framework\Exception;
  30416. use PHPUnit\Framework\Test;
  30417. use PHPUnit\Framework\TestCase;
  30418. use PHPUnit\Framework\TestListener;
  30419. use PHPUnit\Framework\TestSuite;
  30420. use PHPUnit\Framework\Warning;
  30421. use PHPUnit\Util\Printer;
  30422. /**
  30423. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  30424. */
  30425. final class XmlResultPrinter extends \PHPUnit\Util\Printer implements \PHPUnit\Framework\TestListener
  30426. {
  30427. /**
  30428. * @var \DOMDocument
  30429. */
  30430. private $document;
  30431. /**
  30432. * @var \DOMElement
  30433. */
  30434. private $root;
  30435. /**
  30436. * @var NamePrettifier
  30437. */
  30438. private $prettifier;
  30439. /**
  30440. * @var null|\Throwable
  30441. */
  30442. private $exception;
  30443. /**
  30444. * @param resource|string $out
  30445. *
  30446. * @throws Exception
  30447. */
  30448. public function __construct($out = null)
  30449. {
  30450. $this->document = new \DOMDocument('1.0', 'UTF-8');
  30451. $this->document->formatOutput = \true;
  30452. $this->root = $this->document->createElement('tests');
  30453. $this->document->appendChild($this->root);
  30454. $this->prettifier = new \PHPUnit\Util\TestDox\NamePrettifier();
  30455. parent::__construct($out);
  30456. }
  30457. /**
  30458. * Flush buffer and close output.
  30459. */
  30460. public function flush() : void
  30461. {
  30462. $this->write($this->document->saveXML());
  30463. parent::flush();
  30464. }
  30465. /**
  30466. * An error occurred.
  30467. */
  30468. public function addError(\PHPUnit\Framework\Test $test, \Throwable $t, float $time) : void
  30469. {
  30470. $this->exception = $t;
  30471. }
  30472. /**
  30473. * A warning occurred.
  30474. */
  30475. public function addWarning(\PHPUnit\Framework\Test $test, \PHPUnit\Framework\Warning $e, float $time) : void
  30476. {
  30477. }
  30478. /**
  30479. * A failure occurred.
  30480. */
  30481. public function addFailure(\PHPUnit\Framework\Test $test, \PHPUnit\Framework\AssertionFailedError $e, float $time) : void
  30482. {
  30483. $this->exception = $e;
  30484. }
  30485. /**
  30486. * Incomplete test.
  30487. */
  30488. public function addIncompleteTest(\PHPUnit\Framework\Test $test, \Throwable $t, float $time) : void
  30489. {
  30490. }
  30491. /**
  30492. * Risky test.
  30493. */
  30494. public function addRiskyTest(\PHPUnit\Framework\Test $test, \Throwable $t, float $time) : void
  30495. {
  30496. }
  30497. /**
  30498. * Skipped test.
  30499. */
  30500. public function addSkippedTest(\PHPUnit\Framework\Test $test, \Throwable $t, float $time) : void
  30501. {
  30502. }
  30503. /**
  30504. * A test suite started.
  30505. */
  30506. public function startTestSuite(\PHPUnit\Framework\TestSuite $suite) : void
  30507. {
  30508. }
  30509. /**
  30510. * A test suite ended.
  30511. */
  30512. public function endTestSuite(\PHPUnit\Framework\TestSuite $suite) : void
  30513. {
  30514. }
  30515. /**
  30516. * A test started.
  30517. */
  30518. public function startTest(\PHPUnit\Framework\Test $test) : void
  30519. {
  30520. $this->exception = null;
  30521. }
  30522. /**
  30523. * A test ended.
  30524. *
  30525. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  30526. */
  30527. public function endTest(\PHPUnit\Framework\Test $test, float $time) : void
  30528. {
  30529. if (!$test instanceof \PHPUnit\Framework\TestCase) {
  30530. return;
  30531. }
  30532. $groups = \array_filter($test->getGroups(), static function ($group) {
  30533. return !($group === 'small' || $group === 'medium' || $group === 'large');
  30534. });
  30535. $testNode = $this->document->createElement('test');
  30536. $testNode->setAttribute('className', \get_class($test));
  30537. $testNode->setAttribute('methodName', $test->getName());
  30538. $testNode->setAttribute('prettifiedClassName', $this->prettifier->prettifyTestClass(\get_class($test)));
  30539. $testNode->setAttribute('prettifiedMethodName', $this->prettifier->prettifyTestCase($test));
  30540. $testNode->setAttribute('status', (string) $test->getStatus());
  30541. $testNode->setAttribute('time', (string) $time);
  30542. $testNode->setAttribute('size', (string) $test->getSize());
  30543. $testNode->setAttribute('groups', \implode(',', $groups));
  30544. foreach ($groups as $group) {
  30545. $groupNode = $this->document->createElement('group');
  30546. $groupNode->setAttribute('name', $group);
  30547. $testNode->appendChild($groupNode);
  30548. }
  30549. $annotations = $test->getAnnotations();
  30550. foreach (['class', 'method'] as $type) {
  30551. foreach ($annotations[$type] as $annotation => $values) {
  30552. if ($annotation !== 'covers' && $annotation !== 'uses') {
  30553. continue;
  30554. }
  30555. foreach ($values as $value) {
  30556. $coversNode = $this->document->createElement($annotation);
  30557. $coversNode->setAttribute('target', $value);
  30558. $testNode->appendChild($coversNode);
  30559. }
  30560. }
  30561. }
  30562. foreach ($test->doubledTypes() as $doubledType) {
  30563. $testDoubleNode = $this->document->createElement('testDouble');
  30564. $testDoubleNode->setAttribute('type', $doubledType);
  30565. $testNode->appendChild($testDoubleNode);
  30566. }
  30567. $inlineAnnotations = \PHPUnit\Util\Test::getInlineAnnotations(\get_class($test), $test->getName(\false));
  30568. if (isset($inlineAnnotations['given'], $inlineAnnotations['when'], $inlineAnnotations['then'])) {
  30569. $testNode->setAttribute('given', $inlineAnnotations['given']['value']);
  30570. $testNode->setAttribute('givenStartLine', (string) $inlineAnnotations['given']['line']);
  30571. $testNode->setAttribute('when', $inlineAnnotations['when']['value']);
  30572. $testNode->setAttribute('whenStartLine', (string) $inlineAnnotations['when']['line']);
  30573. $testNode->setAttribute('then', $inlineAnnotations['then']['value']);
  30574. $testNode->setAttribute('thenStartLine', (string) $inlineAnnotations['then']['line']);
  30575. }
  30576. if ($this->exception !== null) {
  30577. if ($this->exception instanceof \PHPUnit\Framework\Exception) {
  30578. $steps = $this->exception->getSerializableTrace();
  30579. } else {
  30580. $steps = $this->exception->getTrace();
  30581. }
  30582. try {
  30583. $file = (new \ReflectionClass($test))->getFileName();
  30584. // @codeCoverageIgnoreStart
  30585. } catch (\ReflectionException $e) {
  30586. throw new \PHPUnit\Framework\Exception($e->getMessage(), (int) $e->getCode(), $e);
  30587. }
  30588. // @codeCoverageIgnoreEnd
  30589. foreach ($steps as $step) {
  30590. if (isset($step['file']) && $step['file'] === $file) {
  30591. $testNode->setAttribute('exceptionLine', (string) $step['line']);
  30592. break;
  30593. }
  30594. }
  30595. $testNode->setAttribute('exceptionMessage', $this->exception->getMessage());
  30596. }
  30597. $this->root->appendChild($testNode);
  30598. }
  30599. }
  30600. <?php
  30601. declare (strict_types=1);
  30602. /*
  30603. * This file is part of PHPUnit.
  30604. *
  30605. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  30606. *
  30607. * For the full copyright and license information, please view the LICENSE
  30608. * file that was distributed with this source code.
  30609. */
  30610. namespace PHPUnit\Util\TestDox;
  30611. use PHPUnit\Framework\AssertionFailedError;
  30612. use PHPUnit\Framework\Test;
  30613. use PHPUnit\Framework\TestCase;
  30614. use PHPUnit\Framework\TestResult;
  30615. use PHPUnit\Framework\TestSuite;
  30616. use PHPUnit\Framework\Warning;
  30617. use PHPUnit\Runner\BaseTestRunner;
  30618. use PHPUnit\Runner\PhptTestCase;
  30619. use PHPUnit\Runner\TestSuiteSorter;
  30620. use PHPUnit\TextUI\DefaultResultPrinter;
  30621. /**
  30622. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  30623. */
  30624. class TestDoxPrinter extends \PHPUnit\TextUI\DefaultResultPrinter
  30625. {
  30626. /**
  30627. * @var NamePrettifier
  30628. */
  30629. protected $prettifier;
  30630. /**
  30631. * @var int The number of test results received from the TestRunner
  30632. */
  30633. protected $testIndex = 0;
  30634. /**
  30635. * @var int The number of test results already sent to the output
  30636. */
  30637. protected $testFlushIndex = 0;
  30638. /**
  30639. * @var array<int, array> Buffer for test results
  30640. */
  30641. protected $testResults = [];
  30642. /**
  30643. * @var array<string, int> Lookup table for testname to testResults[index]
  30644. */
  30645. protected $testNameResultIndex = [];
  30646. /**
  30647. * @var bool
  30648. */
  30649. protected $enableOutputBuffer = \false;
  30650. /**
  30651. * @var array array<string>
  30652. */
  30653. protected $originalExecutionOrder = [];
  30654. /**
  30655. * @var int
  30656. */
  30657. protected $spinState = 0;
  30658. /**
  30659. * @var bool
  30660. */
  30661. protected $showProgress = \true;
  30662. /**
  30663. * @param null|resource|string $out
  30664. * @param int|string $numberOfColumns
  30665. *
  30666. * @throws \PHPUnit\Framework\Exception
  30667. */
  30668. public function __construct($out = null, bool $verbose = \false, string $colors = self::COLOR_DEFAULT, bool $debug = \false, $numberOfColumns = 80, bool $reverse = \false)
  30669. {
  30670. parent::__construct($out, $verbose, $colors, $debug, $numberOfColumns, $reverse);
  30671. $this->prettifier = new \PHPUnit\Util\TestDox\NamePrettifier($this->colors);
  30672. }
  30673. public function setOriginalExecutionOrder(array $order) : void
  30674. {
  30675. $this->originalExecutionOrder = $order;
  30676. $this->enableOutputBuffer = !empty($order);
  30677. }
  30678. public function setShowProgressAnimation(bool $showProgress) : void
  30679. {
  30680. $this->showProgress = $showProgress;
  30681. }
  30682. public function printResult(\PHPUnit\Framework\TestResult $result) : void
  30683. {
  30684. }
  30685. /**
  30686. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  30687. */
  30688. public function endTest(\PHPUnit\Framework\Test $test, float $time) : void
  30689. {
  30690. if (!$test instanceof \PHPUnit\Framework\TestCase && !$test instanceof \PHPUnit\Runner\PhptTestCase && !$test instanceof \PHPUnit\Framework\TestSuite) {
  30691. return;
  30692. }
  30693. if ($this->testHasPassed()) {
  30694. $this->registerTestResult($test, null, \PHPUnit\Runner\BaseTestRunner::STATUS_PASSED, $time, \false);
  30695. }
  30696. if ($test instanceof \PHPUnit\Framework\TestCase || $test instanceof \PHPUnit\Runner\PhptTestCase) {
  30697. $this->testIndex++;
  30698. }
  30699. parent::endTest($test, $time);
  30700. }
  30701. /**
  30702. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  30703. */
  30704. public function addError(\PHPUnit\Framework\Test $test, \Throwable $t, float $time) : void
  30705. {
  30706. $this->registerTestResult($test, $t, \PHPUnit\Runner\BaseTestRunner::STATUS_ERROR, $time, \true);
  30707. }
  30708. /**
  30709. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  30710. */
  30711. public function addWarning(\PHPUnit\Framework\Test $test, \PHPUnit\Framework\Warning $e, float $time) : void
  30712. {
  30713. $this->registerTestResult($test, $e, \PHPUnit\Runner\BaseTestRunner::STATUS_WARNING, $time, \true);
  30714. }
  30715. /**
  30716. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  30717. */
  30718. public function addFailure(\PHPUnit\Framework\Test $test, \PHPUnit\Framework\AssertionFailedError $e, float $time) : void
  30719. {
  30720. $this->registerTestResult($test, $e, \PHPUnit\Runner\BaseTestRunner::STATUS_FAILURE, $time, \true);
  30721. }
  30722. /**
  30723. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  30724. */
  30725. public function addIncompleteTest(\PHPUnit\Framework\Test $test, \Throwable $t, float $time) : void
  30726. {
  30727. $this->registerTestResult($test, $t, \PHPUnit\Runner\BaseTestRunner::STATUS_INCOMPLETE, $time, \false);
  30728. }
  30729. /**
  30730. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  30731. */
  30732. public function addRiskyTest(\PHPUnit\Framework\Test $test, \Throwable $t, float $time) : void
  30733. {
  30734. $this->registerTestResult($test, $t, \PHPUnit\Runner\BaseTestRunner::STATUS_RISKY, $time, \false);
  30735. }
  30736. /**
  30737. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  30738. */
  30739. public function addSkippedTest(\PHPUnit\Framework\Test $test, \Throwable $t, float $time) : void
  30740. {
  30741. $this->registerTestResult($test, $t, \PHPUnit\Runner\BaseTestRunner::STATUS_SKIPPED, $time, \false);
  30742. }
  30743. public function writeProgress(string $progress) : void
  30744. {
  30745. $this->flushOutputBuffer();
  30746. }
  30747. public function flush() : void
  30748. {
  30749. $this->flushOutputBuffer(\true);
  30750. }
  30751. /**
  30752. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  30753. */
  30754. protected function registerTestResult(\PHPUnit\Framework\Test $test, ?\Throwable $t, int $status, float $time, bool $verbose) : void
  30755. {
  30756. $testName = \PHPUnit\Runner\TestSuiteSorter::getTestSorterUID($test);
  30757. $result = ['className' => $this->formatClassName($test), 'testName' => $testName, 'testMethod' => $this->formatTestName($test), 'message' => '', 'status' => $status, 'time' => $time, 'verbose' => $verbose];
  30758. if ($t !== null) {
  30759. $result['message'] = $this->formatTestResultMessage($t, $result);
  30760. }
  30761. $this->testResults[$this->testIndex] = $result;
  30762. $this->testNameResultIndex[$testName] = $this->testIndex;
  30763. }
  30764. protected function formatTestName(\PHPUnit\Framework\Test $test) : string
  30765. {
  30766. return $test->getName();
  30767. }
  30768. protected function formatClassName(\PHPUnit\Framework\Test $test) : string
  30769. {
  30770. return \get_class($test);
  30771. }
  30772. protected function testHasPassed() : bool
  30773. {
  30774. if (!isset($this->testResults[$this->testIndex]['status'])) {
  30775. return \true;
  30776. }
  30777. if ($this->testResults[$this->testIndex]['status'] === \PHPUnit\Runner\BaseTestRunner::STATUS_PASSED) {
  30778. return \true;
  30779. }
  30780. return \false;
  30781. }
  30782. protected function flushOutputBuffer(bool $forceFlush = \false) : void
  30783. {
  30784. if ($this->testFlushIndex === $this->testIndex) {
  30785. return;
  30786. }
  30787. if ($this->testFlushIndex > 0) {
  30788. if ($this->enableOutputBuffer) {
  30789. $prevResult = $this->getTestResultByName($this->originalExecutionOrder[$this->testFlushIndex - 1]);
  30790. } else {
  30791. $prevResult = $this->testResults[$this->testFlushIndex - 1];
  30792. }
  30793. } else {
  30794. $prevResult = $this->getEmptyTestResult();
  30795. }
  30796. if (!$this->enableOutputBuffer) {
  30797. $this->writeTestResult($prevResult, $this->testResults[$this->testFlushIndex++]);
  30798. } else {
  30799. do {
  30800. $flushed = \false;
  30801. if (!$forceFlush && isset($this->originalExecutionOrder[$this->testFlushIndex])) {
  30802. $result = $this->getTestResultByName($this->originalExecutionOrder[$this->testFlushIndex]);
  30803. } else {
  30804. // This test(name) cannot found in original execution order,
  30805. // flush result to output stream right away
  30806. $result = $this->testResults[$this->testFlushIndex];
  30807. }
  30808. if (!empty($result)) {
  30809. $this->hideSpinner();
  30810. $this->writeTestResult($prevResult, $result);
  30811. $this->testFlushIndex++;
  30812. $prevResult = $result;
  30813. $flushed = \true;
  30814. } else {
  30815. $this->showSpinner();
  30816. }
  30817. } while ($flushed && $this->testFlushIndex < $this->testIndex);
  30818. }
  30819. }
  30820. protected function showSpinner() : void
  30821. {
  30822. if (!$this->showProgress) {
  30823. return;
  30824. }
  30825. if ($this->spinState) {
  30826. $this->undrawSpinner();
  30827. }
  30828. $this->spinState++;
  30829. $this->drawSpinner();
  30830. }
  30831. protected function hideSpinner() : void
  30832. {
  30833. if (!$this->showProgress) {
  30834. return;
  30835. }
  30836. if ($this->spinState) {
  30837. $this->undrawSpinner();
  30838. }
  30839. $this->spinState = 0;
  30840. }
  30841. protected function drawSpinner() : void
  30842. {
  30843. // optional for CLI printers: show the user a 'buffering output' spinner
  30844. }
  30845. protected function undrawSpinner() : void
  30846. {
  30847. // remove the spinner from the current line
  30848. }
  30849. protected function writeTestResult(array $prevResult, array $result) : void
  30850. {
  30851. }
  30852. protected function getEmptyTestResult() : array
  30853. {
  30854. return ['className' => '', 'testName' => '', 'message' => '', 'failed' => '', 'verbose' => ''];
  30855. }
  30856. protected function getTestResultByName(?string $testName) : array
  30857. {
  30858. if (isset($this->testNameResultIndex[$testName])) {
  30859. return $this->testResults[$this->testNameResultIndex[$testName]];
  30860. }
  30861. return [];
  30862. }
  30863. protected function formatThrowable(\Throwable $t, ?int $status = null) : string
  30864. {
  30865. $message = \trim(\PHPUnit\Framework\TestFailure::exceptionToString($t));
  30866. if ($message) {
  30867. $message .= \PHP_EOL . \PHP_EOL . $this->formatStacktrace($t);
  30868. } else {
  30869. $message = $this->formatStacktrace($t);
  30870. }
  30871. return $message;
  30872. }
  30873. protected function formatStacktrace(\Throwable $t) : string
  30874. {
  30875. return \PHPUnit\Util\Filter::getFilteredStacktrace($t);
  30876. }
  30877. protected function formatTestResultMessage(\Throwable $t, array $result, string $prefix = '│') : string
  30878. {
  30879. $message = $this->formatThrowable($t, $result['status']);
  30880. if ($message === '') {
  30881. return '';
  30882. }
  30883. if (!($this->verbose || $result['verbose'])) {
  30884. return '';
  30885. }
  30886. return $this->prefixLines($prefix, $message);
  30887. }
  30888. protected function prefixLines(string $prefix, string $message) : string
  30889. {
  30890. $message = \trim($message);
  30891. return \implode(\PHP_EOL, \array_map(static function (string $text) use($prefix) {
  30892. return ' ' . $prefix . ($text ? ' ' . $text : '');
  30893. }, \preg_split('/\\r\\n|\\r|\\n/', $message)));
  30894. }
  30895. }
  30896. <?php
  30897. declare (strict_types=1);
  30898. /*
  30899. * This file is part of PHPUnit.
  30900. *
  30901. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  30902. *
  30903. * For the full copyright and license information, please view the LICENSE
  30904. * file that was distributed with this source code.
  30905. */
  30906. namespace PHPUnit\Util\TestDox;
  30907. use PHPUnit\Framework\TestResult;
  30908. /**
  30909. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  30910. */
  30911. final class HtmlResultPrinter extends \PHPUnit\Util\TestDox\ResultPrinter
  30912. {
  30913. /**
  30914. * @var string
  30915. */
  30916. private const PAGE_HEADER = <<<EOT
  30917. <!doctype html>
  30918. <html lang="en">
  30919. <head>
  30920. <meta charset="utf-8"/>
  30921. <title>Test Documentation</title>
  30922. <style>
  30923. body {
  30924. text-rendering: optimizeLegibility;
  30925. font-variant-ligatures: common-ligatures;
  30926. font-kerning: normal;
  30927. margin-left: 2em;
  30928. }
  30929. body > ul > li {
  30930. font-family: Source Serif Pro, PT Sans, Trebuchet MS, Helvetica, Arial;
  30931. font-size: 2em;
  30932. }
  30933. h2 {
  30934. font-family: Tahoma, Helvetica, Arial;
  30935. font-size: 3em;
  30936. }
  30937. ul {
  30938. list-style: none;
  30939. margin-bottom: 1em;
  30940. }
  30941. </style>
  30942. </head>
  30943. <body>
  30944. EOT;
  30945. /**
  30946. * @var string
  30947. */
  30948. private const CLASS_HEADER = <<<EOT
  30949. <h2 id="%s">%s</h2>
  30950. <ul>
  30951. EOT;
  30952. /**
  30953. * @var string
  30954. */
  30955. private const CLASS_FOOTER = <<<EOT
  30956. </ul>
  30957. EOT;
  30958. /**
  30959. * @var string
  30960. */
  30961. private const PAGE_FOOTER = <<<EOT
  30962. </body>
  30963. </html>
  30964. EOT;
  30965. public function printResult(\PHPUnit\Framework\TestResult $result) : void
  30966. {
  30967. }
  30968. /**
  30969. * Handler for 'start run' event.
  30970. */
  30971. protected function startRun() : void
  30972. {
  30973. $this->write(self::PAGE_HEADER);
  30974. }
  30975. /**
  30976. * Handler for 'start class' event.
  30977. */
  30978. protected function startClass(string $name) : void
  30979. {
  30980. $this->write(\sprintf(self::CLASS_HEADER, $name, $this->currentTestClassPrettified));
  30981. }
  30982. /**
  30983. * Handler for 'on test' event.
  30984. */
  30985. protected function onTest(string $name, bool $success = \true) : void
  30986. {
  30987. $this->write(\sprintf(" <li style=\"color: %s;\">%s %s</li>\n", $success ? '#555753' : '#ef2929', $success ? '✓' : '�', $name));
  30988. }
  30989. /**
  30990. * Handler for 'end class' event.
  30991. */
  30992. protected function endClass(string $name) : void
  30993. {
  30994. $this->write(self::CLASS_FOOTER);
  30995. }
  30996. /**
  30997. * Handler for 'end run' event.
  30998. */
  30999. protected function endRun() : void
  31000. {
  31001. $this->write(self::PAGE_FOOTER);
  31002. }
  31003. }
  31004. <?php
  31005. declare (strict_types=1);
  31006. /*
  31007. * This file is part of PHPUnit.
  31008. *
  31009. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  31010. *
  31011. * For the full copyright and license information, please view the LICENSE
  31012. * file that was distributed with this source code.
  31013. */
  31014. namespace PHPUnit\Runner;
  31015. use PHPUnit\Framework\TestCase;
  31016. use PHPUnit\Util\FileLoader;
  31017. /**
  31018. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  31019. *
  31020. * @deprecated see https://github.com/sebastianbergmann/phpunit/issues/4039
  31021. */
  31022. final class StandardTestSuiteLoader implements \PHPUnit\Runner\TestSuiteLoader
  31023. {
  31024. /**
  31025. * @throws Exception
  31026. */
  31027. public function load(string $suiteClassFile) : \ReflectionClass
  31028. {
  31029. $suiteClassName = \basename($suiteClassFile, '.php');
  31030. $loadedClasses = \get_declared_classes();
  31031. if (!\class_exists($suiteClassName, \false)) {
  31032. /* @noinspection UnusedFunctionResultInspection */
  31033. \PHPUnit\Util\FileLoader::checkAndLoad($suiteClassFile);
  31034. $loadedClasses = \array_values(\array_diff(\get_declared_classes(), $loadedClasses));
  31035. if (empty($loadedClasses)) {
  31036. throw $this->exceptionFor($suiteClassName, $suiteClassFile);
  31037. }
  31038. }
  31039. if (!\class_exists($suiteClassName, \false)) {
  31040. $offset = 0 - \strlen($suiteClassName);
  31041. foreach ($loadedClasses as $loadedClass) {
  31042. if (\substr($loadedClass, $offset) === $suiteClassName && \basename(\str_replace('\\', '/', $loadedClass)) === $suiteClassName) {
  31043. $suiteClassName = $loadedClass;
  31044. break;
  31045. }
  31046. }
  31047. }
  31048. if (!\class_exists($suiteClassName, \false)) {
  31049. throw $this->exceptionFor($suiteClassName, $suiteClassFile);
  31050. }
  31051. try {
  31052. $class = new \ReflectionClass($suiteClassName);
  31053. // @codeCoverageIgnoreStart
  31054. } catch (\ReflectionException $e) {
  31055. throw new \PHPUnit\Runner\Exception($e->getMessage(), (int) $e->getCode(), $e);
  31056. }
  31057. // @codeCoverageIgnoreEnd
  31058. if ($class->isSubclassOf(\PHPUnit\Framework\TestCase::class) && !$class->isAbstract()) {
  31059. return $class;
  31060. }
  31061. if ($class->hasMethod('suite')) {
  31062. try {
  31063. $method = $class->getMethod('suite');
  31064. // @codeCoverageIgnoreStart
  31065. } catch (\ReflectionException $e) {
  31066. throw new \PHPUnit\Runner\Exception($e->getMessage(), (int) $e->getCode(), $e);
  31067. }
  31068. // @codeCoverageIgnoreEnd
  31069. if (!$method->isAbstract() && $method->isPublic() && $method->isStatic()) {
  31070. return $class;
  31071. }
  31072. }
  31073. throw $this->exceptionFor($suiteClassName, $suiteClassFile);
  31074. }
  31075. public function reload(\ReflectionClass $aClass) : \ReflectionClass
  31076. {
  31077. return $aClass;
  31078. }
  31079. private function exceptionFor(string $className, string $filename) : \PHPUnit\Runner\Exception
  31080. {
  31081. return new \PHPUnit\Runner\Exception(\sprintf("Class '%s' could not be found in '%s'.", $className, $filename));
  31082. }
  31083. }
  31084. <?php
  31085. declare (strict_types=1);
  31086. /*
  31087. * This file is part of PHPUnit.
  31088. *
  31089. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  31090. *
  31091. * For the full copyright and license information, please view the LICENSE
  31092. * file that was distributed with this source code.
  31093. */
  31094. namespace PHPUnit\Runner;
  31095. use PHPUnit\Framework\DataProviderTestSuite;
  31096. use PHPUnit\Framework\Test;
  31097. use PHPUnit\Framework\TestCase;
  31098. use PHPUnit\Framework\TestSuite;
  31099. use PHPUnit\Util\Test as TestUtil;
  31100. /**
  31101. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  31102. */
  31103. final class TestSuiteSorter
  31104. {
  31105. /**
  31106. * @var int
  31107. */
  31108. public const ORDER_DEFAULT = 0;
  31109. /**
  31110. * @var int
  31111. */
  31112. public const ORDER_RANDOMIZED = 1;
  31113. /**
  31114. * @var int
  31115. */
  31116. public const ORDER_REVERSED = 2;
  31117. /**
  31118. * @var int
  31119. */
  31120. public const ORDER_DEFECTS_FIRST = 3;
  31121. /**
  31122. * @var int
  31123. */
  31124. public const ORDER_DURATION = 4;
  31125. /**
  31126. * Order tests by @size annotation 'small', 'medium', 'large'
  31127. *
  31128. * @var int
  31129. */
  31130. public const ORDER_SIZE = 5;
  31131. /**
  31132. * List of sorting weights for all test result codes. A higher number gives higher priority.
  31133. */
  31134. private const DEFECT_SORT_WEIGHT = [\PHPUnit\Runner\BaseTestRunner::STATUS_ERROR => 6, \PHPUnit\Runner\BaseTestRunner::STATUS_FAILURE => 5, \PHPUnit\Runner\BaseTestRunner::STATUS_WARNING => 4, \PHPUnit\Runner\BaseTestRunner::STATUS_INCOMPLETE => 3, \PHPUnit\Runner\BaseTestRunner::STATUS_RISKY => 2, \PHPUnit\Runner\BaseTestRunner::STATUS_SKIPPED => 1, \PHPUnit\Runner\BaseTestRunner::STATUS_UNKNOWN => 0];
  31135. private const SIZE_SORT_WEIGHT = [\PHPUnit\Util\Test::SMALL => 1, \PHPUnit\Util\Test::MEDIUM => 2, \PHPUnit\Util\Test::LARGE => 3, \PHPUnit\Util\Test::UNKNOWN => 4];
  31136. /**
  31137. * @var array<string, int> Associative array of (string => DEFECT_SORT_WEIGHT) elements
  31138. */
  31139. private $defectSortOrder = [];
  31140. /**
  31141. * @var TestResultCache
  31142. */
  31143. private $cache;
  31144. /**
  31145. * @var string[] A list of normalized names of tests before reordering
  31146. */
  31147. private $originalExecutionOrder = [];
  31148. /**
  31149. * @var string[] A list of normalized names of tests affected by reordering
  31150. */
  31151. private $executionOrder = [];
  31152. /**
  31153. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  31154. */
  31155. public static function getTestSorterUID(\PHPUnit\Framework\Test $test) : string
  31156. {
  31157. if ($test instanceof \PHPUnit\Runner\PhptTestCase) {
  31158. return $test->getName();
  31159. }
  31160. if ($test instanceof \PHPUnit\Framework\TestCase) {
  31161. $testName = $test->getName(\true);
  31162. if (\strpos($testName, '::') === \false) {
  31163. $testName = \get_class($test) . '::' . $testName;
  31164. }
  31165. return $testName;
  31166. }
  31167. return $test->getName();
  31168. }
  31169. public function __construct(?\PHPUnit\Runner\TestResultCache $cache = null)
  31170. {
  31171. $this->cache = $cache ?? new \PHPUnit\Runner\NullTestResultCache();
  31172. }
  31173. /**
  31174. * @throws Exception
  31175. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  31176. */
  31177. public function reorderTestsInSuite(\PHPUnit\Framework\Test $suite, int $order, bool $resolveDependencies, int $orderDefects, bool $isRootTestSuite = \true) : void
  31178. {
  31179. $allowedOrders = [self::ORDER_DEFAULT, self::ORDER_REVERSED, self::ORDER_RANDOMIZED, self::ORDER_DURATION, self::ORDER_SIZE];
  31180. if (!\in_array($order, $allowedOrders, \true)) {
  31181. throw new \PHPUnit\Runner\Exception('$order must be one of TestSuiteSorter::ORDER_[DEFAULT|REVERSED|RANDOMIZED|DURATION|SIZE]');
  31182. }
  31183. $allowedOrderDefects = [self::ORDER_DEFAULT, self::ORDER_DEFECTS_FIRST];
  31184. if (!\in_array($orderDefects, $allowedOrderDefects, \true)) {
  31185. throw new \PHPUnit\Runner\Exception('$orderDefects must be one of TestSuiteSorter::ORDER_DEFAULT, TestSuiteSorter::ORDER_DEFECTS_FIRST');
  31186. }
  31187. if ($isRootTestSuite) {
  31188. $this->originalExecutionOrder = $this->calculateTestExecutionOrder($suite);
  31189. }
  31190. if ($suite instanceof \PHPUnit\Framework\TestSuite) {
  31191. foreach ($suite as $_suite) {
  31192. $this->reorderTestsInSuite($_suite, $order, $resolveDependencies, $orderDefects, \false);
  31193. }
  31194. if ($orderDefects === self::ORDER_DEFECTS_FIRST) {
  31195. $this->addSuiteToDefectSortOrder($suite);
  31196. }
  31197. $this->sort($suite, $order, $resolveDependencies, $orderDefects);
  31198. }
  31199. if ($isRootTestSuite) {
  31200. $this->executionOrder = $this->calculateTestExecutionOrder($suite);
  31201. }
  31202. }
  31203. public function getOriginalExecutionOrder() : array
  31204. {
  31205. return $this->originalExecutionOrder;
  31206. }
  31207. public function getExecutionOrder() : array
  31208. {
  31209. return $this->executionOrder;
  31210. }
  31211. private function sort(\PHPUnit\Framework\TestSuite $suite, int $order, bool $resolveDependencies, int $orderDefects) : void
  31212. {
  31213. if (empty($suite->tests())) {
  31214. return;
  31215. }
  31216. if ($order === self::ORDER_REVERSED) {
  31217. $suite->setTests($this->reverse($suite->tests()));
  31218. } elseif ($order === self::ORDER_RANDOMIZED) {
  31219. $suite->setTests($this->randomize($suite->tests()));
  31220. } elseif ($order === self::ORDER_DURATION && $this->cache !== null) {
  31221. $suite->setTests($this->sortByDuration($suite->tests()));
  31222. } elseif ($order === self::ORDER_SIZE) {
  31223. $suite->setTests($this->sortBySize($suite->tests()));
  31224. }
  31225. if ($orderDefects === self::ORDER_DEFECTS_FIRST && $this->cache !== null) {
  31226. $suite->setTests($this->sortDefectsFirst($suite->tests()));
  31227. }
  31228. if ($resolveDependencies && !$suite instanceof \PHPUnit\Framework\DataProviderTestSuite && $this->suiteOnlyContainsTests($suite)) {
  31229. /** @var TestCase[] $tests */
  31230. $tests = $suite->tests();
  31231. $suite->setTests($this->resolveDependencies($tests));
  31232. }
  31233. }
  31234. /**
  31235. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  31236. */
  31237. private function addSuiteToDefectSortOrder(\PHPUnit\Framework\TestSuite $suite) : void
  31238. {
  31239. $max = 0;
  31240. foreach ($suite->tests() as $test) {
  31241. $testname = self::getTestSorterUID($test);
  31242. if (!isset($this->defectSortOrder[$testname])) {
  31243. $this->defectSortOrder[$testname] = self::DEFECT_SORT_WEIGHT[$this->cache->getState($testname)];
  31244. $max = \max($max, $this->defectSortOrder[$testname]);
  31245. }
  31246. }
  31247. $this->defectSortOrder[$suite->getName()] = $max;
  31248. }
  31249. private function suiteOnlyContainsTests(\PHPUnit\Framework\TestSuite $suite) : bool
  31250. {
  31251. return \array_reduce($suite->tests(), static function ($carry, $test) {
  31252. return $carry && ($test instanceof \PHPUnit\Framework\TestCase || $test instanceof \PHPUnit\Framework\DataProviderTestSuite);
  31253. }, \true);
  31254. }
  31255. private function reverse(array $tests) : array
  31256. {
  31257. return \array_reverse($tests);
  31258. }
  31259. private function randomize(array $tests) : array
  31260. {
  31261. \shuffle($tests);
  31262. return $tests;
  31263. }
  31264. private function sortDefectsFirst(array $tests) : array
  31265. {
  31266. \usort(
  31267. $tests,
  31268. /**
  31269. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  31270. */
  31271. function ($left, $right) {
  31272. return $this->cmpDefectPriorityAndTime($left, $right);
  31273. }
  31274. );
  31275. return $tests;
  31276. }
  31277. private function sortByDuration(array $tests) : array
  31278. {
  31279. \usort(
  31280. $tests,
  31281. /**
  31282. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  31283. */
  31284. function ($left, $right) {
  31285. return $this->cmpDuration($left, $right);
  31286. }
  31287. );
  31288. return $tests;
  31289. }
  31290. private function sortBySize(array $tests) : array
  31291. {
  31292. \usort(
  31293. $tests,
  31294. /**
  31295. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  31296. */
  31297. function ($left, $right) {
  31298. return $this->cmpSize($left, $right);
  31299. }
  31300. );
  31301. return $tests;
  31302. }
  31303. /**
  31304. * Comparator callback function to sort tests for "reach failure as fast as possible":
  31305. * 1. sort tests by defect weight defined in self::DEFECT_SORT_WEIGHT
  31306. * 2. when tests are equally defective, sort the fastest to the front
  31307. * 3. do not reorder successful tests
  31308. *
  31309. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  31310. */
  31311. private function cmpDefectPriorityAndTime(\PHPUnit\Framework\Test $a, \PHPUnit\Framework\Test $b) : int
  31312. {
  31313. $priorityA = $this->defectSortOrder[self::getTestSorterUID($a)] ?? 0;
  31314. $priorityB = $this->defectSortOrder[self::getTestSorterUID($b)] ?? 0;
  31315. if ($priorityB <=> $priorityA) {
  31316. // Sort defect weight descending
  31317. return $priorityB <=> $priorityA;
  31318. }
  31319. if ($priorityA || $priorityB) {
  31320. return $this->cmpDuration($a, $b);
  31321. }
  31322. // do not change execution order
  31323. return 0;
  31324. }
  31325. /**
  31326. * Compares test duration for sorting tests by duration ascending.
  31327. *
  31328. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  31329. */
  31330. private function cmpDuration(\PHPUnit\Framework\Test $a, \PHPUnit\Framework\Test $b) : int
  31331. {
  31332. return $this->cache->getTime(self::getTestSorterUID($a)) <=> $this->cache->getTime(self::getTestSorterUID($b));
  31333. }
  31334. /**
  31335. * Compares test size for sorting tests small->medium->large->unknown
  31336. */
  31337. private function cmpSize(\PHPUnit\Framework\Test $a, \PHPUnit\Framework\Test $b) : int
  31338. {
  31339. $sizeA = $a instanceof \PHPUnit\Framework\TestCase || $a instanceof \PHPUnit\Framework\DataProviderTestSuite ? $a->getSize() : \PHPUnit\Util\Test::UNKNOWN;
  31340. $sizeB = $b instanceof \PHPUnit\Framework\TestCase || $b instanceof \PHPUnit\Framework\DataProviderTestSuite ? $b->getSize() : \PHPUnit\Util\Test::UNKNOWN;
  31341. return self::SIZE_SORT_WEIGHT[$sizeA] <=> self::SIZE_SORT_WEIGHT[$sizeB];
  31342. }
  31343. /**
  31344. * Reorder Tests within a TestCase in such a way as to resolve as many dependencies as possible.
  31345. * The algorithm will leave the tests in original running order when it can.
  31346. * For more details see the documentation for test dependencies.
  31347. *
  31348. * Short description of algorithm:
  31349. * 1. Pick the next Test from remaining tests to be checked for dependencies.
  31350. * 2. If the test has no dependencies: mark done, start again from the top
  31351. * 3. If the test has dependencies but none left to do: mark done, start again from the top
  31352. * 4. When we reach the end add any leftover tests to the end. These will be marked 'skipped' during execution.
  31353. *
  31354. * @param array<DataProviderTestSuite|TestCase> $tests
  31355. *
  31356. * @return array<DataProviderTestSuite|TestCase>
  31357. */
  31358. private function resolveDependencies(array $tests) : array
  31359. {
  31360. $newTestOrder = [];
  31361. $i = 0;
  31362. do {
  31363. $todoNames = \array_map(
  31364. /**
  31365. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  31366. */
  31367. static function ($test) {
  31368. return self::getTestSorterUID($test);
  31369. },
  31370. $tests
  31371. );
  31372. if (!$tests[$i]->hasDependencies() || empty(\array_intersect($this->getNormalizedDependencyNames($tests[$i]), $todoNames))) {
  31373. $newTestOrder = \array_merge($newTestOrder, \array_splice($tests, $i, 1));
  31374. $i = 0;
  31375. } else {
  31376. $i++;
  31377. }
  31378. } while (!empty($tests) && $i < \count($tests));
  31379. return \array_merge($newTestOrder, $tests);
  31380. }
  31381. /**
  31382. * @param DataProviderTestSuite|TestCase $test
  31383. *
  31384. * @return array<string> A list of full test names as "TestSuiteClassName::testMethodName"
  31385. */
  31386. private function getNormalizedDependencyNames($test) : array
  31387. {
  31388. if ($test instanceof \PHPUnit\Framework\DataProviderTestSuite) {
  31389. $testClass = \substr($test->getName(), 0, \strpos($test->getName(), '::'));
  31390. } else {
  31391. $testClass = \get_class($test);
  31392. }
  31393. $names = \array_map(static function ($name) use($testClass) {
  31394. return \strpos($name, '::') === \false ? $testClass . '::' . $name : $name;
  31395. }, $test->getDependencies());
  31396. return $names;
  31397. }
  31398. /**
  31399. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  31400. */
  31401. private function calculateTestExecutionOrder(\PHPUnit\Framework\Test $suite) : array
  31402. {
  31403. $tests = [];
  31404. if ($suite instanceof \PHPUnit\Framework\TestSuite) {
  31405. foreach ($suite->tests() as $test) {
  31406. if (!$test instanceof \PHPUnit\Framework\TestSuite) {
  31407. $tests[] = self::getTestSorterUID($test);
  31408. } else {
  31409. $tests = \array_merge($tests, $this->calculateTestExecutionOrder($test));
  31410. }
  31411. }
  31412. }
  31413. return $tests;
  31414. }
  31415. }
  31416. <?php
  31417. declare (strict_types=1);
  31418. /*
  31419. * This file is part of PHPUnit.
  31420. *
  31421. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  31422. *
  31423. * For the full copyright and license information, please view the LICENSE
  31424. * file that was distributed with this source code.
  31425. */
  31426. namespace PHPUnit\Runner;
  31427. /**
  31428. * An interface to define how a test suite should be loaded.
  31429. *
  31430. * @deprecated see https://github.com/sebastianbergmann/phpunit/issues/4039
  31431. */
  31432. interface TestSuiteLoader
  31433. {
  31434. public function load(string $suiteClassFile) : \ReflectionClass;
  31435. public function reload(\ReflectionClass $aClass) : \ReflectionClass;
  31436. }
  31437. <?php
  31438. declare (strict_types=1);
  31439. /*
  31440. * This file is part of PHPUnit.
  31441. *
  31442. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  31443. *
  31444. * For the full copyright and license information, please view the LICENSE
  31445. * file that was distributed with this source code.
  31446. */
  31447. namespace PHPUnit\Runner;
  31448. /**
  31449. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  31450. */
  31451. interface TestResultCache
  31452. {
  31453. public function setState(string $testName, int $state) : void;
  31454. public function getState(string $testName) : int;
  31455. public function setTime(string $testName, float $time) : void;
  31456. public function getTime(string $testName) : float;
  31457. public function load() : void;
  31458. public function persist() : void;
  31459. }
  31460. <?php
  31461. declare (strict_types=1);
  31462. /*
  31463. * This file is part of PHPUnit.
  31464. *
  31465. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  31466. *
  31467. * For the full copyright and license information, please view the LICENSE
  31468. * file that was distributed with this source code.
  31469. */
  31470. namespace PHPUnit\Runner\Filter;
  31471. /**
  31472. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  31473. */
  31474. final class ExcludeGroupFilterIterator extends \PHPUnit\Runner\Filter\GroupFilterIterator
  31475. {
  31476. protected function doAccept(string $hash) : bool
  31477. {
  31478. return !\in_array($hash, $this->groupTests, \true);
  31479. }
  31480. }
  31481. <?php
  31482. declare (strict_types=1);
  31483. /*
  31484. * This file is part of PHPUnit.
  31485. *
  31486. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  31487. *
  31488. * For the full copyright and license information, please view the LICENSE
  31489. * file that was distributed with this source code.
  31490. */
  31491. namespace PHPUnit\Runner\Filter;
  31492. /**
  31493. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  31494. */
  31495. final class IncludeGroupFilterIterator extends \PHPUnit\Runner\Filter\GroupFilterIterator
  31496. {
  31497. protected function doAccept(string $hash) : bool
  31498. {
  31499. return \in_array($hash, $this->groupTests, \true);
  31500. }
  31501. }
  31502. <?php
  31503. declare (strict_types=1);
  31504. /*
  31505. * This file is part of PHPUnit.
  31506. *
  31507. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  31508. *
  31509. * For the full copyright and license information, please view the LICENSE
  31510. * file that was distributed with this source code.
  31511. */
  31512. namespace PHPUnit\Runner\Filter;
  31513. use PHPUnit\Framework\TestSuite;
  31514. use PHPUnit\Runner\Exception;
  31515. /**
  31516. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  31517. */
  31518. final class Factory
  31519. {
  31520. /**
  31521. * @psalm-var array<int,array{0: \ReflectionClass, 1: array|string}>
  31522. */
  31523. private $filters = [];
  31524. /**
  31525. * @param array|string $args
  31526. *
  31527. * @throws Exception
  31528. */
  31529. public function addFilter(\ReflectionClass $filter, $args) : void
  31530. {
  31531. if (!$filter->isSubclassOf(\RecursiveFilterIterator::class)) {
  31532. throw new \PHPUnit\Runner\Exception(\sprintf('Class "%s" does not extend RecursiveFilterIterator', $filter->name));
  31533. }
  31534. $this->filters[] = [$filter, $args];
  31535. }
  31536. public function factory(\Iterator $iterator, \PHPUnit\Framework\TestSuite $suite) : \FilterIterator
  31537. {
  31538. foreach ($this->filters as $filter) {
  31539. [$class, $args] = $filter;
  31540. $iterator = $class->newInstance($iterator, $args, $suite);
  31541. }
  31542. \assert($iterator instanceof \FilterIterator);
  31543. return $iterator;
  31544. }
  31545. }
  31546. <?php
  31547. declare (strict_types=1);
  31548. /*
  31549. * This file is part of PHPUnit.
  31550. *
  31551. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  31552. *
  31553. * For the full copyright and license information, please view the LICENSE
  31554. * file that was distributed with this source code.
  31555. */
  31556. namespace PHPUnit\Runner\Filter;
  31557. use PHPUnit\Framework\TestSuite;
  31558. /**
  31559. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  31560. */
  31561. abstract class GroupFilterIterator extends \RecursiveFilterIterator
  31562. {
  31563. /**
  31564. * @var string[]
  31565. */
  31566. protected $groupTests = [];
  31567. public function __construct(\RecursiveIterator $iterator, array $groups, \PHPUnit\Framework\TestSuite $suite)
  31568. {
  31569. parent::__construct($iterator);
  31570. foreach ($suite->getGroupDetails() as $group => $tests) {
  31571. if (\in_array((string) $group, $groups, \true)) {
  31572. $testHashes = \array_map('spl_object_hash', $tests);
  31573. $this->groupTests = \array_merge($this->groupTests, $testHashes);
  31574. }
  31575. }
  31576. }
  31577. public function accept() : bool
  31578. {
  31579. $test = $this->getInnerIterator()->current();
  31580. if ($test instanceof \PHPUnit\Framework\TestSuite) {
  31581. return \true;
  31582. }
  31583. return $this->doAccept(\spl_object_hash($test));
  31584. }
  31585. protected abstract function doAccept(string $hash);
  31586. }
  31587. <?php
  31588. declare (strict_types=1);
  31589. /*
  31590. * This file is part of PHPUnit.
  31591. *
  31592. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  31593. *
  31594. * For the full copyright and license information, please view the LICENSE
  31595. * file that was distributed with this source code.
  31596. */
  31597. namespace PHPUnit\Runner\Filter;
  31598. use PHPUnit\Framework\TestSuite;
  31599. use PHPUnit\Framework\WarningTestCase;
  31600. use PHPUnit\Util\RegularExpression;
  31601. /**
  31602. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  31603. */
  31604. final class NameFilterIterator extends \RecursiveFilterIterator
  31605. {
  31606. /**
  31607. * @var string
  31608. */
  31609. private $filter;
  31610. /**
  31611. * @var int
  31612. */
  31613. private $filterMin;
  31614. /**
  31615. * @var int
  31616. */
  31617. private $filterMax;
  31618. /**
  31619. * @throws \Exception
  31620. */
  31621. public function __construct(\RecursiveIterator $iterator, string $filter)
  31622. {
  31623. parent::__construct($iterator);
  31624. $this->setFilter($filter);
  31625. }
  31626. /**
  31627. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  31628. */
  31629. public function accept() : bool
  31630. {
  31631. $test = $this->getInnerIterator()->current();
  31632. if ($test instanceof \PHPUnit\Framework\TestSuite) {
  31633. return \true;
  31634. }
  31635. $tmp = \PHPUnit\Util\Test::describe($test);
  31636. if ($test instanceof \PHPUnit\Framework\WarningTestCase) {
  31637. $name = $test->getMessage();
  31638. } elseif ($tmp[0] !== '') {
  31639. $name = \implode('::', $tmp);
  31640. } else {
  31641. $name = $tmp[1];
  31642. }
  31643. $accepted = @\preg_match($this->filter, $name, $matches);
  31644. if ($accepted && isset($this->filterMax)) {
  31645. $set = \end($matches);
  31646. $accepted = $set >= $this->filterMin && $set <= $this->filterMax;
  31647. }
  31648. return (bool) $accepted;
  31649. }
  31650. /**
  31651. * @throws \Exception
  31652. */
  31653. private function setFilter(string $filter) : void
  31654. {
  31655. if (\PHPUnit\Util\RegularExpression::safeMatch($filter, '') === \false) {
  31656. // Handles:
  31657. // * testAssertEqualsSucceeds#4
  31658. // * testAssertEqualsSucceeds#4-8
  31659. if (\preg_match('/^(.*?)#(\\d+)(?:-(\\d+))?$/', $filter, $matches)) {
  31660. if (isset($matches[3]) && $matches[2] < $matches[3]) {
  31661. $filter = \sprintf('%s.*with data set #(\\d+)$', $matches[1]);
  31662. $this->filterMin = (int) $matches[2];
  31663. $this->filterMax = (int) $matches[3];
  31664. } else {
  31665. $filter = \sprintf('%s.*with data set #%s$', $matches[1], $matches[2]);
  31666. }
  31667. } elseif (\preg_match('/^(.*?)@(.+)$/', $filter, $matches)) {
  31668. $filter = \sprintf('%s.*with data set "%s"$', $matches[1], $matches[2]);
  31669. }
  31670. // Escape delimiters in regular expression. Do NOT use preg_quote,
  31671. // to keep magic characters.
  31672. $filter = \sprintf('/%s/i', \str_replace('/', '\\/', $filter));
  31673. }
  31674. $this->filter = $filter;
  31675. }
  31676. }
  31677. <?php
  31678. declare (strict_types=1);
  31679. /*
  31680. * This file is part of PHPUnit.
  31681. *
  31682. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  31683. *
  31684. * For the full copyright and license information, please view the LICENSE
  31685. * file that was distributed with this source code.
  31686. */
  31687. namespace PHPUnit\Runner;
  31688. use PHPUnit\SebastianBergmann\Version as VersionId;
  31689. final class Version
  31690. {
  31691. /**
  31692. * @var string
  31693. */
  31694. private static $pharVersion = '';
  31695. /**
  31696. * @var string
  31697. */
  31698. private static $version = '';
  31699. /**
  31700. * Returns the current version of PHPUnit.
  31701. */
  31702. public static function id() : string
  31703. {
  31704. if (self::$pharVersion !== '') {
  31705. return self::$pharVersion;
  31706. }
  31707. if (self::$version === '') {
  31708. self::$version = (new \PHPUnit\SebastianBergmann\Version('9.2.5', \dirname(__DIR__, 2)))->getVersion();
  31709. }
  31710. return self::$version;
  31711. }
  31712. public static function series() : string
  31713. {
  31714. if (\strpos(self::id(), '-')) {
  31715. $version = \explode('-', self::id())[0];
  31716. } else {
  31717. $version = self::id();
  31718. }
  31719. return \implode('.', \array_slice(\explode('.', $version), 0, 2));
  31720. }
  31721. public static function getVersionString() : string
  31722. {
  31723. return 'PHPUnit ' . self::id() . ' by Sebastian Bergmann and contributors.';
  31724. }
  31725. }
  31726. <?php
  31727. declare (strict_types=1);
  31728. /*
  31729. * This file is part of PHPUnit.
  31730. *
  31731. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  31732. *
  31733. * For the full copyright and license information, please view the LICENSE
  31734. * file that was distributed with this source code.
  31735. */
  31736. namespace PHPUnit\Runner;
  31737. use PHPUnit\Util\ErrorHandler;
  31738. use PHPUnit\Util\Filesystem;
  31739. /**
  31740. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  31741. */
  31742. final class DefaultTestResultCache implements \Serializable, \PHPUnit\Runner\TestResultCache
  31743. {
  31744. /**
  31745. * @var string
  31746. */
  31747. public const DEFAULT_RESULT_CACHE_FILENAME = '.phpunit.result.cache';
  31748. /**
  31749. * Provide extra protection against incomplete or corrupt caches
  31750. *
  31751. * @var int[]
  31752. */
  31753. private const ALLOWED_CACHE_TEST_STATUSES = [\PHPUnit\Runner\BaseTestRunner::STATUS_SKIPPED, \PHPUnit\Runner\BaseTestRunner::STATUS_INCOMPLETE, \PHPUnit\Runner\BaseTestRunner::STATUS_FAILURE, \PHPUnit\Runner\BaseTestRunner::STATUS_ERROR, \PHPUnit\Runner\BaseTestRunner::STATUS_RISKY, \PHPUnit\Runner\BaseTestRunner::STATUS_WARNING];
  31754. /**
  31755. * Path and filename for result cache file
  31756. *
  31757. * @var string
  31758. */
  31759. private $cacheFilename;
  31760. /**
  31761. * The list of defective tests
  31762. *
  31763. * <code>
  31764. * // Mark a test skipped
  31765. * $this->defects[$testName] = BaseTestRunner::TEST_SKIPPED;
  31766. * </code>
  31767. *
  31768. * @var array<string, int>
  31769. */
  31770. private $defects = [];
  31771. /**
  31772. * The list of execution duration of suites and tests (in seconds)
  31773. *
  31774. * <code>
  31775. * // Record running time for test
  31776. * $this->times[$testName] = 1.234;
  31777. * </code>
  31778. *
  31779. * @var array<string, float>
  31780. */
  31781. private $times = [];
  31782. public function __construct(?string $filepath = null)
  31783. {
  31784. if ($filepath !== null && \is_dir($filepath)) {
  31785. // cache path provided, use default cache filename in that location
  31786. $filepath .= \DIRECTORY_SEPARATOR . self::DEFAULT_RESULT_CACHE_FILENAME;
  31787. }
  31788. $this->cacheFilename = $filepath ?? $_ENV['PHPUNIT_RESULT_CACHE'] ?? self::DEFAULT_RESULT_CACHE_FILENAME;
  31789. }
  31790. /**
  31791. * @throws Exception
  31792. */
  31793. public function persist() : void
  31794. {
  31795. $this->saveToFile();
  31796. }
  31797. /**
  31798. * @throws Exception
  31799. */
  31800. public function saveToFile() : void
  31801. {
  31802. if (\defined('PHPUNIT_TESTSUITE_RESULTCACHE')) {
  31803. return;
  31804. }
  31805. if (!\PHPUnit\Util\Filesystem::createDirectory(\dirname($this->cacheFilename))) {
  31806. throw new \PHPUnit\Runner\Exception(\sprintf('Cannot create directory "%s" for result cache file', $this->cacheFilename));
  31807. }
  31808. \file_put_contents($this->cacheFilename, \serialize($this));
  31809. }
  31810. public function setState(string $testName, int $state) : void
  31811. {
  31812. if ($state !== \PHPUnit\Runner\BaseTestRunner::STATUS_PASSED) {
  31813. $this->defects[$testName] = $state;
  31814. }
  31815. }
  31816. public function getState(string $testName) : int
  31817. {
  31818. return $this->defects[$testName] ?? \PHPUnit\Runner\BaseTestRunner::STATUS_UNKNOWN;
  31819. }
  31820. public function setTime(string $testName, float $time) : void
  31821. {
  31822. $this->times[$testName] = $time;
  31823. }
  31824. public function getTime(string $testName) : float
  31825. {
  31826. return $this->times[$testName] ?? 0.0;
  31827. }
  31828. public function load() : void
  31829. {
  31830. $this->clear();
  31831. if (!\is_file($this->cacheFilename)) {
  31832. return;
  31833. }
  31834. $cacheData = @\file_get_contents($this->cacheFilename);
  31835. // @codeCoverageIgnoreStart
  31836. if ($cacheData === \false) {
  31837. return;
  31838. }
  31839. // @codeCoverageIgnoreEnd
  31840. $cache = \PHPUnit\Util\ErrorHandler::invokeIgnoringWarnings(static function () use($cacheData) {
  31841. return @\unserialize($cacheData, ['allowed_classes' => [self::class]]);
  31842. });
  31843. if ($cache === \false) {
  31844. return;
  31845. }
  31846. if ($cache instanceof self) {
  31847. /* @var DefaultTestResultCache $cache */
  31848. $cache->copyStateToCache($this);
  31849. }
  31850. }
  31851. public function copyStateToCache(self $targetCache) : void
  31852. {
  31853. foreach ($this->defects as $name => $state) {
  31854. $targetCache->setState($name, $state);
  31855. }
  31856. foreach ($this->times as $name => $time) {
  31857. $targetCache->setTime($name, $time);
  31858. }
  31859. }
  31860. public function clear() : void
  31861. {
  31862. $this->defects = [];
  31863. $this->times = [];
  31864. }
  31865. public function serialize() : string
  31866. {
  31867. return \serialize(['defects' => $this->defects, 'times' => $this->times]);
  31868. }
  31869. /**
  31870. * @param string $serialized
  31871. */
  31872. public function unserialize($serialized) : void
  31873. {
  31874. $data = \unserialize($serialized);
  31875. if (isset($data['times'])) {
  31876. foreach ($data['times'] as $testName => $testTime) {
  31877. \assert(\is_string($testName));
  31878. \assert(\is_float($testTime));
  31879. $this->times[$testName] = $testTime;
  31880. }
  31881. }
  31882. if (isset($data['defects'])) {
  31883. foreach ($data['defects'] as $testName => $testResult) {
  31884. \assert(\is_string($testName));
  31885. \assert(\is_int($testResult));
  31886. if (\in_array($testResult, self::ALLOWED_CACHE_TEST_STATUSES, \true)) {
  31887. $this->defects[$testName] = $testResult;
  31888. }
  31889. }
  31890. }
  31891. }
  31892. }
  31893. <?php
  31894. declare (strict_types=1);
  31895. /*
  31896. * This file is part of PHPUnit.
  31897. *
  31898. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  31899. *
  31900. * For the full copyright and license information, please view the LICENSE
  31901. * file that was distributed with this source code.
  31902. */
  31903. namespace PHPUnit\Runner;
  31904. /**
  31905. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  31906. */
  31907. final class Exception extends \RuntimeException implements \PHPUnit\Exception
  31908. {
  31909. }
  31910. <?php
  31911. declare (strict_types=1);
  31912. /*
  31913. * This file is part of PHPUnit.
  31914. *
  31915. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  31916. *
  31917. * For the full copyright and license information, please view the LICENSE
  31918. * file that was distributed with this source code.
  31919. */
  31920. namespace PHPUnit\Runner;
  31921. interface AfterTestErrorHook extends \PHPUnit\Runner\TestHook
  31922. {
  31923. public function executeAfterTestError(string $test, string $message, float $time) : void;
  31924. }
  31925. <?php
  31926. declare (strict_types=1);
  31927. /*
  31928. * This file is part of PHPUnit.
  31929. *
  31930. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  31931. *
  31932. * For the full copyright and license information, please view the LICENSE
  31933. * file that was distributed with this source code.
  31934. */
  31935. namespace PHPUnit\Runner;
  31936. interface AfterTestWarningHook extends \PHPUnit\Runner\TestHook
  31937. {
  31938. public function executeAfterTestWarning(string $test, string $message, float $time) : void;
  31939. }
  31940. <?php
  31941. declare (strict_types=1);
  31942. /*
  31943. * This file is part of PHPUnit.
  31944. *
  31945. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  31946. *
  31947. * For the full copyright and license information, please view the LICENSE
  31948. * file that was distributed with this source code.
  31949. */
  31950. namespace PHPUnit\Runner;
  31951. interface AfterTestFailureHook extends \PHPUnit\Runner\TestHook
  31952. {
  31953. public function executeAfterTestFailure(string $test, string $message, float $time) : void;
  31954. }
  31955. <?php
  31956. declare (strict_types=1);
  31957. /*
  31958. * This file is part of PHPUnit.
  31959. *
  31960. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  31961. *
  31962. * For the full copyright and license information, please view the LICENSE
  31963. * file that was distributed with this source code.
  31964. */
  31965. namespace PHPUnit\Runner;
  31966. interface AfterIncompleteTestHook extends \PHPUnit\Runner\TestHook
  31967. {
  31968. public function executeAfterIncompleteTest(string $test, string $message, float $time) : void;
  31969. }
  31970. <?php
  31971. declare (strict_types=1);
  31972. /*
  31973. * This file is part of PHPUnit.
  31974. *
  31975. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  31976. *
  31977. * For the full copyright and license information, please view the LICENSE
  31978. * file that was distributed with this source code.
  31979. */
  31980. namespace PHPUnit\Runner;
  31981. interface AfterSkippedTestHook extends \PHPUnit\Runner\TestHook
  31982. {
  31983. public function executeAfterSkippedTest(string $test, string $message, float $time) : void;
  31984. }
  31985. <?php
  31986. declare (strict_types=1);
  31987. /*
  31988. * This file is part of PHPUnit.
  31989. *
  31990. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  31991. *
  31992. * For the full copyright and license information, please view the LICENSE
  31993. * file that was distributed with this source code.
  31994. */
  31995. namespace PHPUnit\Runner;
  31996. use PHPUnit\Framework\AssertionFailedError;
  31997. use PHPUnit\Framework\Test;
  31998. use PHPUnit\Framework\TestListener;
  31999. use PHPUnit\Framework\TestSuite;
  32000. use PHPUnit\Framework\Warning;
  32001. use PHPUnit\Util\Test as TestUtil;
  32002. /**
  32003. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  32004. */
  32005. final class TestListenerAdapter implements \PHPUnit\Framework\TestListener
  32006. {
  32007. /**
  32008. * @var TestHook[]
  32009. */
  32010. private $hooks = [];
  32011. /**
  32012. * @var bool
  32013. */
  32014. private $lastTestWasNotSuccessful;
  32015. public function add(\PHPUnit\Runner\TestHook $hook) : void
  32016. {
  32017. $this->hooks[] = $hook;
  32018. }
  32019. public function startTest(\PHPUnit\Framework\Test $test) : void
  32020. {
  32021. foreach ($this->hooks as $hook) {
  32022. if ($hook instanceof \PHPUnit\Runner\BeforeTestHook) {
  32023. $hook->executeBeforeTest(\PHPUnit\Util\Test::describeAsString($test));
  32024. }
  32025. }
  32026. $this->lastTestWasNotSuccessful = \false;
  32027. }
  32028. public function addError(\PHPUnit\Framework\Test $test, \Throwable $t, float $time) : void
  32029. {
  32030. foreach ($this->hooks as $hook) {
  32031. if ($hook instanceof \PHPUnit\Runner\AfterTestErrorHook) {
  32032. $hook->executeAfterTestError(\PHPUnit\Util\Test::describeAsString($test), $t->getMessage(), $time);
  32033. }
  32034. }
  32035. $this->lastTestWasNotSuccessful = \true;
  32036. }
  32037. public function addWarning(\PHPUnit\Framework\Test $test, \PHPUnit\Framework\Warning $e, float $time) : void
  32038. {
  32039. foreach ($this->hooks as $hook) {
  32040. if ($hook instanceof \PHPUnit\Runner\AfterTestWarningHook) {
  32041. $hook->executeAfterTestWarning(\PHPUnit\Util\Test::describeAsString($test), $e->getMessage(), $time);
  32042. }
  32043. }
  32044. $this->lastTestWasNotSuccessful = \true;
  32045. }
  32046. public function addFailure(\PHPUnit\Framework\Test $test, \PHPUnit\Framework\AssertionFailedError $e, float $time) : void
  32047. {
  32048. foreach ($this->hooks as $hook) {
  32049. if ($hook instanceof \PHPUnit\Runner\AfterTestFailureHook) {
  32050. $hook->executeAfterTestFailure(\PHPUnit\Util\Test::describeAsString($test), $e->getMessage(), $time);
  32051. }
  32052. }
  32053. $this->lastTestWasNotSuccessful = \true;
  32054. }
  32055. public function addIncompleteTest(\PHPUnit\Framework\Test $test, \Throwable $t, float $time) : void
  32056. {
  32057. foreach ($this->hooks as $hook) {
  32058. if ($hook instanceof \PHPUnit\Runner\AfterIncompleteTestHook) {
  32059. $hook->executeAfterIncompleteTest(\PHPUnit\Util\Test::describeAsString($test), $t->getMessage(), $time);
  32060. }
  32061. }
  32062. $this->lastTestWasNotSuccessful = \true;
  32063. }
  32064. public function addRiskyTest(\PHPUnit\Framework\Test $test, \Throwable $t, float $time) : void
  32065. {
  32066. foreach ($this->hooks as $hook) {
  32067. if ($hook instanceof \PHPUnit\Runner\AfterRiskyTestHook) {
  32068. $hook->executeAfterRiskyTest(\PHPUnit\Util\Test::describeAsString($test), $t->getMessage(), $time);
  32069. }
  32070. }
  32071. $this->lastTestWasNotSuccessful = \true;
  32072. }
  32073. public function addSkippedTest(\PHPUnit\Framework\Test $test, \Throwable $t, float $time) : void
  32074. {
  32075. foreach ($this->hooks as $hook) {
  32076. if ($hook instanceof \PHPUnit\Runner\AfterSkippedTestHook) {
  32077. $hook->executeAfterSkippedTest(\PHPUnit\Util\Test::describeAsString($test), $t->getMessage(), $time);
  32078. }
  32079. }
  32080. $this->lastTestWasNotSuccessful = \true;
  32081. }
  32082. public function endTest(\PHPUnit\Framework\Test $test, float $time) : void
  32083. {
  32084. if (!$this->lastTestWasNotSuccessful) {
  32085. foreach ($this->hooks as $hook) {
  32086. if ($hook instanceof \PHPUnit\Runner\AfterSuccessfulTestHook) {
  32087. $hook->executeAfterSuccessfulTest(\PHPUnit\Util\Test::describeAsString($test), $time);
  32088. }
  32089. }
  32090. }
  32091. foreach ($this->hooks as $hook) {
  32092. if ($hook instanceof \PHPUnit\Runner\AfterTestHook) {
  32093. $hook->executeAfterTest(\PHPUnit\Util\Test::describeAsString($test), $time);
  32094. }
  32095. }
  32096. }
  32097. public function startTestSuite(\PHPUnit\Framework\TestSuite $suite) : void
  32098. {
  32099. }
  32100. public function endTestSuite(\PHPUnit\Framework\TestSuite $suite) : void
  32101. {
  32102. }
  32103. }
  32104. <?php
  32105. declare (strict_types=1);
  32106. /*
  32107. * This file is part of PHPUnit.
  32108. *
  32109. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  32110. *
  32111. * For the full copyright and license information, please view the LICENSE
  32112. * file that was distributed with this source code.
  32113. */
  32114. namespace PHPUnit\Runner;
  32115. interface AfterRiskyTestHook extends \PHPUnit\Runner\TestHook
  32116. {
  32117. public function executeAfterRiskyTest(string $test, string $message, float $time) : void;
  32118. }
  32119. <?php
  32120. declare (strict_types=1);
  32121. /*
  32122. * This file is part of PHPUnit.
  32123. *
  32124. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  32125. *
  32126. * For the full copyright and license information, please view the LICENSE
  32127. * file that was distributed with this source code.
  32128. */
  32129. namespace PHPUnit\Runner;
  32130. interface BeforeFirstTestHook extends \PHPUnit\Runner\Hook
  32131. {
  32132. public function executeBeforeFirstTest() : void;
  32133. }
  32134. <?php
  32135. declare (strict_types=1);
  32136. /*
  32137. * This file is part of PHPUnit.
  32138. *
  32139. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  32140. *
  32141. * For the full copyright and license information, please view the LICENSE
  32142. * file that was distributed with this source code.
  32143. */
  32144. namespace PHPUnit\Runner;
  32145. interface AfterSuccessfulTestHook extends \PHPUnit\Runner\TestHook
  32146. {
  32147. public function executeAfterSuccessfulTest(string $test, float $time) : void;
  32148. }
  32149. <?php
  32150. declare (strict_types=1);
  32151. /*
  32152. * This file is part of PHPUnit.
  32153. *
  32154. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  32155. *
  32156. * For the full copyright and license information, please view the LICENSE
  32157. * file that was distributed with this source code.
  32158. */
  32159. namespace PHPUnit\Runner;
  32160. interface TestHook extends \PHPUnit\Runner\Hook
  32161. {
  32162. }
  32163. <?php
  32164. declare (strict_types=1);
  32165. /*
  32166. * This file is part of PHPUnit.
  32167. *
  32168. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  32169. *
  32170. * For the full copyright and license information, please view the LICENSE
  32171. * file that was distributed with this source code.
  32172. */
  32173. namespace PHPUnit\Runner;
  32174. interface BeforeTestHook extends \PHPUnit\Runner\TestHook
  32175. {
  32176. public function executeBeforeTest(string $test) : void;
  32177. }
  32178. <?php
  32179. declare (strict_types=1);
  32180. /*
  32181. * This file is part of PHPUnit.
  32182. *
  32183. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  32184. *
  32185. * For the full copyright and license information, please view the LICENSE
  32186. * file that was distributed with this source code.
  32187. */
  32188. namespace PHPUnit\Runner;
  32189. interface AfterTestHook extends \PHPUnit\Runner\TestHook
  32190. {
  32191. /**
  32192. * This hook will fire after any test, regardless of the result.
  32193. *
  32194. * For more fine grained control, have a look at the other hooks
  32195. * that extend PHPUnit\Runner\Hook.
  32196. */
  32197. public function executeAfterTest(string $test, float $time) : void;
  32198. }
  32199. <?php
  32200. declare (strict_types=1);
  32201. /*
  32202. * This file is part of PHPUnit.
  32203. *
  32204. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  32205. *
  32206. * For the full copyright and license information, please view the LICENSE
  32207. * file that was distributed with this source code.
  32208. */
  32209. namespace PHPUnit\Runner;
  32210. interface Hook
  32211. {
  32212. }
  32213. <?php
  32214. declare (strict_types=1);
  32215. /*
  32216. * This file is part of PHPUnit.
  32217. *
  32218. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  32219. *
  32220. * For the full copyright and license information, please view the LICENSE
  32221. * file that was distributed with this source code.
  32222. */
  32223. namespace PHPUnit\Runner;
  32224. interface AfterLastTestHook extends \PHPUnit\Runner\Hook
  32225. {
  32226. public function executeAfterLastTest() : void;
  32227. }
  32228. <?php
  32229. declare (strict_types=1);
  32230. /*
  32231. * This file is part of PHPUnit.
  32232. *
  32233. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  32234. *
  32235. * For the full copyright and license information, please view the LICENSE
  32236. * file that was distributed with this source code.
  32237. */
  32238. namespace PHPUnit\Runner;
  32239. /**
  32240. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  32241. */
  32242. final class NullTestResultCache implements \PHPUnit\Runner\TestResultCache
  32243. {
  32244. public function setState(string $testName, int $state) : void
  32245. {
  32246. }
  32247. public function getState(string $testName) : int
  32248. {
  32249. return \PHPUnit\Runner\BaseTestRunner::STATUS_UNKNOWN;
  32250. }
  32251. public function setTime(string $testName, float $time) : void
  32252. {
  32253. }
  32254. public function getTime(string $testName) : float
  32255. {
  32256. return 0;
  32257. }
  32258. public function load() : void
  32259. {
  32260. }
  32261. public function persist() : void
  32262. {
  32263. }
  32264. }
  32265. <?php
  32266. declare (strict_types=1);
  32267. /*
  32268. * This file is part of PHPUnit.
  32269. *
  32270. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  32271. *
  32272. * For the full copyright and license information, please view the LICENSE
  32273. * file that was distributed with this source code.
  32274. */
  32275. namespace PHPUnit\Runner;
  32276. use PHPUnit\Framework\Assert;
  32277. use PHPUnit\Framework\AssertionFailedError;
  32278. use PHPUnit\Framework\ExpectationFailedException;
  32279. use PHPUnit\Framework\IncompleteTestError;
  32280. use PHPUnit\Framework\PHPTAssertionFailedError;
  32281. use PHPUnit\Framework\SelfDescribing;
  32282. use PHPUnit\Framework\SkippedTestError;
  32283. use PHPUnit\Framework\SyntheticSkippedError;
  32284. use PHPUnit\Framework\Test;
  32285. use PHPUnit\Framework\TestResult;
  32286. use PHPUnit\Util\PHP\AbstractPhpProcess;
  32287. use PHPUnit\SebastianBergmann\Template\Template;
  32288. use PHPUnit\SebastianBergmann\Timer\Timer;
  32289. /**
  32290. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  32291. */
  32292. final class PhptTestCase implements \PHPUnit\Framework\SelfDescribing, \PHPUnit\Framework\Test
  32293. {
  32294. /**
  32295. * @var string[]
  32296. */
  32297. private const SETTINGS = ['allow_url_fopen=1', 'auto_append_file=', 'auto_prepend_file=', 'disable_functions=', 'display_errors=1', 'docref_ext=.html', 'docref_root=', 'error_append_string=', 'error_prepend_string=', 'error_reporting=-1', 'html_errors=0', 'log_errors=0', 'magic_quotes_runtime=0', 'open_basedir=', 'output_buffering=Off', 'output_handler=', 'report_memleaks=0', 'report_zend_debug=0', 'safe_mode=0', 'xdebug.default_enable=0'];
  32298. /**
  32299. * @var string
  32300. */
  32301. private $filename;
  32302. /**
  32303. * @var AbstractPhpProcess
  32304. */
  32305. private $phpUtil;
  32306. /**
  32307. * @var string
  32308. */
  32309. private $output = '';
  32310. /**
  32311. * Constructs a test case with the given filename.
  32312. *
  32313. * @throws Exception
  32314. */
  32315. public function __construct(string $filename, \PHPUnit\Util\PHP\AbstractPhpProcess $phpUtil = null)
  32316. {
  32317. if (!\is_file($filename)) {
  32318. throw new \PHPUnit\Runner\Exception(\sprintf('File "%s" does not exist.', $filename));
  32319. }
  32320. $this->filename = $filename;
  32321. $this->phpUtil = $phpUtil ?: \PHPUnit\Util\PHP\AbstractPhpProcess::factory();
  32322. }
  32323. /**
  32324. * Counts the number of test cases executed by run(TestResult result).
  32325. */
  32326. public function count() : int
  32327. {
  32328. return 1;
  32329. }
  32330. /**
  32331. * Runs a test and collects its result in a TestResult instance.
  32332. *
  32333. * @throws Exception
  32334. * @throws \SebastianBergmann\CodeCoverage\CoveredCodeNotExecutedException
  32335. * @throws \SebastianBergmann\CodeCoverage\InvalidArgumentException
  32336. * @throws \SebastianBergmann\CodeCoverage\RuntimeException
  32337. * @throws \SebastianBergmann\CodeCoverage\UnintentionallyCoveredCodeException
  32338. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  32339. */
  32340. public function run(\PHPUnit\Framework\TestResult $result = null) : \PHPUnit\Framework\TestResult
  32341. {
  32342. if ($result === null) {
  32343. $result = new \PHPUnit\Framework\TestResult();
  32344. }
  32345. try {
  32346. $sections = $this->parse();
  32347. } catch (\PHPUnit\Runner\Exception $e) {
  32348. $result->startTest($this);
  32349. $result->addFailure($this, new \PHPUnit\Framework\SkippedTestError($e->getMessage()), 0);
  32350. $result->endTest($this, 0);
  32351. return $result;
  32352. }
  32353. $code = $this->render($sections['FILE']);
  32354. $xfail = \false;
  32355. $settings = $this->parseIniSection(self::SETTINGS);
  32356. $result->startTest($this);
  32357. if (isset($sections['INI'])) {
  32358. $settings = $this->parseIniSection($sections['INI'], $settings);
  32359. }
  32360. if (isset($sections['ENV'])) {
  32361. $env = $this->parseEnvSection($sections['ENV']);
  32362. $this->phpUtil->setEnv($env);
  32363. }
  32364. $this->phpUtil->setUseStderrRedirection(\true);
  32365. if ($result->enforcesTimeLimit()) {
  32366. $this->phpUtil->setTimeout($result->getTimeoutForLargeTests());
  32367. }
  32368. $skip = $this->runSkip($sections, $result, $settings);
  32369. if ($skip) {
  32370. return $result;
  32371. }
  32372. if (isset($sections['XFAIL'])) {
  32373. $xfail = \trim($sections['XFAIL']);
  32374. }
  32375. if (isset($sections['STDIN'])) {
  32376. $this->phpUtil->setStdin($sections['STDIN']);
  32377. }
  32378. if (isset($sections['ARGS'])) {
  32379. $this->phpUtil->setArgs($sections['ARGS']);
  32380. }
  32381. if ($result->getCollectCodeCoverageInformation()) {
  32382. $this->renderForCoverage($code);
  32383. }
  32384. $timer = new \PHPUnit\SebastianBergmann\Timer\Timer();
  32385. $timer->start();
  32386. $jobResult = $this->phpUtil->runJob($code, $this->stringifyIni($settings));
  32387. $time = $timer->stop()->asSeconds();
  32388. $this->output = $jobResult['stdout'] ?? '';
  32389. if ($result->getCollectCodeCoverageInformation() && ($coverage = $this->cleanupForCoverage())) {
  32390. $result->getCodeCoverage()->append($coverage, $this, \true, [], [], \true);
  32391. }
  32392. try {
  32393. $this->assertPhptExpectation($sections, $this->output);
  32394. } catch (\PHPUnit\Framework\AssertionFailedError $e) {
  32395. $failure = $e;
  32396. if ($xfail !== \false) {
  32397. $failure = new \PHPUnit\Framework\IncompleteTestError($xfail, 0, $e);
  32398. } elseif ($e instanceof \PHPUnit\Framework\ExpectationFailedException) {
  32399. $comparisonFailure = $e->getComparisonFailure();
  32400. if ($comparisonFailure) {
  32401. $diff = $comparisonFailure->getDiff();
  32402. } else {
  32403. $diff = $e->getMessage();
  32404. }
  32405. $hint = $this->getLocationHintFromDiff($diff, $sections);
  32406. $trace = \array_merge($hint, \debug_backtrace(\DEBUG_BACKTRACE_IGNORE_ARGS));
  32407. $failure = new \PHPUnit\Framework\PHPTAssertionFailedError($e->getMessage(), 0, $trace[0]['file'], $trace[0]['line'], $trace, $comparisonFailure ? $diff : '');
  32408. }
  32409. $result->addFailure($this, $failure, $time);
  32410. } catch (\Throwable $t) {
  32411. $result->addError($this, $t, $time);
  32412. }
  32413. if ($xfail !== \false && $result->allCompletelyImplemented()) {
  32414. $result->addFailure($this, new \PHPUnit\Framework\IncompleteTestError('XFAIL section but test passes'), $time);
  32415. }
  32416. $this->runClean($sections);
  32417. $result->endTest($this, $time);
  32418. return $result;
  32419. }
  32420. /**
  32421. * Returns the name of the test case.
  32422. */
  32423. public function getName() : string
  32424. {
  32425. return $this->toString();
  32426. }
  32427. /**
  32428. * Returns a string representation of the test case.
  32429. */
  32430. public function toString() : string
  32431. {
  32432. return $this->filename;
  32433. }
  32434. public function usesDataProvider() : bool
  32435. {
  32436. return \false;
  32437. }
  32438. public function getNumAssertions() : int
  32439. {
  32440. return 1;
  32441. }
  32442. public function getActualOutput() : string
  32443. {
  32444. return $this->output;
  32445. }
  32446. public function hasOutput() : bool
  32447. {
  32448. return !empty($this->output);
  32449. }
  32450. /**
  32451. * Parse --INI-- section key value pairs and return as array.
  32452. *
  32453. * @param array|string $content
  32454. */
  32455. private function parseIniSection($content, array $ini = []) : array
  32456. {
  32457. if (\is_string($content)) {
  32458. $content = \explode("\n", \trim($content));
  32459. }
  32460. foreach ($content as $setting) {
  32461. if (\strpos($setting, '=') === \false) {
  32462. continue;
  32463. }
  32464. $setting = \explode('=', $setting, 2);
  32465. $name = \trim($setting[0]);
  32466. $value = \trim($setting[1]);
  32467. if ($name === 'extension' || $name === 'zend_extension') {
  32468. if (!isset($ini[$name])) {
  32469. $ini[$name] = [];
  32470. }
  32471. $ini[$name][] = $value;
  32472. continue;
  32473. }
  32474. $ini[$name] = $value;
  32475. }
  32476. return $ini;
  32477. }
  32478. private function parseEnvSection(string $content) : array
  32479. {
  32480. $env = [];
  32481. foreach (\explode("\n", \trim($content)) as $e) {
  32482. $e = \explode('=', \trim($e), 2);
  32483. if (!empty($e[0]) && isset($e[1])) {
  32484. $env[$e[0]] = $e[1];
  32485. }
  32486. }
  32487. return $env;
  32488. }
  32489. /**
  32490. * @throws ExpectationFailedException
  32491. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  32492. * @throws Exception
  32493. */
  32494. private function assertPhptExpectation(array $sections, string $output) : void
  32495. {
  32496. $assertions = ['EXPECT' => 'assertEquals', 'EXPECTF' => 'assertStringMatchesFormat', 'EXPECTREGEX' => 'assertMatchesRegularExpression'];
  32497. $actual = \preg_replace('/\\r\\n/', "\n", \trim($output));
  32498. foreach ($assertions as $sectionName => $sectionAssertion) {
  32499. if (isset($sections[$sectionName])) {
  32500. $sectionContent = \preg_replace('/\\r\\n/', "\n", \trim($sections[$sectionName]));
  32501. $expected = $sectionName === 'EXPECTREGEX' ? "/{$sectionContent}/" : $sectionContent;
  32502. if ($expected === null) {
  32503. throw new \PHPUnit\Runner\Exception('No PHPT expectation found');
  32504. }
  32505. \PHPUnit\Framework\Assert::$sectionAssertion($expected, $actual);
  32506. return;
  32507. }
  32508. }
  32509. throw new \PHPUnit\Runner\Exception('No PHPT assertion found');
  32510. }
  32511. /**
  32512. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  32513. */
  32514. private function runSkip(array &$sections, \PHPUnit\Framework\TestResult $result, array $settings) : bool
  32515. {
  32516. if (!isset($sections['SKIPIF'])) {
  32517. return \false;
  32518. }
  32519. $skipif = $this->render($sections['SKIPIF']);
  32520. $jobResult = $this->phpUtil->runJob($skipif, $this->stringifyIni($settings));
  32521. if (!\strncasecmp('skip', \ltrim($jobResult['stdout']), 4)) {
  32522. $message = '';
  32523. if (\preg_match('/^\\s*skip\\s*(.+)\\s*/i', $jobResult['stdout'], $skipMatch)) {
  32524. $message = \substr($skipMatch[1], 2);
  32525. }
  32526. $hint = $this->getLocationHint($message, $sections, 'SKIPIF');
  32527. $trace = \array_merge($hint, \debug_backtrace(\DEBUG_BACKTRACE_IGNORE_ARGS));
  32528. $result->addFailure($this, new \PHPUnit\Framework\SyntheticSkippedError($message, 0, $trace[0]['file'], $trace[0]['line'], $trace), 0);
  32529. $result->endTest($this, 0);
  32530. return \true;
  32531. }
  32532. return \false;
  32533. }
  32534. private function runClean(array &$sections) : void
  32535. {
  32536. $this->phpUtil->setStdin('');
  32537. $this->phpUtil->setArgs('');
  32538. if (isset($sections['CLEAN'])) {
  32539. $cleanCode = $this->render($sections['CLEAN']);
  32540. $this->phpUtil->runJob($cleanCode, self::SETTINGS);
  32541. }
  32542. }
  32543. /**
  32544. * @throws Exception
  32545. */
  32546. private function parse() : array
  32547. {
  32548. $sections = [];
  32549. $section = '';
  32550. $unsupportedSections = ['CGI', 'COOKIE', 'DEFLATE_POST', 'EXPECTHEADERS', 'EXTENSIONS', 'GET', 'GZIP_POST', 'HEADERS', 'PHPDBG', 'POST', 'POST_RAW', 'PUT', 'REDIRECTTEST', 'REQUEST'];
  32551. $lineNr = 0;
  32552. foreach (\file($this->filename) as $line) {
  32553. $lineNr++;
  32554. if (\preg_match('/^--([_A-Z]+)--/', $line, $result)) {
  32555. $section = $result[1];
  32556. $sections[$section] = '';
  32557. $sections[$section . '_offset'] = $lineNr;
  32558. continue;
  32559. }
  32560. if (empty($section)) {
  32561. throw new \PHPUnit\Runner\Exception('Invalid PHPT file: empty section header');
  32562. }
  32563. $sections[$section] .= $line;
  32564. }
  32565. if (isset($sections['FILEEOF'])) {
  32566. $sections['FILE'] = \rtrim($sections['FILEEOF'], "\r\n");
  32567. unset($sections['FILEEOF']);
  32568. }
  32569. $this->parseExternal($sections);
  32570. if (!$this->validate($sections)) {
  32571. throw new \PHPUnit\Runner\Exception('Invalid PHPT file');
  32572. }
  32573. foreach ($unsupportedSections as $section) {
  32574. if (isset($sections[$section])) {
  32575. throw new \PHPUnit\Runner\Exception("PHPUnit does not support PHPT {$section} sections");
  32576. }
  32577. }
  32578. return $sections;
  32579. }
  32580. /**
  32581. * @throws Exception
  32582. */
  32583. private function parseExternal(array &$sections) : void
  32584. {
  32585. $allowSections = ['FILE', 'EXPECT', 'EXPECTF', 'EXPECTREGEX'];
  32586. $testDirectory = \dirname($this->filename) . \DIRECTORY_SEPARATOR;
  32587. foreach ($allowSections as $section) {
  32588. if (isset($sections[$section . '_EXTERNAL'])) {
  32589. $externalFilename = \trim($sections[$section . '_EXTERNAL']);
  32590. if (!\is_file($testDirectory . $externalFilename) || !\is_readable($testDirectory . $externalFilename)) {
  32591. throw new \PHPUnit\Runner\Exception(\sprintf('Could not load --%s-- %s for PHPT file', $section . '_EXTERNAL', $testDirectory . $externalFilename));
  32592. }
  32593. $sections[$section] = \file_get_contents($testDirectory . $externalFilename);
  32594. }
  32595. }
  32596. }
  32597. private function validate(array &$sections) : bool
  32598. {
  32599. $requiredSections = ['FILE', ['EXPECT', 'EXPECTF', 'EXPECTREGEX']];
  32600. foreach ($requiredSections as $section) {
  32601. if (\is_array($section)) {
  32602. $foundSection = \false;
  32603. foreach ($section as $anySection) {
  32604. if (isset($sections[$anySection])) {
  32605. $foundSection = \true;
  32606. break;
  32607. }
  32608. }
  32609. if (!$foundSection) {
  32610. return \false;
  32611. }
  32612. continue;
  32613. }
  32614. if (!isset($sections[$section])) {
  32615. return \false;
  32616. }
  32617. }
  32618. return \true;
  32619. }
  32620. private function render(string $code) : string
  32621. {
  32622. return \str_replace(['__DIR__', '__FILE__'], ["'" . \dirname($this->filename) . "'", "'" . $this->filename . "'"], $code);
  32623. }
  32624. private function getCoverageFiles() : array
  32625. {
  32626. $baseDir = \dirname(\realpath($this->filename)) . \DIRECTORY_SEPARATOR;
  32627. $basename = \basename($this->filename, 'phpt');
  32628. return ['coverage' => $baseDir . $basename . 'coverage', 'job' => $baseDir . $basename . 'php'];
  32629. }
  32630. private function renderForCoverage(string &$job) : void
  32631. {
  32632. $files = $this->getCoverageFiles();
  32633. $template = new \PHPUnit\SebastianBergmann\Template\Template(__DIR__ . '/../Util/PHP/Template/PhptTestCase.tpl');
  32634. $composerAutoload = '\'\'';
  32635. if (\defined('PHPUNIT_COMPOSER_INSTALL') && !\defined('PHPUNIT_TESTSUITE')) {
  32636. $composerAutoload = \var_export(PHPUNIT_COMPOSER_INSTALL, \true);
  32637. }
  32638. $phar = '\'\'';
  32639. if (\defined('__PHPUNIT_PHAR__')) {
  32640. $phar = \var_export(__PHPUNIT_PHAR__, \true);
  32641. }
  32642. $globals = '';
  32643. if (!empty($GLOBALS['__PHPUNIT_BOOTSTRAP'])) {
  32644. $globals = '$GLOBALS[\'__PHPUNIT_BOOTSTRAP\'] = ' . \var_export($GLOBALS['__PHPUNIT_BOOTSTRAP'], \true) . ";\n";
  32645. }
  32646. $template->setVar(['composerAutoload' => $composerAutoload, 'phar' => $phar, 'globals' => $globals, 'job' => $files['job'], 'coverageFile' => $files['coverage']]);
  32647. \file_put_contents($files['job'], $job);
  32648. $job = $template->render();
  32649. }
  32650. private function cleanupForCoverage() : array
  32651. {
  32652. $files = $this->getCoverageFiles();
  32653. $coverage = @\unserialize(\file_get_contents($files['coverage']));
  32654. if ($coverage === \false) {
  32655. $coverage = [];
  32656. }
  32657. foreach ($files as $file) {
  32658. @\unlink($file);
  32659. }
  32660. return $coverage;
  32661. }
  32662. private function stringifyIni(array $ini) : array
  32663. {
  32664. $settings = [];
  32665. foreach ($ini as $key => $value) {
  32666. if (\is_array($value)) {
  32667. foreach ($value as $val) {
  32668. $settings[] = $key . '=' . $val;
  32669. }
  32670. continue;
  32671. }
  32672. $settings[] = $key . '=' . $value;
  32673. }
  32674. return $settings;
  32675. }
  32676. private function getLocationHintFromDiff(string $message, array $sections) : array
  32677. {
  32678. $needle = '';
  32679. $previousLine = '';
  32680. $block = 'message';
  32681. foreach (\preg_split('/\\r\\n|\\r|\\n/', $message) as $line) {
  32682. $line = \trim($line);
  32683. if ($block === 'message' && $line === '--- Expected') {
  32684. $block = 'expected';
  32685. }
  32686. if ($block === 'expected' && $line === '@@ @@') {
  32687. $block = 'diff';
  32688. }
  32689. if ($block === 'diff') {
  32690. if (\strpos($line, '+') === 0) {
  32691. $needle = $this->getCleanDiffLine($previousLine);
  32692. break;
  32693. }
  32694. if (\strpos($line, '-') === 0) {
  32695. $needle = $this->getCleanDiffLine($line);
  32696. break;
  32697. }
  32698. }
  32699. if (!empty($line)) {
  32700. $previousLine = $line;
  32701. }
  32702. }
  32703. return $this->getLocationHint($needle, $sections);
  32704. }
  32705. private function getCleanDiffLine(string $line) : string
  32706. {
  32707. if (\preg_match('/^[\\-+]([\'\\"]?)(.*)\\1$/', $line, $matches)) {
  32708. $line = $matches[2];
  32709. }
  32710. return $line;
  32711. }
  32712. private function getLocationHint(string $needle, array $sections, ?string $sectionName = null) : array
  32713. {
  32714. $needle = \trim($needle);
  32715. if (empty($needle)) {
  32716. return [['file' => \realpath($this->filename), 'line' => 1]];
  32717. }
  32718. if ($sectionName) {
  32719. $search = [$sectionName];
  32720. } else {
  32721. $search = [
  32722. // 'FILE',
  32723. 'EXPECT',
  32724. 'EXPECTF',
  32725. 'EXPECTREGEX',
  32726. ];
  32727. }
  32728. foreach ($search as $section) {
  32729. if (!isset($sections[$section])) {
  32730. continue;
  32731. }
  32732. if (isset($sections[$section . '_EXTERNAL'])) {
  32733. $externalFile = \trim($sections[$section . '_EXTERNAL']);
  32734. return [['file' => \realpath(\dirname($this->filename) . \DIRECTORY_SEPARATOR . $externalFile), 'line' => 1], ['file' => \realpath($this->filename), 'line' => ($sections[$section . '_EXTERNAL_offset'] ?? 0) + 1]];
  32735. }
  32736. $sectionOffset = $sections[$section . '_offset'] ?? 0;
  32737. $offset = $sectionOffset + 1;
  32738. foreach (\preg_split('/\\r\\n|\\r|\\n/', $sections[$section]) as $line) {
  32739. if (\strpos($line, $needle) !== \false) {
  32740. return [['file' => \realpath($this->filename), 'line' => $offset]];
  32741. }
  32742. $offset++;
  32743. }
  32744. }
  32745. if ($sectionName) {
  32746. // String not found in specified section, show user the start of the named section
  32747. return [['file' => \realpath($this->filename), 'line' => $sectionOffset]];
  32748. }
  32749. // No section specified, show user start of code
  32750. return [['file' => \realpath($this->filename), 'line' => 1]];
  32751. }
  32752. }
  32753. <?php
  32754. declare (strict_types=1);
  32755. /*
  32756. * This file is part of PHPUnit.
  32757. *
  32758. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  32759. *
  32760. * For the full copyright and license information, please view the LICENSE
  32761. * file that was distributed with this source code.
  32762. */
  32763. namespace PHPUnit\Runner;
  32764. use PHPUnit\Framework\Exception;
  32765. use PHPUnit\Framework\Test;
  32766. use PHPUnit\Framework\TestSuite;
  32767. use PHPUnit\SebastianBergmann\FileIterator\Facade as FileIteratorFacade;
  32768. /**
  32769. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  32770. */
  32771. abstract class BaseTestRunner
  32772. {
  32773. /**
  32774. * @var int
  32775. */
  32776. public const STATUS_UNKNOWN = -1;
  32777. /**
  32778. * @var int
  32779. */
  32780. public const STATUS_PASSED = 0;
  32781. /**
  32782. * @var int
  32783. */
  32784. public const STATUS_SKIPPED = 1;
  32785. /**
  32786. * @var int
  32787. */
  32788. public const STATUS_INCOMPLETE = 2;
  32789. /**
  32790. * @var int
  32791. */
  32792. public const STATUS_FAILURE = 3;
  32793. /**
  32794. * @var int
  32795. */
  32796. public const STATUS_ERROR = 4;
  32797. /**
  32798. * @var int
  32799. */
  32800. public const STATUS_RISKY = 5;
  32801. /**
  32802. * @var int
  32803. */
  32804. public const STATUS_WARNING = 6;
  32805. /**
  32806. * @var string
  32807. */
  32808. public const SUITE_METHODNAME = 'suite';
  32809. /**
  32810. * Returns the loader to be used.
  32811. */
  32812. public function getLoader() : \PHPUnit\Runner\TestSuiteLoader
  32813. {
  32814. return new \PHPUnit\Runner\StandardTestSuiteLoader();
  32815. }
  32816. /**
  32817. * Returns the Test corresponding to the given suite.
  32818. * This is a template method, subclasses override
  32819. * the runFailed() and clearStatus() methods.
  32820. *
  32821. * @param string|string[] $suffixes
  32822. *
  32823. * @throws Exception
  32824. */
  32825. public function getTest(string $suiteClassFile, $suffixes = '') : ?\PHPUnit\Framework\TestSuite
  32826. {
  32827. if (\is_dir($suiteClassFile)) {
  32828. /** @var string[] $files */
  32829. $files = (new \PHPUnit\SebastianBergmann\FileIterator\Facade())->getFilesAsArray($suiteClassFile, $suffixes);
  32830. $suite = new \PHPUnit\Framework\TestSuite($suiteClassFile);
  32831. $suite->addTestFiles($files);
  32832. return $suite;
  32833. }
  32834. if (\is_file($suiteClassFile) && \substr($suiteClassFile, -5, 5) === '.phpt') {
  32835. $suite = new \PHPUnit\Framework\TestSuite();
  32836. $suite->addTestFile($suiteClassFile);
  32837. return $suite;
  32838. }
  32839. try {
  32840. $testClass = $this->loadSuiteClass($suiteClassFile);
  32841. } catch (\PHPUnit\Exception $e) {
  32842. $this->runFailed($e->getMessage());
  32843. return null;
  32844. }
  32845. try {
  32846. $suiteMethod = $testClass->getMethod(self::SUITE_METHODNAME);
  32847. if (!$suiteMethod->isStatic()) {
  32848. $this->runFailed('suite() method must be static.');
  32849. return null;
  32850. }
  32851. $test = $suiteMethod->invoke(null, $testClass->getName());
  32852. } catch (\ReflectionException $e) {
  32853. $test = new \PHPUnit\Framework\TestSuite($testClass);
  32854. }
  32855. $this->clearStatus();
  32856. return $test;
  32857. }
  32858. /**
  32859. * Returns the loaded ReflectionClass for a suite name.
  32860. */
  32861. protected function loadSuiteClass(string $suiteClassFile) : \ReflectionClass
  32862. {
  32863. return $this->getLoader()->load($suiteClassFile);
  32864. }
  32865. /**
  32866. * Clears the status message.
  32867. */
  32868. protected function clearStatus() : void
  32869. {
  32870. }
  32871. /**
  32872. * Override to define how to handle a failed loading of
  32873. * a test suite.
  32874. */
  32875. protected abstract function runFailed(string $message) : void;
  32876. }
  32877. <?php
  32878. declare (strict_types=1);
  32879. /*
  32880. * This file is part of PHPUnit.
  32881. *
  32882. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  32883. *
  32884. * For the full copyright and license information, please view the LICENSE
  32885. * file that was distributed with this source code.
  32886. */
  32887. namespace PHPUnit\Runner;
  32888. /**
  32889. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  32890. */
  32891. final class ResultCacheExtension implements \PHPUnit\Runner\AfterIncompleteTestHook, \PHPUnit\Runner\AfterLastTestHook, \PHPUnit\Runner\AfterRiskyTestHook, \PHPUnit\Runner\AfterSkippedTestHook, \PHPUnit\Runner\AfterSuccessfulTestHook, \PHPUnit\Runner\AfterTestErrorHook, \PHPUnit\Runner\AfterTestFailureHook, \PHPUnit\Runner\AfterTestWarningHook
  32892. {
  32893. /**
  32894. * @var TestResultCache
  32895. */
  32896. private $cache;
  32897. public function __construct(\PHPUnit\Runner\TestResultCache $cache)
  32898. {
  32899. $this->cache = $cache;
  32900. }
  32901. public function flush() : void
  32902. {
  32903. $this->cache->persist();
  32904. }
  32905. public function executeAfterSuccessfulTest(string $test, float $time) : void
  32906. {
  32907. $testName = $this->getTestName($test);
  32908. $this->cache->setTime($testName, \round($time, 3));
  32909. }
  32910. public function executeAfterIncompleteTest(string $test, string $message, float $time) : void
  32911. {
  32912. $testName = $this->getTestName($test);
  32913. $this->cache->setTime($testName, \round($time, 3));
  32914. $this->cache->setState($testName, \PHPUnit\Runner\BaseTestRunner::STATUS_INCOMPLETE);
  32915. }
  32916. public function executeAfterRiskyTest(string $test, string $message, float $time) : void
  32917. {
  32918. $testName = $this->getTestName($test);
  32919. $this->cache->setTime($testName, \round($time, 3));
  32920. $this->cache->setState($testName, \PHPUnit\Runner\BaseTestRunner::STATUS_RISKY);
  32921. }
  32922. public function executeAfterSkippedTest(string $test, string $message, float $time) : void
  32923. {
  32924. $testName = $this->getTestName($test);
  32925. $this->cache->setTime($testName, \round($time, 3));
  32926. $this->cache->setState($testName, \PHPUnit\Runner\BaseTestRunner::STATUS_SKIPPED);
  32927. }
  32928. public function executeAfterTestError(string $test, string $message, float $time) : void
  32929. {
  32930. $testName = $this->getTestName($test);
  32931. $this->cache->setTime($testName, \round($time, 3));
  32932. $this->cache->setState($testName, \PHPUnit\Runner\BaseTestRunner::STATUS_ERROR);
  32933. }
  32934. public function executeAfterTestFailure(string $test, string $message, float $time) : void
  32935. {
  32936. $testName = $this->getTestName($test);
  32937. $this->cache->setTime($testName, \round($time, 3));
  32938. $this->cache->setState($testName, \PHPUnit\Runner\BaseTestRunner::STATUS_FAILURE);
  32939. }
  32940. public function executeAfterTestWarning(string $test, string $message, float $time) : void
  32941. {
  32942. $testName = $this->getTestName($test);
  32943. $this->cache->setTime($testName, \round($time, 3));
  32944. $this->cache->setState($testName, \PHPUnit\Runner\BaseTestRunner::STATUS_WARNING);
  32945. }
  32946. public function executeAfterLastTest() : void
  32947. {
  32948. $this->flush();
  32949. }
  32950. /**
  32951. * @param string $test A long description format of the current test
  32952. *
  32953. * @return string The test name without TestSuiteClassName:: and @dataprovider details
  32954. */
  32955. private function getTestName(string $test) : string
  32956. {
  32957. $matches = [];
  32958. if (\preg_match('/^(?<name>\\S+::\\S+)(?:(?<dataname> with data set (?:#\\d+|"[^"]+"))\\s\\()?/', $test, $matches)) {
  32959. $test = $matches['name'] . ($matches['dataname'] ?? '');
  32960. }
  32961. return $test;
  32962. }
  32963. }
  32964. <?php
  32965. declare (strict_types=1);
  32966. /*
  32967. * This file is part of PHPUnit.
  32968. *
  32969. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  32970. *
  32971. * For the full copyright and license information, please view the LICENSE
  32972. * file that was distributed with this source code.
  32973. */
  32974. namespace PHPUnit\TextUI;
  32975. use PHPUnit\Util\Color;
  32976. use PHPUnit\SebastianBergmann\Environment\Console;
  32977. /**
  32978. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  32979. */
  32980. final class Help
  32981. {
  32982. private const LEFT_MARGIN = ' ';
  32983. private const HELP_TEXT = ['Usage' => [['text' => 'phpunit [options] UnitTest.php'], ['text' => 'phpunit [options] <directory>']], 'Code Coverage Options' => [['arg' => '--coverage-clover <file>', 'desc' => 'Generate code coverage report in Clover XML format'], ['arg' => '--coverage-crap4j <file>', 'desc' => 'Generate code coverage report in Crap4J XML format'], ['arg' => '--coverage-html <dir>', 'desc' => 'Generate code coverage report in HTML format'], ['arg' => '--coverage-php <file>', 'desc' => 'Export PHP_CodeCoverage object to file'], ['arg' => '--coverage-text=<file>', 'desc' => 'Generate code coverage report in text format [default: standard output]'], ['arg' => '--coverage-xml <dir>', 'desc' => 'Generate code coverage report in PHPUnit XML format'], ['arg' => '--whitelist <dir>', 'desc' => 'Whitelist <dir> for code coverage analysis'], ['arg' => '--disable-coverage-ignore', 'desc' => 'Disable annotations for ignoring code coverage'], ['arg' => '--no-coverage', 'desc' => 'Ignore code coverage configuration'], ['arg' => '--dump-xdebug-filter <file>', 'desc' => 'Generate script to set Xdebug code coverage filter']], 'Logging Options' => [['arg' => '--log-junit <file>', 'desc' => 'Log test execution in JUnit XML format to file'], ['arg' => '--log-teamcity <file>', 'desc' => 'Log test execution in TeamCity format to file'], ['arg' => '--testdox-html <file>', 'desc' => 'Write agile documentation in HTML format to file'], ['arg' => '--testdox-text <file>', 'desc' => 'Write agile documentation in Text format to file'], ['arg' => '--testdox-xml <file>', 'desc' => 'Write agile documentation in XML format to file'], ['arg' => '--reverse-list', 'desc' => 'Print defects in reverse order']], 'Test Selection Options' => [['arg' => '--filter <pattern>', 'desc' => 'Filter which tests to run'], ['arg' => '--testsuite <name>', 'desc' => 'Filter which testsuite to run'], ['arg' => '--group <name>', 'desc' => 'Only runs tests from the specified group(s)'], ['arg' => '--exclude-group <name>', 'desc' => 'Exclude tests from the specified group(s)'], ['arg' => '--list-groups', 'desc' => 'List available test groups'], ['arg' => '--list-suites', 'desc' => 'List available test suites'], ['arg' => '--list-tests', 'desc' => 'List available tests'], ['arg' => '--list-tests-xml <file>', 'desc' => 'List available tests in XML format'], ['arg' => '--test-suffix <suffixes>', 'desc' => 'Only search for test in files with specified suffix(es). Default: Test.php,.phpt']], 'Test Execution Options' => [['arg' => '--dont-report-useless-tests', 'desc' => 'Do not report tests that do not test anything'], ['arg' => '--strict-coverage', 'desc' => 'Be strict about @covers annotation usage'], ['arg' => '--strict-global-state', 'desc' => 'Be strict about changes to global state'], ['arg' => '--disallow-test-output', 'desc' => 'Be strict about output during tests'], ['arg' => '--disallow-resource-usage', 'desc' => 'Be strict about resource usage during small tests'], ['arg' => '--enforce-time-limit', 'desc' => 'Enforce time limit based on test size'], ['arg' => '--default-time-limit=<sec>', 'desc' => 'Timeout in seconds for tests without @small, @medium or @large'], ['arg' => '--disallow-todo-tests', 'desc' => 'Disallow @todo-annotated tests'], ['spacer' => ''], ['arg' => '--process-isolation', 'desc' => 'Run each test in a separate PHP process'], ['arg' => '--globals-backup', 'desc' => 'Backup and restore $GLOBALS for each test'], ['arg' => '--static-backup', 'desc' => 'Backup and restore static attributes for each test'], ['spacer' => ''], ['arg' => '--colors=<flag>', 'desc' => 'Use colors in output ("never", "auto" or "always")'], ['arg' => '--columns <n>', 'desc' => 'Number of columns to use for progress output'], ['arg' => '--columns max', 'desc' => 'Use maximum number of columns for progress output'], ['arg' => '--stderr', 'desc' => 'Write to STDERR instead of STDOUT'], ['arg' => '--stop-on-defect', 'desc' => 'Stop execution upon first not-passed test'], ['arg' => '--stop-on-error', 'desc' => 'Stop execution upon first error'], ['arg' => '--stop-on-failure', 'desc' => 'Stop execution upon first error or failure'], ['arg' => '--stop-on-warning', 'desc' => 'Stop execution upon first warning'], ['arg' => '--stop-on-risky', 'desc' => 'Stop execution upon first risky test'], ['arg' => '--stop-on-skipped', 'desc' => 'Stop execution upon first skipped test'], ['arg' => '--stop-on-incomplete', 'desc' => 'Stop execution upon first incomplete test'], ['arg' => '--fail-on-incomplete', 'desc' => 'Treat incomplete tests as failures'], ['arg' => '--fail-on-risky', 'desc' => 'Treat risky tests as failures'], ['arg' => '--fail-on-skipped', 'desc' => 'Treat skipped tests as failures'], ['arg' => '--fail-on-warning', 'desc' => 'Treat tests with warnings as failures'], ['arg' => '-v|--verbose', 'desc' => 'Output more verbose information'], ['arg' => '--debug', 'desc' => 'Display debugging information'], ['spacer' => ''], ['arg' => '--repeat <times>', 'desc' => 'Runs the test(s) repeatedly'], ['arg' => '--teamcity', 'desc' => 'Report test execution progress in TeamCity format'], ['arg' => '--testdox', 'desc' => 'Report test execution progress in TestDox format'], ['arg' => '--testdox-group', 'desc' => 'Only include tests from the specified group(s)'], ['arg' => '--testdox-exclude-group', 'desc' => 'Exclude tests from the specified group(s)'], ['arg' => '--no-interaction', 'desc' => 'Disable TestDox progress animation'], ['arg' => '--printer <printer>', 'desc' => 'TestListener implementation to use'], ['spacer' => ''], ['arg' => '--order-by=<order>', 'desc' => 'Run tests in order: default|defects|duration|no-depends|random|reverse|size'], ['arg' => '--random-order-seed=<N>', 'desc' => 'Use a specific random seed <N> for random order'], ['arg' => '--cache-result', 'desc' => 'Write test results to cache file'], ['arg' => '--do-not-cache-result', 'desc' => 'Do not write test results to cache file']], 'Configuration Options' => [['arg' => '--prepend <file>', 'desc' => 'A PHP script that is included as early as possible'], ['arg' => '--bootstrap <file>', 'desc' => 'A PHP script that is included before the tests run'], ['arg' => '-c|--configuration <file>', 'desc' => 'Read configuration from XML file'], ['arg' => '--no-configuration', 'desc' => 'Ignore default configuration file (phpunit.xml)'], ['arg' => '--no-logging', 'desc' => 'Ignore logging configuration'], ['arg' => '--extensions <extensions>', 'desc' => 'A comma separated list of PHPUnit extensions to load'], ['arg' => '--no-extensions', 'desc' => 'Do not load PHPUnit extensions'], ['arg' => '--include-path <path(s)>', 'desc' => 'Prepend PHP\'s include_path with given path(s)'], ['arg' => '-d <key[=value]>', 'desc' => 'Sets a php.ini value'], ['arg' => '--generate-configuration', 'desc' => 'Generate configuration file with suggested settings'], ['arg' => '--cache-result-file=<file>', 'desc' => 'Specify result cache path and filename']], 'Miscellaneous Options' => [['arg' => '-h|--help', 'desc' => 'Prints this usage information'], ['arg' => '--version', 'desc' => 'Prints the version and exits'], ['arg' => '--atleast-version <min>', 'desc' => 'Checks that version is greater than min and exits'], ['arg' => '--check-version', 'desc' => 'Check whether PHPUnit is the latest version']]];
  32984. /**
  32985. * @var int Number of columns required to write the longest option name to the console
  32986. */
  32987. private $maxArgLength = 0;
  32988. /**
  32989. * @var int Number of columns left for the description field after padding and option
  32990. */
  32991. private $maxDescLength;
  32992. /**
  32993. * @var bool Use color highlights for sections, options and parameters
  32994. */
  32995. private $hasColor = \false;
  32996. public function __construct(?int $width = null, ?bool $withColor = null)
  32997. {
  32998. if ($width === null) {
  32999. $width = (new \PHPUnit\SebastianBergmann\Environment\Console())->getNumberOfColumns();
  33000. }
  33001. if ($withColor === null) {
  33002. $this->hasColor = (new \PHPUnit\SebastianBergmann\Environment\Console())->hasColorSupport();
  33003. } else {
  33004. $this->hasColor = $withColor;
  33005. }
  33006. foreach (self::HELP_TEXT as $options) {
  33007. foreach ($options as $option) {
  33008. if (isset($option['arg'])) {
  33009. $this->maxArgLength = \max($this->maxArgLength, isset($option['arg']) ? \strlen($option['arg']) : 0);
  33010. }
  33011. }
  33012. }
  33013. $this->maxDescLength = $width - $this->maxArgLength - 4;
  33014. }
  33015. /**
  33016. * Write the help file to the CLI, adapting width and colors to the console
  33017. */
  33018. public function writeToConsole() : void
  33019. {
  33020. if ($this->hasColor) {
  33021. $this->writeWithColor();
  33022. } else {
  33023. $this->writePlaintext();
  33024. }
  33025. }
  33026. private function writePlaintext() : void
  33027. {
  33028. foreach (self::HELP_TEXT as $section => $options) {
  33029. print "{$section}:" . \PHP_EOL;
  33030. if ($section !== 'Usage') {
  33031. print \PHP_EOL;
  33032. }
  33033. foreach ($options as $option) {
  33034. if (isset($option['spacer'])) {
  33035. print \PHP_EOL;
  33036. }
  33037. if (isset($option['text'])) {
  33038. print self::LEFT_MARGIN . $option['text'] . \PHP_EOL;
  33039. }
  33040. if (isset($option['arg'])) {
  33041. $arg = \str_pad($option['arg'], $this->maxArgLength);
  33042. print self::LEFT_MARGIN . $arg . ' ' . $option['desc'] . \PHP_EOL;
  33043. }
  33044. }
  33045. print \PHP_EOL;
  33046. }
  33047. }
  33048. private function writeWithColor() : void
  33049. {
  33050. foreach (self::HELP_TEXT as $section => $options) {
  33051. print \PHPUnit\Util\Color::colorize('fg-yellow', "{$section}:") . \PHP_EOL;
  33052. foreach ($options as $option) {
  33053. if (isset($option['spacer'])) {
  33054. print \PHP_EOL;
  33055. }
  33056. if (isset($option['text'])) {
  33057. print self::LEFT_MARGIN . $option['text'] . \PHP_EOL;
  33058. }
  33059. if (isset($option['arg'])) {
  33060. $arg = \PHPUnit\Util\Color::colorize('fg-green', \str_pad($option['arg'], $this->maxArgLength));
  33061. $arg = \preg_replace_callback('/(<[^>]+>)/', static function ($matches) {
  33062. return \PHPUnit\Util\Color::colorize('fg-cyan', $matches[0]);
  33063. }, $arg);
  33064. $desc = \explode(\PHP_EOL, \wordwrap($option['desc'], $this->maxDescLength, \PHP_EOL));
  33065. print self::LEFT_MARGIN . $arg . ' ' . $desc[0] . \PHP_EOL;
  33066. for ($i = 1; $i < \count($desc); $i++) {
  33067. print \str_repeat(' ', $this->maxArgLength + 3) . $desc[$i] . \PHP_EOL;
  33068. }
  33069. }
  33070. }
  33071. print \PHP_EOL;
  33072. }
  33073. }
  33074. }
  33075. <?php
  33076. declare (strict_types=1);
  33077. /*
  33078. * This file is part of PHPUnit.
  33079. *
  33080. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  33081. *
  33082. * For the full copyright and license information, please view the LICENSE
  33083. * file that was distributed with this source code.
  33084. */
  33085. namespace PHPUnit\TextUI;
  33086. use PHPUnit\Framework\Exception;
  33087. use PHPUnit\Framework\TestResult;
  33088. use PHPUnit\Framework\TestSuite;
  33089. use PHPUnit\Runner\AfterLastTestHook;
  33090. use PHPUnit\Runner\BaseTestRunner;
  33091. use PHPUnit\Runner\BeforeFirstTestHook;
  33092. use PHPUnit\Runner\DefaultTestResultCache;
  33093. use PHPUnit\Runner\Filter\ExcludeGroupFilterIterator;
  33094. use PHPUnit\Runner\Filter\Factory;
  33095. use PHPUnit\Runner\Filter\IncludeGroupFilterIterator;
  33096. use PHPUnit\Runner\Filter\NameFilterIterator;
  33097. use PHPUnit\Runner\Hook;
  33098. use PHPUnit\Runner\NullTestResultCache;
  33099. use PHPUnit\Runner\ResultCacheExtension;
  33100. use PHPUnit\Runner\StandardTestSuiteLoader;
  33101. use PHPUnit\Runner\TestHook;
  33102. use PHPUnit\Runner\TestListenerAdapter;
  33103. use PHPUnit\Runner\TestSuiteLoader;
  33104. use PHPUnit\Runner\TestSuiteSorter;
  33105. use PHPUnit\Runner\Version;
  33106. use PHPUnit\TextUI\Configuration\Configuration;
  33107. use PHPUnit\TextUI\Configuration\ExtensionHandler;
  33108. use PHPUnit\TextUI\Configuration\PhpHandler;
  33109. use PHPUnit\TextUI\Configuration\Registry;
  33110. use PHPUnit\Util\Filesystem;
  33111. use PHPUnit\Util\Log\JUnit;
  33112. use PHPUnit\Util\Log\TeamCity;
  33113. use PHPUnit\Util\Printer;
  33114. use PHPUnit\Util\TestDox\CliTestDoxPrinter;
  33115. use PHPUnit\Util\TestDox\HtmlResultPrinter;
  33116. use PHPUnit\Util\TestDox\TextResultPrinter;
  33117. use PHPUnit\Util\TestDox\XmlResultPrinter;
  33118. use PHPUnit\Util\XdebugFilterScriptGenerator;
  33119. use PHPUnit\SebastianBergmann\CodeCoverage\CodeCoverage;
  33120. use PHPUnit\SebastianBergmann\CodeCoverage\Exception as CodeCoverageException;
  33121. use PHPUnit\SebastianBergmann\CodeCoverage\Filter as CodeCoverageFilter;
  33122. use PHPUnit\SebastianBergmann\CodeCoverage\Report\Clover as CloverReport;
  33123. use PHPUnit\SebastianBergmann\CodeCoverage\Report\Crap4j as Crap4jReport;
  33124. use PHPUnit\SebastianBergmann\CodeCoverage\Report\Html\Facade as HtmlReport;
  33125. use PHPUnit\SebastianBergmann\CodeCoverage\Report\PHP as PhpReport;
  33126. use PHPUnit\SebastianBergmann\CodeCoverage\Report\Text as TextReport;
  33127. use PHPUnit\SebastianBergmann\CodeCoverage\Report\Xml\Facade as XmlReport;
  33128. use PHPUnit\SebastianBergmann\Comparator\Comparator;
  33129. use PHPUnit\SebastianBergmann\Environment\Runtime;
  33130. use PHPUnit\SebastianBergmann\Invoker\Invoker;
  33131. use PHPUnit\SebastianBergmann\Timer\Timer;
  33132. /**
  33133. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  33134. */
  33135. final class TestRunner extends \PHPUnit\Runner\BaseTestRunner
  33136. {
  33137. public const SUCCESS_EXIT = 0;
  33138. public const FAILURE_EXIT = 1;
  33139. public const EXCEPTION_EXIT = 2;
  33140. /**
  33141. * @var bool
  33142. */
  33143. private static $versionStringPrinted = \false;
  33144. /**
  33145. * @var CodeCoverageFilter
  33146. */
  33147. private $codeCoverageFilter;
  33148. /**
  33149. * @var TestSuiteLoader
  33150. */
  33151. private $loader;
  33152. /**
  33153. * @var ResultPrinter
  33154. */
  33155. private $printer;
  33156. /**
  33157. * @var Runtime
  33158. */
  33159. private $runtime;
  33160. /**
  33161. * @var bool
  33162. */
  33163. private $messagePrinted = \false;
  33164. /**
  33165. * @var Hook[]
  33166. */
  33167. private $extensions = [];
  33168. /**
  33169. * @var Timer
  33170. */
  33171. private $timer;
  33172. public function __construct(\PHPUnit\Runner\TestSuiteLoader $loader = null, \PHPUnit\SebastianBergmann\CodeCoverage\Filter $filter = null)
  33173. {
  33174. if ($filter === null) {
  33175. $filter = new \PHPUnit\SebastianBergmann\CodeCoverage\Filter();
  33176. }
  33177. $this->codeCoverageFilter = $filter;
  33178. $this->loader = $loader;
  33179. $this->runtime = new \PHPUnit\SebastianBergmann\Environment\Runtime();
  33180. $this->timer = new \PHPUnit\SebastianBergmann\Timer\Timer();
  33181. }
  33182. /**
  33183. * @throws \PHPUnit\Runner\Exception
  33184. * @throws Exception
  33185. */
  33186. public function run(\PHPUnit\Framework\TestSuite $suite, array $arguments = [], array $warnings = [], bool $exit = \true) : \PHPUnit\Framework\TestResult
  33187. {
  33188. if (isset($arguments['configuration'])) {
  33189. $GLOBALS['__PHPUNIT_CONFIGURATION_FILE'] = $arguments['configuration'];
  33190. }
  33191. $this->handleConfiguration($arguments);
  33192. if (\is_int($arguments['columns']) && $arguments['columns'] < 16) {
  33193. $arguments['columns'] = 16;
  33194. $tooFewColumnsRequested = \true;
  33195. }
  33196. if (isset($arguments['bootstrap'])) {
  33197. $GLOBALS['__PHPUNIT_BOOTSTRAP'] = $arguments['bootstrap'];
  33198. }
  33199. if ($arguments['backupGlobals'] === \true) {
  33200. $suite->setBackupGlobals(\true);
  33201. }
  33202. if ($arguments['backupStaticAttributes'] === \true) {
  33203. $suite->setBackupStaticAttributes(\true);
  33204. }
  33205. if ($arguments['beStrictAboutChangesToGlobalState'] === \true) {
  33206. $suite->setBeStrictAboutChangesToGlobalState(\true);
  33207. }
  33208. if ($arguments['executionOrder'] === \PHPUnit\Runner\TestSuiteSorter::ORDER_RANDOMIZED) {
  33209. \mt_srand($arguments['randomOrderSeed']);
  33210. }
  33211. if ($arguments['cacheResult']) {
  33212. if (!isset($arguments['cacheResultFile'])) {
  33213. if (isset($arguments['configuration'])) {
  33214. \assert($arguments['configuration'] instanceof \PHPUnit\TextUI\Configuration\Configuration);
  33215. $cacheLocation = $arguments['configuration']->filename();
  33216. } else {
  33217. $cacheLocation = $_SERVER['PHP_SELF'];
  33218. }
  33219. $arguments['cacheResultFile'] = null;
  33220. $cacheResultFile = \realpath($cacheLocation);
  33221. if ($cacheResultFile !== \false) {
  33222. $arguments['cacheResultFile'] = \dirname($cacheResultFile);
  33223. }
  33224. }
  33225. $cache = new \PHPUnit\Runner\DefaultTestResultCache($arguments['cacheResultFile']);
  33226. $this->addExtension(new \PHPUnit\Runner\ResultCacheExtension($cache));
  33227. }
  33228. if ($arguments['executionOrder'] !== \PHPUnit\Runner\TestSuiteSorter::ORDER_DEFAULT || $arguments['executionOrderDefects'] !== \PHPUnit\Runner\TestSuiteSorter::ORDER_DEFAULT || $arguments['resolveDependencies']) {
  33229. $cache = $cache ?? new \PHPUnit\Runner\NullTestResultCache();
  33230. $cache->load();
  33231. $sorter = new \PHPUnit\Runner\TestSuiteSorter($cache);
  33232. $sorter->reorderTestsInSuite($suite, $arguments['executionOrder'], $arguments['resolveDependencies'], $arguments['executionOrderDefects']);
  33233. $originalExecutionOrder = $sorter->getOriginalExecutionOrder();
  33234. unset($sorter);
  33235. }
  33236. if (\is_int($arguments['repeat']) && $arguments['repeat'] > 0) {
  33237. $_suite = new \PHPUnit\Framework\TestSuite();
  33238. /* @noinspection PhpUnusedLocalVariableInspection */
  33239. foreach (\range(1, $arguments['repeat']) as $step) {
  33240. $_suite->addTest($suite);
  33241. }
  33242. $suite = $_suite;
  33243. unset($_suite);
  33244. }
  33245. $result = $this->createTestResult();
  33246. $listener = new \PHPUnit\Runner\TestListenerAdapter();
  33247. $listenerNeeded = \false;
  33248. foreach ($this->extensions as $extension) {
  33249. if ($extension instanceof \PHPUnit\Runner\TestHook) {
  33250. $listener->add($extension);
  33251. $listenerNeeded = \true;
  33252. }
  33253. }
  33254. if ($listenerNeeded) {
  33255. $result->addListener($listener);
  33256. }
  33257. unset($listener, $listenerNeeded);
  33258. if (!$arguments['convertDeprecationsToExceptions']) {
  33259. $result->convertDeprecationsToExceptions(\false);
  33260. }
  33261. if (!$arguments['convertErrorsToExceptions']) {
  33262. $result->convertErrorsToExceptions(\false);
  33263. }
  33264. if (!$arguments['convertNoticesToExceptions']) {
  33265. $result->convertNoticesToExceptions(\false);
  33266. }
  33267. if (!$arguments['convertWarningsToExceptions']) {
  33268. $result->convertWarningsToExceptions(\false);
  33269. }
  33270. if ($arguments['stopOnError']) {
  33271. $result->stopOnError(\true);
  33272. }
  33273. if ($arguments['stopOnFailure']) {
  33274. $result->stopOnFailure(\true);
  33275. }
  33276. if ($arguments['stopOnWarning']) {
  33277. $result->stopOnWarning(\true);
  33278. }
  33279. if ($arguments['stopOnIncomplete']) {
  33280. $result->stopOnIncomplete(\true);
  33281. }
  33282. if ($arguments['stopOnRisky']) {
  33283. $result->stopOnRisky(\true);
  33284. }
  33285. if ($arguments['stopOnSkipped']) {
  33286. $result->stopOnSkipped(\true);
  33287. }
  33288. if ($arguments['stopOnDefect']) {
  33289. $result->stopOnDefect(\true);
  33290. }
  33291. if ($arguments['registerMockObjectsFromTestArgumentsRecursively']) {
  33292. $result->setRegisterMockObjectsFromTestArgumentsRecursively(\true);
  33293. }
  33294. if ($this->printer === null) {
  33295. if (isset($arguments['printer'])) {
  33296. if ($arguments['printer'] instanceof \PHPUnit\TextUI\ResultPrinter) {
  33297. $this->printer = $arguments['printer'];
  33298. } elseif (\is_string($arguments['printer']) && \class_exists($arguments['printer'], \false)) {
  33299. try {
  33300. $reflector = new \ReflectionClass($arguments['printer']);
  33301. if ($reflector->implementsInterface(\PHPUnit\TextUI\ResultPrinter::class)) {
  33302. $this->printer = $this->createPrinter($arguments['printer'], $arguments);
  33303. }
  33304. // @codeCoverageIgnoreStart
  33305. } catch (\ReflectionException $e) {
  33306. throw new \PHPUnit\Framework\Exception($e->getMessage(), (int) $e->getCode(), $e);
  33307. }
  33308. // @codeCoverageIgnoreEnd
  33309. }
  33310. } else {
  33311. $this->printer = $this->createPrinter(\PHPUnit\TextUI\DefaultResultPrinter::class, $arguments);
  33312. }
  33313. }
  33314. if (isset($originalExecutionOrder) && $this->printer instanceof \PHPUnit\Util\TestDox\CliTestDoxPrinter) {
  33315. \assert($this->printer instanceof \PHPUnit\Util\TestDox\CliTestDoxPrinter);
  33316. $this->printer->setOriginalExecutionOrder($originalExecutionOrder);
  33317. $this->printer->setShowProgressAnimation(!$arguments['noInteraction']);
  33318. }
  33319. $this->printer->write(\PHPUnit\Runner\Version::getVersionString() . "\n");
  33320. self::$versionStringPrinted = \true;
  33321. if ($arguments['verbose']) {
  33322. $this->writeMessage('Runtime', $this->runtime->getNameWithVersionAndCodeCoverageDriver());
  33323. if (isset($arguments['configuration'])) {
  33324. \assert($arguments['configuration'] instanceof \PHPUnit\TextUI\Configuration\Configuration);
  33325. $this->writeMessage('Configuration', $arguments['configuration']->filename());
  33326. }
  33327. foreach ($arguments['loadedExtensions'] as $extension) {
  33328. $this->writeMessage('Extension', $extension);
  33329. }
  33330. foreach ($arguments['notLoadedExtensions'] as $extension) {
  33331. $this->writeMessage('Extension', $extension);
  33332. }
  33333. }
  33334. foreach ($warnings as $warning) {
  33335. $this->writeMessage('Warning', $warning);
  33336. }
  33337. if ($arguments['executionOrder'] === \PHPUnit\Runner\TestSuiteSorter::ORDER_RANDOMIZED) {
  33338. $this->writeMessage('Random seed', (string) $arguments['randomOrderSeed']);
  33339. }
  33340. if (isset($tooFewColumnsRequested)) {
  33341. $this->writeMessage('Error', 'Less than 16 columns requested, number of columns set to 16');
  33342. }
  33343. if ($this->runtime->discardsComments()) {
  33344. $this->writeMessage('Warning', 'opcache.save_comments=0 set; annotations will not work');
  33345. }
  33346. if (isset($arguments['configuration'])) {
  33347. \assert($arguments['configuration'] instanceof \PHPUnit\TextUI\Configuration\Configuration);
  33348. if ($arguments['configuration']->hasValidationErrors()) {
  33349. $this->write("\n Warning - The configuration file did not pass validation!\n The following problems have been detected:\n");
  33350. foreach ($arguments['configuration']->validationErrors() as $line => $errors) {
  33351. $this->write(\sprintf("\n Line %d:\n", $line));
  33352. foreach ($errors as $msg) {
  33353. $this->write(\sprintf(" - %s\n", $msg));
  33354. }
  33355. }
  33356. $this->write("\n Test results may not be as expected.\n\n");
  33357. }
  33358. }
  33359. if (isset($arguments['conflictBetweenPrinterClassAndTestdox'])) {
  33360. $this->writeMessage('Warning', 'Directives printerClass and testdox are mutually exclusive');
  33361. }
  33362. foreach ($arguments['listeners'] as $listener) {
  33363. $result->addListener($listener);
  33364. }
  33365. $result->addListener($this->printer);
  33366. $codeCoverageReports = 0;
  33367. if (!isset($arguments['noLogging'])) {
  33368. if (isset($arguments['testdoxHTMLFile'])) {
  33369. $result->addListener(new \PHPUnit\Util\TestDox\HtmlResultPrinter($arguments['testdoxHTMLFile'], $arguments['testdoxGroups'], $arguments['testdoxExcludeGroups']));
  33370. }
  33371. if (isset($arguments['testdoxTextFile'])) {
  33372. $result->addListener(new \PHPUnit\Util\TestDox\TextResultPrinter($arguments['testdoxTextFile'], $arguments['testdoxGroups'], $arguments['testdoxExcludeGroups']));
  33373. }
  33374. if (isset($arguments['testdoxXMLFile'])) {
  33375. $result->addListener(new \PHPUnit\Util\TestDox\XmlResultPrinter($arguments['testdoxXMLFile']));
  33376. }
  33377. if (isset($arguments['teamcityLogfile'])) {
  33378. $result->addListener(new \PHPUnit\Util\Log\TeamCity($arguments['teamcityLogfile']));
  33379. }
  33380. if (isset($arguments['junitLogfile'])) {
  33381. $result->addListener(new \PHPUnit\Util\Log\JUnit($arguments['junitLogfile'], $arguments['reportUselessTests']));
  33382. }
  33383. if (isset($arguments['coverageClover'])) {
  33384. $codeCoverageReports++;
  33385. }
  33386. if (isset($arguments['coverageCrap4J'])) {
  33387. $codeCoverageReports++;
  33388. }
  33389. if (isset($arguments['coverageHtml'])) {
  33390. $codeCoverageReports++;
  33391. }
  33392. if (isset($arguments['coveragePHP'])) {
  33393. $codeCoverageReports++;
  33394. }
  33395. if (isset($arguments['coverageText'])) {
  33396. $codeCoverageReports++;
  33397. }
  33398. if (isset($arguments['coverageXml'])) {
  33399. $codeCoverageReports++;
  33400. }
  33401. }
  33402. if (isset($arguments['noCoverage'])) {
  33403. $codeCoverageReports = 0;
  33404. }
  33405. if ($codeCoverageReports > 0 && !$this->runtime->canCollectCodeCoverage()) {
  33406. $this->writeMessage('Error', 'No code coverage driver is available');
  33407. $codeCoverageReports = 0;
  33408. }
  33409. if ($codeCoverageReports > 0 || isset($arguments['xdebugFilterFile'])) {
  33410. $whitelistFromConfigurationFile = \false;
  33411. $whitelistFromOption = \false;
  33412. if (isset($arguments['whitelist'])) {
  33413. if (!\is_array($arguments['whitelist'])) {
  33414. $whitelistDirectories = [$arguments['whitelist']];
  33415. } else {
  33416. $whitelistDirectories = $arguments['whitelist'];
  33417. }
  33418. foreach ($whitelistDirectories as $whitelistDirectory) {
  33419. $this->codeCoverageFilter->addDirectoryToWhitelist($whitelistDirectory);
  33420. }
  33421. $whitelistFromOption = \true;
  33422. }
  33423. if (isset($arguments['configuration'])) {
  33424. \assert($arguments['configuration'] instanceof \PHPUnit\TextUI\Configuration\Configuration);
  33425. $filterConfiguration = $arguments['configuration']->filter();
  33426. if ($filterConfiguration->hasNonEmptyWhitelist()) {
  33427. $whitelistFromConfigurationFile = \true;
  33428. foreach ($filterConfiguration->directories() as $directory) {
  33429. $this->codeCoverageFilter->addDirectoryToWhitelist($directory->path(), $directory->suffix(), $directory->prefix());
  33430. }
  33431. foreach ($filterConfiguration->files() as $file) {
  33432. $this->codeCoverageFilter->addFileToWhitelist($file->path());
  33433. }
  33434. foreach ($filterConfiguration->excludeDirectories() as $directory) {
  33435. $this->codeCoverageFilter->removeDirectoryFromWhitelist($directory->path(), $directory->suffix(), $directory->prefix());
  33436. }
  33437. foreach ($filterConfiguration->excludeFiles() as $file) {
  33438. $this->codeCoverageFilter->removeFileFromWhitelist($file->path());
  33439. }
  33440. }
  33441. }
  33442. }
  33443. if ($codeCoverageReports > 0) {
  33444. try {
  33445. $codeCoverage = new \PHPUnit\SebastianBergmann\CodeCoverage\CodeCoverage(null, $this->codeCoverageFilter);
  33446. $codeCoverage->setUnintentionallyCoveredSubclassesWhitelist([\PHPUnit\SebastianBergmann\Comparator\Comparator::class]);
  33447. $codeCoverage->setCheckForUnintentionallyCoveredCode($arguments['strictCoverage']);
  33448. $codeCoverage->setCheckForMissingCoversAnnotation($arguments['strictCoverage']);
  33449. if (isset($arguments['ignoreDeprecatedCodeUnitsFromCodeCoverage'])) {
  33450. $codeCoverage->setIgnoreDeprecatedCode($arguments['ignoreDeprecatedCodeUnitsFromCodeCoverage']);
  33451. }
  33452. if (isset($arguments['disableCodeCoverageIgnore']) && $arguments['disableCodeCoverageIgnore'] === \true) {
  33453. $codeCoverage->setDisableIgnoredLines(\true);
  33454. }
  33455. if (isset($arguments['configuration'])) {
  33456. \assert($arguments['configuration'] instanceof \PHPUnit\TextUI\Configuration\Configuration);
  33457. $filterConfiguration = $arguments['configuration']->filter();
  33458. if ($filterConfiguration->hasNonEmptyWhitelist()) {
  33459. $codeCoverage->setAddUncoveredFilesFromWhitelist($filterConfiguration->addUncoveredFilesFromWhitelist());
  33460. $codeCoverage->setProcessUncoveredFilesFromWhitelist($filterConfiguration->processUncoveredFilesFromWhitelist());
  33461. }
  33462. }
  33463. if (!$this->codeCoverageFilter->hasWhitelist()) {
  33464. if (!$whitelistFromConfigurationFile && !$whitelistFromOption) {
  33465. $this->writeMessage('Error', 'No whitelist is configured, no code coverage will be generated.');
  33466. } else {
  33467. $this->writeMessage('Error', 'Incorrect whitelist config, no code coverage will be generated.');
  33468. }
  33469. $codeCoverageReports = 0;
  33470. unset($codeCoverage);
  33471. }
  33472. } catch (\PHPUnit\SebastianBergmann\CodeCoverage\Exception $e) {
  33473. $this->writeMessage('Error', $e->getMessage());
  33474. $codeCoverageReports = 0;
  33475. }
  33476. }
  33477. if (isset($arguments['xdebugFilterFile'], $filterConfiguration)) {
  33478. $this->write("\n");
  33479. $script = (new \PHPUnit\Util\XdebugFilterScriptGenerator())->generate($filterConfiguration);
  33480. if ($arguments['xdebugFilterFile'] !== 'php://stdout' && $arguments['xdebugFilterFile'] !== 'php://stderr' && !\PHPUnit\Util\Filesystem::createDirectory(\dirname($arguments['xdebugFilterFile']))) {
  33481. $this->write(\sprintf('Cannot write Xdebug filter script to %s ' . \PHP_EOL, $arguments['xdebugFilterFile']));
  33482. exit(self::EXCEPTION_EXIT);
  33483. }
  33484. \file_put_contents($arguments['xdebugFilterFile'], $script);
  33485. $this->write(\sprintf('Wrote Xdebug filter script to %s ' . \PHP_EOL, $arguments['xdebugFilterFile']));
  33486. exit(self::SUCCESS_EXIT);
  33487. }
  33488. $this->printer->write("\n");
  33489. if (isset($codeCoverage)) {
  33490. $result->setCodeCoverage($codeCoverage);
  33491. if ($codeCoverageReports > 1 && isset($arguments['cacheTokens'])) {
  33492. $codeCoverage->setCacheTokens($arguments['cacheTokens']);
  33493. }
  33494. }
  33495. $result->beStrictAboutTestsThatDoNotTestAnything($arguments['reportUselessTests']);
  33496. $result->beStrictAboutOutputDuringTests($arguments['disallowTestOutput']);
  33497. $result->beStrictAboutTodoAnnotatedTests($arguments['disallowTodoAnnotatedTests']);
  33498. $result->beStrictAboutResourceUsageDuringSmallTests($arguments['beStrictAboutResourceUsageDuringSmallTests']);
  33499. if ($arguments['enforceTimeLimit'] === \true && !(new \PHPUnit\SebastianBergmann\Invoker\Invoker())->canInvokeWithTimeout()) {
  33500. $this->writeMessage('Error', 'PHP extension pcntl is required for enforcing time limits');
  33501. }
  33502. $result->enforceTimeLimit($arguments['enforceTimeLimit']);
  33503. $result->setDefaultTimeLimit($arguments['defaultTimeLimit']);
  33504. $result->setTimeoutForSmallTests($arguments['timeoutForSmallTests']);
  33505. $result->setTimeoutForMediumTests($arguments['timeoutForMediumTests']);
  33506. $result->setTimeoutForLargeTests($arguments['timeoutForLargeTests']);
  33507. if (isset($arguments['forceCoversAnnotation']) && $arguments['forceCoversAnnotation'] === \true) {
  33508. $result->forceCoversAnnotation();
  33509. }
  33510. $this->processSuiteFilters($suite, $arguments);
  33511. $suite->setRunTestInSeparateProcess($arguments['processIsolation']);
  33512. foreach ($this->extensions as $extension) {
  33513. if ($extension instanceof \PHPUnit\Runner\BeforeFirstTestHook) {
  33514. $extension->executeBeforeFirstTest();
  33515. }
  33516. }
  33517. $testSuiteWarningsPrinted = \false;
  33518. foreach ($suite->warnings() as $warning) {
  33519. $this->writeMessage('Warning', $warning);
  33520. $testSuiteWarningsPrinted = \true;
  33521. }
  33522. if ($testSuiteWarningsPrinted) {
  33523. $this->write(\PHP_EOL);
  33524. }
  33525. $suite->run($result);
  33526. foreach ($this->extensions as $extension) {
  33527. if ($extension instanceof \PHPUnit\Runner\AfterLastTestHook) {
  33528. $extension->executeAfterLastTest();
  33529. }
  33530. }
  33531. $result->flushListeners();
  33532. $this->printer->printResult($result);
  33533. if (isset($codeCoverage)) {
  33534. if (isset($arguments['coverageClover'])) {
  33535. $this->codeCoverageGenerationStart('Clover XML');
  33536. try {
  33537. $writer = new \PHPUnit\SebastianBergmann\CodeCoverage\Report\Clover();
  33538. $writer->process($codeCoverage, $arguments['coverageClover']);
  33539. $this->codeCoverageGenerationSucceeded();
  33540. unset($writer);
  33541. } catch (\PHPUnit\SebastianBergmann\CodeCoverage\Exception $e) {
  33542. $this->codeCoverageGenerationFailed($e);
  33543. }
  33544. }
  33545. if (isset($arguments['coverageCrap4J'])) {
  33546. $this->codeCoverageGenerationStart('Crap4J XML');
  33547. try {
  33548. $writer = new \PHPUnit\SebastianBergmann\CodeCoverage\Report\Crap4j($arguments['crap4jThreshold']);
  33549. $writer->process($codeCoverage, $arguments['coverageCrap4J']);
  33550. $this->codeCoverageGenerationSucceeded();
  33551. unset($writer);
  33552. } catch (\PHPUnit\SebastianBergmann\CodeCoverage\Exception $e) {
  33553. $this->codeCoverageGenerationFailed($e);
  33554. }
  33555. }
  33556. if (isset($arguments['coverageHtml'])) {
  33557. $this->codeCoverageGenerationStart('HTML');
  33558. try {
  33559. $writer = new \PHPUnit\SebastianBergmann\CodeCoverage\Report\Html\Facade($arguments['reportLowUpperBound'], $arguments['reportHighLowerBound'], \sprintf(' and <a href="https://phpunit.de/">PHPUnit %s</a>', \PHPUnit\Runner\Version::id()));
  33560. $writer->process($codeCoverage, $arguments['coverageHtml']);
  33561. $this->codeCoverageGenerationSucceeded();
  33562. unset($writer);
  33563. } catch (\PHPUnit\SebastianBergmann\CodeCoverage\Exception $e) {
  33564. $this->codeCoverageGenerationFailed($e);
  33565. }
  33566. }
  33567. if (isset($arguments['coveragePHP'])) {
  33568. $this->codeCoverageGenerationStart('PHP');
  33569. try {
  33570. $writer = new \PHPUnit\SebastianBergmann\CodeCoverage\Report\PHP();
  33571. $writer->process($codeCoverage, $arguments['coveragePHP']);
  33572. $this->codeCoverageGenerationSucceeded();
  33573. unset($writer);
  33574. } catch (\PHPUnit\SebastianBergmann\CodeCoverage\Exception $e) {
  33575. $this->codeCoverageGenerationFailed($e);
  33576. }
  33577. }
  33578. if (isset($arguments['coverageText'])) {
  33579. if ($arguments['coverageText'] === 'php://stdout') {
  33580. $outputStream = $this->printer;
  33581. $colors = $arguments['colors'] && $arguments['colors'] !== \PHPUnit\TextUI\DefaultResultPrinter::COLOR_NEVER;
  33582. } else {
  33583. $outputStream = new \PHPUnit\Util\Printer($arguments['coverageText']);
  33584. $colors = \false;
  33585. }
  33586. $processor = new \PHPUnit\SebastianBergmann\CodeCoverage\Report\Text($arguments['reportLowUpperBound'], $arguments['reportHighLowerBound'], $arguments['coverageTextShowUncoveredFiles'], $arguments['coverageTextShowOnlySummary']);
  33587. $outputStream->write($processor->process($codeCoverage, $colors));
  33588. }
  33589. if (isset($arguments['coverageXml'])) {
  33590. $this->codeCoverageGenerationStart('PHPUnit XML');
  33591. try {
  33592. $writer = new \PHPUnit\SebastianBergmann\CodeCoverage\Report\Xml\Facade(\PHPUnit\Runner\Version::id());
  33593. $writer->process($codeCoverage, $arguments['coverageXml']);
  33594. $this->codeCoverageGenerationSucceeded();
  33595. unset($writer);
  33596. } catch (\PHPUnit\SebastianBergmann\CodeCoverage\Exception $e) {
  33597. $this->codeCoverageGenerationFailed($e);
  33598. }
  33599. }
  33600. }
  33601. if ($exit) {
  33602. if ($result->wasSuccessfulIgnoringWarnings()) {
  33603. if ($arguments['failOnRisky'] && !$result->allHarmless()) {
  33604. exit(self::FAILURE_EXIT);
  33605. }
  33606. if ($arguments['failOnWarning'] && $result->warningCount() > 0) {
  33607. exit(self::FAILURE_EXIT);
  33608. }
  33609. if ($arguments['failOnIncomplete'] && $result->notImplementedCount() > 0) {
  33610. exit(self::FAILURE_EXIT);
  33611. }
  33612. if ($arguments['failOnSkipped'] && $result->skippedCount() > 0) {
  33613. exit(self::FAILURE_EXIT);
  33614. }
  33615. exit(self::SUCCESS_EXIT);
  33616. }
  33617. if ($result->errorCount() > 0) {
  33618. exit(self::EXCEPTION_EXIT);
  33619. }
  33620. if ($result->failureCount() > 0) {
  33621. exit(self::FAILURE_EXIT);
  33622. }
  33623. }
  33624. return $result;
  33625. }
  33626. /**
  33627. * Returns the loader to be used.
  33628. */
  33629. public function getLoader() : \PHPUnit\Runner\TestSuiteLoader
  33630. {
  33631. if ($this->loader === null) {
  33632. $this->loader = new \PHPUnit\Runner\StandardTestSuiteLoader();
  33633. }
  33634. return $this->loader;
  33635. }
  33636. public function addExtension(\PHPUnit\Runner\Hook $extension) : void
  33637. {
  33638. $this->extensions[] = $extension;
  33639. }
  33640. /**
  33641. * Override to define how to handle a failed loading of
  33642. * a test suite.
  33643. */
  33644. protected function runFailed(string $message) : void
  33645. {
  33646. $this->write($message . \PHP_EOL);
  33647. exit(self::FAILURE_EXIT);
  33648. }
  33649. private function createTestResult() : \PHPUnit\Framework\TestResult
  33650. {
  33651. return new \PHPUnit\Framework\TestResult();
  33652. }
  33653. private function write(string $buffer) : void
  33654. {
  33655. if (\PHP_SAPI !== 'cli' && \PHP_SAPI !== 'phpdbg') {
  33656. $buffer = \htmlspecialchars($buffer);
  33657. }
  33658. if ($this->printer !== null) {
  33659. $this->printer->write($buffer);
  33660. } else {
  33661. print $buffer;
  33662. }
  33663. }
  33664. /**
  33665. * @throws Exception
  33666. */
  33667. private function handleConfiguration(array &$arguments) : void
  33668. {
  33669. if (isset($arguments['configuration']) && !$arguments['configuration'] instanceof \PHPUnit\TextUI\Configuration\Configuration) {
  33670. $arguments['configuration'] = \PHPUnit\TextUI\Configuration\Registry::getInstance()->get($arguments['configuration']);
  33671. }
  33672. $arguments['debug'] = $arguments['debug'] ?? \false;
  33673. $arguments['filter'] = $arguments['filter'] ?? \false;
  33674. $arguments['listeners'] = $arguments['listeners'] ?? [];
  33675. if (isset($arguments['configuration'])) {
  33676. (new \PHPUnit\TextUI\Configuration\PhpHandler())->handle($arguments['configuration']->php());
  33677. $phpunitConfiguration = $arguments['configuration']->phpunit();
  33678. $arguments['backupGlobals'] = $arguments['backupGlobals'] ?? $phpunitConfiguration->backupGlobals();
  33679. $arguments['backupStaticAttributes'] = $arguments['backupStaticAttributes'] ?? $phpunitConfiguration->backupStaticAttributes();
  33680. $arguments['beStrictAboutChangesToGlobalState'] = $arguments['beStrictAboutChangesToGlobalState'] ?? $phpunitConfiguration->beStrictAboutChangesToGlobalState();
  33681. $arguments['cacheResult'] = $arguments['cacheResult'] ?? $phpunitConfiguration->cacheResult();
  33682. $arguments['cacheTokens'] = $arguments['cacheTokens'] ?? $phpunitConfiguration->cacheTokens();
  33683. $arguments['colors'] = $arguments['colors'] ?? $phpunitConfiguration->colors();
  33684. $arguments['convertDeprecationsToExceptions'] = $arguments['convertDeprecationsToExceptions'] ?? $phpunitConfiguration->convertDeprecationsToExceptions();
  33685. $arguments['convertErrorsToExceptions'] = $arguments['convertErrorsToExceptions'] ?? $phpunitConfiguration->convertErrorsToExceptions();
  33686. $arguments['convertNoticesToExceptions'] = $arguments['convertNoticesToExceptions'] ?? $phpunitConfiguration->convertNoticesToExceptions();
  33687. $arguments['convertWarningsToExceptions'] = $arguments['convertWarningsToExceptions'] ?? $phpunitConfiguration->convertWarningsToExceptions();
  33688. $arguments['processIsolation'] = $arguments['processIsolation'] ?? $phpunitConfiguration->processIsolation();
  33689. $arguments['stopOnDefect'] = $arguments['stopOnDefect'] ?? $phpunitConfiguration->stopOnDefect();
  33690. $arguments['stopOnError'] = $arguments['stopOnError'] ?? $phpunitConfiguration->stopOnError();
  33691. $arguments['stopOnFailure'] = $arguments['stopOnFailure'] ?? $phpunitConfiguration->stopOnFailure();
  33692. $arguments['stopOnWarning'] = $arguments['stopOnWarning'] ?? $phpunitConfiguration->stopOnWarning();
  33693. $arguments['stopOnIncomplete'] = $arguments['stopOnIncomplete'] ?? $phpunitConfiguration->stopOnIncomplete();
  33694. $arguments['stopOnRisky'] = $arguments['stopOnRisky'] ?? $phpunitConfiguration->stopOnRisky();
  33695. $arguments['stopOnSkipped'] = $arguments['stopOnSkipped'] ?? $phpunitConfiguration->stopOnSkipped();
  33696. $arguments['failOnIncomplete'] = $arguments['failOnIncomplete'] ?? $phpunitConfiguration->failOnIncomplete();
  33697. $arguments['failOnRisky'] = $arguments['failOnRisky'] ?? $phpunitConfiguration->failOnRisky();
  33698. $arguments['failOnSkipped'] = $arguments['failOnSkipped'] ?? $phpunitConfiguration->failOnSkipped();
  33699. $arguments['failOnWarning'] = $arguments['failOnWarning'] ?? $phpunitConfiguration->failOnWarning();
  33700. $arguments['enforceTimeLimit'] = $arguments['enforceTimeLimit'] ?? $phpunitConfiguration->enforceTimeLimit();
  33701. $arguments['defaultTimeLimit'] = $arguments['defaultTimeLimit'] ?? $phpunitConfiguration->defaultTimeLimit();
  33702. $arguments['timeoutForSmallTests'] = $arguments['timeoutForSmallTests'] ?? $phpunitConfiguration->timeoutForSmallTests();
  33703. $arguments['timeoutForMediumTests'] = $arguments['timeoutForMediumTests'] ?? $phpunitConfiguration->timeoutForMediumTests();
  33704. $arguments['timeoutForLargeTests'] = $arguments['timeoutForLargeTests'] ?? $phpunitConfiguration->timeoutForLargeTests();
  33705. $arguments['reportUselessTests'] = $arguments['reportUselessTests'] ?? $phpunitConfiguration->beStrictAboutTestsThatDoNotTestAnything();
  33706. $arguments['strictCoverage'] = $arguments['strictCoverage'] ?? $phpunitConfiguration->beStrictAboutCoversAnnotation();
  33707. $arguments['ignoreDeprecatedCodeUnitsFromCodeCoverage'] = $arguments['ignoreDeprecatedCodeUnitsFromCodeCoverage'] ?? $phpunitConfiguration->ignoreDeprecatedCodeUnitsFromCodeCoverage();
  33708. $arguments['disallowTestOutput'] = $arguments['disallowTestOutput'] ?? $phpunitConfiguration->beStrictAboutOutputDuringTests();
  33709. $arguments['disallowTodoAnnotatedTests'] = $arguments['disallowTodoAnnotatedTests'] ?? $phpunitConfiguration->beStrictAboutTodoAnnotatedTests();
  33710. $arguments['beStrictAboutResourceUsageDuringSmallTests'] = $arguments['beStrictAboutResourceUsageDuringSmallTests'] ?? $phpunitConfiguration->beStrictAboutResourceUsageDuringSmallTests();
  33711. $arguments['verbose'] = $arguments['verbose'] ?? $phpunitConfiguration->verbose();
  33712. $arguments['reverseDefectList'] = $arguments['reverseDefectList'] ?? $phpunitConfiguration->reverseDefectList();
  33713. $arguments['forceCoversAnnotation'] = $arguments['forceCoversAnnotation'] ?? $phpunitConfiguration->forceCoversAnnotation();
  33714. $arguments['disableCodeCoverageIgnore'] = $arguments['disableCodeCoverageIgnore'] ?? $phpunitConfiguration->disableCodeCoverageIgnore();
  33715. $arguments['registerMockObjectsFromTestArgumentsRecursively'] = $arguments['registerMockObjectsFromTestArgumentsRecursively'] ?? $phpunitConfiguration->registerMockObjectsFromTestArgumentsRecursively();
  33716. $arguments['noInteraction'] = $arguments['noInteraction'] ?? $phpunitConfiguration->noInteraction();
  33717. $arguments['executionOrder'] = $arguments['executionOrder'] ?? $phpunitConfiguration->executionOrder();
  33718. $arguments['resolveDependencies'] = $arguments['resolveDependencies'] ?? $phpunitConfiguration->resolveDependencies();
  33719. if (!isset($arguments['bootstrap']) && $phpunitConfiguration->hasBootstrap()) {
  33720. $arguments['bootstrap'] = $phpunitConfiguration->bootstrap();
  33721. }
  33722. if (!isset($arguments['cacheResultFile']) && $phpunitConfiguration->hasCacheResultFile()) {
  33723. $arguments['cacheResultFile'] = $phpunitConfiguration->cacheResultFile();
  33724. }
  33725. if (!isset($arguments['executionOrderDefects'])) {
  33726. $arguments['executionOrderDefects'] = $phpunitConfiguration->defectsFirst() ? \PHPUnit\Runner\TestSuiteSorter::ORDER_DEFECTS_FIRST : \PHPUnit\Runner\TestSuiteSorter::ORDER_DEFAULT;
  33727. }
  33728. if ($phpunitConfiguration->conflictBetweenPrinterClassAndTestdox()) {
  33729. $arguments['conflictBetweenPrinterClassAndTestdox'] = \true;
  33730. }
  33731. $groupCliArgs = [];
  33732. if (!empty($arguments['groups'])) {
  33733. $groupCliArgs = $arguments['groups'];
  33734. }
  33735. $groupConfiguration = $arguments['configuration']->groups();
  33736. if (!isset($arguments['groups']) && $groupConfiguration->hasInclude()) {
  33737. $arguments['groups'] = $groupConfiguration->include()->asArrayOfStrings();
  33738. }
  33739. if (!isset($arguments['excludeGroups']) && $groupConfiguration->hasExclude()) {
  33740. $arguments['excludeGroups'] = \array_diff($groupConfiguration->exclude()->asArrayOfStrings(), $groupCliArgs);
  33741. }
  33742. $extensionHandler = new \PHPUnit\TextUI\Configuration\ExtensionHandler();
  33743. foreach ($arguments['configuration']->extensions() as $extension) {
  33744. $this->addExtension($extensionHandler->createHookInstance($extension));
  33745. }
  33746. foreach ($arguments['configuration']->listeners() as $listener) {
  33747. $arguments['listeners'][] = $extensionHandler->createTestListenerInstance($listener);
  33748. }
  33749. unset($extensionHandler);
  33750. foreach ($arguments['unavailableExtensions'] as $extension) {
  33751. $arguments['warnings'][] = \sprintf('Extension "%s" is not available', $extension);
  33752. }
  33753. $loggingConfiguration = $arguments['configuration']->logging();
  33754. if (!isset($arguments['coverageClover']) && $loggingConfiguration->hasCodeCoverageClover()) {
  33755. $arguments['coverageClover'] = $loggingConfiguration->codeCoverageClover()->target()->path();
  33756. }
  33757. if (!isset($arguments['coverageCrap4J']) && $loggingConfiguration->hasCodeCoverageCrap4j()) {
  33758. $arguments['coverageCrap4J'] = $loggingConfiguration->codeCoverageCrap4j()->target()->path();
  33759. if (!isset($arguments['crap4jThreshold'])) {
  33760. $arguments['crap4jThreshold'] = $loggingConfiguration->codeCoverageCrap4j()->threshold();
  33761. }
  33762. }
  33763. if (!isset($arguments['coverageHtml']) && $loggingConfiguration->hasCodeCoverageHtml()) {
  33764. $arguments['coverageHtml'] = $loggingConfiguration->codeCoverageHtml()->target()->path();
  33765. if (!isset($arguments['reportLowUpperBound'])) {
  33766. $arguments['reportLowUpperBound'] = $loggingConfiguration->codeCoverageHtml()->lowUpperBound();
  33767. }
  33768. if (!isset($arguments['reportHighLowerBound'])) {
  33769. $arguments['reportHighLowerBound'] = $loggingConfiguration->codeCoverageHtml()->highLowerBound();
  33770. }
  33771. }
  33772. if (!isset($arguments['coveragePHP']) && $loggingConfiguration->hasCodeCoveragePhp()) {
  33773. $arguments['coveragePHP'] = $loggingConfiguration->codeCoveragePhp()->target()->path();
  33774. }
  33775. if (!isset($arguments['coverageText']) && $loggingConfiguration->hasCodeCoverageText()) {
  33776. $arguments['coverageText'] = $loggingConfiguration->codeCoverageText()->target()->path();
  33777. $arguments['coverageTextShowUncoveredFiles'] = $loggingConfiguration->codeCoverageText()->showUncoveredFiles();
  33778. $arguments['coverageTextShowOnlySummary'] = $loggingConfiguration->codeCoverageText()->showOnlySummary();
  33779. }
  33780. if (!isset($arguments['coverageXml']) && $loggingConfiguration->hasCodeCoverageXml()) {
  33781. $arguments['coverageXml'] = $loggingConfiguration->codeCoverageXml()->target()->path();
  33782. }
  33783. if ($loggingConfiguration->hasPlainText()) {
  33784. $arguments['listeners'][] = new \PHPUnit\TextUI\DefaultResultPrinter($loggingConfiguration->plainText()->target()->path(), \true);
  33785. }
  33786. if (!isset($arguments['teamcityLogfile']) && $loggingConfiguration->hasTeamCity()) {
  33787. $arguments['teamcityLogfile'] = $loggingConfiguration->teamCity()->target()->path();
  33788. }
  33789. if (!isset($arguments['junitLogfile']) && $loggingConfiguration->hasJunit()) {
  33790. $arguments['junitLogfile'] = $loggingConfiguration->junit()->target()->path();
  33791. }
  33792. if (!isset($arguments['testdoxHTMLFile']) && $loggingConfiguration->hasTestDoxHtml()) {
  33793. $arguments['testdoxHTMLFile'] = $loggingConfiguration->testDoxHtml()->target()->path();
  33794. }
  33795. if (!isset($arguments['testdoxTextFile']) && $loggingConfiguration->hasTestDoxText()) {
  33796. $arguments['testdoxTextFile'] = $loggingConfiguration->testDoxText()->target()->path();
  33797. }
  33798. if (!isset($arguments['testdoxXMLFile']) && $loggingConfiguration->hasTestDoxXml()) {
  33799. $arguments['testdoxXMLFile'] = $loggingConfiguration->testDoxXml()->target()->path();
  33800. }
  33801. $testdoxGroupConfiguration = $arguments['configuration']->testdoxGroups();
  33802. if (!isset($arguments['testdoxGroups']) && $testdoxGroupConfiguration->hasInclude()) {
  33803. $arguments['testdoxGroups'] = $testdoxGroupConfiguration->include()->asArrayOfStrings();
  33804. }
  33805. if (!isset($arguments['testdoxExcludeGroups']) && $testdoxGroupConfiguration->hasExclude()) {
  33806. $arguments['testdoxExcludeGroups'] = $testdoxGroupConfiguration->exclude()->asArrayOfStrings();
  33807. }
  33808. }
  33809. $extensionHandler = new \PHPUnit\TextUI\Configuration\ExtensionHandler();
  33810. foreach ($arguments['extensions'] as $extension) {
  33811. $this->addExtension($extensionHandler->createHookInstance($extension));
  33812. }
  33813. unset($extensionHandler);
  33814. $arguments['addUncoveredFilesFromWhitelist'] = $arguments['addUncoveredFilesFromWhitelist'] ?? \true;
  33815. $arguments['backupGlobals'] = $arguments['backupGlobals'] ?? null;
  33816. $arguments['backupStaticAttributes'] = $arguments['backupStaticAttributes'] ?? null;
  33817. $arguments['beStrictAboutChangesToGlobalState'] = $arguments['beStrictAboutChangesToGlobalState'] ?? null;
  33818. $arguments['beStrictAboutResourceUsageDuringSmallTests'] = $arguments['beStrictAboutResourceUsageDuringSmallTests'] ?? \false;
  33819. $arguments['cacheResult'] = $arguments['cacheResult'] ?? \true;
  33820. $arguments['cacheTokens'] = $arguments['cacheTokens'] ?? \false;
  33821. $arguments['colors'] = $arguments['colors'] ?? \PHPUnit\TextUI\DefaultResultPrinter::COLOR_DEFAULT;
  33822. $arguments['columns'] = $arguments['columns'] ?? 80;
  33823. $arguments['convertDeprecationsToExceptions'] = $arguments['convertDeprecationsToExceptions'] ?? \true;
  33824. $arguments['convertErrorsToExceptions'] = $arguments['convertErrorsToExceptions'] ?? \true;
  33825. $arguments['convertNoticesToExceptions'] = $arguments['convertNoticesToExceptions'] ?? \true;
  33826. $arguments['convertWarningsToExceptions'] = $arguments['convertWarningsToExceptions'] ?? \true;
  33827. $arguments['crap4jThreshold'] = $arguments['crap4jThreshold'] ?? 30;
  33828. $arguments['disallowTestOutput'] = $arguments['disallowTestOutput'] ?? \false;
  33829. $arguments['disallowTodoAnnotatedTests'] = $arguments['disallowTodoAnnotatedTests'] ?? \false;
  33830. $arguments['defaultTimeLimit'] = $arguments['defaultTimeLimit'] ?? 0;
  33831. $arguments['enforceTimeLimit'] = $arguments['enforceTimeLimit'] ?? \false;
  33832. $arguments['excludeGroups'] = $arguments['excludeGroups'] ?? [];
  33833. $arguments['executionOrder'] = $arguments['executionOrder'] ?? \PHPUnit\Runner\TestSuiteSorter::ORDER_DEFAULT;
  33834. $arguments['executionOrderDefects'] = $arguments['executionOrderDefects'] ?? \PHPUnit\Runner\TestSuiteSorter::ORDER_DEFAULT;
  33835. $arguments['failOnIncomplete'] = $arguments['failOnIncomplete'] ?? \false;
  33836. $arguments['failOnRisky'] = $arguments['failOnRisky'] ?? \false;
  33837. $arguments['failOnSkipped'] = $arguments['failOnSkipped'] ?? \false;
  33838. $arguments['failOnWarning'] = $arguments['failOnWarning'] ?? \false;
  33839. $arguments['groups'] = $arguments['groups'] ?? [];
  33840. $arguments['noInteraction'] = $arguments['noInteraction'] ?? \false;
  33841. $arguments['processIsolation'] = $arguments['processIsolation'] ?? \false;
  33842. $arguments['processUncoveredFilesFromWhitelist'] = $arguments['processUncoveredFilesFromWhitelist'] ?? \false;
  33843. $arguments['randomOrderSeed'] = $arguments['randomOrderSeed'] ?? \time();
  33844. $arguments['registerMockObjectsFromTestArgumentsRecursively'] = $arguments['registerMockObjectsFromTestArgumentsRecursively'] ?? \false;
  33845. $arguments['repeat'] = $arguments['repeat'] ?? \false;
  33846. $arguments['reportHighLowerBound'] = $arguments['reportHighLowerBound'] ?? 90;
  33847. $arguments['reportLowUpperBound'] = $arguments['reportLowUpperBound'] ?? 50;
  33848. $arguments['reportUselessTests'] = $arguments['reportUselessTests'] ?? \true;
  33849. $arguments['reverseList'] = $arguments['reverseList'] ?? \false;
  33850. $arguments['resolveDependencies'] = $arguments['resolveDependencies'] ?? \true;
  33851. $arguments['stopOnError'] = $arguments['stopOnError'] ?? \false;
  33852. $arguments['stopOnFailure'] = $arguments['stopOnFailure'] ?? \false;
  33853. $arguments['stopOnIncomplete'] = $arguments['stopOnIncomplete'] ?? \false;
  33854. $arguments['stopOnRisky'] = $arguments['stopOnRisky'] ?? \false;
  33855. $arguments['stopOnSkipped'] = $arguments['stopOnSkipped'] ?? \false;
  33856. $arguments['stopOnWarning'] = $arguments['stopOnWarning'] ?? \false;
  33857. $arguments['stopOnDefect'] = $arguments['stopOnDefect'] ?? \false;
  33858. $arguments['strictCoverage'] = $arguments['strictCoverage'] ?? \false;
  33859. $arguments['testdoxExcludeGroups'] = $arguments['testdoxExcludeGroups'] ?? [];
  33860. $arguments['testdoxGroups'] = $arguments['testdoxGroups'] ?? [];
  33861. $arguments['timeoutForLargeTests'] = $arguments['timeoutForLargeTests'] ?? 60;
  33862. $arguments['timeoutForMediumTests'] = $arguments['timeoutForMediumTests'] ?? 10;
  33863. $arguments['timeoutForSmallTests'] = $arguments['timeoutForSmallTests'] ?? 1;
  33864. $arguments['verbose'] = $arguments['verbose'] ?? \false;
  33865. }
  33866. private function processSuiteFilters(\PHPUnit\Framework\TestSuite $suite, array $arguments) : void
  33867. {
  33868. if (!$arguments['filter'] && empty($arguments['groups']) && empty($arguments['excludeGroups'])) {
  33869. return;
  33870. }
  33871. $filterFactory = new \PHPUnit\Runner\Filter\Factory();
  33872. if (!empty($arguments['excludeGroups'])) {
  33873. $filterFactory->addFilter(new \ReflectionClass(\PHPUnit\Runner\Filter\ExcludeGroupFilterIterator::class), $arguments['excludeGroups']);
  33874. }
  33875. if (!empty($arguments['groups'])) {
  33876. $filterFactory->addFilter(new \ReflectionClass(\PHPUnit\Runner\Filter\IncludeGroupFilterIterator::class), $arguments['groups']);
  33877. }
  33878. if ($arguments['filter']) {
  33879. $filterFactory->addFilter(new \ReflectionClass(\PHPUnit\Runner\Filter\NameFilterIterator::class), $arguments['filter']);
  33880. }
  33881. $suite->injectFilter($filterFactory);
  33882. }
  33883. private function writeMessage(string $type, string $message) : void
  33884. {
  33885. if (!$this->messagePrinted) {
  33886. $this->write("\n");
  33887. }
  33888. $this->write(\sprintf("%-15s%s\n", $type . ':', $message));
  33889. $this->messagePrinted = \true;
  33890. }
  33891. private function createPrinter(string $class, array $arguments) : \PHPUnit\TextUI\ResultPrinter
  33892. {
  33893. $object = new $class(isset($arguments['stderr']) && $arguments['stderr'] === \true ? 'php://stderr' : null, $arguments['verbose'], $arguments['colors'], $arguments['debug'], $arguments['columns'], $arguments['reverseList']);
  33894. \assert($object instanceof \PHPUnit\TextUI\ResultPrinter);
  33895. return $object;
  33896. }
  33897. private function codeCoverageGenerationStart(string $format) : void
  33898. {
  33899. $this->printer->write(\sprintf("\nGenerating code coverage report in %s format ... ", $format));
  33900. $this->timer->start();
  33901. }
  33902. private function codeCoverageGenerationSucceeded() : void
  33903. {
  33904. $this->printer->write(\sprintf("done [%s]\n", $this->timer->stop()->asString()));
  33905. }
  33906. private function codeCoverageGenerationFailed(\Exception $e) : void
  33907. {
  33908. $this->printer->write(\sprintf("failed [%s]\n%s\n", $this->timer->stop()->asString(), $e->getMessage()));
  33909. }
  33910. }
  33911. <?php
  33912. declare (strict_types=1);
  33913. /*
  33914. * This file is part of PHPUnit.
  33915. *
  33916. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  33917. *
  33918. * For the full copyright and license information, please view the LICENSE
  33919. * file that was distributed with this source code.
  33920. */
  33921. namespace PHPUnit\TextUI;
  33922. use PHPUnit\Framework\TestListener;
  33923. use PHPUnit\Framework\TestResult;
  33924. interface ResultPrinter extends \PHPUnit\Framework\TestListener
  33925. {
  33926. public function printResult(\PHPUnit\Framework\TestResult $result) : void;
  33927. public function write(string $buffer) : void;
  33928. }
  33929. <?php
  33930. declare (strict_types=1);
  33931. /*
  33932. * This file is part of PHPUnit.
  33933. *
  33934. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  33935. *
  33936. * For the full copyright and license information, please view the LICENSE
  33937. * file that was distributed with this source code.
  33938. */
  33939. namespace PHPUnit\TextUI;
  33940. use PHPUnit\Framework\AssertionFailedError;
  33941. use PHPUnit\Framework\Exception;
  33942. use PHPUnit\Framework\InvalidArgumentException;
  33943. use PHPUnit\Framework\Test;
  33944. use PHPUnit\Framework\TestCase;
  33945. use PHPUnit\Framework\TestFailure;
  33946. use PHPUnit\Framework\TestResult;
  33947. use PHPUnit\Framework\TestSuite;
  33948. use PHPUnit\Framework\Warning;
  33949. use PHPUnit\Runner\PhptTestCase;
  33950. use PHPUnit\Util\Color;
  33951. use PHPUnit\Util\Printer;
  33952. use PHPUnit\SebastianBergmann\Environment\Console;
  33953. use PHPUnit\SebastianBergmann\Timer\ResourceUsageFormatter;
  33954. use PHPUnit\SebastianBergmann\Timer\Timer;
  33955. /**
  33956. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  33957. */
  33958. class DefaultResultPrinter extends \PHPUnit\Util\Printer implements \PHPUnit\TextUI\ResultPrinter
  33959. {
  33960. public const EVENT_TEST_START = 0;
  33961. public const EVENT_TEST_END = 1;
  33962. public const EVENT_TESTSUITE_START = 2;
  33963. public const EVENT_TESTSUITE_END = 3;
  33964. public const COLOR_NEVER = 'never';
  33965. public const COLOR_AUTO = 'auto';
  33966. public const COLOR_ALWAYS = 'always';
  33967. public const COLOR_DEFAULT = self::COLOR_NEVER;
  33968. private const AVAILABLE_COLORS = [self::COLOR_NEVER, self::COLOR_AUTO, self::COLOR_ALWAYS];
  33969. /**
  33970. * @var int
  33971. */
  33972. protected $column = 0;
  33973. /**
  33974. * @var int
  33975. */
  33976. protected $maxColumn;
  33977. /**
  33978. * @var bool
  33979. */
  33980. protected $lastTestFailed = \false;
  33981. /**
  33982. * @var int
  33983. */
  33984. protected $numAssertions = 0;
  33985. /**
  33986. * @var int
  33987. */
  33988. protected $numTests = -1;
  33989. /**
  33990. * @var int
  33991. */
  33992. protected $numTestsRun = 0;
  33993. /**
  33994. * @var int
  33995. */
  33996. protected $numTestsWidth;
  33997. /**
  33998. * @var bool
  33999. */
  34000. protected $colors = \false;
  34001. /**
  34002. * @var bool
  34003. */
  34004. protected $debug = \false;
  34005. /**
  34006. * @var bool
  34007. */
  34008. protected $verbose = \false;
  34009. /**
  34010. * @var int
  34011. */
  34012. private $numberOfColumns;
  34013. /**
  34014. * @var bool
  34015. */
  34016. private $reverse;
  34017. /**
  34018. * @var bool
  34019. */
  34020. private $defectListPrinted = \false;
  34021. /**
  34022. * @var Timer
  34023. */
  34024. private $timer;
  34025. /**
  34026. * Constructor.
  34027. *
  34028. * @param null|resource|string $out
  34029. * @param int|string $numberOfColumns
  34030. *
  34031. * @throws Exception
  34032. */
  34033. public function __construct($out = null, bool $verbose = \false, string $colors = self::COLOR_DEFAULT, bool $debug = \false, $numberOfColumns = 80, bool $reverse = \false)
  34034. {
  34035. parent::__construct($out);
  34036. if (!\in_array($colors, self::AVAILABLE_COLORS, \true)) {
  34037. throw \PHPUnit\Framework\InvalidArgumentException::create(3, \vsprintf('value from "%s", "%s" or "%s"', self::AVAILABLE_COLORS));
  34038. }
  34039. if (!\is_int($numberOfColumns) && $numberOfColumns !== 'max') {
  34040. throw \PHPUnit\Framework\InvalidArgumentException::create(5, 'integer or "max"');
  34041. }
  34042. $console = new \PHPUnit\SebastianBergmann\Environment\Console();
  34043. $maxNumberOfColumns = $console->getNumberOfColumns();
  34044. if ($numberOfColumns === 'max' || $numberOfColumns !== 80 && $numberOfColumns > $maxNumberOfColumns) {
  34045. $numberOfColumns = $maxNumberOfColumns;
  34046. }
  34047. $this->numberOfColumns = $numberOfColumns;
  34048. $this->verbose = $verbose;
  34049. $this->debug = $debug;
  34050. $this->reverse = $reverse;
  34051. if ($colors === self::COLOR_AUTO && $console->hasColorSupport()) {
  34052. $this->colors = \true;
  34053. } else {
  34054. $this->colors = self::COLOR_ALWAYS === $colors;
  34055. }
  34056. $this->timer = new \PHPUnit\SebastianBergmann\Timer\Timer();
  34057. $this->timer->start();
  34058. }
  34059. public function printResult(\PHPUnit\Framework\TestResult $result) : void
  34060. {
  34061. $this->printHeader($result);
  34062. $this->printErrors($result);
  34063. $this->printWarnings($result);
  34064. $this->printFailures($result);
  34065. $this->printRisky($result);
  34066. if ($this->verbose) {
  34067. $this->printIncompletes($result);
  34068. $this->printSkipped($result);
  34069. }
  34070. $this->printFooter($result);
  34071. }
  34072. /**
  34073. * An error occurred.
  34074. */
  34075. public function addError(\PHPUnit\Framework\Test $test, \Throwable $t, float $time) : void
  34076. {
  34077. $this->writeProgressWithColor('fg-red, bold', 'E');
  34078. $this->lastTestFailed = \true;
  34079. }
  34080. /**
  34081. * A failure occurred.
  34082. */
  34083. public function addFailure(\PHPUnit\Framework\Test $test, \PHPUnit\Framework\AssertionFailedError $e, float $time) : void
  34084. {
  34085. $this->writeProgressWithColor('bg-red, fg-white', 'F');
  34086. $this->lastTestFailed = \true;
  34087. }
  34088. /**
  34089. * A warning occurred.
  34090. */
  34091. public function addWarning(\PHPUnit\Framework\Test $test, \PHPUnit\Framework\Warning $e, float $time) : void
  34092. {
  34093. $this->writeProgressWithColor('fg-yellow, bold', 'W');
  34094. $this->lastTestFailed = \true;
  34095. }
  34096. /**
  34097. * Incomplete test.
  34098. */
  34099. public function addIncompleteTest(\PHPUnit\Framework\Test $test, \Throwable $t, float $time) : void
  34100. {
  34101. $this->writeProgressWithColor('fg-yellow, bold', 'I');
  34102. $this->lastTestFailed = \true;
  34103. }
  34104. /**
  34105. * Risky test.
  34106. */
  34107. public function addRiskyTest(\PHPUnit\Framework\Test $test, \Throwable $t, float $time) : void
  34108. {
  34109. $this->writeProgressWithColor('fg-yellow, bold', 'R');
  34110. $this->lastTestFailed = \true;
  34111. }
  34112. /**
  34113. * Skipped test.
  34114. */
  34115. public function addSkippedTest(\PHPUnit\Framework\Test $test, \Throwable $t, float $time) : void
  34116. {
  34117. $this->writeProgressWithColor('fg-cyan, bold', 'S');
  34118. $this->lastTestFailed = \true;
  34119. }
  34120. /**
  34121. * A testsuite started.
  34122. */
  34123. public function startTestSuite(\PHPUnit\Framework\TestSuite $suite) : void
  34124. {
  34125. if ($this->numTests == -1) {
  34126. $this->numTests = \count($suite);
  34127. $this->numTestsWidth = \strlen((string) $this->numTests);
  34128. $this->maxColumn = $this->numberOfColumns - \strlen(' / (XXX%)') - 2 * $this->numTestsWidth;
  34129. }
  34130. }
  34131. /**
  34132. * A testsuite ended.
  34133. */
  34134. public function endTestSuite(\PHPUnit\Framework\TestSuite $suite) : void
  34135. {
  34136. }
  34137. /**
  34138. * A test started.
  34139. */
  34140. public function startTest(\PHPUnit\Framework\Test $test) : void
  34141. {
  34142. if ($this->debug) {
  34143. $this->write(\sprintf("Test '%s' started\n", \PHPUnit\Util\Test::describeAsString($test)));
  34144. }
  34145. }
  34146. /**
  34147. * A test ended.
  34148. */
  34149. public function endTest(\PHPUnit\Framework\Test $test, float $time) : void
  34150. {
  34151. if ($this->debug) {
  34152. $this->write(\sprintf("Test '%s' ended\n", \PHPUnit\Util\Test::describeAsString($test)));
  34153. }
  34154. if (!$this->lastTestFailed) {
  34155. $this->writeProgress('.');
  34156. }
  34157. if ($test instanceof \PHPUnit\Framework\TestCase) {
  34158. $this->numAssertions += $test->getNumAssertions();
  34159. } elseif ($test instanceof \PHPUnit\Runner\PhptTestCase) {
  34160. $this->numAssertions++;
  34161. }
  34162. $this->lastTestFailed = \false;
  34163. if ($test instanceof \PHPUnit\Framework\TestCase && !$test->hasExpectationOnOutput()) {
  34164. $this->write($test->getActualOutput());
  34165. }
  34166. }
  34167. protected function printDefects(array $defects, string $type) : void
  34168. {
  34169. $count = \count($defects);
  34170. if ($count == 0) {
  34171. return;
  34172. }
  34173. if ($this->defectListPrinted) {
  34174. $this->write("\n--\n\n");
  34175. }
  34176. $this->write(\sprintf("There %s %d %s%s:\n", $count == 1 ? 'was' : 'were', $count, $type, $count == 1 ? '' : 's'));
  34177. $i = 1;
  34178. if ($this->reverse) {
  34179. $defects = \array_reverse($defects);
  34180. }
  34181. foreach ($defects as $defect) {
  34182. $this->printDefect($defect, $i++);
  34183. }
  34184. $this->defectListPrinted = \true;
  34185. }
  34186. protected function printDefect(\PHPUnit\Framework\TestFailure $defect, int $count) : void
  34187. {
  34188. $this->printDefectHeader($defect, $count);
  34189. $this->printDefectTrace($defect);
  34190. }
  34191. protected function printDefectHeader(\PHPUnit\Framework\TestFailure $defect, int $count) : void
  34192. {
  34193. $this->write(\sprintf("\n%d) %s\n", $count, $defect->getTestName()));
  34194. }
  34195. protected function printDefectTrace(\PHPUnit\Framework\TestFailure $defect) : void
  34196. {
  34197. $e = $defect->thrownException();
  34198. $this->write((string) $e);
  34199. while ($e = $e->getPrevious()) {
  34200. $this->write("\nCaused by\n" . $e);
  34201. }
  34202. }
  34203. protected function printErrors(\PHPUnit\Framework\TestResult $result) : void
  34204. {
  34205. $this->printDefects($result->errors(), 'error');
  34206. }
  34207. protected function printFailures(\PHPUnit\Framework\TestResult $result) : void
  34208. {
  34209. $this->printDefects($result->failures(), 'failure');
  34210. }
  34211. protected function printWarnings(\PHPUnit\Framework\TestResult $result) : void
  34212. {
  34213. $this->printDefects($result->warnings(), 'warning');
  34214. }
  34215. protected function printIncompletes(\PHPUnit\Framework\TestResult $result) : void
  34216. {
  34217. $this->printDefects($result->notImplemented(), 'incomplete test');
  34218. }
  34219. protected function printRisky(\PHPUnit\Framework\TestResult $result) : void
  34220. {
  34221. $this->printDefects($result->risky(), 'risky test');
  34222. }
  34223. protected function printSkipped(\PHPUnit\Framework\TestResult $result) : void
  34224. {
  34225. $this->printDefects($result->skipped(), 'skipped test');
  34226. }
  34227. protected function printHeader(\PHPUnit\Framework\TestResult $result) : void
  34228. {
  34229. if (\count($result) > 0) {
  34230. $this->write(\PHP_EOL . \PHP_EOL . (new \PHPUnit\SebastianBergmann\Timer\ResourceUsageFormatter())->resourceUsage($this->timer->stop()) . \PHP_EOL . \PHP_EOL);
  34231. }
  34232. }
  34233. protected function printFooter(\PHPUnit\Framework\TestResult $result) : void
  34234. {
  34235. if (\count($result) === 0) {
  34236. $this->writeWithColor('fg-black, bg-yellow', 'No tests executed!');
  34237. return;
  34238. }
  34239. if ($result->wasSuccessfulAndNoTestIsRiskyOrSkippedOrIncomplete()) {
  34240. $this->writeWithColor('fg-black, bg-green', \sprintf('OK (%d test%s, %d assertion%s)', \count($result), \count($result) === 1 ? '' : 's', $this->numAssertions, $this->numAssertions === 1 ? '' : 's'));
  34241. return;
  34242. }
  34243. $color = 'fg-black, bg-yellow';
  34244. if ($result->wasSuccessful()) {
  34245. if ($this->verbose || !$result->allHarmless()) {
  34246. $this->write("\n");
  34247. }
  34248. $this->writeWithColor($color, 'OK, but incomplete, skipped, or risky tests!');
  34249. } else {
  34250. $this->write("\n");
  34251. if ($result->errorCount()) {
  34252. $color = 'fg-white, bg-red';
  34253. $this->writeWithColor($color, 'ERRORS!');
  34254. } elseif ($result->failureCount()) {
  34255. $color = 'fg-white, bg-red';
  34256. $this->writeWithColor($color, 'FAILURES!');
  34257. } elseif ($result->warningCount()) {
  34258. $color = 'fg-black, bg-yellow';
  34259. $this->writeWithColor($color, 'WARNINGS!');
  34260. }
  34261. }
  34262. $this->writeCountString(\count($result), 'Tests', $color, \true);
  34263. $this->writeCountString($this->numAssertions, 'Assertions', $color, \true);
  34264. $this->writeCountString($result->errorCount(), 'Errors', $color);
  34265. $this->writeCountString($result->failureCount(), 'Failures', $color);
  34266. $this->writeCountString($result->warningCount(), 'Warnings', $color);
  34267. $this->writeCountString($result->skippedCount(), 'Skipped', $color);
  34268. $this->writeCountString($result->notImplementedCount(), 'Incomplete', $color);
  34269. $this->writeCountString($result->riskyCount(), 'Risky', $color);
  34270. $this->writeWithColor($color, '.');
  34271. }
  34272. protected function writeProgress(string $progress) : void
  34273. {
  34274. if ($this->debug) {
  34275. return;
  34276. }
  34277. $this->write($progress);
  34278. $this->column++;
  34279. $this->numTestsRun++;
  34280. if ($this->column == $this->maxColumn || $this->numTestsRun == $this->numTests) {
  34281. if ($this->numTestsRun == $this->numTests) {
  34282. $this->write(\str_repeat(' ', $this->maxColumn - $this->column));
  34283. }
  34284. $this->write(\sprintf(' %' . $this->numTestsWidth . 'd / %' . $this->numTestsWidth . 'd (%3s%%)', $this->numTestsRun, $this->numTests, \floor($this->numTestsRun / $this->numTests * 100)));
  34285. if ($this->column == $this->maxColumn) {
  34286. $this->writeNewLine();
  34287. }
  34288. }
  34289. }
  34290. protected function writeNewLine() : void
  34291. {
  34292. $this->column = 0;
  34293. $this->write("\n");
  34294. }
  34295. /**
  34296. * Formats a buffer with a specified ANSI color sequence if colors are
  34297. * enabled.
  34298. */
  34299. protected function colorizeTextBox(string $color, string $buffer) : string
  34300. {
  34301. if (!$this->colors) {
  34302. return $buffer;
  34303. }
  34304. $lines = \preg_split('/\\r\\n|\\r|\\n/', $buffer);
  34305. $padding = \max(\array_map('\\strlen', $lines));
  34306. $styledLines = [];
  34307. foreach ($lines as $line) {
  34308. $styledLines[] = \PHPUnit\Util\Color::colorize($color, \str_pad($line, $padding));
  34309. }
  34310. return \implode(\PHP_EOL, $styledLines);
  34311. }
  34312. /**
  34313. * Writes a buffer out with a color sequence if colors are enabled.
  34314. */
  34315. protected function writeWithColor(string $color, string $buffer, bool $lf = \true) : void
  34316. {
  34317. $this->write($this->colorizeTextBox($color, $buffer));
  34318. if ($lf) {
  34319. $this->write(\PHP_EOL);
  34320. }
  34321. }
  34322. /**
  34323. * Writes progress with a color sequence if colors are enabled.
  34324. */
  34325. protected function writeProgressWithColor(string $color, string $buffer) : void
  34326. {
  34327. $buffer = $this->colorizeTextBox($color, $buffer);
  34328. $this->writeProgress($buffer);
  34329. }
  34330. private function writeCountString(int $count, string $name, string $color, bool $always = \false) : void
  34331. {
  34332. static $first = \true;
  34333. if ($always || $count > 0) {
  34334. $this->writeWithColor($color, \sprintf('%s%s: %d', !$first ? ', ' : '', $name, $count), \false);
  34335. $first = \false;
  34336. }
  34337. }
  34338. }
  34339. <?php
  34340. declare (strict_types=1);
  34341. /*
  34342. * This file is part of PHPUnit.
  34343. *
  34344. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  34345. *
  34346. * For the full copyright and license information, please view the LICENSE
  34347. * file that was distributed with this source code.
  34348. */
  34349. namespace PHPUnit\TextUI\Configuration;
  34350. /**
  34351. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  34352. */
  34353. final class GroupCollectionIterator implements \Countable, \Iterator
  34354. {
  34355. /**
  34356. * @var Group[]
  34357. */
  34358. private $groups;
  34359. /**
  34360. * @var int
  34361. */
  34362. private $position;
  34363. public function __construct(\PHPUnit\TextUI\Configuration\GroupCollection $groups)
  34364. {
  34365. $this->groups = $groups->asArray();
  34366. }
  34367. public function count() : int
  34368. {
  34369. return \iterator_count($this);
  34370. }
  34371. public function rewind() : void
  34372. {
  34373. $this->position = 0;
  34374. }
  34375. public function valid() : bool
  34376. {
  34377. return $this->position < \count($this->groups);
  34378. }
  34379. public function key() : int
  34380. {
  34381. return $this->position;
  34382. }
  34383. public function current() : \PHPUnit\TextUI\Configuration\Group
  34384. {
  34385. return $this->groups[$this->position];
  34386. }
  34387. public function next() : void
  34388. {
  34389. $this->position++;
  34390. }
  34391. }
  34392. <?php
  34393. declare (strict_types=1);
  34394. /*
  34395. * This file is part of PHPUnit.
  34396. *
  34397. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  34398. *
  34399. * For the full copyright and license information, please view the LICENSE
  34400. * file that was distributed with this source code.
  34401. */
  34402. namespace PHPUnit\TextUI\Configuration;
  34403. /**
  34404. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  34405. * @psalm-immutable
  34406. */
  34407. final class GroupCollection implements \IteratorAggregate
  34408. {
  34409. /**
  34410. * @var Group[]
  34411. */
  34412. private $groups;
  34413. /**
  34414. * @param Group[] $groups
  34415. */
  34416. public static function fromArray(array $groups) : self
  34417. {
  34418. return new self(...$groups);
  34419. }
  34420. private function __construct(\PHPUnit\TextUI\Configuration\Group ...$groups)
  34421. {
  34422. $this->groups = $groups;
  34423. }
  34424. /**
  34425. * @return Group[]
  34426. */
  34427. public function asArray() : array
  34428. {
  34429. return $this->groups;
  34430. }
  34431. /**
  34432. * @return string[]
  34433. */
  34434. public function asArrayOfStrings() : array
  34435. {
  34436. $result = [];
  34437. foreach ($this->groups as $group) {
  34438. $result[] = $group->name();
  34439. }
  34440. return $result;
  34441. }
  34442. public function isEmpty() : bool
  34443. {
  34444. return empty($this->groups);
  34445. }
  34446. public function getIterator() : \PHPUnit\TextUI\Configuration\GroupCollectionIterator
  34447. {
  34448. return new \PHPUnit\TextUI\Configuration\GroupCollectionIterator($this);
  34449. }
  34450. }
  34451. <?php
  34452. declare (strict_types=1);
  34453. /*
  34454. * This file is part of PHPUnit.
  34455. *
  34456. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  34457. *
  34458. * For the full copyright and license information, please view the LICENSE
  34459. * file that was distributed with this source code.
  34460. */
  34461. namespace PHPUnit\TextUI\Configuration;
  34462. /**
  34463. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  34464. * @psalm-immutable
  34465. */
  34466. final class Groups
  34467. {
  34468. /**
  34469. * @var GroupCollection
  34470. */
  34471. private $include;
  34472. /**
  34473. * @var GroupCollection
  34474. */
  34475. private $exclude;
  34476. public function __construct(\PHPUnit\TextUI\Configuration\GroupCollection $include, \PHPUnit\TextUI\Configuration\GroupCollection $exclude)
  34477. {
  34478. $this->include = $include;
  34479. $this->exclude = $exclude;
  34480. }
  34481. public function hasInclude() : bool
  34482. {
  34483. return !$this->include->isEmpty();
  34484. }
  34485. public function include() : \PHPUnit\TextUI\Configuration\GroupCollection
  34486. {
  34487. return $this->include;
  34488. }
  34489. public function hasExclude() : bool
  34490. {
  34491. return !$this->exclude->isEmpty();
  34492. }
  34493. public function exclude() : \PHPUnit\TextUI\Configuration\GroupCollection
  34494. {
  34495. return $this->exclude;
  34496. }
  34497. }
  34498. <?php
  34499. declare (strict_types=1);
  34500. /*
  34501. * This file is part of PHPUnit.
  34502. *
  34503. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  34504. *
  34505. * For the full copyright and license information, please view the LICENSE
  34506. * file that was distributed with this source code.
  34507. */
  34508. namespace PHPUnit\TextUI\Configuration;
  34509. /**
  34510. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  34511. * @psalm-immutable
  34512. */
  34513. final class Group
  34514. {
  34515. /**
  34516. * @var string
  34517. */
  34518. private $name;
  34519. public function __construct(string $name)
  34520. {
  34521. $this->name = $name;
  34522. }
  34523. public function name() : string
  34524. {
  34525. return $this->name;
  34526. }
  34527. }
  34528. <?php
  34529. declare (strict_types=1);
  34530. /*
  34531. * This file is part of PHPUnit.
  34532. *
  34533. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  34534. *
  34535. * For the full copyright and license information, please view the LICENSE
  34536. * file that was distributed with this source code.
  34537. */
  34538. namespace PHPUnit\TextUI\Configuration;
  34539. /**
  34540. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  34541. */
  34542. final class Generator
  34543. {
  34544. /**
  34545. * @var string
  34546. */
  34547. private const TEMPLATE = <<<EOT
  34548. <?xml version="1.0" encoding="UTF-8"?>
  34549. <phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  34550. xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/{phpunit_version}/phpunit.xsd"
  34551. bootstrap="{bootstrap_script}"
  34552. executionOrder="depends,defects"
  34553. forceCoversAnnotation="true"
  34554. beStrictAboutCoversAnnotation="true"
  34555. beStrictAboutOutputDuringTests="true"
  34556. beStrictAboutTodoAnnotatedTests="true"
  34557. verbose="true">
  34558. <testsuites>
  34559. <testsuite name="default">
  34560. <directory suffix="Test.php">{tests_directory}</directory>
  34561. </testsuite>
  34562. </testsuites>
  34563. <filter>
  34564. <whitelist processUncoveredFilesFromWhitelist="true">
  34565. <directory suffix=".php">{src_directory}</directory>
  34566. </whitelist>
  34567. </filter>
  34568. </phpunit>
  34569. EOT;
  34570. public function generateDefaultConfiguration(string $phpunitVersion, string $bootstrapScript, string $testsDirectory, string $srcDirectory) : string
  34571. {
  34572. return \str_replace(['{phpunit_version}', '{bootstrap_script}', '{tests_directory}', '{src_directory}'], [$phpunitVersion, $bootstrapScript, $testsDirectory, $srcDirectory], self::TEMPLATE);
  34573. }
  34574. }
  34575. <?php
  34576. declare (strict_types=1);
  34577. /*
  34578. * This file is part of PHPUnit.
  34579. *
  34580. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  34581. *
  34582. * For the full copyright and license information, please view the LICENSE
  34583. * file that was distributed with this source code.
  34584. */
  34585. namespace PHPUnit\TextUI\Configuration\Logging;
  34586. use PHPUnit\TextUI\Configuration\File;
  34587. /**
  34588. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  34589. * @psalm-immutable
  34590. */
  34591. final class Junit
  34592. {
  34593. /**
  34594. * @var File
  34595. */
  34596. private $target;
  34597. public function __construct(\PHPUnit\TextUI\Configuration\File $target)
  34598. {
  34599. $this->target = $target;
  34600. }
  34601. public function target() : \PHPUnit\TextUI\Configuration\File
  34602. {
  34603. return $this->target;
  34604. }
  34605. }
  34606. <?php
  34607. declare (strict_types=1);
  34608. /*
  34609. * This file is part of PHPUnit.
  34610. *
  34611. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  34612. *
  34613. * For the full copyright and license information, please view the LICENSE
  34614. * file that was distributed with this source code.
  34615. */
  34616. namespace PHPUnit\TextUI\Configuration\Logging;
  34617. use PHPUnit\TextUI\Configuration\Exception;
  34618. use PHPUnit\TextUI\Configuration\Logging\CodeCoverage\Clover;
  34619. use PHPUnit\TextUI\Configuration\Logging\CodeCoverage\Crap4j;
  34620. use PHPUnit\TextUI\Configuration\Logging\CodeCoverage\Html as CodeCoverageHtml;
  34621. use PHPUnit\TextUI\Configuration\Logging\CodeCoverage\Php;
  34622. use PHPUnit\TextUI\Configuration\Logging\CodeCoverage\Text as CodeCoverageText;
  34623. use PHPUnit\TextUI\Configuration\Logging\CodeCoverage\Xml as CodeCoverageXml;
  34624. use PHPUnit\TextUI\Configuration\Logging\TestDox\Html as TestDoxHtml;
  34625. use PHPUnit\TextUI\Configuration\Logging\TestDox\Text as TestDoxText;
  34626. use PHPUnit\TextUI\Configuration\Logging\TestDox\Xml as TestDoxXml;
  34627. /**
  34628. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  34629. * @psalm-immutable
  34630. */
  34631. final class Logging
  34632. {
  34633. /**
  34634. * @var ?Clover
  34635. */
  34636. private $codeCoverageClover;
  34637. /**
  34638. * @var ?Crap4j
  34639. */
  34640. private $codeCoverageCrap4j;
  34641. /**
  34642. * @var ?CodeCoverageHtml
  34643. */
  34644. private $codeCoverageHtml;
  34645. /**
  34646. * @var ?Php
  34647. */
  34648. private $codeCoveragePhp;
  34649. /**
  34650. * @var ?CodeCoverageText
  34651. */
  34652. private $codeCoverageText;
  34653. /**
  34654. * @var ?CodeCoverageXml
  34655. */
  34656. private $codeCoverageXml;
  34657. /**
  34658. * @var ?Junit
  34659. */
  34660. private $junit;
  34661. /**
  34662. * @var ?PlainText
  34663. */
  34664. private $plainText;
  34665. /**
  34666. * @var ?TeamCity
  34667. */
  34668. private $teamCity;
  34669. /**
  34670. * @var ?TestDoxHtml
  34671. */
  34672. private $testDoxHtml;
  34673. /**
  34674. * @var ?TestDoxText
  34675. */
  34676. private $testDoxText;
  34677. /**
  34678. * @var ?TestDoxXml
  34679. */
  34680. private $testDoxXml;
  34681. public function __construct(?\PHPUnit\TextUI\Configuration\Logging\CodeCoverage\Clover $codeCoverageClover, ?\PHPUnit\TextUI\Configuration\Logging\CodeCoverage\Crap4j $codeCoverageCrap4j, ?\PHPUnit\TextUI\Configuration\Logging\CodeCoverage\Html $codeCoverageHtml, ?\PHPUnit\TextUI\Configuration\Logging\CodeCoverage\Php $codeCoveragePhp, ?\PHPUnit\TextUI\Configuration\Logging\CodeCoverage\Text $codeCoverageText, ?\PHPUnit\TextUI\Configuration\Logging\CodeCoverage\Xml $codeCoverageXml, ?\PHPUnit\TextUI\Configuration\Logging\Junit $junit, ?\PHPUnit\TextUI\Configuration\Logging\PlainText $plainText, ?\PHPUnit\TextUI\Configuration\Logging\TeamCity $teamCity, ?\PHPUnit\TextUI\Configuration\Logging\TestDox\Html $testDoxHtml, ?\PHPUnit\TextUI\Configuration\Logging\TestDox\Text $testDoxText, ?\PHPUnit\TextUI\Configuration\Logging\TestDox\Xml $testDoxXml)
  34682. {
  34683. $this->codeCoverageClover = $codeCoverageClover;
  34684. $this->codeCoverageCrap4j = $codeCoverageCrap4j;
  34685. $this->codeCoverageHtml = $codeCoverageHtml;
  34686. $this->codeCoveragePhp = $codeCoveragePhp;
  34687. $this->codeCoverageText = $codeCoverageText;
  34688. $this->codeCoverageXml = $codeCoverageXml;
  34689. $this->junit = $junit;
  34690. $this->plainText = $plainText;
  34691. $this->teamCity = $teamCity;
  34692. $this->testDoxHtml = $testDoxHtml;
  34693. $this->testDoxText = $testDoxText;
  34694. $this->testDoxXml = $testDoxXml;
  34695. }
  34696. public function hasCodeCoverageClover() : bool
  34697. {
  34698. return $this->codeCoverageClover !== null;
  34699. }
  34700. public function codeCoverageClover() : \PHPUnit\TextUI\Configuration\Logging\CodeCoverage\Clover
  34701. {
  34702. if ($this->codeCoverageClover === null) {
  34703. throw new \PHPUnit\TextUI\Configuration\Exception('Logger "Clover XML" is not configured');
  34704. }
  34705. return $this->codeCoverageClover;
  34706. }
  34707. public function hasCodeCoverageCrap4j() : bool
  34708. {
  34709. return $this->codeCoverageCrap4j !== null;
  34710. }
  34711. public function codeCoverageCrap4j() : \PHPUnit\TextUI\Configuration\Logging\CodeCoverage\Crap4j
  34712. {
  34713. if ($this->codeCoverageCrap4j === null) {
  34714. throw new \PHPUnit\TextUI\Configuration\Exception('Logger "Crap4j XML" is not configured');
  34715. }
  34716. return $this->codeCoverageCrap4j;
  34717. }
  34718. public function hasCodeCoverageHtml() : bool
  34719. {
  34720. return $this->codeCoverageHtml !== null;
  34721. }
  34722. public function codeCoverageHtml() : \PHPUnit\TextUI\Configuration\Logging\CodeCoverage\Html
  34723. {
  34724. if ($this->codeCoverageHtml === null) {
  34725. throw new \PHPUnit\TextUI\Configuration\Exception('Logger "Code Coverage HTML" is not configured');
  34726. }
  34727. return $this->codeCoverageHtml;
  34728. }
  34729. public function hasCodeCoveragePhp() : bool
  34730. {
  34731. return $this->codeCoveragePhp !== null;
  34732. }
  34733. public function codeCoveragePhp() : \PHPUnit\TextUI\Configuration\Logging\CodeCoverage\Php
  34734. {
  34735. if ($this->codeCoveragePhp === null) {
  34736. throw new \PHPUnit\TextUI\Configuration\Exception('Logger "Code Coverage PHP" is not configured');
  34737. }
  34738. return $this->codeCoveragePhp;
  34739. }
  34740. public function hasCodeCoverageText() : bool
  34741. {
  34742. return $this->codeCoverageText !== null;
  34743. }
  34744. public function codeCoverageText() : \PHPUnit\TextUI\Configuration\Logging\CodeCoverage\Text
  34745. {
  34746. if ($this->codeCoverageText === null) {
  34747. throw new \PHPUnit\TextUI\Configuration\Exception('Logger "Code Coverage Text" is not configured');
  34748. }
  34749. return $this->codeCoverageText;
  34750. }
  34751. public function hasCodeCoverageXml() : bool
  34752. {
  34753. return $this->codeCoverageXml !== null;
  34754. }
  34755. public function codeCoverageXml() : \PHPUnit\TextUI\Configuration\Logging\CodeCoverage\Xml
  34756. {
  34757. if ($this->codeCoverageXml === null) {
  34758. throw new \PHPUnit\TextUI\Configuration\Exception('Logger "Code Coverage XML" is not configured');
  34759. }
  34760. return $this->codeCoverageXml;
  34761. }
  34762. public function hasJunit() : bool
  34763. {
  34764. return $this->junit !== null;
  34765. }
  34766. public function junit() : \PHPUnit\TextUI\Configuration\Logging\Junit
  34767. {
  34768. if ($this->junit === null) {
  34769. throw new \PHPUnit\TextUI\Configuration\Exception('Logger "JUnit XML" is not configured');
  34770. }
  34771. return $this->junit;
  34772. }
  34773. public function hasPlainText() : bool
  34774. {
  34775. return $this->plainText !== null;
  34776. }
  34777. public function plainText() : \PHPUnit\TextUI\Configuration\Logging\PlainText
  34778. {
  34779. if ($this->plainText === null) {
  34780. throw new \PHPUnit\TextUI\Configuration\Exception('Logger "Plain Text" is not configured');
  34781. }
  34782. return $this->plainText;
  34783. }
  34784. public function hasTeamCity() : bool
  34785. {
  34786. return $this->teamCity !== null;
  34787. }
  34788. public function teamCity() : \PHPUnit\TextUI\Configuration\Logging\TeamCity
  34789. {
  34790. if ($this->teamCity === null) {
  34791. throw new \PHPUnit\TextUI\Configuration\Exception('Logger "Team City" is not configured');
  34792. }
  34793. return $this->teamCity;
  34794. }
  34795. public function hasTestDoxHtml() : bool
  34796. {
  34797. return $this->testDoxHtml !== null;
  34798. }
  34799. public function testDoxHtml() : \PHPUnit\TextUI\Configuration\Logging\TestDox\Html
  34800. {
  34801. if ($this->testDoxHtml === null) {
  34802. throw new \PHPUnit\TextUI\Configuration\Exception('Logger "TestDox HTML" is not configured');
  34803. }
  34804. return $this->testDoxHtml;
  34805. }
  34806. public function hasTestDoxText() : bool
  34807. {
  34808. return $this->testDoxText !== null;
  34809. }
  34810. public function testDoxText() : \PHPUnit\TextUI\Configuration\Logging\TestDox\Text
  34811. {
  34812. if ($this->testDoxText === null) {
  34813. throw new \PHPUnit\TextUI\Configuration\Exception('Logger "TestDox Text" is not configured');
  34814. }
  34815. return $this->testDoxText;
  34816. }
  34817. public function hasTestDoxXml() : bool
  34818. {
  34819. return $this->testDoxXml !== null;
  34820. }
  34821. public function testDoxXml() : \PHPUnit\TextUI\Configuration\Logging\TestDox\Xml
  34822. {
  34823. if ($this->testDoxXml === null) {
  34824. throw new \PHPUnit\TextUI\Configuration\Exception('Logger "TestDox XML" is not configured');
  34825. }
  34826. return $this->testDoxXml;
  34827. }
  34828. }
  34829. <?php
  34830. declare (strict_types=1);
  34831. /*
  34832. * This file is part of PHPUnit.
  34833. *
  34834. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  34835. *
  34836. * For the full copyright and license information, please view the LICENSE
  34837. * file that was distributed with this source code.
  34838. */
  34839. namespace PHPUnit\TextUI\Configuration\Logging;
  34840. use PHPUnit\TextUI\Configuration\File;
  34841. /**
  34842. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  34843. * @psalm-immutable
  34844. */
  34845. final class TeamCity
  34846. {
  34847. /**
  34848. * @var File
  34849. */
  34850. private $target;
  34851. public function __construct(\PHPUnit\TextUI\Configuration\File $target)
  34852. {
  34853. $this->target = $target;
  34854. }
  34855. public function target() : \PHPUnit\TextUI\Configuration\File
  34856. {
  34857. return $this->target;
  34858. }
  34859. }
  34860. <?php
  34861. declare (strict_types=1);
  34862. /*
  34863. * This file is part of PHPUnit.
  34864. *
  34865. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  34866. *
  34867. * For the full copyright and license information, please view the LICENSE
  34868. * file that was distributed with this source code.
  34869. */
  34870. namespace PHPUnit\TextUI\Configuration\Logging;
  34871. use PHPUnit\TextUI\Configuration\File;
  34872. /**
  34873. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  34874. * @psalm-immutable
  34875. */
  34876. final class PlainText
  34877. {
  34878. /**
  34879. * @var File
  34880. */
  34881. private $target;
  34882. public function __construct(\PHPUnit\TextUI\Configuration\File $target)
  34883. {
  34884. $this->target = $target;
  34885. }
  34886. public function target() : \PHPUnit\TextUI\Configuration\File
  34887. {
  34888. return $this->target;
  34889. }
  34890. }
  34891. <?php
  34892. declare (strict_types=1);
  34893. /*
  34894. * This file is part of PHPUnit.
  34895. *
  34896. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  34897. *
  34898. * For the full copyright and license information, please view the LICENSE
  34899. * file that was distributed with this source code.
  34900. */
  34901. namespace PHPUnit\TextUI\Configuration\Logging\CodeCoverage;
  34902. use PHPUnit\TextUI\Configuration\Directory;
  34903. /**
  34904. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  34905. * @psalm-immutable
  34906. */
  34907. final class Xml
  34908. {
  34909. /**
  34910. * @var Directory
  34911. */
  34912. private $target;
  34913. public function __construct(\PHPUnit\TextUI\Configuration\Directory $target)
  34914. {
  34915. $this->target = $target;
  34916. }
  34917. public function target() : \PHPUnit\TextUI\Configuration\Directory
  34918. {
  34919. return $this->target;
  34920. }
  34921. }
  34922. <?php
  34923. declare (strict_types=1);
  34924. /*
  34925. * This file is part of PHPUnit.
  34926. *
  34927. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  34928. *
  34929. * For the full copyright and license information, please view the LICENSE
  34930. * file that was distributed with this source code.
  34931. */
  34932. namespace PHPUnit\TextUI\Configuration\Logging\CodeCoverage;
  34933. use PHPUnit\TextUI\Configuration\File;
  34934. /**
  34935. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  34936. * @psalm-immutable
  34937. */
  34938. final class Php
  34939. {
  34940. /**
  34941. * @var File
  34942. */
  34943. private $target;
  34944. public function __construct(\PHPUnit\TextUI\Configuration\File $target)
  34945. {
  34946. $this->target = $target;
  34947. }
  34948. public function target() : \PHPUnit\TextUI\Configuration\File
  34949. {
  34950. return $this->target;
  34951. }
  34952. }
  34953. <?php
  34954. declare (strict_types=1);
  34955. /*
  34956. * This file is part of PHPUnit.
  34957. *
  34958. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  34959. *
  34960. * For the full copyright and license information, please view the LICENSE
  34961. * file that was distributed with this source code.
  34962. */
  34963. namespace PHPUnit\TextUI\Configuration\Logging\CodeCoverage;
  34964. use PHPUnit\TextUI\Configuration\Directory;
  34965. /**
  34966. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  34967. * @psalm-immutable
  34968. */
  34969. final class Html
  34970. {
  34971. /**
  34972. * @var Directory
  34973. */
  34974. private $target;
  34975. /**
  34976. * @var int
  34977. */
  34978. private $lowUpperBound;
  34979. /**
  34980. * @var int
  34981. */
  34982. private $highLowerBound;
  34983. public function __construct(\PHPUnit\TextUI\Configuration\Directory $target, int $lowUpperBound, int $highLowerBound)
  34984. {
  34985. $this->target = $target;
  34986. $this->lowUpperBound = $lowUpperBound;
  34987. $this->highLowerBound = $highLowerBound;
  34988. }
  34989. public function target() : \PHPUnit\TextUI\Configuration\Directory
  34990. {
  34991. return $this->target;
  34992. }
  34993. public function lowUpperBound() : int
  34994. {
  34995. return $this->lowUpperBound;
  34996. }
  34997. public function highLowerBound() : int
  34998. {
  34999. return $this->highLowerBound;
  35000. }
  35001. }
  35002. <?php
  35003. declare (strict_types=1);
  35004. /*
  35005. * This file is part of PHPUnit.
  35006. *
  35007. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  35008. *
  35009. * For the full copyright and license information, please view the LICENSE
  35010. * file that was distributed with this source code.
  35011. */
  35012. namespace PHPUnit\TextUI\Configuration\Logging\CodeCoverage;
  35013. use PHPUnit\TextUI\Configuration\File;
  35014. /**
  35015. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  35016. * @psalm-immutable
  35017. */
  35018. final class Crap4j
  35019. {
  35020. /**
  35021. * @var File
  35022. */
  35023. private $target;
  35024. /**
  35025. * @var int
  35026. */
  35027. private $threshold;
  35028. public function __construct(\PHPUnit\TextUI\Configuration\File $target, int $threshold)
  35029. {
  35030. $this->target = $target;
  35031. $this->threshold = $threshold;
  35032. }
  35033. public function target() : \PHPUnit\TextUI\Configuration\File
  35034. {
  35035. return $this->target;
  35036. }
  35037. public function threshold() : int
  35038. {
  35039. return $this->threshold;
  35040. }
  35041. }
  35042. <?php
  35043. declare (strict_types=1);
  35044. /*
  35045. * This file is part of PHPUnit.
  35046. *
  35047. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  35048. *
  35049. * For the full copyright and license information, please view the LICENSE
  35050. * file that was distributed with this source code.
  35051. */
  35052. namespace PHPUnit\TextUI\Configuration\Logging\CodeCoverage;
  35053. use PHPUnit\TextUI\Configuration\File;
  35054. /**
  35055. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  35056. * @psalm-immutable
  35057. */
  35058. final class Text
  35059. {
  35060. /**
  35061. * @var File
  35062. */
  35063. private $target;
  35064. /**
  35065. * @var bool
  35066. */
  35067. private $showUncoveredFiles;
  35068. /**
  35069. * @var bool
  35070. */
  35071. private $showOnlySummary;
  35072. public function __construct(\PHPUnit\TextUI\Configuration\File $target, bool $showUncoveredFiles, bool $showOnlySummary)
  35073. {
  35074. $this->target = $target;
  35075. $this->showUncoveredFiles = $showUncoveredFiles;
  35076. $this->showOnlySummary = $showOnlySummary;
  35077. }
  35078. public function target() : \PHPUnit\TextUI\Configuration\File
  35079. {
  35080. return $this->target;
  35081. }
  35082. public function showUncoveredFiles() : bool
  35083. {
  35084. return $this->showUncoveredFiles;
  35085. }
  35086. public function showOnlySummary() : bool
  35087. {
  35088. return $this->showOnlySummary;
  35089. }
  35090. }
  35091. <?php
  35092. declare (strict_types=1);
  35093. /*
  35094. * This file is part of PHPUnit.
  35095. *
  35096. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  35097. *
  35098. * For the full copyright and license information, please view the LICENSE
  35099. * file that was distributed with this source code.
  35100. */
  35101. namespace PHPUnit\TextUI\Configuration\Logging\CodeCoverage;
  35102. use PHPUnit\TextUI\Configuration\File;
  35103. /**
  35104. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  35105. * @psalm-immutable
  35106. */
  35107. final class Clover
  35108. {
  35109. /**
  35110. * @var File
  35111. */
  35112. private $target;
  35113. public function __construct(\PHPUnit\TextUI\Configuration\File $target)
  35114. {
  35115. $this->target = $target;
  35116. }
  35117. public function target() : \PHPUnit\TextUI\Configuration\File
  35118. {
  35119. return $this->target;
  35120. }
  35121. }
  35122. <?php
  35123. declare (strict_types=1);
  35124. /*
  35125. * This file is part of PHPUnit.
  35126. *
  35127. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  35128. *
  35129. * For the full copyright and license information, please view the LICENSE
  35130. * file that was distributed with this source code.
  35131. */
  35132. namespace PHPUnit\TextUI\Configuration\Logging\TestDox;
  35133. use PHPUnit\TextUI\Configuration\File;
  35134. /**
  35135. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  35136. * @psalm-immutable
  35137. */
  35138. final class Xml
  35139. {
  35140. /**
  35141. * @var File
  35142. */
  35143. private $target;
  35144. public function __construct(\PHPUnit\TextUI\Configuration\File $target)
  35145. {
  35146. $this->target = $target;
  35147. }
  35148. public function target() : \PHPUnit\TextUI\Configuration\File
  35149. {
  35150. return $this->target;
  35151. }
  35152. }
  35153. <?php
  35154. declare (strict_types=1);
  35155. /*
  35156. * This file is part of PHPUnit.
  35157. *
  35158. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  35159. *
  35160. * For the full copyright and license information, please view the LICENSE
  35161. * file that was distributed with this source code.
  35162. */
  35163. namespace PHPUnit\TextUI\Configuration\Logging\TestDox;
  35164. use PHPUnit\TextUI\Configuration\File;
  35165. /**
  35166. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  35167. * @psalm-immutable
  35168. */
  35169. final class Html
  35170. {
  35171. /**
  35172. * @var File
  35173. */
  35174. private $target;
  35175. public function __construct(\PHPUnit\TextUI\Configuration\File $target)
  35176. {
  35177. $this->target = $target;
  35178. }
  35179. public function target() : \PHPUnit\TextUI\Configuration\File
  35180. {
  35181. return $this->target;
  35182. }
  35183. }
  35184. <?php
  35185. declare (strict_types=1);
  35186. /*
  35187. * This file is part of PHPUnit.
  35188. *
  35189. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  35190. *
  35191. * For the full copyright and license information, please view the LICENSE
  35192. * file that was distributed with this source code.
  35193. */
  35194. namespace PHPUnit\TextUI\Configuration\Logging\TestDox;
  35195. use PHPUnit\TextUI\Configuration\File;
  35196. /**
  35197. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  35198. * @psalm-immutable
  35199. */
  35200. final class Text
  35201. {
  35202. /**
  35203. * @var File
  35204. */
  35205. private $target;
  35206. public function __construct(\PHPUnit\TextUI\Configuration\File $target)
  35207. {
  35208. $this->target = $target;
  35209. }
  35210. public function target() : \PHPUnit\TextUI\Configuration\File
  35211. {
  35212. return $this->target;
  35213. }
  35214. }
  35215. <?php
  35216. declare (strict_types=1);
  35217. /*
  35218. * This file is part of PHPUnit.
  35219. *
  35220. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  35221. *
  35222. * For the full copyright and license information, please view the LICENSE
  35223. * file that was distributed with this source code.
  35224. */
  35225. namespace PHPUnit\TextUI\Configuration;
  35226. /**
  35227. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  35228. */
  35229. final class DirectoryCollectionIterator implements \Countable, \Iterator
  35230. {
  35231. /**
  35232. * @var Directory[]
  35233. */
  35234. private $directories;
  35235. /**
  35236. * @var int
  35237. */
  35238. private $position;
  35239. public function __construct(\PHPUnit\TextUI\Configuration\DirectoryCollection $directories)
  35240. {
  35241. $this->directories = $directories->asArray();
  35242. }
  35243. public function count() : int
  35244. {
  35245. return \iterator_count($this);
  35246. }
  35247. public function rewind() : void
  35248. {
  35249. $this->position = 0;
  35250. }
  35251. public function valid() : bool
  35252. {
  35253. return $this->position < \count($this->directories);
  35254. }
  35255. public function key() : int
  35256. {
  35257. return $this->position;
  35258. }
  35259. public function current() : \PHPUnit\TextUI\Configuration\Directory
  35260. {
  35261. return $this->directories[$this->position];
  35262. }
  35263. public function next() : void
  35264. {
  35265. $this->position++;
  35266. }
  35267. }
  35268. <?php
  35269. declare (strict_types=1);
  35270. /*
  35271. * This file is part of PHPUnit.
  35272. *
  35273. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  35274. *
  35275. * For the full copyright and license information, please view the LICENSE
  35276. * file that was distributed with this source code.
  35277. */
  35278. namespace PHPUnit\TextUI\Configuration;
  35279. /**
  35280. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  35281. * @psalm-immutable
  35282. */
  35283. final class DirectoryCollection implements \Countable, \IteratorAggregate
  35284. {
  35285. /**
  35286. * @var Directory[]
  35287. */
  35288. private $directories;
  35289. /**
  35290. * @param Directory[] $directories
  35291. */
  35292. public static function fromArray(array $directories) : self
  35293. {
  35294. return new self(...$directories);
  35295. }
  35296. private function __construct(\PHPUnit\TextUI\Configuration\Directory ...$directories)
  35297. {
  35298. $this->directories = $directories;
  35299. }
  35300. /**
  35301. * @return Directory[]
  35302. */
  35303. public function asArray() : array
  35304. {
  35305. return $this->directories;
  35306. }
  35307. public function count() : int
  35308. {
  35309. return \count($this->directories);
  35310. }
  35311. public function getIterator() : \PHPUnit\TextUI\Configuration\DirectoryCollectionIterator
  35312. {
  35313. return new \PHPUnit\TextUI\Configuration\DirectoryCollectionIterator($this);
  35314. }
  35315. public function isEmpty() : bool
  35316. {
  35317. return $this->count() === 0;
  35318. }
  35319. }
  35320. <?php
  35321. declare (strict_types=1);
  35322. /*
  35323. * This file is part of PHPUnit.
  35324. *
  35325. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  35326. *
  35327. * For the full copyright and license information, please view the LICENSE
  35328. * file that was distributed with this source code.
  35329. */
  35330. namespace PHPUnit\TextUI\Configuration;
  35331. /**
  35332. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  35333. * @psalm-immutable
  35334. */
  35335. final class File
  35336. {
  35337. /**
  35338. * @var string
  35339. */
  35340. private $path;
  35341. public function __construct(string $path)
  35342. {
  35343. $this->path = $path;
  35344. }
  35345. public function path() : string
  35346. {
  35347. return $this->path;
  35348. }
  35349. }
  35350. <?php
  35351. declare (strict_types=1);
  35352. /*
  35353. * This file is part of PHPUnit.
  35354. *
  35355. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  35356. *
  35357. * For the full copyright and license information, please view the LICENSE
  35358. * file that was distributed with this source code.
  35359. */
  35360. namespace PHPUnit\TextUI\Configuration;
  35361. /**
  35362. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  35363. */
  35364. final class FileCollectionIterator implements \Countable, \Iterator
  35365. {
  35366. /**
  35367. * @var File[]
  35368. */
  35369. private $files;
  35370. /**
  35371. * @var int
  35372. */
  35373. private $position;
  35374. public function __construct(\PHPUnit\TextUI\Configuration\FileCollection $files)
  35375. {
  35376. $this->files = $files->asArray();
  35377. }
  35378. public function count() : int
  35379. {
  35380. return \iterator_count($this);
  35381. }
  35382. public function rewind() : void
  35383. {
  35384. $this->position = 0;
  35385. }
  35386. public function valid() : bool
  35387. {
  35388. return $this->position < \count($this->files);
  35389. }
  35390. public function key() : int
  35391. {
  35392. return $this->position;
  35393. }
  35394. public function current() : \PHPUnit\TextUI\Configuration\File
  35395. {
  35396. return $this->files[$this->position];
  35397. }
  35398. public function next() : void
  35399. {
  35400. $this->position++;
  35401. }
  35402. }
  35403. <?php
  35404. declare (strict_types=1);
  35405. /*
  35406. * This file is part of PHPUnit.
  35407. *
  35408. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  35409. *
  35410. * For the full copyright and license information, please view the LICENSE
  35411. * file that was distributed with this source code.
  35412. */
  35413. namespace PHPUnit\TextUI\Configuration;
  35414. /**
  35415. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  35416. * @psalm-immutable
  35417. */
  35418. final class FileCollection implements \Countable, \IteratorAggregate
  35419. {
  35420. /**
  35421. * @var File[]
  35422. */
  35423. private $files;
  35424. /**
  35425. * @param File[] $files
  35426. */
  35427. public static function fromArray(array $files) : self
  35428. {
  35429. return new self(...$files);
  35430. }
  35431. private function __construct(\PHPUnit\TextUI\Configuration\File ...$files)
  35432. {
  35433. $this->files = $files;
  35434. }
  35435. /**
  35436. * @return File[]
  35437. */
  35438. public function asArray() : array
  35439. {
  35440. return $this->files;
  35441. }
  35442. public function count() : int
  35443. {
  35444. return \count($this->files);
  35445. }
  35446. public function getIterator() : \PHPUnit\TextUI\Configuration\FileCollectionIterator
  35447. {
  35448. return new \PHPUnit\TextUI\Configuration\FileCollectionIterator($this);
  35449. }
  35450. public function isEmpty() : bool
  35451. {
  35452. return $this->count() === 0;
  35453. }
  35454. }
  35455. <?php
  35456. declare (strict_types=1);
  35457. /*
  35458. * This file is part of PHPUnit.
  35459. *
  35460. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  35461. *
  35462. * For the full copyright and license information, please view the LICENSE
  35463. * file that was distributed with this source code.
  35464. */
  35465. namespace PHPUnit\TextUI\Configuration;
  35466. /**
  35467. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  35468. * @psalm-immutable
  35469. */
  35470. final class Directory
  35471. {
  35472. /**
  35473. * @var string
  35474. */
  35475. private $path;
  35476. public function __construct(string $path)
  35477. {
  35478. $this->path = $path;
  35479. }
  35480. public function path() : string
  35481. {
  35482. return $this->path;
  35483. }
  35484. }
  35485. <?php
  35486. declare (strict_types=1);
  35487. /*
  35488. * This file is part of PHPUnit.
  35489. *
  35490. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  35491. *
  35492. * For the full copyright and license information, please view the LICENSE
  35493. * file that was distributed with this source code.
  35494. */
  35495. namespace PHPUnit\TextUI\Configuration;
  35496. use PHPUnit\Runner\TestSuiteSorter;
  35497. use PHPUnit\TextUI\Configuration\Logging\CodeCoverage\Clover;
  35498. use PHPUnit\TextUI\Configuration\Logging\CodeCoverage\Crap4j;
  35499. use PHPUnit\TextUI\Configuration\Logging\CodeCoverage\Html as CodeCoverageHtml;
  35500. use PHPUnit\TextUI\Configuration\Logging\CodeCoverage\Php as CodeCoveragePhp;
  35501. use PHPUnit\TextUI\Configuration\Logging\CodeCoverage\Text as CodeCoverageText;
  35502. use PHPUnit\TextUI\Configuration\Logging\CodeCoverage\Xml as CodeCoverageXml;
  35503. use PHPUnit\TextUI\Configuration\Logging\Junit;
  35504. use PHPUnit\TextUI\Configuration\Logging\Logging;
  35505. use PHPUnit\TextUI\Configuration\Logging\PlainText;
  35506. use PHPUnit\TextUI\Configuration\Logging\TeamCity;
  35507. use PHPUnit\TextUI\Configuration\Logging\TestDox\Html as TestDoxHtml;
  35508. use PHPUnit\TextUI\Configuration\Logging\TestDox\Text as TestDoxText;
  35509. use PHPUnit\TextUI\Configuration\Logging\TestDox\Xml as TestDoxXml;
  35510. use PHPUnit\TextUI\Configuration\TestSuite as TestSuiteConfiguration;
  35511. use PHPUnit\TextUI\DefaultResultPrinter;
  35512. use PHPUnit\Util\TestDox\CliTestDoxPrinter;
  35513. use PHPUnit\Util\VersionComparisonOperator;
  35514. use PHPUnit\Util\Xml;
  35515. /**
  35516. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  35517. */
  35518. final class Loader
  35519. {
  35520. public function load(string $filename) : \PHPUnit\TextUI\Configuration\Configuration
  35521. {
  35522. $document = \PHPUnit\Util\Xml::loadFile($filename, \false, \true, \true);
  35523. $xpath = new \DOMXPath($document);
  35524. return new \PHPUnit\TextUI\Configuration\Configuration($filename, $this->validate($document), $this->extensions($filename, $xpath), $this->filter($filename, $xpath), $this->groups($xpath), $this->testdoxGroups($xpath), $this->listeners($filename, $xpath), $this->logging($filename, $xpath), $this->php($filename, $xpath), $this->phpunit($filename, $document), $this->testSuite($filename, $xpath));
  35525. }
  35526. public function logging(string $filename, \DOMXPath $xpath) : \PHPUnit\TextUI\Configuration\Logging\Logging
  35527. {
  35528. $codeCoverageClover = null;
  35529. $codeCoverageCrap4j = null;
  35530. $codeCoverageHtml = null;
  35531. $codeCoveragePhp = null;
  35532. $codeCoverageText = null;
  35533. $codeCoverageXml = null;
  35534. $junit = null;
  35535. $plainText = null;
  35536. $teamCity = null;
  35537. $testDoxHtml = null;
  35538. $testDoxText = null;
  35539. $testDoxXml = null;
  35540. foreach ($xpath->query('logging/log') as $log) {
  35541. \assert($log instanceof \DOMElement);
  35542. $type = (string) $log->getAttribute('type');
  35543. $target = (string) $log->getAttribute('target');
  35544. if (!$target) {
  35545. continue;
  35546. }
  35547. $target = $this->toAbsolutePath($filename, $target);
  35548. switch ($type) {
  35549. case 'coverage-clover':
  35550. $codeCoverageClover = new \PHPUnit\TextUI\Configuration\Logging\CodeCoverage\Clover(new \PHPUnit\TextUI\Configuration\File($target));
  35551. break;
  35552. case 'coverage-crap4j':
  35553. $codeCoverageCrap4j = new \PHPUnit\TextUI\Configuration\Logging\CodeCoverage\Crap4j(new \PHPUnit\TextUI\Configuration\File($target), $this->getIntegerAttribute($log, 'threshold', 30));
  35554. break;
  35555. case 'coverage-html':
  35556. $codeCoverageHtml = new \PHPUnit\TextUI\Configuration\Logging\CodeCoverage\Html(new \PHPUnit\TextUI\Configuration\Directory($target), $this->getIntegerAttribute($log, 'lowUpperBound', 50), $this->getIntegerAttribute($log, 'highLowerBound', 90));
  35557. break;
  35558. case 'coverage-php':
  35559. $codeCoveragePhp = new \PHPUnit\TextUI\Configuration\Logging\CodeCoverage\Php(new \PHPUnit\TextUI\Configuration\File($target));
  35560. break;
  35561. case 'coverage-text':
  35562. $codeCoverageText = new \PHPUnit\TextUI\Configuration\Logging\CodeCoverage\Text(new \PHPUnit\TextUI\Configuration\File($target), $this->getBooleanAttribute($log, 'showUncoveredFiles', \false), $this->getBooleanAttribute($log, 'showOnlySummary', \false));
  35563. break;
  35564. case 'coverage-xml':
  35565. $codeCoverageXml = new \PHPUnit\TextUI\Configuration\Logging\CodeCoverage\Xml(new \PHPUnit\TextUI\Configuration\Directory($target));
  35566. break;
  35567. case 'plain':
  35568. $plainText = new \PHPUnit\TextUI\Configuration\Logging\PlainText(new \PHPUnit\TextUI\Configuration\File($target));
  35569. break;
  35570. case 'junit':
  35571. $junit = new \PHPUnit\TextUI\Configuration\Logging\Junit(new \PHPUnit\TextUI\Configuration\File($target));
  35572. break;
  35573. case 'teamcity':
  35574. $teamCity = new \PHPUnit\TextUI\Configuration\Logging\TeamCity(new \PHPUnit\TextUI\Configuration\File($target));
  35575. break;
  35576. case 'testdox-html':
  35577. $testDoxHtml = new \PHPUnit\TextUI\Configuration\Logging\TestDox\Html(new \PHPUnit\TextUI\Configuration\File($target));
  35578. break;
  35579. case 'testdox-text':
  35580. $testDoxText = new \PHPUnit\TextUI\Configuration\Logging\TestDox\Text(new \PHPUnit\TextUI\Configuration\File($target));
  35581. break;
  35582. case 'testdox-xml':
  35583. $testDoxXml = new \PHPUnit\TextUI\Configuration\Logging\TestDox\Xml(new \PHPUnit\TextUI\Configuration\File($target));
  35584. break;
  35585. }
  35586. }
  35587. return new \PHPUnit\TextUI\Configuration\Logging\Logging($codeCoverageClover, $codeCoverageCrap4j, $codeCoverageHtml, $codeCoveragePhp, $codeCoverageText, $codeCoverageXml, $junit, $plainText, $teamCity, $testDoxHtml, $testDoxText, $testDoxXml);
  35588. }
  35589. /**
  35590. * @psalm-return array<int,array<int,string>>
  35591. */
  35592. private function validate(\DOMDocument $document) : array
  35593. {
  35594. $original = \libxml_use_internal_errors(\true);
  35595. $xsdFilename = __DIR__ . '/../../../phpunit.xsd';
  35596. if (\defined('__PHPUNIT_PHAR_ROOT__')) {
  35597. $xsdFilename = __PHPUNIT_PHAR_ROOT__ . '/phpunit.xsd';
  35598. }
  35599. $document->schemaValidate($xsdFilename);
  35600. $tmp = \libxml_get_errors();
  35601. \libxml_clear_errors();
  35602. \libxml_use_internal_errors($original);
  35603. $errors = [];
  35604. foreach ($tmp as $error) {
  35605. if (!isset($errors[$error->line])) {
  35606. $errors[$error->line] = [];
  35607. }
  35608. $errors[$error->line][] = \trim($error->message);
  35609. }
  35610. return $errors;
  35611. }
  35612. private function extensions(string $filename, \DOMXPath $xpath) : \PHPUnit\TextUI\Configuration\ExtensionCollection
  35613. {
  35614. $extensions = [];
  35615. foreach ($xpath->query('extensions/extension') as $extension) {
  35616. \assert($extension instanceof \DOMElement);
  35617. $extensions[] = $this->getElementConfigurationParameters($filename, $extension);
  35618. }
  35619. return \PHPUnit\TextUI\Configuration\ExtensionCollection::fromArray($extensions);
  35620. }
  35621. private function getElementConfigurationParameters(string $filename, \DOMElement $element) : \PHPUnit\TextUI\Configuration\Extension
  35622. {
  35623. /** @psalm-var class-string $class */
  35624. $class = (string) $element->getAttribute('class');
  35625. $file = '';
  35626. $arguments = $this->getConfigurationArguments($filename, $element->childNodes);
  35627. if ($element->getAttribute('file')) {
  35628. $file = $this->toAbsolutePath($filename, (string) $element->getAttribute('file'), \true);
  35629. }
  35630. return new \PHPUnit\TextUI\Configuration\Extension($class, $file, $arguments);
  35631. }
  35632. private function toAbsolutePath(string $filename, string $path, bool $useIncludePath = \false) : string
  35633. {
  35634. $path = \trim($path);
  35635. if (\strpos($path, '/') === 0) {
  35636. return $path;
  35637. }
  35638. // Matches the following on Windows:
  35639. // - \\NetworkComputer\Path
  35640. // - \\.\D:
  35641. // - \\.\c:
  35642. // - C:\Windows
  35643. // - C:\windows
  35644. // - C:/windows
  35645. // - c:/windows
  35646. if (\defined('PHP_WINDOWS_VERSION_BUILD') && ($path[0] === '\\' || \strlen($path) >= 3 && \preg_match('#^[A-Z]\\:[/\\\\]#i', \substr($path, 0, 3)))) {
  35647. return $path;
  35648. }
  35649. if (\strpos($path, '://') !== \false) {
  35650. return $path;
  35651. }
  35652. $file = \dirname($filename) . \DIRECTORY_SEPARATOR . $path;
  35653. if ($useIncludePath && !\file_exists($file)) {
  35654. $includePathFile = \stream_resolve_include_path($path);
  35655. if ($includePathFile) {
  35656. $file = $includePathFile;
  35657. }
  35658. }
  35659. return $file;
  35660. }
  35661. private function getConfigurationArguments(string $filename, \DOMNodeList $nodes) : array
  35662. {
  35663. $arguments = [];
  35664. if ($nodes->length === 0) {
  35665. return $arguments;
  35666. }
  35667. foreach ($nodes as $node) {
  35668. if (!$node instanceof \DOMElement) {
  35669. continue;
  35670. }
  35671. if ($node->tagName !== 'arguments') {
  35672. continue;
  35673. }
  35674. foreach ($node->childNodes as $argument) {
  35675. if (!$argument instanceof \DOMElement) {
  35676. continue;
  35677. }
  35678. if ($argument->tagName === 'file' || $argument->tagName === 'directory') {
  35679. $arguments[] = $this->toAbsolutePath($filename, (string) $argument->textContent);
  35680. } else {
  35681. $arguments[] = \PHPUnit\Util\Xml::xmlToVariable($argument);
  35682. }
  35683. }
  35684. }
  35685. return $arguments;
  35686. }
  35687. private function filter(string $filename, \DOMXPath $xpath) : \PHPUnit\TextUI\Configuration\Filter
  35688. {
  35689. $addUncoveredFilesFromWhitelist = \true;
  35690. $processUncoveredFilesFromWhitelist = \false;
  35691. $nodes = $xpath->query('filter/whitelist');
  35692. if ($nodes->length === 1) {
  35693. $node = $nodes->item(0);
  35694. \assert($node instanceof \DOMElement);
  35695. if ($node->hasAttribute('addUncoveredFilesFromWhitelist')) {
  35696. $addUncoveredFilesFromWhitelist = (bool) $this->getBoolean((string) $node->getAttribute('addUncoveredFilesFromWhitelist'), \true);
  35697. }
  35698. if ($node->hasAttribute('processUncoveredFilesFromWhitelist')) {
  35699. $processUncoveredFilesFromWhitelist = (bool) $this->getBoolean((string) $node->getAttribute('processUncoveredFilesFromWhitelist'), \false);
  35700. }
  35701. }
  35702. return new \PHPUnit\TextUI\Configuration\Filter($this->readFilterDirectories($filename, $xpath, 'filter/whitelist/directory'), $this->readFilterFiles($filename, $xpath, 'filter/whitelist/file'), $this->readFilterDirectories($filename, $xpath, 'filter/whitelist/exclude/directory'), $this->readFilterFiles($filename, $xpath, 'filter/whitelist/exclude/file'), $addUncoveredFilesFromWhitelist, $processUncoveredFilesFromWhitelist);
  35703. }
  35704. /**
  35705. * if $value is 'false' or 'true', this returns the value that $value represents.
  35706. * Otherwise, returns $default, which may be a string in rare cases.
  35707. * See PHPUnit\TextUI\ConfigurationTest::testPHPConfigurationIsReadCorrectly
  35708. *
  35709. * @param bool|string $default
  35710. *
  35711. * @return bool|string
  35712. */
  35713. private function getBoolean(string $value, $default)
  35714. {
  35715. if (\strtolower($value) === 'false') {
  35716. return \false;
  35717. }
  35718. if (\strtolower($value) === 'true') {
  35719. return \true;
  35720. }
  35721. return $default;
  35722. }
  35723. private function readFilterDirectories(string $filename, \DOMXPath $xpath, string $query) : \PHPUnit\TextUI\Configuration\FilterDirectoryCollection
  35724. {
  35725. $directories = [];
  35726. foreach ($xpath->query($query) as $directoryNode) {
  35727. \assert($directoryNode instanceof \DOMElement);
  35728. $directoryPath = (string) $directoryNode->textContent;
  35729. if (!$directoryPath) {
  35730. continue;
  35731. }
  35732. $directories[] = new \PHPUnit\TextUI\Configuration\FilterDirectory($this->toAbsolutePath($filename, $directoryPath), $directoryNode->hasAttribute('prefix') ? (string) $directoryNode->getAttribute('prefix') : '', $directoryNode->hasAttribute('suffix') ? (string) $directoryNode->getAttribute('suffix') : '.php', $directoryNode->hasAttribute('group') ? (string) $directoryNode->getAttribute('group') : 'DEFAULT');
  35733. }
  35734. return \PHPUnit\TextUI\Configuration\FilterDirectoryCollection::fromArray($directories);
  35735. }
  35736. private function readFilterFiles(string $filename, \DOMXPath $xpath, string $query) : \PHPUnit\TextUI\Configuration\FilterFileCollection
  35737. {
  35738. $files = [];
  35739. foreach ($xpath->query($query) as $file) {
  35740. $filePath = (string) $file->textContent;
  35741. if ($filePath) {
  35742. $files[] = new \PHPUnit\TextUI\Configuration\FilterFile($this->toAbsolutePath($filename, $filePath));
  35743. }
  35744. }
  35745. return \PHPUnit\TextUI\Configuration\FilterFileCollection::fromArray($files);
  35746. }
  35747. private function groups(\DOMXPath $xpath) : \PHPUnit\TextUI\Configuration\Groups
  35748. {
  35749. return $this->parseGroupConfiguration($xpath, 'groups');
  35750. }
  35751. private function testdoxGroups(\DOMXPath $xpath) : \PHPUnit\TextUI\Configuration\Groups
  35752. {
  35753. return $this->parseGroupConfiguration($xpath, 'testdoxGroups');
  35754. }
  35755. private function parseGroupConfiguration(\DOMXPath $xpath, string $root) : \PHPUnit\TextUI\Configuration\Groups
  35756. {
  35757. $include = [];
  35758. $exclude = [];
  35759. foreach ($xpath->query($root . '/include/group') as $group) {
  35760. $include[] = new \PHPUnit\TextUI\Configuration\Group((string) $group->textContent);
  35761. }
  35762. foreach ($xpath->query($root . '/exclude/group') as $group) {
  35763. $exclude[] = new \PHPUnit\TextUI\Configuration\Group((string) $group->textContent);
  35764. }
  35765. return new \PHPUnit\TextUI\Configuration\Groups(\PHPUnit\TextUI\Configuration\GroupCollection::fromArray($include), \PHPUnit\TextUI\Configuration\GroupCollection::fromArray($exclude));
  35766. }
  35767. private function listeners(string $filename, \DOMXPath $xpath) : \PHPUnit\TextUI\Configuration\ExtensionCollection
  35768. {
  35769. $listeners = [];
  35770. foreach ($xpath->query('listeners/listener') as $listener) {
  35771. \assert($listener instanceof \DOMElement);
  35772. $listeners[] = $this->getElementConfigurationParameters($filename, $listener);
  35773. }
  35774. return \PHPUnit\TextUI\Configuration\ExtensionCollection::fromArray($listeners);
  35775. }
  35776. private function getBooleanAttribute(\DOMElement $element, string $attribute, bool $default) : bool
  35777. {
  35778. if (!$element->hasAttribute($attribute)) {
  35779. return $default;
  35780. }
  35781. return (bool) $this->getBoolean((string) $element->getAttribute($attribute), \false);
  35782. }
  35783. private function getIntegerAttribute(\DOMElement $element, string $attribute, int $default) : int
  35784. {
  35785. if (!$element->hasAttribute($attribute)) {
  35786. return $default;
  35787. }
  35788. return $this->getInteger((string) $element->getAttribute($attribute), $default);
  35789. }
  35790. private function getStringAttribute(\DOMElement $element, string $attribute) : ?string
  35791. {
  35792. if (!$element->hasAttribute($attribute)) {
  35793. return null;
  35794. }
  35795. return (string) $element->getAttribute($attribute);
  35796. }
  35797. private function getInteger(string $value, int $default) : int
  35798. {
  35799. if (\is_numeric($value)) {
  35800. return (int) $value;
  35801. }
  35802. return $default;
  35803. }
  35804. private function php(string $filename, \DOMXPath $xpath) : \PHPUnit\TextUI\Configuration\Php
  35805. {
  35806. $includePaths = [];
  35807. foreach ($xpath->query('php/includePath') as $includePath) {
  35808. $path = (string) $includePath->textContent;
  35809. if ($path) {
  35810. $includePaths[] = new \PHPUnit\TextUI\Configuration\Directory($this->toAbsolutePath($filename, $path));
  35811. }
  35812. }
  35813. $iniSettings = [];
  35814. foreach ($xpath->query('php/ini') as $ini) {
  35815. \assert($ini instanceof \DOMElement);
  35816. $iniSettings[] = new \PHPUnit\TextUI\Configuration\IniSetting((string) $ini->getAttribute('name'), (string) $ini->getAttribute('value'));
  35817. }
  35818. $constants = [];
  35819. foreach ($xpath->query('php/const') as $const) {
  35820. \assert($const instanceof \DOMElement);
  35821. $value = (string) $const->getAttribute('value');
  35822. $constants[] = new \PHPUnit\TextUI\Configuration\Constant((string) $const->getAttribute('name'), $this->getBoolean($value, $value));
  35823. }
  35824. $variables = ['var' => [], 'env' => [], 'post' => [], 'get' => [], 'cookie' => [], 'server' => [], 'files' => [], 'request' => []];
  35825. foreach (['var', 'env', 'post', 'get', 'cookie', 'server', 'files', 'request'] as $array) {
  35826. foreach ($xpath->query('php/' . $array) as $var) {
  35827. \assert($var instanceof \DOMElement);
  35828. $name = (string) $var->getAttribute('name');
  35829. $value = (string) $var->getAttribute('value');
  35830. $force = \false;
  35831. $verbatim = \false;
  35832. if ($var->hasAttribute('force')) {
  35833. $force = (bool) $this->getBoolean($var->getAttribute('force'), \false);
  35834. }
  35835. if ($var->hasAttribute('verbatim')) {
  35836. $verbatim = $this->getBoolean($var->getAttribute('verbatim'), \false);
  35837. }
  35838. if (!$verbatim) {
  35839. $value = $this->getBoolean($value, $value);
  35840. }
  35841. $variables[$array][] = new \PHPUnit\TextUI\Configuration\Variable($name, $value, $force);
  35842. }
  35843. }
  35844. return new \PHPUnit\TextUI\Configuration\Php(\PHPUnit\TextUI\Configuration\DirectoryCollection::fromArray($includePaths), \PHPUnit\TextUI\Configuration\IniSettingCollection::fromArray($iniSettings), \PHPUnit\TextUI\Configuration\ConstantCollection::fromArray($constants), \PHPUnit\TextUI\Configuration\VariableCollection::fromArray($variables['var']), \PHPUnit\TextUI\Configuration\VariableCollection::fromArray($variables['env']), \PHPUnit\TextUI\Configuration\VariableCollection::fromArray($variables['post']), \PHPUnit\TextUI\Configuration\VariableCollection::fromArray($variables['get']), \PHPUnit\TextUI\Configuration\VariableCollection::fromArray($variables['cookie']), \PHPUnit\TextUI\Configuration\VariableCollection::fromArray($variables['server']), \PHPUnit\TextUI\Configuration\VariableCollection::fromArray($variables['files']), \PHPUnit\TextUI\Configuration\VariableCollection::fromArray($variables['request']));
  35845. }
  35846. private function phpunit(string $filename, \DOMDocument $document) : \PHPUnit\TextUI\Configuration\PHPUnit
  35847. {
  35848. $executionOrder = \PHPUnit\Runner\TestSuiteSorter::ORDER_DEFAULT;
  35849. $defectsFirst = \false;
  35850. $resolveDependencies = $this->getBooleanAttribute($document->documentElement, 'resolveDependencies', \true);
  35851. if ($document->documentElement->hasAttribute('executionOrder')) {
  35852. foreach (\explode(',', $document->documentElement->getAttribute('executionOrder')) as $order) {
  35853. switch ($order) {
  35854. case 'default':
  35855. $executionOrder = \PHPUnit\Runner\TestSuiteSorter::ORDER_DEFAULT;
  35856. $defectsFirst = \false;
  35857. $resolveDependencies = \true;
  35858. break;
  35859. case 'depends':
  35860. $resolveDependencies = \true;
  35861. break;
  35862. case 'no-depends':
  35863. $resolveDependencies = \false;
  35864. break;
  35865. case 'defects':
  35866. $defectsFirst = \true;
  35867. break;
  35868. case 'duration':
  35869. $executionOrder = \PHPUnit\Runner\TestSuiteSorter::ORDER_DURATION;
  35870. break;
  35871. case 'random':
  35872. $executionOrder = \PHPUnit\Runner\TestSuiteSorter::ORDER_RANDOMIZED;
  35873. break;
  35874. case 'reverse':
  35875. $executionOrder = \PHPUnit\Runner\TestSuiteSorter::ORDER_REVERSED;
  35876. break;
  35877. case 'size':
  35878. $executionOrder = \PHPUnit\Runner\TestSuiteSorter::ORDER_SIZE;
  35879. break;
  35880. }
  35881. }
  35882. }
  35883. $printerClass = $this->getStringAttribute($document->documentElement, 'printerClass');
  35884. $testdox = $this->getBooleanAttribute($document->documentElement, 'testdox', \false);
  35885. $conflictBetweenPrinterClassAndTestdox = \false;
  35886. if ($testdox) {
  35887. if ($printerClass !== null) {
  35888. $conflictBetweenPrinterClassAndTestdox = \true;
  35889. }
  35890. $printerClass = \PHPUnit\Util\TestDox\CliTestDoxPrinter::class;
  35891. }
  35892. $cacheResultFile = $this->getStringAttribute($document->documentElement, 'cacheResultFile');
  35893. if ($cacheResultFile !== null) {
  35894. $cacheResultFile = $this->toAbsolutePath($filename, $cacheResultFile);
  35895. }
  35896. $bootstrap = $this->getStringAttribute($document->documentElement, 'bootstrap');
  35897. if ($bootstrap !== null) {
  35898. $bootstrap = $this->toAbsolutePath($filename, $bootstrap);
  35899. }
  35900. $extensionsDirectory = $this->getStringAttribute($document->documentElement, 'extensionsDirectory');
  35901. if ($extensionsDirectory !== null) {
  35902. $extensionsDirectory = $this->toAbsolutePath($filename, $extensionsDirectory);
  35903. }
  35904. $testSuiteLoaderFile = $this->getStringAttribute($document->documentElement, 'testSuiteLoaderFile');
  35905. if ($testSuiteLoaderFile !== null) {
  35906. $testSuiteLoaderFile = $this->toAbsolutePath($filename, $testSuiteLoaderFile);
  35907. }
  35908. $printerFile = $this->getStringAttribute($document->documentElement, 'printerFile');
  35909. if ($printerFile !== null) {
  35910. $printerFile = $this->toAbsolutePath($filename, $printerFile);
  35911. }
  35912. return new \PHPUnit\TextUI\Configuration\PHPUnit($this->getBooleanAttribute($document->documentElement, 'cacheResult', \false), $cacheResultFile, $this->getBooleanAttribute($document->documentElement, 'cacheTokens', \false), $this->getColumns($document), $this->getColors($document), $this->getBooleanAttribute($document->documentElement, 'stderr', \false), $this->getBooleanAttribute($document->documentElement, 'noInteraction', \false), $this->getBooleanAttribute($document->documentElement, 'verbose', \false), $this->getBooleanAttribute($document->documentElement, 'reverseDefectList', \false), $this->getBooleanAttribute($document->documentElement, 'convertDeprecationsToExceptions', \true), $this->getBooleanAttribute($document->documentElement, 'convertErrorsToExceptions', \true), $this->getBooleanAttribute($document->documentElement, 'convertNoticesToExceptions', \true), $this->getBooleanAttribute($document->documentElement, 'convertWarningsToExceptions', \true), $this->getBooleanAttribute($document->documentElement, 'forceCoversAnnotation', \false), $this->getBooleanAttribute($document->documentElement, 'ignoreDeprecatedCodeUnitsFromCodeCoverage', \false), $this->getBooleanAttribute($document->documentElement, 'disableCodeCoverageIgnore', \false), $bootstrap, $this->getBooleanAttribute($document->documentElement, 'processIsolation', \false), $this->getBooleanAttribute($document->documentElement, 'failOnIncomplete', \false), $this->getBooleanAttribute($document->documentElement, 'failOnRisky', \false), $this->getBooleanAttribute($document->documentElement, 'failOnSkipped', \false), $this->getBooleanAttribute($document->documentElement, 'failOnWarning', \false), $this->getBooleanAttribute($document->documentElement, 'stopOnDefect', \false), $this->getBooleanAttribute($document->documentElement, 'stopOnError', \false), $this->getBooleanAttribute($document->documentElement, 'stopOnFailure', \false), $this->getBooleanAttribute($document->documentElement, 'stopOnWarning', \false), $this->getBooleanAttribute($document->documentElement, 'stopOnIncomplete', \false), $this->getBooleanAttribute($document->documentElement, 'stopOnRisky', \false), $this->getBooleanAttribute($document->documentElement, 'stopOnSkipped', \false), $extensionsDirectory, $this->getStringAttribute($document->documentElement, 'testSuiteLoaderClass'), $testSuiteLoaderFile, $printerClass, $printerFile, $this->getBooleanAttribute($document->documentElement, 'beStrictAboutChangesToGlobalState', \false), $this->getBooleanAttribute($document->documentElement, 'beStrictAboutOutputDuringTests', \false), $this->getBooleanAttribute($document->documentElement, 'beStrictAboutResourceUsageDuringSmallTests', \false), $this->getBooleanAttribute($document->documentElement, 'beStrictAboutTestsThatDoNotTestAnything', \true), $this->getBooleanAttribute($document->documentElement, 'beStrictAboutTodoAnnotatedTests', \false), $this->getBooleanAttribute($document->documentElement, 'beStrictAboutCoversAnnotation', \false), $this->getBooleanAttribute($document->documentElement, 'enforceTimeLimit', \false), $this->getIntegerAttribute($document->documentElement, 'defaultTimeLimit', 1), $this->getIntegerAttribute($document->documentElement, 'timeoutForSmallTests', 1), $this->getIntegerAttribute($document->documentElement, 'timeoutForMediumTests', 10), $this->getIntegerAttribute($document->documentElement, 'timeoutForLargeTests', 60), $this->getStringAttribute($document->documentElement, 'defaultTestSuite'), $executionOrder, $resolveDependencies, $defectsFirst, $this->getBooleanAttribute($document->documentElement, 'backupGlobals', \false), $this->getBooleanAttribute($document->documentElement, 'backupStaticAttributes', \false), $this->getBooleanAttribute($document->documentElement, 'registerMockObjectsFromTestArgumentsRecursively', \false), $conflictBetweenPrinterClassAndTestdox);
  35913. }
  35914. private function getColors(\DOMDocument $document) : string
  35915. {
  35916. $colors = \PHPUnit\TextUI\DefaultResultPrinter::COLOR_DEFAULT;
  35917. if ($document->documentElement->hasAttribute('colors')) {
  35918. /* only allow boolean for compatibility with previous versions
  35919. 'always' only allowed from command line */
  35920. if ($this->getBoolean($document->documentElement->getAttribute('colors'), \false)) {
  35921. $colors = \PHPUnit\TextUI\DefaultResultPrinter::COLOR_AUTO;
  35922. } else {
  35923. $colors = \PHPUnit\TextUI\DefaultResultPrinter::COLOR_NEVER;
  35924. }
  35925. }
  35926. return $colors;
  35927. }
  35928. /**
  35929. * @return int|string
  35930. */
  35931. private function getColumns(\DOMDocument $document)
  35932. {
  35933. $columns = 80;
  35934. if ($document->documentElement->hasAttribute('columns')) {
  35935. $columns = (string) $document->documentElement->getAttribute('columns');
  35936. if ($columns !== 'max') {
  35937. $columns = $this->getInteger($columns, 80);
  35938. }
  35939. }
  35940. return $columns;
  35941. }
  35942. private function testSuite(string $filename, \DOMXPath $xpath) : \PHPUnit\TextUI\Configuration\TestSuiteCollection
  35943. {
  35944. $testSuites = [];
  35945. foreach ($this->getTestSuiteElements($xpath) as $element) {
  35946. $exclude = [];
  35947. foreach ($element->getElementsByTagName('exclude') as $excludeNode) {
  35948. $excludeFile = (string) $excludeNode->textContent;
  35949. if ($excludeFile) {
  35950. $exclude[] = new \PHPUnit\TextUI\Configuration\File($this->toAbsolutePath($filename, $excludeFile));
  35951. }
  35952. }
  35953. $directories = [];
  35954. foreach ($element->getElementsByTagName('directory') as $directoryNode) {
  35955. \assert($directoryNode instanceof \DOMElement);
  35956. $directory = (string) $directoryNode->textContent;
  35957. if (empty($directory)) {
  35958. continue;
  35959. }
  35960. $prefix = '';
  35961. if ($directoryNode->hasAttribute('prefix')) {
  35962. $prefix = (string) $directoryNode->getAttribute('prefix');
  35963. }
  35964. $suffix = 'Test.php';
  35965. if ($directoryNode->hasAttribute('suffix')) {
  35966. $suffix = (string) $directoryNode->getAttribute('suffix');
  35967. }
  35968. $phpVersion = \PHP_VERSION;
  35969. if ($directoryNode->hasAttribute('phpVersion')) {
  35970. $phpVersion = (string) $directoryNode->getAttribute('phpVersion');
  35971. }
  35972. $phpVersionOperator = new \PHPUnit\Util\VersionComparisonOperator('>=');
  35973. if ($directoryNode->hasAttribute('phpVersionOperator')) {
  35974. $phpVersionOperator = new \PHPUnit\Util\VersionComparisonOperator((string) $directoryNode->getAttribute('phpVersionOperator'));
  35975. }
  35976. $directories[] = new \PHPUnit\TextUI\Configuration\TestDirectory($this->toAbsolutePath($filename, $directory), $prefix, $suffix, $phpVersion, $phpVersionOperator);
  35977. }
  35978. $files = [];
  35979. foreach ($element->getElementsByTagName('file') as $fileNode) {
  35980. \assert($fileNode instanceof \DOMElement);
  35981. $file = (string) $fileNode->textContent;
  35982. if (empty($file)) {
  35983. continue;
  35984. }
  35985. $phpVersion = \PHP_VERSION;
  35986. if ($fileNode->hasAttribute('phpVersion')) {
  35987. $phpVersion = (string) $fileNode->getAttribute('phpVersion');
  35988. }
  35989. $phpVersionOperator = new \PHPUnit\Util\VersionComparisonOperator('>=');
  35990. if ($fileNode->hasAttribute('phpVersionOperator')) {
  35991. $phpVersionOperator = new \PHPUnit\Util\VersionComparisonOperator((string) $fileNode->getAttribute('phpVersionOperator'));
  35992. }
  35993. $files[] = new \PHPUnit\TextUI\Configuration\TestFile($this->toAbsolutePath($filename, $file), $phpVersion, $phpVersionOperator);
  35994. }
  35995. $testSuites[] = new \PHPUnit\TextUI\Configuration\TestSuite((string) $element->getAttribute('name'), \PHPUnit\TextUI\Configuration\TestDirectoryCollection::fromArray($directories), \PHPUnit\TextUI\Configuration\TestFileCollection::fromArray($files), \PHPUnit\TextUI\Configuration\FileCollection::fromArray($exclude));
  35996. }
  35997. return \PHPUnit\TextUI\Configuration\TestSuiteCollection::fromArray($testSuites);
  35998. }
  35999. /**
  36000. * @return \DOMElement[]
  36001. */
  36002. private function getTestSuiteElements(\DOMXPath $xpath) : array
  36003. {
  36004. /** @var \DOMElement[] $elements */
  36005. $elements = [];
  36006. $testSuiteNodes = $xpath->query('testsuites/testsuite');
  36007. if ($testSuiteNodes->length === 0) {
  36008. $testSuiteNodes = $xpath->query('testsuite');
  36009. }
  36010. if ($testSuiteNodes->length === 1) {
  36011. $element = $testSuiteNodes->item(0);
  36012. \assert($element instanceof \DOMElement);
  36013. $elements[] = $element;
  36014. } else {
  36015. foreach ($testSuiteNodes as $testSuiteNode) {
  36016. \assert($testSuiteNode instanceof \DOMElement);
  36017. $elements[] = $testSuiteNode;
  36018. }
  36019. }
  36020. return $elements;
  36021. }
  36022. }
  36023. <?php
  36024. declare (strict_types=1);
  36025. /*
  36026. * This file is part of PHPUnit.
  36027. *
  36028. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  36029. *
  36030. * For the full copyright and license information, please view the LICENSE
  36031. * file that was distributed with this source code.
  36032. */
  36033. namespace PHPUnit\TextUI\Configuration;
  36034. /**
  36035. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  36036. * @psalm-immutable
  36037. */
  36038. final class FilterDirectory
  36039. {
  36040. /**
  36041. * @var string
  36042. */
  36043. private $path;
  36044. /**
  36045. * @var string
  36046. */
  36047. private $prefix;
  36048. /**
  36049. * @var string
  36050. */
  36051. private $suffix;
  36052. /**
  36053. * @var string
  36054. */
  36055. private $group;
  36056. public function __construct(string $path, string $prefix, string $suffix, string $group)
  36057. {
  36058. $this->path = $path;
  36059. $this->prefix = $prefix;
  36060. $this->suffix = $suffix;
  36061. $this->group = $group;
  36062. }
  36063. public function path() : string
  36064. {
  36065. return $this->path;
  36066. }
  36067. public function prefix() : string
  36068. {
  36069. return $this->prefix;
  36070. }
  36071. public function suffix() : string
  36072. {
  36073. return $this->suffix;
  36074. }
  36075. public function group() : string
  36076. {
  36077. return $this->group;
  36078. }
  36079. }
  36080. <?php
  36081. declare (strict_types=1);
  36082. /*
  36083. * This file is part of PHPUnit.
  36084. *
  36085. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  36086. *
  36087. * For the full copyright and license information, please view the LICENSE
  36088. * file that was distributed with this source code.
  36089. */
  36090. namespace PHPUnit\TextUI\Configuration;
  36091. /**
  36092. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  36093. */
  36094. final class FilterFileCollectionIterator implements \Countable, \Iterator
  36095. {
  36096. /**
  36097. * @var FilterFile[]
  36098. */
  36099. private $files;
  36100. /**
  36101. * @var int
  36102. */
  36103. private $position;
  36104. public function __construct(\PHPUnit\TextUI\Configuration\FilterFileCollection $files)
  36105. {
  36106. $this->files = $files->asArray();
  36107. }
  36108. public function count() : int
  36109. {
  36110. return \iterator_count($this);
  36111. }
  36112. public function rewind() : void
  36113. {
  36114. $this->position = 0;
  36115. }
  36116. public function valid() : bool
  36117. {
  36118. return $this->position < \count($this->files);
  36119. }
  36120. public function key() : int
  36121. {
  36122. return $this->position;
  36123. }
  36124. public function current() : \PHPUnit\TextUI\Configuration\FilterFile
  36125. {
  36126. return $this->files[$this->position];
  36127. }
  36128. public function next() : void
  36129. {
  36130. $this->position++;
  36131. }
  36132. }
  36133. <?php
  36134. declare (strict_types=1);
  36135. /*
  36136. * This file is part of PHPUnit.
  36137. *
  36138. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  36139. *
  36140. * For the full copyright and license information, please view the LICENSE
  36141. * file that was distributed with this source code.
  36142. */
  36143. namespace PHPUnit\TextUI\Configuration;
  36144. /**
  36145. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  36146. */
  36147. final class FilterDirectoryCollectionIterator implements \Countable, \Iterator
  36148. {
  36149. /**
  36150. * @var FilterDirectory[]
  36151. */
  36152. private $directories;
  36153. /**
  36154. * @var int
  36155. */
  36156. private $position;
  36157. public function __construct(\PHPUnit\TextUI\Configuration\FilterDirectoryCollection $directories)
  36158. {
  36159. $this->directories = $directories->asArray();
  36160. }
  36161. public function count() : int
  36162. {
  36163. return \iterator_count($this);
  36164. }
  36165. public function rewind() : void
  36166. {
  36167. $this->position = 0;
  36168. }
  36169. public function valid() : bool
  36170. {
  36171. return $this->position < \count($this->directories);
  36172. }
  36173. public function key() : int
  36174. {
  36175. return $this->position;
  36176. }
  36177. public function current() : \PHPUnit\TextUI\Configuration\FilterDirectory
  36178. {
  36179. return $this->directories[$this->position];
  36180. }
  36181. public function next() : void
  36182. {
  36183. $this->position++;
  36184. }
  36185. }
  36186. <?php
  36187. declare (strict_types=1);
  36188. /*
  36189. * This file is part of PHPUnit.
  36190. *
  36191. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  36192. *
  36193. * For the full copyright and license information, please view the LICENSE
  36194. * file that was distributed with this source code.
  36195. */
  36196. namespace PHPUnit\TextUI\Configuration;
  36197. /**
  36198. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  36199. * @psalm-immutable
  36200. */
  36201. final class Filter
  36202. {
  36203. /**
  36204. * @var FilterDirectoryCollection
  36205. */
  36206. private $directories;
  36207. /**
  36208. * @var FilterFileCollection
  36209. */
  36210. private $files;
  36211. /**
  36212. * @var FilterDirectoryCollection
  36213. */
  36214. private $excludeDirectories;
  36215. /**
  36216. * @var FilterFileCollection
  36217. */
  36218. private $excludeFiles;
  36219. /**
  36220. * @var bool
  36221. */
  36222. private $addUncoveredFilesFromWhitelist;
  36223. /**
  36224. * @var bool
  36225. */
  36226. private $processUncoveredFilesFromWhitelist;
  36227. public function __construct(\PHPUnit\TextUI\Configuration\FilterDirectoryCollection $directories, \PHPUnit\TextUI\Configuration\FilterFileCollection $files, \PHPUnit\TextUI\Configuration\FilterDirectoryCollection $excludeDirectories, \PHPUnit\TextUI\Configuration\FilterFileCollection $excludeFiles, bool $addUncoveredFilesFromWhitelist, bool $processUncoveredFilesFromWhitelist)
  36228. {
  36229. $this->directories = $directories;
  36230. $this->files = $files;
  36231. $this->excludeDirectories = $excludeDirectories;
  36232. $this->excludeFiles = $excludeFiles;
  36233. $this->addUncoveredFilesFromWhitelist = $addUncoveredFilesFromWhitelist;
  36234. $this->processUncoveredFilesFromWhitelist = $processUncoveredFilesFromWhitelist;
  36235. }
  36236. public function hasNonEmptyWhitelist() : bool
  36237. {
  36238. return \count($this->directories) > 0 || \count($this->files) > 0;
  36239. }
  36240. public function directories() : \PHPUnit\TextUI\Configuration\FilterDirectoryCollection
  36241. {
  36242. return $this->directories;
  36243. }
  36244. public function files() : \PHPUnit\TextUI\Configuration\FilterFileCollection
  36245. {
  36246. return $this->files;
  36247. }
  36248. public function excludeDirectories() : \PHPUnit\TextUI\Configuration\FilterDirectoryCollection
  36249. {
  36250. return $this->excludeDirectories;
  36251. }
  36252. public function excludeFiles() : \PHPUnit\TextUI\Configuration\FilterFileCollection
  36253. {
  36254. return $this->excludeFiles;
  36255. }
  36256. public function addUncoveredFilesFromWhitelist() : bool
  36257. {
  36258. return $this->addUncoveredFilesFromWhitelist;
  36259. }
  36260. public function processUncoveredFilesFromWhitelist() : bool
  36261. {
  36262. return $this->processUncoveredFilesFromWhitelist;
  36263. }
  36264. }
  36265. <?php
  36266. declare (strict_types=1);
  36267. /*
  36268. * This file is part of PHPUnit.
  36269. *
  36270. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  36271. *
  36272. * For the full copyright and license information, please view the LICENSE
  36273. * file that was distributed with this source code.
  36274. */
  36275. namespace PHPUnit\TextUI\Configuration;
  36276. /**
  36277. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  36278. * @psalm-immutable
  36279. */
  36280. final class FilterFile
  36281. {
  36282. /**
  36283. * @var string
  36284. */
  36285. private $path;
  36286. public function __construct(string $path)
  36287. {
  36288. $this->path = $path;
  36289. }
  36290. public function path() : string
  36291. {
  36292. return $this->path;
  36293. }
  36294. }
  36295. <?php
  36296. declare (strict_types=1);
  36297. /*
  36298. * This file is part of PHPUnit.
  36299. *
  36300. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  36301. *
  36302. * For the full copyright and license information, please view the LICENSE
  36303. * file that was distributed with this source code.
  36304. */
  36305. namespace PHPUnit\TextUI\Configuration;
  36306. /**
  36307. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  36308. * @psalm-immutable
  36309. */
  36310. final class FilterDirectoryCollection implements \Countable, \IteratorAggregate
  36311. {
  36312. /**
  36313. * @var FilterDirectory[]
  36314. */
  36315. private $directories;
  36316. /**
  36317. * @param FilterDirectory[] $directories
  36318. */
  36319. public static function fromArray(array $directories) : self
  36320. {
  36321. return new self(...$directories);
  36322. }
  36323. private function __construct(\PHPUnit\TextUI\Configuration\FilterDirectory ...$directories)
  36324. {
  36325. $this->directories = $directories;
  36326. }
  36327. /**
  36328. * @return FilterDirectory[]
  36329. */
  36330. public function asArray() : array
  36331. {
  36332. return $this->directories;
  36333. }
  36334. public function count() : int
  36335. {
  36336. return \count($this->directories);
  36337. }
  36338. public function getIterator() : \PHPUnit\TextUI\Configuration\FilterDirectoryCollectionIterator
  36339. {
  36340. return new \PHPUnit\TextUI\Configuration\FilterDirectoryCollectionIterator($this);
  36341. }
  36342. }
  36343. <?php
  36344. declare (strict_types=1);
  36345. /*
  36346. * This file is part of PHPUnit.
  36347. *
  36348. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  36349. *
  36350. * For the full copyright and license information, please view the LICENSE
  36351. * file that was distributed with this source code.
  36352. */
  36353. namespace PHPUnit\TextUI\Configuration;
  36354. /**
  36355. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  36356. * @psalm-immutable
  36357. */
  36358. final class FilterFileCollection implements \Countable, \IteratorAggregate
  36359. {
  36360. /**
  36361. * @var FilterFile[]
  36362. */
  36363. private $files;
  36364. /**
  36365. * @param FilterFile[] $files
  36366. */
  36367. public static function fromArray(array $files) : self
  36368. {
  36369. return new self(...$files);
  36370. }
  36371. private function __construct(\PHPUnit\TextUI\Configuration\FilterFile ...$files)
  36372. {
  36373. $this->files = $files;
  36374. }
  36375. /**
  36376. * @return FilterFile[]
  36377. */
  36378. public function asArray() : array
  36379. {
  36380. return $this->files;
  36381. }
  36382. public function count() : int
  36383. {
  36384. return \count($this->files);
  36385. }
  36386. public function getIterator() : \PHPUnit\TextUI\Configuration\FilterFileCollectionIterator
  36387. {
  36388. return new \PHPUnit\TextUI\Configuration\FilterFileCollectionIterator($this);
  36389. }
  36390. }
  36391. <?php
  36392. declare (strict_types=1);
  36393. /*
  36394. * This file is part of PHPUnit.
  36395. *
  36396. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  36397. *
  36398. * For the full copyright and license information, please view the LICENSE
  36399. * file that was distributed with this source code.
  36400. */
  36401. namespace PHPUnit\TextUI\Configuration;
  36402. use PHPUnit\TextUI\Configuration\Logging\Logging;
  36403. /**
  36404. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  36405. * @psalm-immutable
  36406. */
  36407. final class Configuration
  36408. {
  36409. /**
  36410. * @var string
  36411. */
  36412. private $filename;
  36413. /**
  36414. * @var array
  36415. * @psalm-var array<int,array<int,string>>
  36416. */
  36417. private $validationErrors = [];
  36418. /**
  36419. * @var ExtensionCollection
  36420. */
  36421. private $extensions;
  36422. /**
  36423. * @var Filter
  36424. */
  36425. private $filter;
  36426. /**
  36427. * @var Groups
  36428. */
  36429. private $groups;
  36430. /**
  36431. * @var Groups
  36432. */
  36433. private $testdoxGroups;
  36434. /**
  36435. * @var ExtensionCollection
  36436. */
  36437. private $listeners;
  36438. /**
  36439. * @var Logging
  36440. */
  36441. private $logging;
  36442. /**
  36443. * @var Php
  36444. */
  36445. private $php;
  36446. /**
  36447. * @var PHPUnit
  36448. */
  36449. private $phpunit;
  36450. /**
  36451. * @var TestSuiteCollection
  36452. */
  36453. private $testSuite;
  36454. /**
  36455. * @psalm-param array<int,array<int,string>> $validationErrors
  36456. */
  36457. public function __construct(string $filename, array $validationErrors, \PHPUnit\TextUI\Configuration\ExtensionCollection $extensions, \PHPUnit\TextUI\Configuration\Filter $filter, \PHPUnit\TextUI\Configuration\Groups $groups, \PHPUnit\TextUI\Configuration\Groups $testdoxGroups, \PHPUnit\TextUI\Configuration\ExtensionCollection $listeners, \PHPUnit\TextUI\Configuration\Logging\Logging $logging, \PHPUnit\TextUI\Configuration\Php $php, \PHPUnit\TextUI\Configuration\PHPUnit $phpunit, \PHPUnit\TextUI\Configuration\TestSuiteCollection $testSuite)
  36458. {
  36459. $this->filename = $filename;
  36460. $this->validationErrors = $validationErrors;
  36461. $this->extensions = $extensions;
  36462. $this->filter = $filter;
  36463. $this->groups = $groups;
  36464. $this->testdoxGroups = $testdoxGroups;
  36465. $this->listeners = $listeners;
  36466. $this->logging = $logging;
  36467. $this->php = $php;
  36468. $this->phpunit = $phpunit;
  36469. $this->testSuite = $testSuite;
  36470. }
  36471. public function filename() : string
  36472. {
  36473. return $this->filename;
  36474. }
  36475. public function hasValidationErrors() : bool
  36476. {
  36477. return \count($this->validationErrors) > 0;
  36478. }
  36479. public function validationErrors() : array
  36480. {
  36481. return $this->validationErrors;
  36482. }
  36483. public function extensions() : \PHPUnit\TextUI\Configuration\ExtensionCollection
  36484. {
  36485. return $this->extensions;
  36486. }
  36487. public function filter() : \PHPUnit\TextUI\Configuration\Filter
  36488. {
  36489. return $this->filter;
  36490. }
  36491. public function groups() : \PHPUnit\TextUI\Configuration\Groups
  36492. {
  36493. return $this->groups;
  36494. }
  36495. public function testdoxGroups() : \PHPUnit\TextUI\Configuration\Groups
  36496. {
  36497. return $this->testdoxGroups;
  36498. }
  36499. public function listeners() : \PHPUnit\TextUI\Configuration\ExtensionCollection
  36500. {
  36501. return $this->listeners;
  36502. }
  36503. public function logging() : \PHPUnit\TextUI\Configuration\Logging\Logging
  36504. {
  36505. return $this->logging;
  36506. }
  36507. public function php() : \PHPUnit\TextUI\Configuration\Php
  36508. {
  36509. return $this->php;
  36510. }
  36511. public function phpunit() : \PHPUnit\TextUI\Configuration\PHPUnit
  36512. {
  36513. return $this->phpunit;
  36514. }
  36515. public function testSuite() : \PHPUnit\TextUI\Configuration\TestSuiteCollection
  36516. {
  36517. return $this->testSuite;
  36518. }
  36519. }
  36520. <?php
  36521. declare (strict_types=1);
  36522. /*
  36523. * This file is part of PHPUnit.
  36524. *
  36525. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  36526. *
  36527. * For the full copyright and license information, please view the LICENSE
  36528. * file that was distributed with this source code.
  36529. */
  36530. namespace PHPUnit\TextUI\Configuration;
  36531. /**
  36532. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  36533. * @psalm-immutable
  36534. */
  36535. final class PHPUnit
  36536. {
  36537. /**
  36538. * @var bool
  36539. */
  36540. private $cacheResult;
  36541. /**
  36542. * @var ?string
  36543. */
  36544. private $cacheResultFile;
  36545. /**
  36546. * @var bool
  36547. */
  36548. private $cacheTokens;
  36549. /**
  36550. * @var int|string
  36551. */
  36552. private $columns;
  36553. /**
  36554. * @var string
  36555. */
  36556. private $colors;
  36557. /**
  36558. * @var bool
  36559. */
  36560. private $stderr;
  36561. /**
  36562. * @var bool
  36563. */
  36564. private $noInteraction;
  36565. /**
  36566. * @var bool
  36567. */
  36568. private $verbose;
  36569. /**
  36570. * @var bool
  36571. */
  36572. private $reverseDefectList;
  36573. /**
  36574. * @var bool
  36575. */
  36576. private $convertDeprecationsToExceptions;
  36577. /**
  36578. * @var bool
  36579. */
  36580. private $convertErrorsToExceptions;
  36581. /**
  36582. * @var bool
  36583. */
  36584. private $convertNoticesToExceptions;
  36585. /**
  36586. * @var bool
  36587. */
  36588. private $convertWarningsToExceptions;
  36589. /**
  36590. * @var bool
  36591. */
  36592. private $forceCoversAnnotation;
  36593. /**
  36594. * @var bool
  36595. */
  36596. private $ignoreDeprecatedCodeUnitsFromCodeCoverage;
  36597. /**
  36598. * @var bool
  36599. */
  36600. private $disableCodeCoverageIgnore;
  36601. /**
  36602. * @var ?string
  36603. */
  36604. private $bootstrap;
  36605. /**
  36606. * @var bool
  36607. */
  36608. private $processIsolation;
  36609. /**
  36610. * @var bool
  36611. */
  36612. private $failOnIncomplete;
  36613. /**
  36614. * @var bool
  36615. */
  36616. private $failOnRisky;
  36617. /**
  36618. * @var bool
  36619. */
  36620. private $failOnSkipped;
  36621. /**
  36622. * @var bool
  36623. */
  36624. private $failOnWarning;
  36625. /**
  36626. * @var bool
  36627. */
  36628. private $stopOnDefect;
  36629. /**
  36630. * @var bool
  36631. */
  36632. private $stopOnError;
  36633. /**
  36634. * @var bool
  36635. */
  36636. private $stopOnFailure;
  36637. /**
  36638. * @var bool
  36639. */
  36640. private $stopOnWarning;
  36641. /**
  36642. * @var bool
  36643. */
  36644. private $stopOnIncomplete;
  36645. /**
  36646. * @var bool
  36647. */
  36648. private $stopOnRisky;
  36649. /**
  36650. * @var bool
  36651. */
  36652. private $stopOnSkipped;
  36653. /**
  36654. * @var ?string
  36655. */
  36656. private $extensionsDirectory;
  36657. /**
  36658. * @var ?string
  36659. *
  36660. * @deprecated see https://github.com/sebastianbergmann/phpunit/issues/4039
  36661. */
  36662. private $testSuiteLoaderClass;
  36663. /**
  36664. * @var ?string
  36665. *
  36666. * @deprecated see https://github.com/sebastianbergmann/phpunit/issues/4039
  36667. */
  36668. private $testSuiteLoaderFile;
  36669. /**
  36670. * @var ?string
  36671. */
  36672. private $printerClass;
  36673. /**
  36674. * @var ?string
  36675. */
  36676. private $printerFile;
  36677. /**
  36678. * @var bool
  36679. */
  36680. private $beStrictAboutChangesToGlobalState;
  36681. /**
  36682. * @var bool
  36683. */
  36684. private $beStrictAboutOutputDuringTests;
  36685. /**
  36686. * @var bool
  36687. */
  36688. private $beStrictAboutResourceUsageDuringSmallTests;
  36689. /**
  36690. * @var bool
  36691. */
  36692. private $beStrictAboutTestsThatDoNotTestAnything;
  36693. /**
  36694. * @var bool
  36695. */
  36696. private $beStrictAboutTodoAnnotatedTests;
  36697. /**
  36698. * @var bool
  36699. */
  36700. private $beStrictAboutCoversAnnotation;
  36701. /**
  36702. * @var bool
  36703. */
  36704. private $enforceTimeLimit;
  36705. /**
  36706. * @var int
  36707. */
  36708. private $defaultTimeLimit;
  36709. /**
  36710. * @var int
  36711. */
  36712. private $timeoutForSmallTests;
  36713. /**
  36714. * @var int
  36715. */
  36716. private $timeoutForMediumTests;
  36717. /**
  36718. * @var int
  36719. */
  36720. private $timeoutForLargeTests;
  36721. /**
  36722. * @var ?string
  36723. */
  36724. private $defaultTestSuite;
  36725. /**
  36726. * @var int
  36727. */
  36728. private $executionOrder;
  36729. /**
  36730. * @var bool
  36731. */
  36732. private $resolveDependencies;
  36733. /**
  36734. * @var bool
  36735. */
  36736. private $defectsFirst;
  36737. /**
  36738. * @var bool
  36739. */
  36740. private $backupGlobals;
  36741. /**
  36742. * @var bool
  36743. */
  36744. private $backupStaticAttributes;
  36745. /**
  36746. * @var bool
  36747. */
  36748. private $registerMockObjectsFromTestArgumentsRecursively;
  36749. /**
  36750. * @var bool
  36751. */
  36752. private $conflictBetweenPrinterClassAndTestdox;
  36753. public function __construct(bool $cacheResult, ?string $cacheResultFile, bool $cacheTokens, $columns, string $colors, bool $stderr, bool $noInteraction, bool $verbose, bool $reverseDefectList, bool $convertDeprecationsToExceptions, bool $convertErrorsToExceptions, bool $convertNoticesToExceptions, bool $convertWarningsToExceptions, bool $forceCoversAnnotation, bool $ignoreDeprecatedCodeUnitsFromCodeCoverage, bool $disableCodeCoverageIgnore, ?string $bootstrap, bool $processIsolation, bool $failOnIncomplete, bool $failOnRisky, bool $failOnSkipped, bool $failOnWarning, bool $stopOnDefect, bool $stopOnError, bool $stopOnFailure, bool $stopOnWarning, bool $stopOnIncomplete, bool $stopOnRisky, bool $stopOnSkipped, ?string $extensionsDirectory, ?string $testSuiteLoaderClass, ?string $testSuiteLoaderFile, ?string $printerClass, ?string $printerFile, bool $beStrictAboutChangesToGlobalState, bool $beStrictAboutOutputDuringTests, bool $beStrictAboutResourceUsageDuringSmallTests, bool $beStrictAboutTestsThatDoNotTestAnything, bool $beStrictAboutTodoAnnotatedTests, bool $beStrictAboutCoversAnnotation, bool $enforceTimeLimit, int $defaultTimeLimit, int $timeoutForSmallTests, int $timeoutForMediumTests, int $timeoutForLargeTests, ?string $defaultTestSuite, int $executionOrder, bool $resolveDependencies, bool $defectsFirst, bool $backupGlobals, bool $backupStaticAttributes, bool $registerMockObjectsFromTestArgumentsRecursively, bool $conflictBetweenPrinterClassAndTestdox)
  36754. {
  36755. $this->cacheResult = $cacheResult;
  36756. $this->cacheResultFile = $cacheResultFile;
  36757. $this->cacheTokens = $cacheTokens;
  36758. $this->columns = $columns;
  36759. $this->colors = $colors;
  36760. $this->stderr = $stderr;
  36761. $this->noInteraction = $noInteraction;
  36762. $this->verbose = $verbose;
  36763. $this->reverseDefectList = $reverseDefectList;
  36764. $this->convertDeprecationsToExceptions = $convertDeprecationsToExceptions;
  36765. $this->convertErrorsToExceptions = $convertErrorsToExceptions;
  36766. $this->convertNoticesToExceptions = $convertNoticesToExceptions;
  36767. $this->convertWarningsToExceptions = $convertWarningsToExceptions;
  36768. $this->forceCoversAnnotation = $forceCoversAnnotation;
  36769. $this->ignoreDeprecatedCodeUnitsFromCodeCoverage = $ignoreDeprecatedCodeUnitsFromCodeCoverage;
  36770. $this->disableCodeCoverageIgnore = $disableCodeCoverageIgnore;
  36771. $this->bootstrap = $bootstrap;
  36772. $this->processIsolation = $processIsolation;
  36773. $this->failOnIncomplete = $failOnIncomplete;
  36774. $this->failOnRisky = $failOnRisky;
  36775. $this->failOnSkipped = $failOnSkipped;
  36776. $this->failOnWarning = $failOnWarning;
  36777. $this->stopOnDefect = $stopOnDefect;
  36778. $this->stopOnError = $stopOnError;
  36779. $this->stopOnFailure = $stopOnFailure;
  36780. $this->stopOnWarning = $stopOnWarning;
  36781. $this->stopOnIncomplete = $stopOnIncomplete;
  36782. $this->stopOnRisky = $stopOnRisky;
  36783. $this->stopOnSkipped = $stopOnSkipped;
  36784. $this->extensionsDirectory = $extensionsDirectory;
  36785. $this->testSuiteLoaderClass = $testSuiteLoaderClass;
  36786. $this->testSuiteLoaderFile = $testSuiteLoaderFile;
  36787. $this->printerClass = $printerClass;
  36788. $this->printerFile = $printerFile;
  36789. $this->beStrictAboutChangesToGlobalState = $beStrictAboutChangesToGlobalState;
  36790. $this->beStrictAboutOutputDuringTests = $beStrictAboutOutputDuringTests;
  36791. $this->beStrictAboutResourceUsageDuringSmallTests = $beStrictAboutResourceUsageDuringSmallTests;
  36792. $this->beStrictAboutTestsThatDoNotTestAnything = $beStrictAboutTestsThatDoNotTestAnything;
  36793. $this->beStrictAboutTodoAnnotatedTests = $beStrictAboutTodoAnnotatedTests;
  36794. $this->beStrictAboutCoversAnnotation = $beStrictAboutCoversAnnotation;
  36795. $this->enforceTimeLimit = $enforceTimeLimit;
  36796. $this->defaultTimeLimit = $defaultTimeLimit;
  36797. $this->timeoutForSmallTests = $timeoutForSmallTests;
  36798. $this->timeoutForMediumTests = $timeoutForMediumTests;
  36799. $this->timeoutForLargeTests = $timeoutForLargeTests;
  36800. $this->defaultTestSuite = $defaultTestSuite;
  36801. $this->executionOrder = $executionOrder;
  36802. $this->resolveDependencies = $resolveDependencies;
  36803. $this->defectsFirst = $defectsFirst;
  36804. $this->backupGlobals = $backupGlobals;
  36805. $this->backupStaticAttributes = $backupStaticAttributes;
  36806. $this->registerMockObjectsFromTestArgumentsRecursively = $registerMockObjectsFromTestArgumentsRecursively;
  36807. $this->conflictBetweenPrinterClassAndTestdox = $conflictBetweenPrinterClassAndTestdox;
  36808. }
  36809. public function cacheResult() : bool
  36810. {
  36811. return $this->cacheResult;
  36812. }
  36813. public function hasCacheResultFile() : bool
  36814. {
  36815. return $this->cacheResultFile !== null;
  36816. }
  36817. /**
  36818. * @throws Exception
  36819. */
  36820. public function cacheResultFile() : string
  36821. {
  36822. if (!$this->hasCacheResultFile()) {
  36823. throw new \PHPUnit\TextUI\Configuration\Exception('Cache result file is not configured');
  36824. }
  36825. return (string) $this->cacheResultFile;
  36826. }
  36827. public function cacheTokens() : bool
  36828. {
  36829. return $this->cacheTokens;
  36830. }
  36831. public function columns()
  36832. {
  36833. return $this->columns;
  36834. }
  36835. public function colors() : string
  36836. {
  36837. return $this->colors;
  36838. }
  36839. public function stderr() : bool
  36840. {
  36841. return $this->stderr;
  36842. }
  36843. public function noInteraction() : bool
  36844. {
  36845. return $this->noInteraction;
  36846. }
  36847. public function verbose() : bool
  36848. {
  36849. return $this->verbose;
  36850. }
  36851. public function reverseDefectList() : bool
  36852. {
  36853. return $this->reverseDefectList;
  36854. }
  36855. public function convertDeprecationsToExceptions() : bool
  36856. {
  36857. return $this->convertDeprecationsToExceptions;
  36858. }
  36859. public function convertErrorsToExceptions() : bool
  36860. {
  36861. return $this->convertErrorsToExceptions;
  36862. }
  36863. public function convertNoticesToExceptions() : bool
  36864. {
  36865. return $this->convertNoticesToExceptions;
  36866. }
  36867. public function convertWarningsToExceptions() : bool
  36868. {
  36869. return $this->convertWarningsToExceptions;
  36870. }
  36871. public function forceCoversAnnotation() : bool
  36872. {
  36873. return $this->forceCoversAnnotation;
  36874. }
  36875. public function ignoreDeprecatedCodeUnitsFromCodeCoverage() : bool
  36876. {
  36877. return $this->ignoreDeprecatedCodeUnitsFromCodeCoverage;
  36878. }
  36879. public function disableCodeCoverageIgnore() : bool
  36880. {
  36881. return $this->disableCodeCoverageIgnore;
  36882. }
  36883. public function hasBootstrap() : bool
  36884. {
  36885. return $this->bootstrap !== null;
  36886. }
  36887. /**
  36888. * @throws Exception
  36889. */
  36890. public function bootstrap() : string
  36891. {
  36892. if (!$this->hasBootstrap()) {
  36893. throw new \PHPUnit\TextUI\Configuration\Exception('Bootstrap script is not configured');
  36894. }
  36895. return (string) $this->bootstrap;
  36896. }
  36897. public function processIsolation() : bool
  36898. {
  36899. return $this->processIsolation;
  36900. }
  36901. public function failOnIncomplete() : bool
  36902. {
  36903. return $this->failOnIncomplete;
  36904. }
  36905. public function failOnRisky() : bool
  36906. {
  36907. return $this->failOnRisky;
  36908. }
  36909. public function failOnSkipped() : bool
  36910. {
  36911. return $this->failOnSkipped;
  36912. }
  36913. public function failOnWarning() : bool
  36914. {
  36915. return $this->failOnWarning;
  36916. }
  36917. public function stopOnDefect() : bool
  36918. {
  36919. return $this->stopOnDefect;
  36920. }
  36921. public function stopOnError() : bool
  36922. {
  36923. return $this->stopOnError;
  36924. }
  36925. public function stopOnFailure() : bool
  36926. {
  36927. return $this->stopOnFailure;
  36928. }
  36929. public function stopOnWarning() : bool
  36930. {
  36931. return $this->stopOnWarning;
  36932. }
  36933. public function stopOnIncomplete() : bool
  36934. {
  36935. return $this->stopOnIncomplete;
  36936. }
  36937. public function stopOnRisky() : bool
  36938. {
  36939. return $this->stopOnRisky;
  36940. }
  36941. public function stopOnSkipped() : bool
  36942. {
  36943. return $this->stopOnSkipped;
  36944. }
  36945. public function hasExtensionsDirectory() : bool
  36946. {
  36947. return $this->extensionsDirectory !== null;
  36948. }
  36949. /**
  36950. * @throws Exception
  36951. */
  36952. public function extensionsDirectory() : string
  36953. {
  36954. if (!$this->hasExtensionsDirectory()) {
  36955. throw new \PHPUnit\TextUI\Configuration\Exception('Extensions directory is not configured');
  36956. }
  36957. return (string) $this->extensionsDirectory;
  36958. }
  36959. /**
  36960. * @deprecated see https://github.com/sebastianbergmann/phpunit/issues/4039
  36961. */
  36962. public function hasTestSuiteLoaderClass() : bool
  36963. {
  36964. return $this->testSuiteLoaderClass !== null;
  36965. }
  36966. /**
  36967. * @throws Exception
  36968. *
  36969. * @deprecated see https://github.com/sebastianbergmann/phpunit/issues/4039
  36970. */
  36971. public function testSuiteLoaderClass() : string
  36972. {
  36973. if (!$this->hasTestSuiteLoaderClass()) {
  36974. throw new \PHPUnit\TextUI\Configuration\Exception('TestSuiteLoader class is not configured');
  36975. }
  36976. return (string) $this->testSuiteLoaderClass;
  36977. }
  36978. /**
  36979. * @deprecated see https://github.com/sebastianbergmann/phpunit/issues/4039
  36980. */
  36981. public function hasTestSuiteLoaderFile() : bool
  36982. {
  36983. return $this->testSuiteLoaderFile !== null;
  36984. }
  36985. /**
  36986. * @throws Exception
  36987. *
  36988. * @deprecated see https://github.com/sebastianbergmann/phpunit/issues/4039
  36989. */
  36990. public function testSuiteLoaderFile() : string
  36991. {
  36992. if (!$this->hasTestSuiteLoaderFile()) {
  36993. throw new \PHPUnit\TextUI\Configuration\Exception('TestSuiteLoader sourcecode file is not configured');
  36994. }
  36995. return (string) $this->testSuiteLoaderFile;
  36996. }
  36997. public function hasPrinterClass() : bool
  36998. {
  36999. return $this->printerClass !== null;
  37000. }
  37001. /**
  37002. * @throws Exception
  37003. */
  37004. public function printerClass() : string
  37005. {
  37006. if (!$this->hasPrinterClass()) {
  37007. throw new \PHPUnit\TextUI\Configuration\Exception('ResultPrinter class is not configured');
  37008. }
  37009. return (string) $this->printerClass;
  37010. }
  37011. public function hasPrinterFile() : bool
  37012. {
  37013. return $this->printerFile !== null;
  37014. }
  37015. /**
  37016. * @throws Exception
  37017. */
  37018. public function printerFile() : string
  37019. {
  37020. if (!$this->hasPrinterFile()) {
  37021. throw new \PHPUnit\TextUI\Configuration\Exception('ResultPrinter sourcecode file is not configured');
  37022. }
  37023. return (string) $this->printerFile;
  37024. }
  37025. public function beStrictAboutChangesToGlobalState() : bool
  37026. {
  37027. return $this->beStrictAboutChangesToGlobalState;
  37028. }
  37029. public function beStrictAboutOutputDuringTests() : bool
  37030. {
  37031. return $this->beStrictAboutOutputDuringTests;
  37032. }
  37033. public function beStrictAboutResourceUsageDuringSmallTests() : bool
  37034. {
  37035. return $this->beStrictAboutResourceUsageDuringSmallTests;
  37036. }
  37037. public function beStrictAboutTestsThatDoNotTestAnything() : bool
  37038. {
  37039. return $this->beStrictAboutTestsThatDoNotTestAnything;
  37040. }
  37041. public function beStrictAboutTodoAnnotatedTests() : bool
  37042. {
  37043. return $this->beStrictAboutTodoAnnotatedTests;
  37044. }
  37045. public function beStrictAboutCoversAnnotation() : bool
  37046. {
  37047. return $this->beStrictAboutCoversAnnotation;
  37048. }
  37049. public function enforceTimeLimit() : bool
  37050. {
  37051. return $this->enforceTimeLimit;
  37052. }
  37053. public function defaultTimeLimit() : int
  37054. {
  37055. return $this->defaultTimeLimit;
  37056. }
  37057. public function timeoutForSmallTests() : int
  37058. {
  37059. return $this->timeoutForSmallTests;
  37060. }
  37061. public function timeoutForMediumTests() : int
  37062. {
  37063. return $this->timeoutForMediumTests;
  37064. }
  37065. public function timeoutForLargeTests() : int
  37066. {
  37067. return $this->timeoutForLargeTests;
  37068. }
  37069. public function hasDefaultTestSuite() : bool
  37070. {
  37071. return $this->defaultTestSuite !== null;
  37072. }
  37073. /**
  37074. * @throws Exception
  37075. */
  37076. public function defaultTestSuite() : string
  37077. {
  37078. if (!$this->hasDefaultTestSuite()) {
  37079. throw new \PHPUnit\TextUI\Configuration\Exception('Default test suite is not configured');
  37080. }
  37081. return (string) $this->defaultTestSuite;
  37082. }
  37083. public function executionOrder() : int
  37084. {
  37085. return $this->executionOrder;
  37086. }
  37087. public function resolveDependencies() : bool
  37088. {
  37089. return $this->resolveDependencies;
  37090. }
  37091. public function defectsFirst() : bool
  37092. {
  37093. return $this->defectsFirst;
  37094. }
  37095. public function backupGlobals() : bool
  37096. {
  37097. return $this->backupGlobals;
  37098. }
  37099. public function backupStaticAttributes() : bool
  37100. {
  37101. return $this->backupStaticAttributes;
  37102. }
  37103. public function registerMockObjectsFromTestArgumentsRecursively() : bool
  37104. {
  37105. return $this->registerMockObjectsFromTestArgumentsRecursively;
  37106. }
  37107. public function conflictBetweenPrinterClassAndTestdox() : bool
  37108. {
  37109. return $this->conflictBetweenPrinterClassAndTestdox;
  37110. }
  37111. }
  37112. <?php
  37113. declare (strict_types=1);
  37114. /*
  37115. * This file is part of PHPUnit.
  37116. *
  37117. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  37118. *
  37119. * For the full copyright and license information, please view the LICENSE
  37120. * file that was distributed with this source code.
  37121. */
  37122. namespace PHPUnit\TextUI\Configuration;
  37123. use PHPUnit\Framework\Exception;
  37124. use PHPUnit\Framework\TestListener;
  37125. use PHPUnit\Runner\Hook;
  37126. /**
  37127. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  37128. */
  37129. final class ExtensionHandler
  37130. {
  37131. public function createHookInstance(\PHPUnit\TextUI\Configuration\Extension $extension) : \PHPUnit\Runner\Hook
  37132. {
  37133. $object = $this->createInstance($extension);
  37134. if (!$object instanceof \PHPUnit\Runner\Hook) {
  37135. throw new \PHPUnit\Framework\Exception(\sprintf('Class "%s" does not implement a PHPUnit\\Runner\\Hook interface', $extension->className()));
  37136. }
  37137. return $object;
  37138. }
  37139. public function createTestListenerInstance(\PHPUnit\TextUI\Configuration\Extension $extension) : \PHPUnit\Framework\TestListener
  37140. {
  37141. $object = $this->createInstance($extension);
  37142. if (!$object instanceof \PHPUnit\Framework\TestListener) {
  37143. throw new \PHPUnit\Framework\Exception(\sprintf('Class "%s" does not implement the PHPUnit\\Framework\\TestListener interface', $extension->className()));
  37144. }
  37145. return $object;
  37146. }
  37147. private function createInstance(\PHPUnit\TextUI\Configuration\Extension $extension) : object
  37148. {
  37149. $this->ensureClassExists($extension);
  37150. try {
  37151. $reflector = new \ReflectionClass($extension->className());
  37152. } catch (\ReflectionException $e) {
  37153. throw new \PHPUnit\Framework\Exception($e->getMessage(), (int) $e->getCode(), $e);
  37154. }
  37155. if (!$extension->hasArguments()) {
  37156. return $reflector->newInstance();
  37157. }
  37158. return $reflector->newInstanceArgs($extension->arguments());
  37159. }
  37160. /**
  37161. * @throws Exception
  37162. */
  37163. private function ensureClassExists(\PHPUnit\TextUI\Configuration\Extension $extension) : void
  37164. {
  37165. if (\class_exists($extension->className(), \false)) {
  37166. return;
  37167. }
  37168. if ($extension->hasSourceFile()) {
  37169. /** @noinspection PhpIncludeInspection */
  37170. require_once $extension->sourceFile();
  37171. }
  37172. if (!\class_exists($extension->className())) {
  37173. throw new \PHPUnit\Framework\Exception(\sprintf('Class "%s" does not exist', $extension->className()));
  37174. }
  37175. }
  37176. }
  37177. <?php
  37178. declare (strict_types=1);
  37179. /*
  37180. * This file is part of PHPUnit.
  37181. *
  37182. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  37183. *
  37184. * For the full copyright and license information, please view the LICENSE
  37185. * file that was distributed with this source code.
  37186. */
  37187. namespace PHPUnit\TextUI\Configuration;
  37188. /**
  37189. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  37190. * @psalm-immutable
  37191. */
  37192. final class Extension
  37193. {
  37194. /**
  37195. * @var string
  37196. * @psalm-var class-string
  37197. */
  37198. private $className;
  37199. /**
  37200. * @var string
  37201. */
  37202. private $sourceFile;
  37203. /**
  37204. * @var array
  37205. */
  37206. private $arguments;
  37207. /**
  37208. * @psalm-param class-string $className
  37209. */
  37210. public function __construct(string $className, string $sourceFile, array $arguments)
  37211. {
  37212. $this->className = $className;
  37213. $this->sourceFile = $sourceFile;
  37214. $this->arguments = $arguments;
  37215. }
  37216. /**
  37217. * @psalm-return class-string
  37218. */
  37219. public function className() : string
  37220. {
  37221. return $this->className;
  37222. }
  37223. public function hasSourceFile() : bool
  37224. {
  37225. return $this->sourceFile !== '';
  37226. }
  37227. public function sourceFile() : string
  37228. {
  37229. return $this->sourceFile;
  37230. }
  37231. public function hasArguments() : bool
  37232. {
  37233. return !empty($this->arguments);
  37234. }
  37235. public function arguments() : array
  37236. {
  37237. return $this->arguments;
  37238. }
  37239. }
  37240. <?php
  37241. declare (strict_types=1);
  37242. /*
  37243. * This file is part of PHPUnit.
  37244. *
  37245. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  37246. *
  37247. * For the full copyright and license information, please view the LICENSE
  37248. * file that was distributed with this source code.
  37249. */
  37250. namespace PHPUnit\TextUI\Configuration;
  37251. /**
  37252. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  37253. * @psalm-immutable
  37254. */
  37255. final class ExtensionCollection implements \IteratorAggregate
  37256. {
  37257. /**
  37258. * @var Extension[]
  37259. */
  37260. private $extensions;
  37261. /**
  37262. * @param Extension[] $extensions
  37263. */
  37264. public static function fromArray(array $extensions) : self
  37265. {
  37266. return new self(...$extensions);
  37267. }
  37268. private function __construct(\PHPUnit\TextUI\Configuration\Extension ...$extensions)
  37269. {
  37270. $this->extensions = $extensions;
  37271. }
  37272. /**
  37273. * @return Extension[]
  37274. */
  37275. public function asArray() : array
  37276. {
  37277. return $this->extensions;
  37278. }
  37279. public function getIterator() : \PHPUnit\TextUI\Configuration\ExtensionCollectionIterator
  37280. {
  37281. return new \PHPUnit\TextUI\Configuration\ExtensionCollectionIterator($this);
  37282. }
  37283. }
  37284. <?php
  37285. declare (strict_types=1);
  37286. /*
  37287. * This file is part of PHPUnit.
  37288. *
  37289. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  37290. *
  37291. * For the full copyright and license information, please view the LICENSE
  37292. * file that was distributed with this source code.
  37293. */
  37294. namespace PHPUnit\TextUI\Configuration;
  37295. /**
  37296. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  37297. */
  37298. final class ExtensionCollectionIterator implements \Countable, \Iterator
  37299. {
  37300. /**
  37301. * @var Extension[]
  37302. */
  37303. private $extensions;
  37304. /**
  37305. * @var int
  37306. */
  37307. private $position;
  37308. public function __construct(\PHPUnit\TextUI\Configuration\ExtensionCollection $extensions)
  37309. {
  37310. $this->extensions = $extensions->asArray();
  37311. }
  37312. public function count() : int
  37313. {
  37314. return \iterator_count($this);
  37315. }
  37316. public function rewind() : void
  37317. {
  37318. $this->position = 0;
  37319. }
  37320. public function valid() : bool
  37321. {
  37322. return $this->position < \count($this->extensions);
  37323. }
  37324. public function key() : int
  37325. {
  37326. return $this->position;
  37327. }
  37328. public function current() : \PHPUnit\TextUI\Configuration\Extension
  37329. {
  37330. return $this->extensions[$this->position];
  37331. }
  37332. public function next() : void
  37333. {
  37334. $this->position++;
  37335. }
  37336. }
  37337. <?php
  37338. declare (strict_types=1);
  37339. /*
  37340. * This file is part of PHPUnit.
  37341. *
  37342. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  37343. *
  37344. * For the full copyright and license information, please view the LICENSE
  37345. * file that was distributed with this source code.
  37346. */
  37347. namespace PHPUnit\TextUI\Configuration;
  37348. /**
  37349. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  37350. * @psalm-immutable
  37351. */
  37352. final class TestSuite
  37353. {
  37354. /**
  37355. * @var string
  37356. */
  37357. private $name;
  37358. /**
  37359. * @var TestDirectoryCollection
  37360. */
  37361. private $directories;
  37362. /**
  37363. * @var TestFileCollection
  37364. */
  37365. private $files;
  37366. /**
  37367. * @var FileCollection
  37368. */
  37369. private $exclude;
  37370. public function __construct(string $name, \PHPUnit\TextUI\Configuration\TestDirectoryCollection $directories, \PHPUnit\TextUI\Configuration\TestFileCollection $files, \PHPUnit\TextUI\Configuration\FileCollection $exclude)
  37371. {
  37372. $this->name = $name;
  37373. $this->directories = $directories;
  37374. $this->files = $files;
  37375. $this->exclude = $exclude;
  37376. }
  37377. public function name() : string
  37378. {
  37379. return $this->name;
  37380. }
  37381. public function directories() : \PHPUnit\TextUI\Configuration\TestDirectoryCollection
  37382. {
  37383. return $this->directories;
  37384. }
  37385. public function files() : \PHPUnit\TextUI\Configuration\TestFileCollection
  37386. {
  37387. return $this->files;
  37388. }
  37389. public function exclude() : \PHPUnit\TextUI\Configuration\FileCollection
  37390. {
  37391. return $this->exclude;
  37392. }
  37393. }
  37394. <?php
  37395. declare (strict_types=1);
  37396. /*
  37397. * This file is part of PHPUnit.
  37398. *
  37399. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  37400. *
  37401. * For the full copyright and license information, please view the LICENSE
  37402. * file that was distributed with this source code.
  37403. */
  37404. namespace PHPUnit\TextUI\Configuration;
  37405. use PHPUnit\Util\VersionComparisonOperator;
  37406. /**
  37407. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  37408. * @psalm-immutable
  37409. */
  37410. final class TestDirectory
  37411. {
  37412. /**
  37413. * @var string
  37414. */
  37415. private $path;
  37416. /**
  37417. * @var string
  37418. */
  37419. private $prefix;
  37420. /**
  37421. * @var string
  37422. */
  37423. private $suffix;
  37424. /**
  37425. * @var string
  37426. */
  37427. private $phpVersion;
  37428. /**
  37429. * @var VersionComparisonOperator
  37430. */
  37431. private $phpVersionOperator;
  37432. public function __construct(string $path, string $prefix, string $suffix, string $phpVersion, \PHPUnit\Util\VersionComparisonOperator $phpVersionOperator)
  37433. {
  37434. $this->path = $path;
  37435. $this->prefix = $prefix;
  37436. $this->suffix = $suffix;
  37437. $this->phpVersion = $phpVersion;
  37438. $this->phpVersionOperator = $phpVersionOperator;
  37439. }
  37440. public function path() : string
  37441. {
  37442. return $this->path;
  37443. }
  37444. public function prefix() : string
  37445. {
  37446. return $this->prefix;
  37447. }
  37448. public function suffix() : string
  37449. {
  37450. return $this->suffix;
  37451. }
  37452. public function phpVersion() : string
  37453. {
  37454. return $this->phpVersion;
  37455. }
  37456. public function phpVersionOperator() : \PHPUnit\Util\VersionComparisonOperator
  37457. {
  37458. return $this->phpVersionOperator;
  37459. }
  37460. }
  37461. <?php
  37462. declare (strict_types=1);
  37463. /*
  37464. * This file is part of PHPUnit.
  37465. *
  37466. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  37467. *
  37468. * For the full copyright and license information, please view the LICENSE
  37469. * file that was distributed with this source code.
  37470. */
  37471. namespace PHPUnit\TextUI\Configuration;
  37472. /**
  37473. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  37474. */
  37475. final class TestSuiteCollectionIterator implements \Countable, \Iterator
  37476. {
  37477. /**
  37478. * @var TestSuite[]
  37479. */
  37480. private $testSuites;
  37481. /**
  37482. * @var int
  37483. */
  37484. private $position;
  37485. public function __construct(\PHPUnit\TextUI\Configuration\TestSuiteCollection $testSuites)
  37486. {
  37487. $this->testSuites = $testSuites->asArray();
  37488. }
  37489. public function count() : int
  37490. {
  37491. return \iterator_count($this);
  37492. }
  37493. public function rewind() : void
  37494. {
  37495. $this->position = 0;
  37496. }
  37497. public function valid() : bool
  37498. {
  37499. return $this->position < \count($this->testSuites);
  37500. }
  37501. public function key() : int
  37502. {
  37503. return $this->position;
  37504. }
  37505. public function current() : \PHPUnit\TextUI\Configuration\TestSuite
  37506. {
  37507. return $this->testSuites[$this->position];
  37508. }
  37509. public function next() : void
  37510. {
  37511. $this->position++;
  37512. }
  37513. }
  37514. <?php
  37515. declare (strict_types=1);
  37516. /*
  37517. * This file is part of PHPUnit.
  37518. *
  37519. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  37520. *
  37521. * For the full copyright and license information, please view the LICENSE
  37522. * file that was distributed with this source code.
  37523. */
  37524. namespace PHPUnit\TextUI\Configuration;
  37525. use PHPUnit\Util\VersionComparisonOperator;
  37526. /**
  37527. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  37528. * @psalm-immutable
  37529. */
  37530. final class TestFile
  37531. {
  37532. /**
  37533. * @var string
  37534. */
  37535. private $path;
  37536. /**
  37537. * @var string
  37538. */
  37539. private $phpVersion;
  37540. /**
  37541. * @var VersionComparisonOperator
  37542. */
  37543. private $phpVersionOperator;
  37544. public function __construct(string $path, string $phpVersion, \PHPUnit\Util\VersionComparisonOperator $phpVersionOperator)
  37545. {
  37546. $this->path = $path;
  37547. $this->phpVersion = $phpVersion;
  37548. $this->phpVersionOperator = $phpVersionOperator;
  37549. }
  37550. public function path() : string
  37551. {
  37552. return $this->path;
  37553. }
  37554. public function phpVersion() : string
  37555. {
  37556. return $this->phpVersion;
  37557. }
  37558. public function phpVersionOperator() : \PHPUnit\Util\VersionComparisonOperator
  37559. {
  37560. return $this->phpVersionOperator;
  37561. }
  37562. }
  37563. <?php
  37564. declare (strict_types=1);
  37565. /*
  37566. * This file is part of PHPUnit.
  37567. *
  37568. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  37569. *
  37570. * For the full copyright and license information, please view the LICENSE
  37571. * file that was distributed with this source code.
  37572. */
  37573. namespace PHPUnit\TextUI\Configuration;
  37574. /**
  37575. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  37576. * @psalm-immutable
  37577. */
  37578. final class TestDirectoryCollection implements \Countable, \IteratorAggregate
  37579. {
  37580. /**
  37581. * @var TestDirectory[]
  37582. */
  37583. private $directories;
  37584. /**
  37585. * @param TestDirectory[] $directories
  37586. */
  37587. public static function fromArray(array $directories) : self
  37588. {
  37589. return new self(...$directories);
  37590. }
  37591. private function __construct(\PHPUnit\TextUI\Configuration\TestDirectory ...$directories)
  37592. {
  37593. $this->directories = $directories;
  37594. }
  37595. /**
  37596. * @return TestDirectory[]
  37597. */
  37598. public function asArray() : array
  37599. {
  37600. return $this->directories;
  37601. }
  37602. public function count() : int
  37603. {
  37604. return \count($this->directories);
  37605. }
  37606. public function getIterator() : \PHPUnit\TextUI\Configuration\TestDirectoryCollectionIterator
  37607. {
  37608. return new \PHPUnit\TextUI\Configuration\TestDirectoryCollectionIterator($this);
  37609. }
  37610. public function isEmpty() : bool
  37611. {
  37612. return $this->count() === 0;
  37613. }
  37614. }
  37615. <?php
  37616. declare (strict_types=1);
  37617. /*
  37618. * This file is part of PHPUnit.
  37619. *
  37620. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  37621. *
  37622. * For the full copyright and license information, please view the LICENSE
  37623. * file that was distributed with this source code.
  37624. */
  37625. namespace PHPUnit\TextUI\Configuration;
  37626. /**
  37627. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  37628. * @psalm-immutable
  37629. */
  37630. final class TestSuiteCollection implements \Countable, \IteratorAggregate
  37631. {
  37632. /**
  37633. * @var TestSuite[]
  37634. */
  37635. private $testSuites;
  37636. /**
  37637. * @param TestSuite[] $testSuites
  37638. */
  37639. public static function fromArray(array $testSuites) : self
  37640. {
  37641. return new self(...$testSuites);
  37642. }
  37643. private function __construct(\PHPUnit\TextUI\Configuration\TestSuite ...$testSuites)
  37644. {
  37645. $this->testSuites = $testSuites;
  37646. }
  37647. /**
  37648. * @return TestSuite[]
  37649. */
  37650. public function asArray() : array
  37651. {
  37652. return $this->testSuites;
  37653. }
  37654. public function count() : int
  37655. {
  37656. return \count($this->testSuites);
  37657. }
  37658. public function getIterator() : \PHPUnit\TextUI\Configuration\TestSuiteCollectionIterator
  37659. {
  37660. return new \PHPUnit\TextUI\Configuration\TestSuiteCollectionIterator($this);
  37661. }
  37662. public function isEmpty() : bool
  37663. {
  37664. return $this->count() === 0;
  37665. }
  37666. }
  37667. <?php
  37668. declare (strict_types=1);
  37669. /*
  37670. * This file is part of PHPUnit.
  37671. *
  37672. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  37673. *
  37674. * For the full copyright and license information, please view the LICENSE
  37675. * file that was distributed with this source code.
  37676. */
  37677. namespace PHPUnit\TextUI\Configuration;
  37678. /**
  37679. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  37680. */
  37681. final class TestFileCollectionIterator implements \Countable, \Iterator
  37682. {
  37683. /**
  37684. * @var TestFile[]
  37685. */
  37686. private $files;
  37687. /**
  37688. * @var int
  37689. */
  37690. private $position;
  37691. public function __construct(\PHPUnit\TextUI\Configuration\TestFileCollection $files)
  37692. {
  37693. $this->files = $files->asArray();
  37694. }
  37695. public function count() : int
  37696. {
  37697. return \iterator_count($this);
  37698. }
  37699. public function rewind() : void
  37700. {
  37701. $this->position = 0;
  37702. }
  37703. public function valid() : bool
  37704. {
  37705. return $this->position < \count($this->files);
  37706. }
  37707. public function key() : int
  37708. {
  37709. return $this->position;
  37710. }
  37711. public function current() : \PHPUnit\TextUI\Configuration\TestFile
  37712. {
  37713. return $this->files[$this->position];
  37714. }
  37715. public function next() : void
  37716. {
  37717. $this->position++;
  37718. }
  37719. }
  37720. <?php
  37721. declare (strict_types=1);
  37722. /*
  37723. * This file is part of PHPUnit.
  37724. *
  37725. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  37726. *
  37727. * For the full copyright and license information, please view the LICENSE
  37728. * file that was distributed with this source code.
  37729. */
  37730. namespace PHPUnit\TextUI\Configuration;
  37731. /**
  37732. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  37733. * @psalm-immutable
  37734. */
  37735. final class TestFileCollection implements \Countable, \IteratorAggregate
  37736. {
  37737. /**
  37738. * @var TestFile[]
  37739. */
  37740. private $files;
  37741. /**
  37742. * @param TestFile[] $files
  37743. */
  37744. public static function fromArray(array $files) : self
  37745. {
  37746. return new self(...$files);
  37747. }
  37748. private function __construct(\PHPUnit\TextUI\Configuration\TestFile ...$files)
  37749. {
  37750. $this->files = $files;
  37751. }
  37752. /**
  37753. * @return TestFile[]
  37754. */
  37755. public function asArray() : array
  37756. {
  37757. return $this->files;
  37758. }
  37759. public function count() : int
  37760. {
  37761. return \count($this->files);
  37762. }
  37763. public function getIterator() : \PHPUnit\TextUI\Configuration\TestFileCollectionIterator
  37764. {
  37765. return new \PHPUnit\TextUI\Configuration\TestFileCollectionIterator($this);
  37766. }
  37767. public function isEmpty() : bool
  37768. {
  37769. return $this->count() === 0;
  37770. }
  37771. }
  37772. <?php
  37773. declare (strict_types=1);
  37774. /*
  37775. * This file is part of PHPUnit.
  37776. *
  37777. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  37778. *
  37779. * For the full copyright and license information, please view the LICENSE
  37780. * file that was distributed with this source code.
  37781. */
  37782. namespace PHPUnit\TextUI\Configuration;
  37783. /**
  37784. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  37785. */
  37786. final class TestDirectoryCollectionIterator implements \Countable, \Iterator
  37787. {
  37788. /**
  37789. * @var TestDirectory[]
  37790. */
  37791. private $directories;
  37792. /**
  37793. * @var int
  37794. */
  37795. private $position;
  37796. public function __construct(\PHPUnit\TextUI\Configuration\TestDirectoryCollection $directories)
  37797. {
  37798. $this->directories = $directories->asArray();
  37799. }
  37800. public function count() : int
  37801. {
  37802. return \iterator_count($this);
  37803. }
  37804. public function rewind() : void
  37805. {
  37806. $this->position = 0;
  37807. }
  37808. public function valid() : bool
  37809. {
  37810. return $this->position < \count($this->directories);
  37811. }
  37812. public function key() : int
  37813. {
  37814. return $this->position;
  37815. }
  37816. public function current() : \PHPUnit\TextUI\Configuration\TestDirectory
  37817. {
  37818. return $this->directories[$this->position];
  37819. }
  37820. public function next() : void
  37821. {
  37822. $this->position++;
  37823. }
  37824. }
  37825. <?php
  37826. declare (strict_types=1);
  37827. /*
  37828. * This file is part of PHPUnit.
  37829. *
  37830. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  37831. *
  37832. * For the full copyright and license information, please view the LICENSE
  37833. * file that was distributed with this source code.
  37834. */
  37835. namespace PHPUnit\TextUI\Configuration;
  37836. use PHPUnit\Framework\TestSuite as TestSuiteObject;
  37837. use PHPUnit\SebastianBergmann\FileIterator\Facade;
  37838. /**
  37839. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  37840. */
  37841. final class TestSuiteMapper
  37842. {
  37843. public function map(\PHPUnit\TextUI\Configuration\TestSuiteCollection $configuration, string $filter) : \PHPUnit\Framework\TestSuite
  37844. {
  37845. $filterAsArray = $filter ? \explode(',', $filter) : [];
  37846. $result = new \PHPUnit\Framework\TestSuite();
  37847. foreach ($configuration as $testSuiteConfiguration) {
  37848. if (!empty($filterAsArray) && !\in_array($testSuiteConfiguration->name(), $filterAsArray, \true)) {
  37849. continue;
  37850. }
  37851. $testSuite = new \PHPUnit\Framework\TestSuite($testSuiteConfiguration->name());
  37852. $testSuiteEmpty = \true;
  37853. foreach ($testSuiteConfiguration->directories() as $directory) {
  37854. if (!\version_compare(\PHP_VERSION, $directory->phpVersion(), $directory->phpVersionOperator()->asString())) {
  37855. continue;
  37856. }
  37857. $exclude = [];
  37858. foreach ($testSuiteConfiguration->exclude()->asArray() as $file) {
  37859. $exclude[] = $file->path();
  37860. }
  37861. $testSuite->addTestFiles((new \PHPUnit\SebastianBergmann\FileIterator\Facade())->getFilesAsArray($directory->path(), $directory->suffix(), $directory->prefix(), $exclude));
  37862. $testSuiteEmpty = \false;
  37863. }
  37864. foreach ($testSuiteConfiguration->files() as $file) {
  37865. if (!\version_compare(\PHP_VERSION, $file->phpVersion(), $file->phpVersionOperator()->asString())) {
  37866. continue;
  37867. }
  37868. $testSuite->addTestFile($file->path());
  37869. $testSuiteEmpty = \false;
  37870. }
  37871. if (!$testSuiteEmpty) {
  37872. $result->addTest($testSuite);
  37873. }
  37874. }
  37875. return $result;
  37876. }
  37877. }
  37878. <?php
  37879. declare (strict_types=1);
  37880. /*
  37881. * This file is part of PHPUnit.
  37882. *
  37883. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  37884. *
  37885. * For the full copyright and license information, please view the LICENSE
  37886. * file that was distributed with this source code.
  37887. */
  37888. namespace PHPUnit\TextUI\Configuration;
  37889. /**
  37890. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  37891. */
  37892. final class Exception extends \RuntimeException implements \PHPUnit\Exception
  37893. {
  37894. }
  37895. <?php
  37896. declare (strict_types=1);
  37897. /*
  37898. * This file is part of PHPUnit.
  37899. *
  37900. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  37901. *
  37902. * For the full copyright and license information, please view the LICENSE
  37903. * file that was distributed with this source code.
  37904. */
  37905. namespace PHPUnit\TextUI\Configuration;
  37906. /**
  37907. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  37908. * @psalm-immutable
  37909. */
  37910. final class Php
  37911. {
  37912. /**
  37913. * @var DirectoryCollection
  37914. */
  37915. private $includePaths;
  37916. /**
  37917. * @var IniSettingCollection
  37918. */
  37919. private $iniSettings;
  37920. /**
  37921. * @var ConstantCollection
  37922. */
  37923. private $constants;
  37924. /**
  37925. * @var VariableCollection
  37926. */
  37927. private $globalVariables;
  37928. /**
  37929. * @var VariableCollection
  37930. */
  37931. private $envVariables;
  37932. /**
  37933. * @var VariableCollection
  37934. */
  37935. private $postVariables;
  37936. /**
  37937. * @var VariableCollection
  37938. */
  37939. private $getVariables;
  37940. /**
  37941. * @var VariableCollection
  37942. */
  37943. private $cookieVariables;
  37944. /**
  37945. * @var VariableCollection
  37946. */
  37947. private $serverVariables;
  37948. /**
  37949. * @var VariableCollection
  37950. */
  37951. private $filesVariables;
  37952. /**
  37953. * @var VariableCollection
  37954. */
  37955. private $requestVariables;
  37956. public function __construct(\PHPUnit\TextUI\Configuration\DirectoryCollection $includePaths, \PHPUnit\TextUI\Configuration\IniSettingCollection $iniSettings, \PHPUnit\TextUI\Configuration\ConstantCollection $constants, \PHPUnit\TextUI\Configuration\VariableCollection $globalVariables, \PHPUnit\TextUI\Configuration\VariableCollection $envVariables, \PHPUnit\TextUI\Configuration\VariableCollection $postVariables, \PHPUnit\TextUI\Configuration\VariableCollection $getVariables, \PHPUnit\TextUI\Configuration\VariableCollection $cookieVariables, \PHPUnit\TextUI\Configuration\VariableCollection $serverVariables, \PHPUnit\TextUI\Configuration\VariableCollection $filesVariables, \PHPUnit\TextUI\Configuration\VariableCollection $requestVariables)
  37957. {
  37958. $this->includePaths = $includePaths;
  37959. $this->iniSettings = $iniSettings;
  37960. $this->constants = $constants;
  37961. $this->globalVariables = $globalVariables;
  37962. $this->envVariables = $envVariables;
  37963. $this->postVariables = $postVariables;
  37964. $this->getVariables = $getVariables;
  37965. $this->cookieVariables = $cookieVariables;
  37966. $this->serverVariables = $serverVariables;
  37967. $this->filesVariables = $filesVariables;
  37968. $this->requestVariables = $requestVariables;
  37969. }
  37970. public function includePaths() : \PHPUnit\TextUI\Configuration\DirectoryCollection
  37971. {
  37972. return $this->includePaths;
  37973. }
  37974. public function iniSettings() : \PHPUnit\TextUI\Configuration\IniSettingCollection
  37975. {
  37976. return $this->iniSettings;
  37977. }
  37978. public function constants() : \PHPUnit\TextUI\Configuration\ConstantCollection
  37979. {
  37980. return $this->constants;
  37981. }
  37982. public function globalVariables() : \PHPUnit\TextUI\Configuration\VariableCollection
  37983. {
  37984. return $this->globalVariables;
  37985. }
  37986. public function envVariables() : \PHPUnit\TextUI\Configuration\VariableCollection
  37987. {
  37988. return $this->envVariables;
  37989. }
  37990. public function postVariables() : \PHPUnit\TextUI\Configuration\VariableCollection
  37991. {
  37992. return $this->postVariables;
  37993. }
  37994. public function getVariables() : \PHPUnit\TextUI\Configuration\VariableCollection
  37995. {
  37996. return $this->getVariables;
  37997. }
  37998. public function cookieVariables() : \PHPUnit\TextUI\Configuration\VariableCollection
  37999. {
  38000. return $this->cookieVariables;
  38001. }
  38002. public function serverVariables() : \PHPUnit\TextUI\Configuration\VariableCollection
  38003. {
  38004. return $this->serverVariables;
  38005. }
  38006. public function filesVariables() : \PHPUnit\TextUI\Configuration\VariableCollection
  38007. {
  38008. return $this->filesVariables;
  38009. }
  38010. public function requestVariables() : \PHPUnit\TextUI\Configuration\VariableCollection
  38011. {
  38012. return $this->requestVariables;
  38013. }
  38014. }
  38015. <?php
  38016. declare (strict_types=1);
  38017. /*
  38018. * This file is part of PHPUnit.
  38019. *
  38020. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  38021. *
  38022. * For the full copyright and license information, please view the LICENSE
  38023. * file that was distributed with this source code.
  38024. */
  38025. namespace PHPUnit\TextUI\Configuration;
  38026. /**
  38027. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  38028. * @psalm-immutable
  38029. */
  38030. final class VariableCollection implements \Countable, \IteratorAggregate
  38031. {
  38032. /**
  38033. * @var Variable[]
  38034. */
  38035. private $variables;
  38036. /**
  38037. * @param Variable[] $variables
  38038. */
  38039. public static function fromArray(array $variables) : self
  38040. {
  38041. return new self(...$variables);
  38042. }
  38043. private function __construct(\PHPUnit\TextUI\Configuration\Variable ...$variables)
  38044. {
  38045. $this->variables = $variables;
  38046. }
  38047. /**
  38048. * @return Variable[]
  38049. */
  38050. public function asArray() : array
  38051. {
  38052. return $this->variables;
  38053. }
  38054. public function count() : int
  38055. {
  38056. return \count($this->variables);
  38057. }
  38058. public function getIterator() : \PHPUnit\TextUI\Configuration\VariableCollectionIterator
  38059. {
  38060. return new \PHPUnit\TextUI\Configuration\VariableCollectionIterator($this);
  38061. }
  38062. }
  38063. <?php
  38064. declare (strict_types=1);
  38065. /*
  38066. * This file is part of PHPUnit.
  38067. *
  38068. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  38069. *
  38070. * For the full copyright and license information, please view the LICENSE
  38071. * file that was distributed with this source code.
  38072. */
  38073. namespace PHPUnit\TextUI\Configuration;
  38074. /**
  38075. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  38076. * @psalm-immutable
  38077. */
  38078. final class Variable
  38079. {
  38080. /**
  38081. * @var string
  38082. */
  38083. private $name;
  38084. /**
  38085. * @var mixed
  38086. */
  38087. private $value;
  38088. /**
  38089. * @var bool
  38090. */
  38091. private $force;
  38092. public function __construct(string $name, $value, bool $force)
  38093. {
  38094. $this->name = $name;
  38095. $this->value = $value;
  38096. $this->force = $force;
  38097. }
  38098. public function name() : string
  38099. {
  38100. return $this->name;
  38101. }
  38102. public function value()
  38103. {
  38104. return $this->value;
  38105. }
  38106. public function force() : bool
  38107. {
  38108. return $this->force;
  38109. }
  38110. }
  38111. <?php
  38112. declare (strict_types=1);
  38113. /*
  38114. * This file is part of PHPUnit.
  38115. *
  38116. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  38117. *
  38118. * For the full copyright and license information, please view the LICENSE
  38119. * file that was distributed with this source code.
  38120. */
  38121. namespace PHPUnit\TextUI\Configuration;
  38122. /**
  38123. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  38124. */
  38125. final class ConstantCollectionIterator implements \Countable, \Iterator
  38126. {
  38127. /**
  38128. * @var Constant[]
  38129. */
  38130. private $constants;
  38131. /**
  38132. * @var int
  38133. */
  38134. private $position;
  38135. public function __construct(\PHPUnit\TextUI\Configuration\ConstantCollection $constants)
  38136. {
  38137. $this->constants = $constants->asArray();
  38138. }
  38139. public function count() : int
  38140. {
  38141. return \iterator_count($this);
  38142. }
  38143. public function rewind() : void
  38144. {
  38145. $this->position = 0;
  38146. }
  38147. public function valid() : bool
  38148. {
  38149. return $this->position < \count($this->constants);
  38150. }
  38151. public function key() : int
  38152. {
  38153. return $this->position;
  38154. }
  38155. public function current() : \PHPUnit\TextUI\Configuration\Constant
  38156. {
  38157. return $this->constants[$this->position];
  38158. }
  38159. public function next() : void
  38160. {
  38161. $this->position++;
  38162. }
  38163. }
  38164. <?php
  38165. declare (strict_types=1);
  38166. /*
  38167. * This file is part of PHPUnit.
  38168. *
  38169. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  38170. *
  38171. * For the full copyright and license information, please view the LICENSE
  38172. * file that was distributed with this source code.
  38173. */
  38174. namespace PHPUnit\TextUI\Configuration;
  38175. /**
  38176. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  38177. */
  38178. final class IniSettingCollectionIterator implements \Countable, \Iterator
  38179. {
  38180. /**
  38181. * @var IniSetting[]
  38182. */
  38183. private $iniSettings;
  38184. /**
  38185. * @var int
  38186. */
  38187. private $position;
  38188. public function __construct(\PHPUnit\TextUI\Configuration\IniSettingCollection $iniSettings)
  38189. {
  38190. $this->iniSettings = $iniSettings->asArray();
  38191. }
  38192. public function count() : int
  38193. {
  38194. return \iterator_count($this);
  38195. }
  38196. public function rewind() : void
  38197. {
  38198. $this->position = 0;
  38199. }
  38200. public function valid() : bool
  38201. {
  38202. return $this->position < \count($this->iniSettings);
  38203. }
  38204. public function key() : int
  38205. {
  38206. return $this->position;
  38207. }
  38208. public function current() : \PHPUnit\TextUI\Configuration\IniSetting
  38209. {
  38210. return $this->iniSettings[$this->position];
  38211. }
  38212. public function next() : void
  38213. {
  38214. $this->position++;
  38215. }
  38216. }
  38217. <?php
  38218. declare (strict_types=1);
  38219. /*
  38220. * This file is part of PHPUnit.
  38221. *
  38222. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  38223. *
  38224. * For the full copyright and license information, please view the LICENSE
  38225. * file that was distributed with this source code.
  38226. */
  38227. namespace PHPUnit\TextUI\Configuration;
  38228. /**
  38229. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  38230. * @psalm-immutable
  38231. */
  38232. final class IniSettingCollection implements \Countable, \IteratorAggregate
  38233. {
  38234. /**
  38235. * @var IniSetting[]
  38236. */
  38237. private $iniSettings;
  38238. /**
  38239. * @param IniSetting[] $iniSettings
  38240. */
  38241. public static function fromArray(array $iniSettings) : self
  38242. {
  38243. return new self(...$iniSettings);
  38244. }
  38245. private function __construct(\PHPUnit\TextUI\Configuration\IniSetting ...$iniSettings)
  38246. {
  38247. $this->iniSettings = $iniSettings;
  38248. }
  38249. /**
  38250. * @return IniSetting[]
  38251. */
  38252. public function asArray() : array
  38253. {
  38254. return $this->iniSettings;
  38255. }
  38256. public function count() : int
  38257. {
  38258. return \count($this->iniSettings);
  38259. }
  38260. public function getIterator() : \PHPUnit\TextUI\Configuration\IniSettingCollectionIterator
  38261. {
  38262. return new \PHPUnit\TextUI\Configuration\IniSettingCollectionIterator($this);
  38263. }
  38264. }
  38265. <?php
  38266. declare (strict_types=1);
  38267. /*
  38268. * This file is part of PHPUnit.
  38269. *
  38270. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  38271. *
  38272. * For the full copyright and license information, please view the LICENSE
  38273. * file that was distributed with this source code.
  38274. */
  38275. namespace PHPUnit\TextUI\Configuration;
  38276. /**
  38277. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  38278. */
  38279. final class PhpHandler
  38280. {
  38281. public function handle(\PHPUnit\TextUI\Configuration\Php $configuration) : void
  38282. {
  38283. $this->handleIncludePaths($configuration->includePaths());
  38284. $this->handleIniSettings($configuration->iniSettings());
  38285. $this->handleConstants($configuration->constants());
  38286. $this->handleGlobalVariables($configuration->globalVariables());
  38287. $this->handleServerVariables($configuration->serverVariables());
  38288. $this->handleEnvVariables($configuration->envVariables());
  38289. $this->handleVariables('_POST', $configuration->postVariables());
  38290. $this->handleVariables('_GET', $configuration->getVariables());
  38291. $this->handleVariables('_COOKIE', $configuration->cookieVariables());
  38292. $this->handleVariables('_FILES', $configuration->filesVariables());
  38293. $this->handleVariables('_REQUEST', $configuration->requestVariables());
  38294. }
  38295. private function handleIncludePaths(\PHPUnit\TextUI\Configuration\DirectoryCollection $includePaths) : void
  38296. {
  38297. if (!$includePaths->isEmpty()) {
  38298. $includePathsAsStrings = [];
  38299. foreach ($includePaths as $includePath) {
  38300. $includePathsAsStrings[] = $includePath->path();
  38301. }
  38302. \ini_set('include_path', \implode(\PATH_SEPARATOR, $includePathsAsStrings) . \PATH_SEPARATOR . \ini_get('include_path'));
  38303. }
  38304. }
  38305. private function handleIniSettings(\PHPUnit\TextUI\Configuration\IniSettingCollection $iniSettings) : void
  38306. {
  38307. foreach ($iniSettings as $iniSetting) {
  38308. $value = $iniSetting->value();
  38309. if (\defined($value)) {
  38310. $value = (string) \constant($value);
  38311. }
  38312. \ini_set($iniSetting->name(), $value);
  38313. }
  38314. }
  38315. private function handleConstants(\PHPUnit\TextUI\Configuration\ConstantCollection $constants) : void
  38316. {
  38317. foreach ($constants as $constant) {
  38318. if (!\defined($constant->name())) {
  38319. \define($constant->name(), $constant->value());
  38320. }
  38321. }
  38322. }
  38323. private function handleGlobalVariables(\PHPUnit\TextUI\Configuration\VariableCollection $variables) : void
  38324. {
  38325. foreach ($variables as $variable) {
  38326. $GLOBALS[$variable->name()] = $variable->value();
  38327. }
  38328. }
  38329. private function handleServerVariables(\PHPUnit\TextUI\Configuration\VariableCollection $variables) : void
  38330. {
  38331. foreach ($variables as $variable) {
  38332. $_SERVER[$variable->name()] = $variable->value();
  38333. }
  38334. }
  38335. private function handleVariables(string $target, \PHPUnit\TextUI\Configuration\VariableCollection $variables) : void
  38336. {
  38337. foreach ($variables as $variable) {
  38338. $GLOBALS[$target][$variable->name()] = $variable->value();
  38339. }
  38340. }
  38341. private function handleEnvVariables(\PHPUnit\TextUI\Configuration\VariableCollection $variables) : void
  38342. {
  38343. foreach ($variables as $variable) {
  38344. $name = $variable->name();
  38345. $value = $variable->value();
  38346. $force = $variable->force();
  38347. if ($force || \getenv($name) === \false) {
  38348. \putenv("{$name}={$value}");
  38349. }
  38350. $value = \getenv($name);
  38351. if (!isset($_ENV[$name])) {
  38352. $_ENV[$name] = $value;
  38353. }
  38354. if ($force) {
  38355. $_ENV[$name] = $value;
  38356. }
  38357. }
  38358. }
  38359. }
  38360. <?php
  38361. declare (strict_types=1);
  38362. /*
  38363. * This file is part of PHPUnit.
  38364. *
  38365. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  38366. *
  38367. * For the full copyright and license information, please view the LICENSE
  38368. * file that was distributed with this source code.
  38369. */
  38370. namespace PHPUnit\TextUI\Configuration;
  38371. /**
  38372. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  38373. * @psalm-immutable
  38374. */
  38375. final class Constant
  38376. {
  38377. /**
  38378. * @var string
  38379. */
  38380. private $name;
  38381. /**
  38382. * @var mixed
  38383. */
  38384. private $value;
  38385. public function __construct(string $name, $value)
  38386. {
  38387. $this->name = $name;
  38388. $this->value = $value;
  38389. }
  38390. public function name() : string
  38391. {
  38392. return $this->name;
  38393. }
  38394. public function value()
  38395. {
  38396. return $this->value;
  38397. }
  38398. }
  38399. <?php
  38400. declare (strict_types=1);
  38401. /*
  38402. * This file is part of PHPUnit.
  38403. *
  38404. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  38405. *
  38406. * For the full copyright and license information, please view the LICENSE
  38407. * file that was distributed with this source code.
  38408. */
  38409. namespace PHPUnit\TextUI\Configuration;
  38410. /**
  38411. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  38412. */
  38413. final class VariableCollectionIterator implements \Countable, \Iterator
  38414. {
  38415. /**
  38416. * @var Variable[]
  38417. */
  38418. private $variables;
  38419. /**
  38420. * @var int
  38421. */
  38422. private $position;
  38423. public function __construct(\PHPUnit\TextUI\Configuration\VariableCollection $variables)
  38424. {
  38425. $this->variables = $variables->asArray();
  38426. }
  38427. public function count() : int
  38428. {
  38429. return \iterator_count($this);
  38430. }
  38431. public function rewind() : void
  38432. {
  38433. $this->position = 0;
  38434. }
  38435. public function valid() : bool
  38436. {
  38437. return $this->position < \count($this->variables);
  38438. }
  38439. public function key() : int
  38440. {
  38441. return $this->position;
  38442. }
  38443. public function current() : \PHPUnit\TextUI\Configuration\Variable
  38444. {
  38445. return $this->variables[$this->position];
  38446. }
  38447. public function next() : void
  38448. {
  38449. $this->position++;
  38450. }
  38451. }
  38452. <?php
  38453. declare (strict_types=1);
  38454. /*
  38455. * This file is part of PHPUnit.
  38456. *
  38457. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  38458. *
  38459. * For the full copyright and license information, please view the LICENSE
  38460. * file that was distributed with this source code.
  38461. */
  38462. namespace PHPUnit\TextUI\Configuration;
  38463. /**
  38464. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  38465. * @psalm-immutable
  38466. */
  38467. final class ConstantCollection implements \Countable, \IteratorAggregate
  38468. {
  38469. /**
  38470. * @var Constant[]
  38471. */
  38472. private $constants;
  38473. /**
  38474. * @param Constant[] $constants
  38475. */
  38476. public static function fromArray(array $constants) : self
  38477. {
  38478. return new self(...$constants);
  38479. }
  38480. private function __construct(\PHPUnit\TextUI\Configuration\Constant ...$constants)
  38481. {
  38482. $this->constants = $constants;
  38483. }
  38484. /**
  38485. * @return Constant[]
  38486. */
  38487. public function asArray() : array
  38488. {
  38489. return $this->constants;
  38490. }
  38491. public function count() : int
  38492. {
  38493. return \count($this->constants);
  38494. }
  38495. public function getIterator() : \PHPUnit\TextUI\Configuration\ConstantCollectionIterator
  38496. {
  38497. return new \PHPUnit\TextUI\Configuration\ConstantCollectionIterator($this);
  38498. }
  38499. }
  38500. <?php
  38501. declare (strict_types=1);
  38502. /*
  38503. * This file is part of PHPUnit.
  38504. *
  38505. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  38506. *
  38507. * For the full copyright and license information, please view the LICENSE
  38508. * file that was distributed with this source code.
  38509. */
  38510. namespace PHPUnit\TextUI\Configuration;
  38511. /**
  38512. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  38513. * @psalm-immutable
  38514. */
  38515. final class IniSetting
  38516. {
  38517. /**
  38518. * @var string
  38519. */
  38520. private $name;
  38521. /**
  38522. * @var string
  38523. */
  38524. private $value;
  38525. public function __construct(string $name, string $value)
  38526. {
  38527. $this->name = $name;
  38528. $this->value = $value;
  38529. }
  38530. public function name() : string
  38531. {
  38532. return $this->name;
  38533. }
  38534. public function value() : string
  38535. {
  38536. return $this->value;
  38537. }
  38538. }
  38539. <?php
  38540. declare (strict_types=1);
  38541. /*
  38542. * This file is part of PHPUnit.
  38543. *
  38544. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  38545. *
  38546. * For the full copyright and license information, please view the LICENSE
  38547. * file that was distributed with this source code.
  38548. */
  38549. namespace PHPUnit\TextUI\Configuration;
  38550. /**
  38551. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  38552. */
  38553. final class Registry
  38554. {
  38555. /**
  38556. * @var self
  38557. */
  38558. private static $instance;
  38559. /**
  38560. * @var Configuration[]
  38561. */
  38562. private $configurations = [];
  38563. public static function getInstance() : self
  38564. {
  38565. if (!self::$instance instanceof self) {
  38566. self::$instance = new self();
  38567. }
  38568. return self::$instance;
  38569. }
  38570. private function __construct()
  38571. {
  38572. }
  38573. private function __clone()
  38574. {
  38575. }
  38576. public function get(string $filename) : \PHPUnit\TextUI\Configuration\Configuration
  38577. {
  38578. if (!isset($this->configurations[$filename])) {
  38579. $this->configurations[$filename] = (new \PHPUnit\TextUI\Configuration\Loader())->load($filename);
  38580. }
  38581. return $this->configurations[$filename];
  38582. }
  38583. }
  38584. <?php
  38585. declare (strict_types=1);
  38586. /*
  38587. * This file is part of PHPUnit.
  38588. *
  38589. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  38590. *
  38591. * For the full copyright and license information, please view the LICENSE
  38592. * file that was distributed with this source code.
  38593. */
  38594. namespace PHPUnit\TextUI;
  38595. /**
  38596. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  38597. */
  38598. final class Exception extends \RuntimeException implements \PHPUnit\Exception
  38599. {
  38600. }
  38601. <?php
  38602. declare (strict_types=1);
  38603. /*
  38604. * This file is part of PHPUnit.
  38605. *
  38606. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  38607. *
  38608. * For the full copyright and license information, please view the LICENSE
  38609. * file that was distributed with this source code.
  38610. */
  38611. namespace PHPUnit\TextUI;
  38612. use PHPUnit\PharIo\Manifest\ApplicationName;
  38613. use PHPUnit\PharIo\Manifest\Exception as ManifestException;
  38614. use PHPUnit\PharIo\Manifest\ManifestLoader;
  38615. use PHPUnit\PharIo\Version\Version as PharIoVersion;
  38616. use PHPUnit\Framework\Exception;
  38617. use PHPUnit\Framework\Test;
  38618. use PHPUnit\Framework\TestSuite;
  38619. use PHPUnit\Runner\StandardTestSuiteLoader;
  38620. use PHPUnit\Runner\TestSuiteLoader;
  38621. use PHPUnit\Runner\Version;
  38622. use PHPUnit\TextUI\Arguments\Arguments;
  38623. use PHPUnit\TextUI\Arguments\ArgumentsBuilder;
  38624. use PHPUnit\TextUI\Arguments\ArgumentsMapper;
  38625. use PHPUnit\TextUI\Arguments\Exception as ArgumentsException;
  38626. use PHPUnit\TextUI\Configuration\Generator;
  38627. use PHPUnit\TextUI\Configuration\PhpHandler;
  38628. use PHPUnit\TextUI\Configuration\Registry;
  38629. use PHPUnit\TextUI\Configuration\TestSuiteMapper;
  38630. use PHPUnit\Util\FileLoader;
  38631. use PHPUnit\Util\Filesystem;
  38632. use PHPUnit\Util\Printer;
  38633. use PHPUnit\Util\TextTestListRenderer;
  38634. use PHPUnit\Util\XmlTestListRenderer;
  38635. use PHPUnit\SebastianBergmann\FileIterator\Facade as FileIteratorFacade;
  38636. /**
  38637. * A TestRunner for the Command Line Interface (CLI)
  38638. * PHP SAPI Module.
  38639. */
  38640. class Command
  38641. {
  38642. /**
  38643. * @var array<string,mixed>
  38644. */
  38645. protected $arguments = [];
  38646. /**
  38647. * @var array<string,mixed>
  38648. */
  38649. protected $longOptions = [];
  38650. /**
  38651. * @var bool
  38652. */
  38653. private $versionStringPrinted = \false;
  38654. /**
  38655. * @psalm-var list<string>
  38656. */
  38657. private $warnings = [];
  38658. /**
  38659. * @throws \PHPUnit\Framework\Exception
  38660. */
  38661. public static function main(bool $exit = \true) : int
  38662. {
  38663. return (new static())->run($_SERVER['argv'], $exit);
  38664. }
  38665. /**
  38666. * @throws Exception
  38667. */
  38668. public function run(array $argv, bool $exit = \true) : int
  38669. {
  38670. $this->handleArguments($argv);
  38671. $runner = $this->createRunner();
  38672. if ($this->arguments['test'] instanceof \PHPUnit\Framework\TestSuite) {
  38673. $suite = $this->arguments['test'];
  38674. } else {
  38675. $suite = $runner->getTest($this->arguments['test'], $this->arguments['testSuffixes']);
  38676. }
  38677. if ($this->arguments['listGroups']) {
  38678. return $this->handleListGroups($suite, $exit);
  38679. }
  38680. if ($this->arguments['listSuites']) {
  38681. return $this->handleListSuites($exit);
  38682. }
  38683. if ($this->arguments['listTests']) {
  38684. return $this->handleListTests($suite, $exit);
  38685. }
  38686. if ($this->arguments['listTestsXml']) {
  38687. return $this->handleListTestsXml($suite, $this->arguments['listTestsXml'], $exit);
  38688. }
  38689. unset($this->arguments['test'], $this->arguments['testFile']);
  38690. try {
  38691. $result = $runner->run($suite, $this->arguments, $this->warnings, $exit);
  38692. } catch (\PHPUnit\Framework\Exception $e) {
  38693. print $e->getMessage() . \PHP_EOL;
  38694. }
  38695. $return = \PHPUnit\TextUI\TestRunner::FAILURE_EXIT;
  38696. if (isset($result) && $result->wasSuccessful()) {
  38697. $return = \PHPUnit\TextUI\TestRunner::SUCCESS_EXIT;
  38698. } elseif (!isset($result) || $result->errorCount() > 0) {
  38699. $return = \PHPUnit\TextUI\TestRunner::EXCEPTION_EXIT;
  38700. }
  38701. if ($exit) {
  38702. exit($return);
  38703. }
  38704. return $return;
  38705. }
  38706. /**
  38707. * Create a TestRunner, override in subclasses.
  38708. */
  38709. protected function createRunner() : \PHPUnit\TextUI\TestRunner
  38710. {
  38711. return new \PHPUnit\TextUI\TestRunner($this->arguments['loader']);
  38712. }
  38713. /**
  38714. * Handles the command-line arguments.
  38715. *
  38716. * A child class of PHPUnit\TextUI\Command can hook into the argument
  38717. * parsing by adding the switch(es) to the $longOptions array and point to a
  38718. * callback method that handles the switch(es) in the child class like this
  38719. *
  38720. * <code>
  38721. * <?php
  38722. * class MyCommand extends PHPUnit\TextUI\Command
  38723. * {
  38724. * public function __construct()
  38725. * {
  38726. * // my-switch won't accept a value, it's an on/off
  38727. * $this->longOptions['my-switch'] = 'myHandler';
  38728. * // my-secondswitch will accept a value - note the equals sign
  38729. * $this->longOptions['my-secondswitch='] = 'myOtherHandler';
  38730. * }
  38731. *
  38732. * // --my-switch -> myHandler()
  38733. * protected function myHandler()
  38734. * {
  38735. * }
  38736. *
  38737. * // --my-secondswitch foo -> myOtherHandler('foo')
  38738. * protected function myOtherHandler ($value)
  38739. * {
  38740. * }
  38741. *
  38742. * // You will also need this - the static keyword in the
  38743. * // PHPUnit\TextUI\Command will mean that it'll be
  38744. * // PHPUnit\TextUI\Command that gets instantiated,
  38745. * // not MyCommand
  38746. * public static function main($exit = true)
  38747. * {
  38748. * $command = new static;
  38749. *
  38750. * return $command->run($_SERVER['argv'], $exit);
  38751. * }
  38752. *
  38753. * }
  38754. * </code>
  38755. *
  38756. * @throws Exception
  38757. */
  38758. protected function handleArguments(array $argv) : void
  38759. {
  38760. try {
  38761. $arguments = (new \PHPUnit\TextUI\Arguments\ArgumentsBuilder())->fromParameters($argv, \array_keys($this->longOptions));
  38762. } catch (\PHPUnit\TextUI\Arguments\Exception $e) {
  38763. $this->exitWithErrorMessage($e->getMessage());
  38764. }
  38765. \assert(isset($arguments) && $arguments instanceof \PHPUnit\TextUI\Arguments\Arguments);
  38766. if ($arguments->hasGenerateConfiguration() && $arguments->generateConfiguration()) {
  38767. $this->printVersionString();
  38768. print 'Generating phpunit.xml in ' . \getcwd() . \PHP_EOL . \PHP_EOL;
  38769. print 'Bootstrap script (relative to path shown above; default: vendor/autoload.php): ';
  38770. $bootstrapScript = \trim(\fgets(\STDIN));
  38771. print 'Tests directory (relative to path shown above; default: tests): ';
  38772. $testsDirectory = \trim(\fgets(\STDIN));
  38773. print 'Source directory (relative to path shown above; default: src): ';
  38774. $src = \trim(\fgets(\STDIN));
  38775. if ($bootstrapScript === '') {
  38776. $bootstrapScript = 'vendor/autoload.php';
  38777. }
  38778. if ($testsDirectory === '') {
  38779. $testsDirectory = 'tests';
  38780. }
  38781. if ($src === '') {
  38782. $src = 'src';
  38783. }
  38784. $generator = new \PHPUnit\TextUI\Configuration\Generator();
  38785. \file_put_contents('phpunit.xml', $generator->generateDefaultConfiguration(\PHPUnit\Runner\Version::series(), $bootstrapScript, $testsDirectory, $src));
  38786. print \PHP_EOL . 'Generated phpunit.xml in ' . \getcwd() . \PHP_EOL;
  38787. exit(\PHPUnit\TextUI\TestRunner::SUCCESS_EXIT);
  38788. }
  38789. if ($arguments->hasAtLeastVersion()) {
  38790. if (\version_compare(\PHPUnit\Runner\Version::id(), $arguments->atLeastVersion(), '>=')) {
  38791. exit(\PHPUnit\TextUI\TestRunner::SUCCESS_EXIT);
  38792. }
  38793. exit(\PHPUnit\TextUI\TestRunner::FAILURE_EXIT);
  38794. }
  38795. if ($arguments->hasVersion() && $arguments->version()) {
  38796. $this->printVersionString();
  38797. exit(\PHPUnit\TextUI\TestRunner::SUCCESS_EXIT);
  38798. }
  38799. if ($arguments->hasCheckVersion() && $arguments->checkVersion()) {
  38800. $this->handleVersionCheck();
  38801. }
  38802. if ($arguments->hasHelp()) {
  38803. $this->showHelp();
  38804. exit(\PHPUnit\TextUI\TestRunner::SUCCESS_EXIT);
  38805. }
  38806. if ($arguments->hasUnrecognizedOrderBy()) {
  38807. $this->exitWithErrorMessage(\sprintf('unrecognized --order-by option: %s', $arguments->unrecognizedOrderBy()));
  38808. }
  38809. if ($arguments->hasIniSettings()) {
  38810. foreach ($arguments->iniSettings() as $name => $value) {
  38811. \ini_set($name, $value);
  38812. }
  38813. }
  38814. if ($arguments->hasIncludePath()) {
  38815. \ini_set('include_path', $arguments->includePath() . \PATH_SEPARATOR . \ini_get('include_path'));
  38816. }
  38817. $this->arguments = (new \PHPUnit\TextUI\Arguments\ArgumentsMapper())->mapToLegacyArray($arguments);
  38818. if ($arguments->hasUnrecognizedOptions()) {
  38819. foreach ($arguments->unrecognizedOptions() as $name => $value) {
  38820. if (isset($this->longOptions[$name])) {
  38821. $handler = $this->longOptions[$name];
  38822. } elseif (isset($this->longOptions[$name . '='])) {
  38823. $handler = $this->longOptions[$name . '='];
  38824. }
  38825. if (isset($handler) && \is_callable([$this, $handler])) {
  38826. $this->{$handler}($value);
  38827. unset($handler);
  38828. }
  38829. }
  38830. }
  38831. $this->handleCustomTestSuite();
  38832. if (!isset($this->arguments['testSuffixes'])) {
  38833. $this->arguments['testSuffixes'] = ['Test.php', '.phpt'];
  38834. }
  38835. if (!isset($this->arguments['test']) && $arguments->hasArgument()) {
  38836. $this->arguments['test'] = \realpath($arguments->argument());
  38837. if ($this->arguments['test'] === \false) {
  38838. $this->exitWithErrorMessage(\sprintf('Cannot open file "%s".', $arguments->argument()));
  38839. }
  38840. }
  38841. if ($this->arguments['loader'] !== null) {
  38842. $this->arguments['loader'] = $this->handleLoader($this->arguments['loader']);
  38843. }
  38844. if (isset($this->arguments['configuration']) && \is_dir($this->arguments['configuration'])) {
  38845. $configurationFile = $this->arguments['configuration'] . '/phpunit.xml';
  38846. if (\file_exists($configurationFile)) {
  38847. $this->arguments['configuration'] = \realpath($configurationFile);
  38848. } elseif (\file_exists($configurationFile . '.dist')) {
  38849. $this->arguments['configuration'] = \realpath($configurationFile . '.dist');
  38850. }
  38851. } elseif (!isset($this->arguments['configuration']) && $this->arguments['useDefaultConfiguration']) {
  38852. if (\file_exists('phpunit.xml')) {
  38853. $this->arguments['configuration'] = \realpath('phpunit.xml');
  38854. } elseif (\file_exists('phpunit.xml.dist')) {
  38855. $this->arguments['configuration'] = \realpath('phpunit.xml.dist');
  38856. }
  38857. }
  38858. if (isset($this->arguments['configuration'])) {
  38859. try {
  38860. $configuration = \PHPUnit\TextUI\Configuration\Registry::getInstance()->get($this->arguments['configuration']);
  38861. } catch (\Throwable $e) {
  38862. print $e->getMessage() . \PHP_EOL;
  38863. exit(\PHPUnit\TextUI\TestRunner::FAILURE_EXIT);
  38864. }
  38865. $phpunitConfiguration = $configuration->phpunit();
  38866. (new \PHPUnit\TextUI\Configuration\PhpHandler())->handle($configuration->php());
  38867. if (isset($this->arguments['bootstrap'])) {
  38868. $this->handleBootstrap($this->arguments['bootstrap']);
  38869. } elseif ($phpunitConfiguration->hasBootstrap()) {
  38870. $this->handleBootstrap($phpunitConfiguration->bootstrap());
  38871. }
  38872. if (!isset($this->arguments['stderr'])) {
  38873. $this->arguments['stderr'] = $phpunitConfiguration->stderr();
  38874. }
  38875. if (!isset($this->arguments['noExtensions']) && $phpunitConfiguration->hasExtensionsDirectory() && \extension_loaded('phar')) {
  38876. $this->handleExtensions($phpunitConfiguration->extensionsDirectory());
  38877. }
  38878. if (!isset($this->arguments['columns'])) {
  38879. $this->arguments['columns'] = $phpunitConfiguration->columns();
  38880. }
  38881. if (!isset($this->arguments['printer']) && $phpunitConfiguration->hasPrinterClass()) {
  38882. $file = $phpunitConfiguration->hasPrinterFile() ? $phpunitConfiguration->printerFile() : '';
  38883. $this->arguments['printer'] = $this->handlePrinter($phpunitConfiguration->printerClass(), $file);
  38884. }
  38885. if ($phpunitConfiguration->hasTestSuiteLoaderClass()) {
  38886. $file = $phpunitConfiguration->hasTestSuiteLoaderFile() ? $phpunitConfiguration->testSuiteLoaderFile() : '';
  38887. $this->arguments['loader'] = $this->handleLoader($phpunitConfiguration->testSuiteLoaderClass(), $file);
  38888. }
  38889. if (!isset($this->arguments['testsuite']) && $phpunitConfiguration->hasDefaultTestSuite()) {
  38890. $this->arguments['testsuite'] = $phpunitConfiguration->defaultTestSuite();
  38891. }
  38892. if (!isset($this->arguments['test'])) {
  38893. $this->arguments['test'] = (new \PHPUnit\TextUI\Configuration\TestSuiteMapper())->map($configuration->testSuite(), $this->arguments['testsuite'] ?? '');
  38894. }
  38895. } elseif (isset($this->arguments['bootstrap'])) {
  38896. $this->handleBootstrap($this->arguments['bootstrap']);
  38897. }
  38898. if (isset($this->arguments['printer']) && \is_string($this->arguments['printer'])) {
  38899. $this->arguments['printer'] = $this->handlePrinter($this->arguments['printer']);
  38900. }
  38901. if (!isset($this->arguments['test'])) {
  38902. $this->showHelp();
  38903. exit(\PHPUnit\TextUI\TestRunner::EXCEPTION_EXIT);
  38904. }
  38905. }
  38906. /**
  38907. * Handles the loading of the PHPUnit\Runner\TestSuiteLoader implementation.
  38908. *
  38909. * @deprecated see https://github.com/sebastianbergmann/phpunit/issues/4039
  38910. */
  38911. protected function handleLoader(string $loaderClass, string $loaderFile = '') : ?\PHPUnit\Runner\TestSuiteLoader
  38912. {
  38913. $this->warnings[] = 'Using a custom test suite loader is deprecated';
  38914. if (!\class_exists($loaderClass, \false)) {
  38915. if ($loaderFile == '') {
  38916. $loaderFile = \PHPUnit\Util\Filesystem::classNameToFilename($loaderClass);
  38917. }
  38918. $loaderFile = \stream_resolve_include_path($loaderFile);
  38919. if ($loaderFile) {
  38920. require $loaderFile;
  38921. }
  38922. }
  38923. if (\class_exists($loaderClass, \false)) {
  38924. try {
  38925. $class = new \ReflectionClass($loaderClass);
  38926. // @codeCoverageIgnoreStart
  38927. } catch (\ReflectionException $e) {
  38928. throw new \PHPUnit\Framework\Exception($e->getMessage(), (int) $e->getCode(), $e);
  38929. }
  38930. // @codeCoverageIgnoreEnd
  38931. if ($class->implementsInterface(\PHPUnit\Runner\TestSuiteLoader::class) && $class->isInstantiable()) {
  38932. $object = $class->newInstance();
  38933. \assert($object instanceof \PHPUnit\Runner\TestSuiteLoader);
  38934. return $object;
  38935. }
  38936. }
  38937. if ($loaderClass == \PHPUnit\Runner\StandardTestSuiteLoader::class) {
  38938. return null;
  38939. }
  38940. $this->exitWithErrorMessage(\sprintf('Could not use "%s" as loader.', $loaderClass));
  38941. return null;
  38942. }
  38943. /**
  38944. * Handles the loading of the PHPUnit\Util\Printer implementation.
  38945. *
  38946. * @return null|Printer|string
  38947. */
  38948. protected function handlePrinter(string $printerClass, string $printerFile = '')
  38949. {
  38950. if (!\class_exists($printerClass, \false)) {
  38951. if ($printerFile === '') {
  38952. $printerFile = \PHPUnit\Util\Filesystem::classNameToFilename($printerClass);
  38953. }
  38954. $printerFile = \stream_resolve_include_path($printerFile);
  38955. if ($printerFile) {
  38956. require $printerFile;
  38957. }
  38958. }
  38959. if (!\class_exists($printerClass)) {
  38960. $this->exitWithErrorMessage(\sprintf('Could not use "%s" as printer: class does not exist', $printerClass));
  38961. }
  38962. try {
  38963. $class = new \ReflectionClass($printerClass);
  38964. // @codeCoverageIgnoreStart
  38965. } catch (\ReflectionException $e) {
  38966. throw new \PHPUnit\Framework\Exception($e->getMessage(), (int) $e->getCode(), $e);
  38967. // @codeCoverageIgnoreEnd
  38968. }
  38969. if (!$class->implementsInterface(\PHPUnit\TextUI\ResultPrinter::class)) {
  38970. $this->exitWithErrorMessage(\sprintf('Could not use "%s" as printer: class does not implement %s', $printerClass, \PHPUnit\TextUI\ResultPrinter::class));
  38971. }
  38972. if (!$class->isInstantiable()) {
  38973. $this->exitWithErrorMessage(\sprintf('Could not use "%s" as printer: class cannot be instantiated', $printerClass));
  38974. }
  38975. if ($class->isSubclassOf(\PHPUnit\TextUI\ResultPrinter::class)) {
  38976. return $printerClass;
  38977. }
  38978. $outputStream = isset($this->arguments['stderr']) ? 'php://stderr' : null;
  38979. return $class->newInstance($outputStream);
  38980. }
  38981. /**
  38982. * Loads a bootstrap file.
  38983. */
  38984. protected function handleBootstrap(string $filename) : void
  38985. {
  38986. try {
  38987. \PHPUnit\Util\FileLoader::checkAndLoad($filename);
  38988. } catch (\PHPUnit\Framework\Exception $e) {
  38989. $this->exitWithErrorMessage($e->getMessage());
  38990. }
  38991. }
  38992. protected function handleVersionCheck() : void
  38993. {
  38994. $this->printVersionString();
  38995. $latestVersion = \file_get_contents('https://phar.phpunit.de/latest-version-of/phpunit');
  38996. $isOutdated = \version_compare($latestVersion, \PHPUnit\Runner\Version::id(), '>');
  38997. if ($isOutdated) {
  38998. \printf('You are not using the latest version of PHPUnit.' . \PHP_EOL . 'The latest version is PHPUnit %s.' . \PHP_EOL, $latestVersion);
  38999. } else {
  39000. print 'You are using the latest version of PHPUnit.' . \PHP_EOL;
  39001. }
  39002. exit(\PHPUnit\TextUI\TestRunner::SUCCESS_EXIT);
  39003. }
  39004. /**
  39005. * Show the help message.
  39006. */
  39007. protected function showHelp() : void
  39008. {
  39009. $this->printVersionString();
  39010. (new \PHPUnit\TextUI\Help())->writeToConsole();
  39011. }
  39012. /**
  39013. * Custom callback for test suite discovery.
  39014. */
  39015. protected function handleCustomTestSuite() : void
  39016. {
  39017. }
  39018. private function printVersionString() : void
  39019. {
  39020. if ($this->versionStringPrinted) {
  39021. return;
  39022. }
  39023. print \PHPUnit\Runner\Version::getVersionString() . \PHP_EOL . \PHP_EOL;
  39024. $this->versionStringPrinted = \true;
  39025. }
  39026. private function exitWithErrorMessage(string $message) : void
  39027. {
  39028. $this->printVersionString();
  39029. print $message . \PHP_EOL;
  39030. exit(\PHPUnit\TextUI\TestRunner::FAILURE_EXIT);
  39031. }
  39032. private function handleExtensions(string $directory) : void
  39033. {
  39034. foreach ((new \PHPUnit\SebastianBergmann\FileIterator\Facade())->getFilesAsArray($directory, '.phar') as $file) {
  39035. if (!\file_exists('phar://' . $file . '/manifest.xml')) {
  39036. $this->arguments['notLoadedExtensions'][] = $file . ' is not an extension for PHPUnit';
  39037. continue;
  39038. }
  39039. try {
  39040. $applicationName = new \PHPUnit\PharIo\Manifest\ApplicationName('phpunit/phpunit');
  39041. $version = new \PHPUnit\PharIo\Version\Version(\PHPUnit\Runner\Version::series());
  39042. $manifest = \PHPUnit\PharIo\Manifest\ManifestLoader::fromFile('phar://' . $file . '/manifest.xml');
  39043. if (!$manifest->isExtensionFor($applicationName)) {
  39044. $this->arguments['notLoadedExtensions'][] = $file . ' is not an extension for PHPUnit';
  39045. continue;
  39046. }
  39047. if (!$manifest->isExtensionFor($applicationName, $version)) {
  39048. $this->arguments['notLoadedExtensions'][] = $file . ' is not compatible with this version of PHPUnit';
  39049. continue;
  39050. }
  39051. } catch (\PHPUnit\PharIo\Manifest\Exception $e) {
  39052. $this->arguments['notLoadedExtensions'][] = $file . ': ' . $e->getMessage();
  39053. continue;
  39054. }
  39055. require $file;
  39056. $this->arguments['loadedExtensions'][] = $manifest->getName() . ' ' . $manifest->getVersion()->getVersionString();
  39057. }
  39058. }
  39059. private function handleListGroups(\PHPUnit\Framework\TestSuite $suite, bool $exit) : int
  39060. {
  39061. $this->printVersionString();
  39062. print 'Available test group(s):' . \PHP_EOL;
  39063. $groups = $suite->getGroups();
  39064. \sort($groups);
  39065. foreach ($groups as $group) {
  39066. \printf(' - %s' . \PHP_EOL, $group);
  39067. }
  39068. if ($exit) {
  39069. exit(\PHPUnit\TextUI\TestRunner::SUCCESS_EXIT);
  39070. }
  39071. return \PHPUnit\TextUI\TestRunner::SUCCESS_EXIT;
  39072. }
  39073. /**
  39074. * @throws \PHPUnit\Framework\Exception
  39075. */
  39076. private function handleListSuites(bool $exit) : int
  39077. {
  39078. $this->printVersionString();
  39079. print 'Available test suite(s):' . \PHP_EOL;
  39080. $configuration = \PHPUnit\TextUI\Configuration\Registry::getInstance()->get($this->arguments['configuration']);
  39081. foreach ($configuration->testSuite() as $testSuite) {
  39082. \printf(' - %s' . \PHP_EOL, $testSuite->name());
  39083. }
  39084. if ($exit) {
  39085. exit(\PHPUnit\TextUI\TestRunner::SUCCESS_EXIT);
  39086. }
  39087. return \PHPUnit\TextUI\TestRunner::SUCCESS_EXIT;
  39088. }
  39089. /**
  39090. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  39091. */
  39092. private function handleListTests(\PHPUnit\Framework\TestSuite $suite, bool $exit) : int
  39093. {
  39094. $this->printVersionString();
  39095. $renderer = new \PHPUnit\Util\TextTestListRenderer();
  39096. print $renderer->render($suite);
  39097. if ($exit) {
  39098. exit(\PHPUnit\TextUI\TestRunner::SUCCESS_EXIT);
  39099. }
  39100. return \PHPUnit\TextUI\TestRunner::SUCCESS_EXIT;
  39101. }
  39102. /**
  39103. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  39104. */
  39105. private function handleListTestsXml(\PHPUnit\Framework\TestSuite $suite, string $target, bool $exit) : int
  39106. {
  39107. $this->printVersionString();
  39108. $renderer = new \PHPUnit\Util\XmlTestListRenderer();
  39109. \file_put_contents($target, $renderer->render($suite));
  39110. \printf('Wrote list of tests that would have been run to %s' . \PHP_EOL, $target);
  39111. if ($exit) {
  39112. exit(\PHPUnit\TextUI\TestRunner::SUCCESS_EXIT);
  39113. }
  39114. return \PHPUnit\TextUI\TestRunner::SUCCESS_EXIT;
  39115. }
  39116. }
  39117. <?php
  39118. declare (strict_types=1);
  39119. /*
  39120. * This file is part of PHPUnit.
  39121. *
  39122. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  39123. *
  39124. * For the full copyright and license information, please view the LICENSE
  39125. * file that was distributed with this source code.
  39126. */
  39127. namespace PHPUnit\TextUI\Arguments;
  39128. use PHPUnit\TextUI\Configuration\Extension;
  39129. /**
  39130. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  39131. * @psalm-immutable
  39132. */
  39133. final class Arguments
  39134. {
  39135. /**
  39136. * @var ?string
  39137. */
  39138. private $argument;
  39139. /**
  39140. * @var ?string
  39141. */
  39142. private $atLeastVersion;
  39143. /**
  39144. * @var ?bool
  39145. */
  39146. private $backupGlobals;
  39147. /**
  39148. * @var ?bool
  39149. */
  39150. private $backupStaticAttributes;
  39151. /**
  39152. * @var ?bool
  39153. */
  39154. private $beStrictAboutChangesToGlobalState;
  39155. /**
  39156. * @var ?bool
  39157. */
  39158. private $beStrictAboutResourceUsageDuringSmallTests;
  39159. /**
  39160. * @var ?string
  39161. */
  39162. private $bootstrap;
  39163. /**
  39164. * @var ?bool
  39165. */
  39166. private $cacheResult;
  39167. /**
  39168. * @var ?string
  39169. */
  39170. private $cacheResultFile;
  39171. /**
  39172. * @var ?bool
  39173. */
  39174. private $checkVersion;
  39175. /**
  39176. * @var ?string
  39177. */
  39178. private $colors;
  39179. /**
  39180. * @var null|int|string
  39181. */
  39182. private $columns;
  39183. /**
  39184. * @var ?string
  39185. */
  39186. private $configuration;
  39187. /**
  39188. * @var ?string
  39189. */
  39190. private $coverageClover;
  39191. /**
  39192. * @var ?string
  39193. */
  39194. private $coverageCrap4J;
  39195. /**
  39196. * @var ?string
  39197. */
  39198. private $coverageHtml;
  39199. /**
  39200. * @var ?string
  39201. */
  39202. private $coveragePhp;
  39203. /**
  39204. * @var ?string
  39205. */
  39206. private $coverageText;
  39207. /**
  39208. * @var ?bool
  39209. */
  39210. private $coverageTextShowUncoveredFiles;
  39211. /**
  39212. * @var ?bool
  39213. */
  39214. private $coverageTextShowOnlySummary;
  39215. /**
  39216. * @var ?string
  39217. */
  39218. private $coverageXml;
  39219. /**
  39220. * @var ?bool
  39221. */
  39222. private $debug;
  39223. /**
  39224. * @var ?int
  39225. */
  39226. private $defaultTimeLimit;
  39227. /**
  39228. * @var ?bool
  39229. */
  39230. private $disableCodeCoverageIgnore;
  39231. /**
  39232. * @var ?bool
  39233. */
  39234. private $disallowTestOutput;
  39235. /**
  39236. * @var ?bool
  39237. */
  39238. private $disallowTodoAnnotatedTests;
  39239. /**
  39240. * @var ?bool
  39241. */
  39242. private $enforceTimeLimit;
  39243. /**
  39244. * @var null|string[]
  39245. */
  39246. private $excludeGroups;
  39247. /**
  39248. * @var ?int
  39249. */
  39250. private $executionOrder;
  39251. /**
  39252. * @var ?int
  39253. */
  39254. private $executionOrderDefects;
  39255. /**
  39256. * @var null|Extension[]
  39257. */
  39258. private $extensions;
  39259. /**
  39260. * @var null|string[]
  39261. */
  39262. private $unavailableExtensions;
  39263. /**
  39264. * @var ?bool
  39265. */
  39266. private $failOnIncomplete;
  39267. /**
  39268. * @var ?bool
  39269. */
  39270. private $failOnRisky;
  39271. /**
  39272. * @var ?bool
  39273. */
  39274. private $failOnSkipped;
  39275. /**
  39276. * @var ?bool
  39277. */
  39278. private $failOnWarning;
  39279. /**
  39280. * @var ?string
  39281. */
  39282. private $filter;
  39283. /**
  39284. * @var ?bool
  39285. */
  39286. private $generateConfiguration;
  39287. /**
  39288. * @var null|string[]
  39289. */
  39290. private $groups;
  39291. /**
  39292. * @var ?bool
  39293. */
  39294. private $help;
  39295. /**
  39296. * @var ?string
  39297. */
  39298. private $includePath;
  39299. /**
  39300. * @var null|string[]
  39301. */
  39302. private $iniSettings;
  39303. /**
  39304. * @var ?string
  39305. */
  39306. private $junitLogfile;
  39307. /**
  39308. * @var ?bool
  39309. */
  39310. private $listGroups;
  39311. /**
  39312. * @var ?bool
  39313. */
  39314. private $listSuites;
  39315. /**
  39316. * @var ?bool
  39317. */
  39318. private $listTests;
  39319. /**
  39320. * @var ?string
  39321. */
  39322. private $listTestsXml;
  39323. /**
  39324. * @var ?string
  39325. */
  39326. private $loader;
  39327. /**
  39328. * @var ?bool
  39329. */
  39330. private $noCoverage;
  39331. /**
  39332. * @var ?bool
  39333. */
  39334. private $noExtensions;
  39335. /**
  39336. * @var ?bool
  39337. */
  39338. private $noInteraction;
  39339. /**
  39340. * @var ?bool
  39341. */
  39342. private $noLogging;
  39343. /**
  39344. * @var ?string
  39345. */
  39346. private $printer;
  39347. /**
  39348. * @var ?bool
  39349. */
  39350. private $processIsolation;
  39351. /**
  39352. * @var ?int
  39353. */
  39354. private $randomOrderSeed;
  39355. /**
  39356. * @var ?int
  39357. */
  39358. private $repeat;
  39359. /**
  39360. * @var ?bool
  39361. */
  39362. private $reportUselessTests;
  39363. /**
  39364. * @var ?bool
  39365. */
  39366. private $resolveDependencies;
  39367. /**
  39368. * @var ?bool
  39369. */
  39370. private $reverseList;
  39371. /**
  39372. * @var ?bool
  39373. */
  39374. private $stderr;
  39375. /**
  39376. * @var ?bool
  39377. */
  39378. private $strictCoverage;
  39379. /**
  39380. * @var ?bool
  39381. */
  39382. private $stopOnDefect;
  39383. /**
  39384. * @var ?bool
  39385. */
  39386. private $stopOnError;
  39387. /**
  39388. * @var ?bool
  39389. */
  39390. private $stopOnFailure;
  39391. /**
  39392. * @var ?bool
  39393. */
  39394. private $stopOnIncomplete;
  39395. /**
  39396. * @var ?bool
  39397. */
  39398. private $stopOnRisky;
  39399. /**
  39400. * @var ?bool
  39401. */
  39402. private $stopOnSkipped;
  39403. /**
  39404. * @var ?bool
  39405. */
  39406. private $stopOnWarning;
  39407. /**
  39408. * @var ?string
  39409. */
  39410. private $teamcityLogfile;
  39411. /**
  39412. * @var null|string[]
  39413. */
  39414. private $testdoxExcludeGroups;
  39415. /**
  39416. * @var null|string[]
  39417. */
  39418. private $testdoxGroups;
  39419. /**
  39420. * @var ?string
  39421. */
  39422. private $testdoxHtmlFile;
  39423. /**
  39424. * @var ?string
  39425. */
  39426. private $testdoxTextFile;
  39427. /**
  39428. * @var ?string
  39429. */
  39430. private $testdoxXmlFile;
  39431. /**
  39432. * @var null|string[]
  39433. */
  39434. private $testSuffixes;
  39435. /**
  39436. * @var ?string
  39437. */
  39438. private $testSuite;
  39439. /**
  39440. * @var null|string[]
  39441. */
  39442. private $unrecognizedOptions;
  39443. /**
  39444. * @var ?string
  39445. */
  39446. private $unrecognizedOrderBy;
  39447. /**
  39448. * @var ?bool
  39449. */
  39450. private $useDefaultConfiguration;
  39451. /**
  39452. * @var ?bool
  39453. */
  39454. private $verbose;
  39455. /**
  39456. * @var ?bool
  39457. */
  39458. private $version;
  39459. /**
  39460. * @var null|string[]
  39461. */
  39462. private $whitelist;
  39463. /**
  39464. * @var ?string
  39465. */
  39466. private $xdebugFilterFile;
  39467. /**
  39468. * @param null|int|string $columns
  39469. */
  39470. public function __construct(?string $argument, ?string $atLeastVersion, ?bool $backupGlobals, ?bool $backupStaticAttributes, ?bool $beStrictAboutChangesToGlobalState, ?bool $beStrictAboutResourceUsageDuringSmallTests, ?string $bootstrap, ?bool $cacheResult, ?string $cacheResultFile, ?bool $checkVersion, ?string $colors, $columns, ?string $configuration, ?string $coverageClover, ?string $coverageCrap4J, ?string $coverageHtml, ?string $coveragePhp, ?string $coverageText, ?bool $coverageTextShowUncoveredFiles, ?bool $coverageTextShowOnlySummary, ?string $coverageXml, ?bool $debug, ?int $defaultTimeLimit, ?bool $disableCodeCoverageIgnore, ?bool $disallowTestOutput, ?bool $disallowTodoAnnotatedTests, ?bool $enforceTimeLimit, ?array $excludeGroups, ?int $executionOrder, ?int $executionOrderDefects, ?array $extensions, ?array $unavailableExtensions, ?bool $failOnIncomplete, ?bool $failOnRisky, ?bool $failOnSkipped, ?bool $failOnWarning, ?string $filter, ?bool $generateConfiguration, ?array $groups, ?bool $help, ?string $includePath, ?array $iniSettings, ?string $junitLogfile, ?bool $listGroups, ?bool $listSuites, ?bool $listTests, ?string $listTestsXml, ?string $loader, ?bool $noCoverage, ?bool $noExtensions, ?bool $noInteraction, ?bool $noLogging, ?string $printer, ?bool $processIsolation, ?int $randomOrderSeed, ?int $repeat, ?bool $reportUselessTests, ?bool $resolveDependencies, ?bool $reverseList, ?bool $stderr, ?bool $strictCoverage, ?bool $stopOnDefect, ?bool $stopOnError, ?bool $stopOnFailure, ?bool $stopOnIncomplete, ?bool $stopOnRisky, ?bool $stopOnSkipped, ?bool $stopOnWarning, ?string $teamcityLogfile, ?array $testdoxExcludeGroups, ?array $testdoxGroups, ?string $testdoxHtmlFile, ?string $testdoxTextFile, ?string $testdoxXmlFile, ?array $testSuffixes, ?string $testSuite, ?array $unrecognizedOptions, ?string $unrecognizedOrderBy, ?bool $useDefaultConfiguration, ?bool $verbose, ?bool $version, ?array $whitelist, ?string $xdebugFilterFile)
  39471. {
  39472. $this->argument = $argument;
  39473. $this->atLeastVersion = $atLeastVersion;
  39474. $this->backupGlobals = $backupGlobals;
  39475. $this->backupStaticAttributes = $backupStaticAttributes;
  39476. $this->beStrictAboutChangesToGlobalState = $beStrictAboutChangesToGlobalState;
  39477. $this->beStrictAboutResourceUsageDuringSmallTests = $beStrictAboutResourceUsageDuringSmallTests;
  39478. $this->bootstrap = $bootstrap;
  39479. $this->cacheResult = $cacheResult;
  39480. $this->cacheResultFile = $cacheResultFile;
  39481. $this->checkVersion = $checkVersion;
  39482. $this->colors = $colors;
  39483. $this->columns = $columns;
  39484. $this->configuration = $configuration;
  39485. $this->coverageClover = $coverageClover;
  39486. $this->coverageCrap4J = $coverageCrap4J;
  39487. $this->coverageHtml = $coverageHtml;
  39488. $this->coveragePhp = $coveragePhp;
  39489. $this->coverageText = $coverageText;
  39490. $this->coverageTextShowUncoveredFiles = $coverageTextShowUncoveredFiles;
  39491. $this->coverageTextShowOnlySummary = $coverageTextShowOnlySummary;
  39492. $this->coverageXml = $coverageXml;
  39493. $this->debug = $debug;
  39494. $this->defaultTimeLimit = $defaultTimeLimit;
  39495. $this->disableCodeCoverageIgnore = $disableCodeCoverageIgnore;
  39496. $this->disallowTestOutput = $disallowTestOutput;
  39497. $this->disallowTodoAnnotatedTests = $disallowTodoAnnotatedTests;
  39498. $this->enforceTimeLimit = $enforceTimeLimit;
  39499. $this->excludeGroups = $excludeGroups;
  39500. $this->executionOrder = $executionOrder;
  39501. $this->executionOrderDefects = $executionOrderDefects;
  39502. $this->extensions = $extensions;
  39503. $this->unavailableExtensions = $unavailableExtensions;
  39504. $this->failOnIncomplete = $failOnIncomplete;
  39505. $this->failOnRisky = $failOnRisky;
  39506. $this->failOnSkipped = $failOnSkipped;
  39507. $this->failOnWarning = $failOnWarning;
  39508. $this->filter = $filter;
  39509. $this->generateConfiguration = $generateConfiguration;
  39510. $this->groups = $groups;
  39511. $this->help = $help;
  39512. $this->includePath = $includePath;
  39513. $this->iniSettings = $iniSettings;
  39514. $this->junitLogfile = $junitLogfile;
  39515. $this->listGroups = $listGroups;
  39516. $this->listSuites = $listSuites;
  39517. $this->listTests = $listTests;
  39518. $this->listTestsXml = $listTestsXml;
  39519. $this->loader = $loader;
  39520. $this->noCoverage = $noCoverage;
  39521. $this->noExtensions = $noExtensions;
  39522. $this->noInteraction = $noInteraction;
  39523. $this->noLogging = $noLogging;
  39524. $this->printer = $printer;
  39525. $this->processIsolation = $processIsolation;
  39526. $this->randomOrderSeed = $randomOrderSeed;
  39527. $this->repeat = $repeat;
  39528. $this->reportUselessTests = $reportUselessTests;
  39529. $this->resolveDependencies = $resolveDependencies;
  39530. $this->reverseList = $reverseList;
  39531. $this->stderr = $stderr;
  39532. $this->strictCoverage = $strictCoverage;
  39533. $this->stopOnDefect = $stopOnDefect;
  39534. $this->stopOnError = $stopOnError;
  39535. $this->stopOnFailure = $stopOnFailure;
  39536. $this->stopOnIncomplete = $stopOnIncomplete;
  39537. $this->stopOnRisky = $stopOnRisky;
  39538. $this->stopOnSkipped = $stopOnSkipped;
  39539. $this->stopOnWarning = $stopOnWarning;
  39540. $this->teamcityLogfile = $teamcityLogfile;
  39541. $this->testdoxExcludeGroups = $testdoxExcludeGroups;
  39542. $this->testdoxGroups = $testdoxGroups;
  39543. $this->testdoxHtmlFile = $testdoxHtmlFile;
  39544. $this->testdoxTextFile = $testdoxTextFile;
  39545. $this->testdoxXmlFile = $testdoxXmlFile;
  39546. $this->testSuffixes = $testSuffixes;
  39547. $this->testSuite = $testSuite;
  39548. $this->unrecognizedOptions = $unrecognizedOptions;
  39549. $this->unrecognizedOrderBy = $unrecognizedOrderBy;
  39550. $this->useDefaultConfiguration = $useDefaultConfiguration;
  39551. $this->verbose = $verbose;
  39552. $this->version = $version;
  39553. $this->whitelist = $whitelist;
  39554. $this->xdebugFilterFile = $xdebugFilterFile;
  39555. }
  39556. public function hasArgument() : bool
  39557. {
  39558. return $this->argument !== null;
  39559. }
  39560. public function argument() : string
  39561. {
  39562. if ($this->argument === null) {
  39563. throw new \PHPUnit\TextUI\Arguments\Exception();
  39564. }
  39565. return $this->argument;
  39566. }
  39567. public function hasAtLeastVersion() : bool
  39568. {
  39569. return $this->atLeastVersion !== null;
  39570. }
  39571. public function atLeastVersion() : string
  39572. {
  39573. if ($this->atLeastVersion === null) {
  39574. throw new \PHPUnit\TextUI\Arguments\Exception();
  39575. }
  39576. return $this->atLeastVersion;
  39577. }
  39578. public function hasBackupGlobals() : bool
  39579. {
  39580. return $this->backupGlobals !== null;
  39581. }
  39582. public function backupGlobals() : bool
  39583. {
  39584. if ($this->backupGlobals === null) {
  39585. throw new \PHPUnit\TextUI\Arguments\Exception();
  39586. }
  39587. return $this->backupGlobals;
  39588. }
  39589. public function hasBackupStaticAttributes() : bool
  39590. {
  39591. return $this->backupStaticAttributes !== null;
  39592. }
  39593. public function backupStaticAttributes() : bool
  39594. {
  39595. if ($this->backupStaticAttributes === null) {
  39596. throw new \PHPUnit\TextUI\Arguments\Exception();
  39597. }
  39598. return $this->backupStaticAttributes;
  39599. }
  39600. public function hasBeStrictAboutChangesToGlobalState() : bool
  39601. {
  39602. return $this->beStrictAboutChangesToGlobalState !== null;
  39603. }
  39604. public function beStrictAboutChangesToGlobalState() : bool
  39605. {
  39606. if ($this->beStrictAboutChangesToGlobalState === null) {
  39607. throw new \PHPUnit\TextUI\Arguments\Exception();
  39608. }
  39609. return $this->beStrictAboutChangesToGlobalState;
  39610. }
  39611. public function hasBeStrictAboutResourceUsageDuringSmallTests() : bool
  39612. {
  39613. return $this->beStrictAboutResourceUsageDuringSmallTests !== null;
  39614. }
  39615. public function beStrictAboutResourceUsageDuringSmallTests() : bool
  39616. {
  39617. if ($this->beStrictAboutResourceUsageDuringSmallTests === null) {
  39618. throw new \PHPUnit\TextUI\Arguments\Exception();
  39619. }
  39620. return $this->beStrictAboutResourceUsageDuringSmallTests;
  39621. }
  39622. public function hasBootstrap() : bool
  39623. {
  39624. return $this->bootstrap !== null;
  39625. }
  39626. public function bootstrap() : string
  39627. {
  39628. if ($this->bootstrap === null) {
  39629. throw new \PHPUnit\TextUI\Arguments\Exception();
  39630. }
  39631. return $this->bootstrap;
  39632. }
  39633. public function hasCacheResult() : bool
  39634. {
  39635. return $this->cacheResult !== null;
  39636. }
  39637. public function cacheResult() : bool
  39638. {
  39639. if ($this->cacheResult === null) {
  39640. throw new \PHPUnit\TextUI\Arguments\Exception();
  39641. }
  39642. return $this->cacheResult;
  39643. }
  39644. public function hasCacheResultFile() : bool
  39645. {
  39646. return $this->cacheResultFile !== null;
  39647. }
  39648. public function cacheResultFile() : string
  39649. {
  39650. if ($this->cacheResultFile === null) {
  39651. throw new \PHPUnit\TextUI\Arguments\Exception();
  39652. }
  39653. return $this->cacheResultFile;
  39654. }
  39655. public function hasCheckVersion() : bool
  39656. {
  39657. return $this->checkVersion !== null;
  39658. }
  39659. public function checkVersion() : bool
  39660. {
  39661. if ($this->checkVersion === null) {
  39662. throw new \PHPUnit\TextUI\Arguments\Exception();
  39663. }
  39664. return $this->checkVersion;
  39665. }
  39666. public function hasColors() : bool
  39667. {
  39668. return $this->colors !== null;
  39669. }
  39670. public function colors() : string
  39671. {
  39672. if ($this->colors === null) {
  39673. throw new \PHPUnit\TextUI\Arguments\Exception();
  39674. }
  39675. return $this->colors;
  39676. }
  39677. public function hasColumns() : bool
  39678. {
  39679. return $this->columns !== null;
  39680. }
  39681. public function columns()
  39682. {
  39683. if ($this->columns === null) {
  39684. throw new \PHPUnit\TextUI\Arguments\Exception();
  39685. }
  39686. return $this->columns;
  39687. }
  39688. public function hasConfiguration() : bool
  39689. {
  39690. return $this->configuration !== null;
  39691. }
  39692. public function configuration() : string
  39693. {
  39694. if ($this->configuration === null) {
  39695. throw new \PHPUnit\TextUI\Arguments\Exception();
  39696. }
  39697. return $this->configuration;
  39698. }
  39699. public function hasCoverageClover() : bool
  39700. {
  39701. return $this->coverageClover !== null;
  39702. }
  39703. public function coverageClover() : string
  39704. {
  39705. if ($this->coverageClover === null) {
  39706. throw new \PHPUnit\TextUI\Arguments\Exception();
  39707. }
  39708. return $this->coverageClover;
  39709. }
  39710. public function hasCoverageCrap4J() : bool
  39711. {
  39712. return $this->coverageCrap4J !== null;
  39713. }
  39714. public function coverageCrap4J() : string
  39715. {
  39716. if ($this->coverageCrap4J === null) {
  39717. throw new \PHPUnit\TextUI\Arguments\Exception();
  39718. }
  39719. return $this->coverageCrap4J;
  39720. }
  39721. public function hasCoverageHtml() : bool
  39722. {
  39723. return $this->coverageHtml !== null;
  39724. }
  39725. public function coverageHtml() : string
  39726. {
  39727. if ($this->coverageHtml === null) {
  39728. throw new \PHPUnit\TextUI\Arguments\Exception();
  39729. }
  39730. return $this->coverageHtml;
  39731. }
  39732. public function hasCoveragePhp() : bool
  39733. {
  39734. return $this->coveragePhp !== null;
  39735. }
  39736. public function coveragePhp() : string
  39737. {
  39738. if ($this->coveragePhp === null) {
  39739. throw new \PHPUnit\TextUI\Arguments\Exception();
  39740. }
  39741. return $this->coveragePhp;
  39742. }
  39743. public function hasCoverageText() : bool
  39744. {
  39745. return $this->coverageText !== null;
  39746. }
  39747. public function coverageText() : string
  39748. {
  39749. if ($this->coverageText === null) {
  39750. throw new \PHPUnit\TextUI\Arguments\Exception();
  39751. }
  39752. return $this->coverageText;
  39753. }
  39754. public function hasCoverageTextShowUncoveredFiles() : bool
  39755. {
  39756. return $this->coverageTextShowUncoveredFiles !== null;
  39757. }
  39758. public function coverageTextShowUncoveredFiles() : bool
  39759. {
  39760. if ($this->coverageTextShowUncoveredFiles === null) {
  39761. throw new \PHPUnit\TextUI\Arguments\Exception();
  39762. }
  39763. return $this->coverageTextShowUncoveredFiles;
  39764. }
  39765. public function hasCoverageTextShowOnlySummary() : bool
  39766. {
  39767. return $this->coverageTextShowOnlySummary !== null;
  39768. }
  39769. public function coverageTextShowOnlySummary() : bool
  39770. {
  39771. if ($this->coverageTextShowOnlySummary === null) {
  39772. throw new \PHPUnit\TextUI\Arguments\Exception();
  39773. }
  39774. return $this->coverageTextShowOnlySummary;
  39775. }
  39776. public function hasCoverageXml() : bool
  39777. {
  39778. return $this->coverageXml !== null;
  39779. }
  39780. public function coverageXml() : string
  39781. {
  39782. if ($this->coverageXml === null) {
  39783. throw new \PHPUnit\TextUI\Arguments\Exception();
  39784. }
  39785. return $this->coverageXml;
  39786. }
  39787. public function hasDebug() : bool
  39788. {
  39789. return $this->debug !== null;
  39790. }
  39791. public function debug() : bool
  39792. {
  39793. if ($this->debug === null) {
  39794. throw new \PHPUnit\TextUI\Arguments\Exception();
  39795. }
  39796. return $this->debug;
  39797. }
  39798. public function hasDefaultTimeLimit() : bool
  39799. {
  39800. return $this->defaultTimeLimit !== null;
  39801. }
  39802. public function defaultTimeLimit() : int
  39803. {
  39804. if ($this->defaultTimeLimit === null) {
  39805. throw new \PHPUnit\TextUI\Arguments\Exception();
  39806. }
  39807. return $this->defaultTimeLimit;
  39808. }
  39809. public function hasDisableCodeCoverageIgnore() : bool
  39810. {
  39811. return $this->disableCodeCoverageIgnore !== null;
  39812. }
  39813. public function disableCodeCoverageIgnore() : bool
  39814. {
  39815. if ($this->disableCodeCoverageIgnore === null) {
  39816. throw new \PHPUnit\TextUI\Arguments\Exception();
  39817. }
  39818. return $this->disableCodeCoverageIgnore;
  39819. }
  39820. public function hasDisallowTestOutput() : bool
  39821. {
  39822. return $this->disallowTestOutput !== null;
  39823. }
  39824. public function disallowTestOutput() : bool
  39825. {
  39826. if ($this->disallowTestOutput === null) {
  39827. throw new \PHPUnit\TextUI\Arguments\Exception();
  39828. }
  39829. return $this->disallowTestOutput;
  39830. }
  39831. public function hasDisallowTodoAnnotatedTests() : bool
  39832. {
  39833. return $this->disallowTodoAnnotatedTests !== null;
  39834. }
  39835. public function disallowTodoAnnotatedTests() : bool
  39836. {
  39837. if ($this->disallowTodoAnnotatedTests === null) {
  39838. throw new \PHPUnit\TextUI\Arguments\Exception();
  39839. }
  39840. return $this->disallowTodoAnnotatedTests;
  39841. }
  39842. public function hasEnforceTimeLimit() : bool
  39843. {
  39844. return $this->enforceTimeLimit !== null;
  39845. }
  39846. public function enforceTimeLimit() : bool
  39847. {
  39848. if ($this->enforceTimeLimit === null) {
  39849. throw new \PHPUnit\TextUI\Arguments\Exception();
  39850. }
  39851. return $this->enforceTimeLimit;
  39852. }
  39853. public function hasExcludeGroups() : bool
  39854. {
  39855. return $this->excludeGroups !== null;
  39856. }
  39857. public function excludeGroups() : array
  39858. {
  39859. if ($this->excludeGroups === null) {
  39860. throw new \PHPUnit\TextUI\Arguments\Exception();
  39861. }
  39862. return $this->excludeGroups;
  39863. }
  39864. public function hasExecutionOrder() : bool
  39865. {
  39866. return $this->executionOrder !== null;
  39867. }
  39868. public function executionOrder() : int
  39869. {
  39870. if ($this->executionOrder === null) {
  39871. throw new \PHPUnit\TextUI\Arguments\Exception();
  39872. }
  39873. return $this->executionOrder;
  39874. }
  39875. public function hasExecutionOrderDefects() : bool
  39876. {
  39877. return $this->executionOrderDefects !== null;
  39878. }
  39879. public function executionOrderDefects() : int
  39880. {
  39881. if ($this->executionOrderDefects === null) {
  39882. throw new \PHPUnit\TextUI\Arguments\Exception();
  39883. }
  39884. return $this->executionOrderDefects;
  39885. }
  39886. public function hasFailOnIncomplete() : bool
  39887. {
  39888. return $this->failOnIncomplete !== null;
  39889. }
  39890. public function failOnIncomplete() : bool
  39891. {
  39892. if ($this->failOnIncomplete === null) {
  39893. throw new \PHPUnit\TextUI\Arguments\Exception();
  39894. }
  39895. return $this->failOnIncomplete;
  39896. }
  39897. public function hasFailOnRisky() : bool
  39898. {
  39899. return $this->failOnRisky !== null;
  39900. }
  39901. public function failOnRisky() : bool
  39902. {
  39903. if ($this->failOnRisky === null) {
  39904. throw new \PHPUnit\TextUI\Arguments\Exception();
  39905. }
  39906. return $this->failOnRisky;
  39907. }
  39908. public function hasFailOnSkipped() : bool
  39909. {
  39910. return $this->failOnSkipped !== null;
  39911. }
  39912. public function failOnSkipped() : bool
  39913. {
  39914. if ($this->failOnSkipped === null) {
  39915. throw new \PHPUnit\TextUI\Arguments\Exception();
  39916. }
  39917. return $this->failOnSkipped;
  39918. }
  39919. public function hasFailOnWarning() : bool
  39920. {
  39921. return $this->failOnWarning !== null;
  39922. }
  39923. public function failOnWarning() : bool
  39924. {
  39925. if ($this->failOnWarning === null) {
  39926. throw new \PHPUnit\TextUI\Arguments\Exception();
  39927. }
  39928. return $this->failOnWarning;
  39929. }
  39930. public function hasFilter() : bool
  39931. {
  39932. return $this->filter !== null;
  39933. }
  39934. public function filter() : string
  39935. {
  39936. if ($this->filter === null) {
  39937. throw new \PHPUnit\TextUI\Arguments\Exception();
  39938. }
  39939. return $this->filter;
  39940. }
  39941. public function hasGenerateConfiguration() : bool
  39942. {
  39943. return $this->generateConfiguration !== null;
  39944. }
  39945. public function generateConfiguration() : bool
  39946. {
  39947. if ($this->generateConfiguration === null) {
  39948. throw new \PHPUnit\TextUI\Arguments\Exception();
  39949. }
  39950. return $this->generateConfiguration;
  39951. }
  39952. public function hasGroups() : bool
  39953. {
  39954. return $this->groups !== null;
  39955. }
  39956. public function groups() : array
  39957. {
  39958. if ($this->groups === null) {
  39959. throw new \PHPUnit\TextUI\Arguments\Exception();
  39960. }
  39961. return $this->groups;
  39962. }
  39963. public function hasHelp() : bool
  39964. {
  39965. return $this->help !== null;
  39966. }
  39967. public function help() : bool
  39968. {
  39969. if ($this->help === null) {
  39970. throw new \PHPUnit\TextUI\Arguments\Exception();
  39971. }
  39972. return $this->help;
  39973. }
  39974. public function hasIncludePath() : bool
  39975. {
  39976. return $this->includePath !== null;
  39977. }
  39978. public function includePath() : string
  39979. {
  39980. if ($this->includePath === null) {
  39981. throw new \PHPUnit\TextUI\Arguments\Exception();
  39982. }
  39983. return $this->includePath;
  39984. }
  39985. public function hasIniSettings() : bool
  39986. {
  39987. return $this->iniSettings !== null;
  39988. }
  39989. public function iniSettings() : array
  39990. {
  39991. if ($this->iniSettings === null) {
  39992. throw new \PHPUnit\TextUI\Arguments\Exception();
  39993. }
  39994. return $this->iniSettings;
  39995. }
  39996. public function hasJunitLogfile() : bool
  39997. {
  39998. return $this->junitLogfile !== null;
  39999. }
  40000. public function junitLogfile() : string
  40001. {
  40002. if ($this->junitLogfile === null) {
  40003. throw new \PHPUnit\TextUI\Arguments\Exception();
  40004. }
  40005. return $this->junitLogfile;
  40006. }
  40007. public function hasListGroups() : bool
  40008. {
  40009. return $this->listGroups !== null;
  40010. }
  40011. public function listGroups() : bool
  40012. {
  40013. if ($this->listGroups === null) {
  40014. throw new \PHPUnit\TextUI\Arguments\Exception();
  40015. }
  40016. return $this->listGroups;
  40017. }
  40018. public function hasListSuites() : bool
  40019. {
  40020. return $this->listSuites !== null;
  40021. }
  40022. public function listSuites() : bool
  40023. {
  40024. if ($this->listSuites === null) {
  40025. throw new \PHPUnit\TextUI\Arguments\Exception();
  40026. }
  40027. return $this->listSuites;
  40028. }
  40029. public function hasListTests() : bool
  40030. {
  40031. return $this->listTests !== null;
  40032. }
  40033. public function listTests() : bool
  40034. {
  40035. if ($this->listTests === null) {
  40036. throw new \PHPUnit\TextUI\Arguments\Exception();
  40037. }
  40038. return $this->listTests;
  40039. }
  40040. public function hasListTestsXml() : bool
  40041. {
  40042. return $this->listTestsXml !== null;
  40043. }
  40044. public function listTestsXml() : string
  40045. {
  40046. if ($this->listTestsXml === null) {
  40047. throw new \PHPUnit\TextUI\Arguments\Exception();
  40048. }
  40049. return $this->listTestsXml;
  40050. }
  40051. public function hasLoader() : bool
  40052. {
  40053. return $this->loader !== null;
  40054. }
  40055. public function loader() : string
  40056. {
  40057. if ($this->loader === null) {
  40058. throw new \PHPUnit\TextUI\Arguments\Exception();
  40059. }
  40060. return $this->loader;
  40061. }
  40062. public function hasNoCoverage() : bool
  40063. {
  40064. return $this->noCoverage !== null;
  40065. }
  40066. public function noCoverage() : bool
  40067. {
  40068. if ($this->noCoverage === null) {
  40069. throw new \PHPUnit\TextUI\Arguments\Exception();
  40070. }
  40071. return $this->noCoverage;
  40072. }
  40073. public function hasNoExtensions() : bool
  40074. {
  40075. return $this->noExtensions !== null;
  40076. }
  40077. public function noExtensions() : bool
  40078. {
  40079. if ($this->noExtensions === null) {
  40080. throw new \PHPUnit\TextUI\Arguments\Exception();
  40081. }
  40082. return $this->noExtensions;
  40083. }
  40084. public function hasExtensions() : bool
  40085. {
  40086. return $this->extensions !== null;
  40087. }
  40088. public function extensions() : array
  40089. {
  40090. if ($this->extensions === null) {
  40091. throw new \PHPUnit\TextUI\Arguments\Exception();
  40092. }
  40093. return $this->extensions;
  40094. }
  40095. public function hasUnavailableExtensions() : bool
  40096. {
  40097. return $this->unavailableExtensions !== null;
  40098. }
  40099. public function unavailableExtensions() : array
  40100. {
  40101. if ($this->unavailableExtensions === null) {
  40102. throw new \PHPUnit\TextUI\Arguments\Exception();
  40103. }
  40104. return $this->unavailableExtensions;
  40105. }
  40106. public function hasNoInteraction() : bool
  40107. {
  40108. return $this->noInteraction !== null;
  40109. }
  40110. public function noInteraction() : bool
  40111. {
  40112. if ($this->noInteraction === null) {
  40113. throw new \PHPUnit\TextUI\Arguments\Exception();
  40114. }
  40115. return $this->noInteraction;
  40116. }
  40117. public function hasNoLogging() : bool
  40118. {
  40119. return $this->noLogging !== null;
  40120. }
  40121. public function noLogging() : bool
  40122. {
  40123. if ($this->noLogging === null) {
  40124. throw new \PHPUnit\TextUI\Arguments\Exception();
  40125. }
  40126. return $this->noLogging;
  40127. }
  40128. public function hasPrinter() : bool
  40129. {
  40130. return $this->printer !== null;
  40131. }
  40132. public function printer() : string
  40133. {
  40134. if ($this->printer === null) {
  40135. throw new \PHPUnit\TextUI\Arguments\Exception();
  40136. }
  40137. return $this->printer;
  40138. }
  40139. public function hasProcessIsolation() : bool
  40140. {
  40141. return $this->processIsolation !== null;
  40142. }
  40143. public function processIsolation() : bool
  40144. {
  40145. if ($this->processIsolation === null) {
  40146. throw new \PHPUnit\TextUI\Arguments\Exception();
  40147. }
  40148. return $this->processIsolation;
  40149. }
  40150. public function hasRandomOrderSeer() : bool
  40151. {
  40152. return $this->randomOrderSeed !== null;
  40153. }
  40154. public function randomOrderSeed() : int
  40155. {
  40156. if ($this->randomOrderSeed === null) {
  40157. throw new \PHPUnit\TextUI\Arguments\Exception();
  40158. }
  40159. return $this->randomOrderSeed;
  40160. }
  40161. public function hasRepeat() : bool
  40162. {
  40163. return $this->repeat !== null;
  40164. }
  40165. public function repeat() : int
  40166. {
  40167. if ($this->repeat === null) {
  40168. throw new \PHPUnit\TextUI\Arguments\Exception();
  40169. }
  40170. return $this->repeat;
  40171. }
  40172. public function hasReportUselessTests() : bool
  40173. {
  40174. return $this->reportUselessTests !== null;
  40175. }
  40176. public function reportUselessTests() : bool
  40177. {
  40178. if ($this->reportUselessTests === null) {
  40179. throw new \PHPUnit\TextUI\Arguments\Exception();
  40180. }
  40181. return $this->reportUselessTests;
  40182. }
  40183. public function hasResolveDependencies() : bool
  40184. {
  40185. return $this->resolveDependencies !== null;
  40186. }
  40187. public function resolveDependencies() : bool
  40188. {
  40189. if ($this->resolveDependencies === null) {
  40190. throw new \PHPUnit\TextUI\Arguments\Exception();
  40191. }
  40192. return $this->resolveDependencies;
  40193. }
  40194. public function hasReverseList() : bool
  40195. {
  40196. return $this->reverseList !== null;
  40197. }
  40198. public function reverseList() : bool
  40199. {
  40200. if ($this->reverseList === null) {
  40201. throw new \PHPUnit\TextUI\Arguments\Exception();
  40202. }
  40203. return $this->reverseList;
  40204. }
  40205. public function hasStderr() : bool
  40206. {
  40207. return $this->stderr !== null;
  40208. }
  40209. public function stderr() : bool
  40210. {
  40211. if ($this->stderr === null) {
  40212. throw new \PHPUnit\TextUI\Arguments\Exception();
  40213. }
  40214. return $this->stderr;
  40215. }
  40216. public function hasStrictCoverage() : bool
  40217. {
  40218. return $this->strictCoverage !== null;
  40219. }
  40220. public function strictCoverage() : bool
  40221. {
  40222. if ($this->strictCoverage === null) {
  40223. throw new \PHPUnit\TextUI\Arguments\Exception();
  40224. }
  40225. return $this->strictCoverage;
  40226. }
  40227. public function hasStopOnDefect() : bool
  40228. {
  40229. return $this->stopOnDefect !== null;
  40230. }
  40231. public function stopOnDefect() : bool
  40232. {
  40233. if ($this->stopOnDefect === null) {
  40234. throw new \PHPUnit\TextUI\Arguments\Exception();
  40235. }
  40236. return $this->stopOnDefect;
  40237. }
  40238. public function hasStopOnError() : bool
  40239. {
  40240. return $this->stopOnError !== null;
  40241. }
  40242. public function stopOnError() : bool
  40243. {
  40244. if ($this->stopOnError === null) {
  40245. throw new \PHPUnit\TextUI\Arguments\Exception();
  40246. }
  40247. return $this->stopOnError;
  40248. }
  40249. public function hasStopOnFailure() : bool
  40250. {
  40251. return $this->stopOnFailure !== null;
  40252. }
  40253. public function stopOnFailure() : bool
  40254. {
  40255. if ($this->stopOnFailure === null) {
  40256. throw new \PHPUnit\TextUI\Arguments\Exception();
  40257. }
  40258. return $this->stopOnFailure;
  40259. }
  40260. public function hasStopOnIncomplete() : bool
  40261. {
  40262. return $this->stopOnIncomplete !== null;
  40263. }
  40264. public function stopOnIncomplete() : bool
  40265. {
  40266. if ($this->stopOnIncomplete === null) {
  40267. throw new \PHPUnit\TextUI\Arguments\Exception();
  40268. }
  40269. return $this->stopOnIncomplete;
  40270. }
  40271. public function hasStopOnRisky() : bool
  40272. {
  40273. return $this->stopOnRisky !== null;
  40274. }
  40275. public function stopOnRisky() : bool
  40276. {
  40277. if ($this->stopOnRisky === null) {
  40278. throw new \PHPUnit\TextUI\Arguments\Exception();
  40279. }
  40280. return $this->stopOnRisky;
  40281. }
  40282. public function hasStopOnSkipped() : bool
  40283. {
  40284. return $this->stopOnSkipped !== null;
  40285. }
  40286. public function stopOnSkipped() : bool
  40287. {
  40288. if ($this->stopOnSkipped === null) {
  40289. throw new \PHPUnit\TextUI\Arguments\Exception();
  40290. }
  40291. return $this->stopOnSkipped;
  40292. }
  40293. public function hasStopOnWarning() : bool
  40294. {
  40295. return $this->stopOnWarning !== null;
  40296. }
  40297. public function stopOnWarning() : bool
  40298. {
  40299. if ($this->stopOnWarning === null) {
  40300. throw new \PHPUnit\TextUI\Arguments\Exception();
  40301. }
  40302. return $this->stopOnWarning;
  40303. }
  40304. public function hasTeamcityLogfile() : bool
  40305. {
  40306. return $this->teamcityLogfile !== null;
  40307. }
  40308. public function teamcityLogfile() : string
  40309. {
  40310. if ($this->teamcityLogfile === null) {
  40311. throw new \PHPUnit\TextUI\Arguments\Exception();
  40312. }
  40313. return $this->teamcityLogfile;
  40314. }
  40315. public function hasTestdoxExcludeGroups() : bool
  40316. {
  40317. return $this->testdoxExcludeGroups !== null;
  40318. }
  40319. public function testdoxExcludeGroups() : array
  40320. {
  40321. if ($this->testdoxExcludeGroups === null) {
  40322. throw new \PHPUnit\TextUI\Arguments\Exception();
  40323. }
  40324. return $this->testdoxExcludeGroups;
  40325. }
  40326. public function hasTestdoxGroups() : bool
  40327. {
  40328. return $this->testdoxGroups !== null;
  40329. }
  40330. public function testdoxGroups() : array
  40331. {
  40332. if ($this->testdoxGroups === null) {
  40333. throw new \PHPUnit\TextUI\Arguments\Exception();
  40334. }
  40335. return $this->testdoxGroups;
  40336. }
  40337. public function hasTestdoxHtmlFile() : bool
  40338. {
  40339. return $this->testdoxHtmlFile !== null;
  40340. }
  40341. public function testdoxHtmlFile() : string
  40342. {
  40343. if ($this->testdoxHtmlFile === null) {
  40344. throw new \PHPUnit\TextUI\Arguments\Exception();
  40345. }
  40346. return $this->testdoxHtmlFile;
  40347. }
  40348. public function hasTestdoxTextFile() : bool
  40349. {
  40350. return $this->testdoxTextFile !== null;
  40351. }
  40352. public function testdoxTextFile() : string
  40353. {
  40354. if ($this->testdoxTextFile === null) {
  40355. throw new \PHPUnit\TextUI\Arguments\Exception();
  40356. }
  40357. return $this->testdoxTextFile;
  40358. }
  40359. public function hasTestdoxXmlFile() : bool
  40360. {
  40361. return $this->testdoxXmlFile !== null;
  40362. }
  40363. public function testdoxXmlFile() : string
  40364. {
  40365. if ($this->testdoxXmlFile === null) {
  40366. throw new \PHPUnit\TextUI\Arguments\Exception();
  40367. }
  40368. return $this->testdoxXmlFile;
  40369. }
  40370. public function hasTestSuffixes() : bool
  40371. {
  40372. return $this->testSuffixes !== null;
  40373. }
  40374. public function testSuffixes() : array
  40375. {
  40376. if ($this->testSuffixes === null) {
  40377. throw new \PHPUnit\TextUI\Arguments\Exception();
  40378. }
  40379. return $this->testSuffixes;
  40380. }
  40381. public function hasTestSuite() : bool
  40382. {
  40383. return $this->testSuite !== null;
  40384. }
  40385. public function testSuite() : string
  40386. {
  40387. if ($this->testSuite === null) {
  40388. throw new \PHPUnit\TextUI\Arguments\Exception();
  40389. }
  40390. return $this->testSuite;
  40391. }
  40392. public function hasUnrecognizedOptions() : bool
  40393. {
  40394. return $this->unrecognizedOptions !== null;
  40395. }
  40396. public function unrecognizedOptions() : array
  40397. {
  40398. if ($this->unrecognizedOptions === null) {
  40399. throw new \PHPUnit\TextUI\Arguments\Exception();
  40400. }
  40401. return $this->unrecognizedOptions;
  40402. }
  40403. public function hasUnrecognizedOrderBy() : bool
  40404. {
  40405. return $this->unrecognizedOrderBy !== null;
  40406. }
  40407. public function unrecognizedOrderBy() : string
  40408. {
  40409. if ($this->unrecognizedOrderBy === null) {
  40410. throw new \PHPUnit\TextUI\Arguments\Exception();
  40411. }
  40412. return $this->unrecognizedOrderBy;
  40413. }
  40414. public function hasUseDefaultConfiguration() : bool
  40415. {
  40416. return $this->useDefaultConfiguration !== null;
  40417. }
  40418. public function useDefaultConfiguration() : bool
  40419. {
  40420. if ($this->useDefaultConfiguration === null) {
  40421. throw new \PHPUnit\TextUI\Arguments\Exception();
  40422. }
  40423. return $this->useDefaultConfiguration;
  40424. }
  40425. public function hasVerbose() : bool
  40426. {
  40427. return $this->verbose !== null;
  40428. }
  40429. public function verbose() : bool
  40430. {
  40431. if ($this->verbose === null) {
  40432. throw new \PHPUnit\TextUI\Arguments\Exception();
  40433. }
  40434. return $this->verbose;
  40435. }
  40436. public function hasVersion() : bool
  40437. {
  40438. return $this->version !== null;
  40439. }
  40440. public function version() : bool
  40441. {
  40442. if ($this->version === null) {
  40443. throw new \PHPUnit\TextUI\Arguments\Exception();
  40444. }
  40445. return $this->version;
  40446. }
  40447. public function hasWhitelist() : bool
  40448. {
  40449. return $this->whitelist !== null;
  40450. }
  40451. public function whitelist() : array
  40452. {
  40453. if ($this->whitelist === null) {
  40454. throw new \PHPUnit\TextUI\Arguments\Exception();
  40455. }
  40456. return $this->whitelist;
  40457. }
  40458. public function hasXdebugFilterFile() : bool
  40459. {
  40460. return $this->xdebugFilterFile !== null;
  40461. }
  40462. public function xdebugFilterFile() : string
  40463. {
  40464. if ($this->xdebugFilterFile === null) {
  40465. throw new \PHPUnit\TextUI\Arguments\Exception();
  40466. }
  40467. return $this->xdebugFilterFile;
  40468. }
  40469. }
  40470. <?php
  40471. declare (strict_types=1);
  40472. /*
  40473. * This file is part of PHPUnit.
  40474. *
  40475. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  40476. *
  40477. * For the full copyright and license information, please view the LICENSE
  40478. * file that was distributed with this source code.
  40479. */
  40480. namespace PHPUnit\TextUI\Arguments;
  40481. use PHPUnit\Runner\TestSuiteSorter;
  40482. use PHPUnit\TextUI\Configuration\Extension;
  40483. use PHPUnit\TextUI\DefaultResultPrinter;
  40484. use PHPUnit\Util\Exception as UtilException;
  40485. use PHPUnit\Util\Getopt;
  40486. use PHPUnit\Util\Log\TeamCity;
  40487. use PHPUnit\Util\TestDox\CliTestDoxPrinter;
  40488. /**
  40489. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  40490. */
  40491. final class ArgumentsBuilder
  40492. {
  40493. private const LONG_OPTIONS = ['atleast-version=', 'prepend=', 'bootstrap=', 'cache-result', 'do-not-cache-result', 'cache-result-file=', 'check-version', 'colors==', 'columns=', 'configuration=', 'coverage-clover=', 'coverage-crap4j=', 'coverage-html=', 'coverage-php=', 'coverage-text==', 'coverage-xml=', 'debug', 'disallow-test-output', 'disallow-resource-usage', 'disallow-todo-tests', 'default-time-limit=', 'enforce-time-limit', 'exclude-group=', 'extensions=', 'filter=', 'generate-configuration', 'globals-backup', 'group=', 'help', 'resolve-dependencies', 'ignore-dependencies', 'include-path=', 'list-groups', 'list-suites', 'list-tests', 'list-tests-xml=', 'loader=', 'log-junit=', 'log-teamcity=', 'no-configuration', 'no-coverage', 'no-logging', 'no-interaction', 'no-extensions', 'order-by=', 'printer=', 'process-isolation', 'repeat=', 'dont-report-useless-tests', 'random-order', 'random-order-seed=', 'reverse-order', 'reverse-list', 'static-backup', 'stderr', 'stop-on-defect', 'stop-on-error', 'stop-on-failure', 'stop-on-warning', 'stop-on-incomplete', 'stop-on-risky', 'stop-on-skipped', 'fail-on-warning', 'fail-on-risky', 'strict-coverage', 'disable-coverage-ignore', 'strict-global-state', 'teamcity', 'testdox', 'testdox-group=', 'testdox-exclude-group=', 'testdox-html=', 'testdox-text=', 'testdox-xml=', 'test-suffix=', 'testsuite=', 'verbose', 'version', 'whitelist=', 'dump-xdebug-filter='];
  40494. private const SHORT_OPTIONS = 'd:c:hv';
  40495. public function fromParameters(array $parameters, array $additionalLongOptions) : \PHPUnit\TextUI\Arguments\Arguments
  40496. {
  40497. try {
  40498. $options = \PHPUnit\Util\Getopt::getopt($parameters, self::SHORT_OPTIONS, \array_merge(self::LONG_OPTIONS, $additionalLongOptions));
  40499. } catch (\PHPUnit\Util\Exception $e) {
  40500. throw new \PHPUnit\TextUI\Arguments\Exception($e->getMessage(), (int) $e->getCode(), $e);
  40501. }
  40502. $argument = null;
  40503. $atLeastVersion = null;
  40504. $backupGlobals = null;
  40505. $backupStaticAttributes = null;
  40506. $beStrictAboutChangesToGlobalState = null;
  40507. $beStrictAboutResourceUsageDuringSmallTests = null;
  40508. $bootstrap = null;
  40509. $cacheResult = null;
  40510. $cacheResultFile = null;
  40511. $checkVersion = null;
  40512. $colors = null;
  40513. $columns = null;
  40514. $configuration = null;
  40515. $coverageClover = null;
  40516. $coverageCrap4J = null;
  40517. $coverageHtml = null;
  40518. $coveragePhp = null;
  40519. $coverageText = null;
  40520. $coverageTextShowUncoveredFiles = null;
  40521. $coverageTextShowOnlySummary = null;
  40522. $coverageXml = null;
  40523. $debug = null;
  40524. $defaultTimeLimit = null;
  40525. $disableCodeCoverageIgnore = null;
  40526. $disallowTestOutput = null;
  40527. $disallowTodoAnnotatedTests = null;
  40528. $enforceTimeLimit = null;
  40529. $excludeGroups = null;
  40530. $executionOrder = null;
  40531. $executionOrderDefects = null;
  40532. $extensions = [];
  40533. $unavailableExtensions = [];
  40534. $failOnIncomplete = null;
  40535. $failOnRisky = null;
  40536. $failOnSkipped = null;
  40537. $failOnWarning = null;
  40538. $filter = null;
  40539. $generateConfiguration = null;
  40540. $groups = null;
  40541. $help = null;
  40542. $includePath = null;
  40543. $iniSettings = [];
  40544. $junitLogfile = null;
  40545. $listGroups = null;
  40546. $listSuites = null;
  40547. $listTests = null;
  40548. $listTestsXml = null;
  40549. $loader = null;
  40550. $noCoverage = null;
  40551. $noExtensions = null;
  40552. $noInteraction = null;
  40553. $noLogging = null;
  40554. $printer = null;
  40555. $processIsolation = null;
  40556. $randomOrderSeed = null;
  40557. $repeat = null;
  40558. $reportUselessTests = null;
  40559. $resolveDependencies = null;
  40560. $reverseList = null;
  40561. $stderr = null;
  40562. $strictCoverage = null;
  40563. $stopOnDefect = null;
  40564. $stopOnError = null;
  40565. $stopOnFailure = null;
  40566. $stopOnIncomplete = null;
  40567. $stopOnRisky = null;
  40568. $stopOnSkipped = null;
  40569. $stopOnWarning = null;
  40570. $teamcityLogfile = null;
  40571. $testdoxExcludeGroups = null;
  40572. $testdoxGroups = null;
  40573. $testdoxHtmlFile = null;
  40574. $testdoxTextFile = null;
  40575. $testdoxXmlFile = null;
  40576. $testSuffixes = null;
  40577. $testSuite = null;
  40578. $unrecognizedOptions = [];
  40579. $unrecognizedOrderBy = null;
  40580. $useDefaultConfiguration = null;
  40581. $verbose = null;
  40582. $version = null;
  40583. $whitelist = null;
  40584. $xdebugFilterFile = null;
  40585. if (isset($options[1][0])) {
  40586. $argument = $options[1][0];
  40587. }
  40588. foreach ($options[0] as $option) {
  40589. switch ($option[0]) {
  40590. case '--colors':
  40591. $colors = $option[1] ?: \PHPUnit\TextUI\DefaultResultPrinter::COLOR_AUTO;
  40592. break;
  40593. case '--bootstrap':
  40594. $bootstrap = $option[1];
  40595. break;
  40596. case '--cache-result':
  40597. $cacheResult = \true;
  40598. break;
  40599. case '--do-not-cache-result':
  40600. $cacheResult = \false;
  40601. break;
  40602. case '--cache-result-file':
  40603. $cacheResultFile = $option[1];
  40604. break;
  40605. case '--columns':
  40606. if (\is_numeric($option[1])) {
  40607. $columns = (int) $option[1];
  40608. } elseif ($option[1] === 'max') {
  40609. $columns = 'max';
  40610. }
  40611. break;
  40612. case 'c':
  40613. case '--configuration':
  40614. $configuration = $option[1];
  40615. break;
  40616. case '--coverage-clover':
  40617. $coverageClover = $option[1];
  40618. break;
  40619. case '--coverage-crap4j':
  40620. $coverageCrap4J = $option[1];
  40621. break;
  40622. case '--coverage-html':
  40623. $coverageHtml = $option[1];
  40624. break;
  40625. case '--coverage-php':
  40626. $coveragePhp = $option[1];
  40627. break;
  40628. case '--coverage-text':
  40629. if ($option[1] === null) {
  40630. $option[1] = 'php://stdout';
  40631. }
  40632. $coverageText = $option[1];
  40633. $coverageTextShowUncoveredFiles = \false;
  40634. $coverageTextShowOnlySummary = \false;
  40635. break;
  40636. case '--coverage-xml':
  40637. $coverageXml = $option[1];
  40638. break;
  40639. case 'd':
  40640. $tmp = \explode('=', $option[1]);
  40641. if (isset($tmp[0])) {
  40642. if (isset($tmp[1])) {
  40643. $iniSettings[$tmp[0]] = $tmp[1];
  40644. } else {
  40645. $iniSettings[$tmp[0]] = '1';
  40646. }
  40647. }
  40648. break;
  40649. case '--debug':
  40650. $debug = \true;
  40651. break;
  40652. case 'h':
  40653. case '--help':
  40654. $help = \true;
  40655. break;
  40656. case '--filter':
  40657. $filter = $option[1];
  40658. break;
  40659. case '--testsuite':
  40660. $testSuite = $option[1];
  40661. break;
  40662. case '--generate-configuration':
  40663. $generateConfiguration = \true;
  40664. break;
  40665. case '--group':
  40666. $groups = \explode(',', $option[1]);
  40667. break;
  40668. case '--exclude-group':
  40669. $excludeGroups = \explode(',', $option[1]);
  40670. break;
  40671. case '--test-suffix':
  40672. $testSuffixes = \explode(',', $option[1]);
  40673. break;
  40674. case '--include-path':
  40675. $includePath = $option[1];
  40676. break;
  40677. case '--list-groups':
  40678. $listGroups = \true;
  40679. break;
  40680. case '--list-suites':
  40681. $listSuites = \true;
  40682. break;
  40683. case '--list-tests':
  40684. $listTests = \true;
  40685. break;
  40686. case '--list-tests-xml':
  40687. $listTestsXml = $option[1];
  40688. break;
  40689. case '--printer':
  40690. $printer = $option[1];
  40691. break;
  40692. case '--loader':
  40693. $loader = $option[1];
  40694. break;
  40695. case '--log-junit':
  40696. $junitLogfile = $option[1];
  40697. break;
  40698. case '--log-teamcity':
  40699. $teamcityLogfile = $option[1];
  40700. break;
  40701. case '--order-by':
  40702. foreach (\explode(',', $option[1]) as $order) {
  40703. switch ($order) {
  40704. case 'default':
  40705. $executionOrder = \PHPUnit\Runner\TestSuiteSorter::ORDER_DEFAULT;
  40706. $executionOrderDefects = \PHPUnit\Runner\TestSuiteSorter::ORDER_DEFAULT;
  40707. $resolveDependencies = \true;
  40708. break;
  40709. case 'defects':
  40710. $executionOrderDefects = \PHPUnit\Runner\TestSuiteSorter::ORDER_DEFECTS_FIRST;
  40711. break;
  40712. case 'depends':
  40713. $resolveDependencies = \true;
  40714. break;
  40715. case 'duration':
  40716. $executionOrder = \PHPUnit\Runner\TestSuiteSorter::ORDER_DURATION;
  40717. break;
  40718. case 'no-depends':
  40719. $resolveDependencies = \false;
  40720. break;
  40721. case 'random':
  40722. $executionOrder = \PHPUnit\Runner\TestSuiteSorter::ORDER_RANDOMIZED;
  40723. break;
  40724. case 'reverse':
  40725. $executionOrder = \PHPUnit\Runner\TestSuiteSorter::ORDER_REVERSED;
  40726. break;
  40727. case 'size':
  40728. $executionOrder = \PHPUnit\Runner\TestSuiteSorter::ORDER_SIZE;
  40729. break;
  40730. default:
  40731. $unrecognizedOrderBy = $order;
  40732. }
  40733. }
  40734. break;
  40735. case '--process-isolation':
  40736. $processIsolation = \true;
  40737. break;
  40738. case '--repeat':
  40739. $repeat = (int) $option[1];
  40740. break;
  40741. case '--stderr':
  40742. $stderr = \true;
  40743. break;
  40744. case '--stop-on-defect':
  40745. $stopOnDefect = \true;
  40746. break;
  40747. case '--stop-on-error':
  40748. $stopOnError = \true;
  40749. break;
  40750. case '--stop-on-failure':
  40751. $stopOnFailure = \true;
  40752. break;
  40753. case '--stop-on-warning':
  40754. $stopOnWarning = \true;
  40755. break;
  40756. case '--stop-on-incomplete':
  40757. $stopOnIncomplete = \true;
  40758. break;
  40759. case '--stop-on-risky':
  40760. $stopOnRisky = \true;
  40761. break;
  40762. case '--stop-on-skipped':
  40763. $stopOnSkipped = \true;
  40764. break;
  40765. case '--fail-on-incomplete':
  40766. $failOnIncomplete = \true;
  40767. break;
  40768. case '--fail-on-risky':
  40769. $failOnRisky = \true;
  40770. break;
  40771. case '--fail-on-Skipped':
  40772. $failOnSkipped = \true;
  40773. break;
  40774. case '--fail-on-warning':
  40775. $failOnWarning = \true;
  40776. break;
  40777. case '--teamcity':
  40778. $printer = \PHPUnit\Util\Log\TeamCity::class;
  40779. break;
  40780. case '--testdox':
  40781. $printer = \PHPUnit\Util\TestDox\CliTestDoxPrinter::class;
  40782. break;
  40783. case '--testdox-group':
  40784. $testdoxGroups = \explode(',', $option[1]);
  40785. break;
  40786. case '--testdox-exclude-group':
  40787. $testdoxExcludeGroups = \explode(',', $option[1]);
  40788. break;
  40789. case '--testdox-html':
  40790. $testdoxHtmlFile = $option[1];
  40791. break;
  40792. case '--testdox-text':
  40793. $testdoxTextFile = $option[1];
  40794. break;
  40795. case '--testdox-xml':
  40796. $testdoxXmlFile = $option[1];
  40797. break;
  40798. case '--no-configuration':
  40799. $useDefaultConfiguration = \false;
  40800. break;
  40801. case '--extensions':
  40802. foreach (\explode(',', $option[1]) as $extensionClass) {
  40803. if (!\class_exists($extensionClass)) {
  40804. $unavailableExtensions[] = $extensionClass;
  40805. continue;
  40806. }
  40807. $extensions[] = new \PHPUnit\TextUI\Configuration\Extension($extensionClass, '', []);
  40808. }
  40809. break;
  40810. case '--no-extensions':
  40811. $noExtensions = \true;
  40812. break;
  40813. case '--no-coverage':
  40814. $noCoverage = \true;
  40815. break;
  40816. case '--no-logging':
  40817. $noLogging = \true;
  40818. break;
  40819. case '--no-interaction':
  40820. $noInteraction = \true;
  40821. break;
  40822. case '--globals-backup':
  40823. $backupGlobals = \true;
  40824. break;
  40825. case '--static-backup':
  40826. $backupStaticAttributes = \true;
  40827. break;
  40828. case 'v':
  40829. case '--verbose':
  40830. $verbose = \true;
  40831. break;
  40832. case '--atleast-version':
  40833. $atLeastVersion = $option[1];
  40834. break;
  40835. case '--version':
  40836. $version = \true;
  40837. break;
  40838. case '--dont-report-useless-tests':
  40839. $reportUselessTests = \false;
  40840. break;
  40841. case '--strict-coverage':
  40842. $strictCoverage = \true;
  40843. break;
  40844. case '--disable-coverage-ignore':
  40845. $disableCodeCoverageIgnore = \true;
  40846. break;
  40847. case '--strict-global-state':
  40848. $beStrictAboutChangesToGlobalState = \true;
  40849. break;
  40850. case '--disallow-test-output':
  40851. $disallowTestOutput = \true;
  40852. break;
  40853. case '--disallow-resource-usage':
  40854. $beStrictAboutResourceUsageDuringSmallTests = \true;
  40855. break;
  40856. case '--default-time-limit':
  40857. $defaultTimeLimit = (int) $option[1];
  40858. break;
  40859. case '--enforce-time-limit':
  40860. $enforceTimeLimit = \true;
  40861. break;
  40862. case '--disallow-todo-tests':
  40863. $disallowTodoAnnotatedTests = \true;
  40864. break;
  40865. case '--reverse-list':
  40866. $reverseList = \true;
  40867. break;
  40868. case '--check-version':
  40869. $checkVersion = \true;
  40870. break;
  40871. case '--whitelist':
  40872. if ($whitelist === null) {
  40873. $whitelist = [];
  40874. }
  40875. $whitelist[] = $option[1];
  40876. break;
  40877. case '--random-order':
  40878. $executionOrder = \PHPUnit\Runner\TestSuiteSorter::ORDER_RANDOMIZED;
  40879. break;
  40880. case '--random-order-seed':
  40881. $randomOrderSeed = (int) $option[1];
  40882. break;
  40883. case '--resolve-dependencies':
  40884. $resolveDependencies = \true;
  40885. break;
  40886. case '--ignore-dependencies':
  40887. $resolveDependencies = \false;
  40888. break;
  40889. case '--reverse-order':
  40890. $executionOrder = \PHPUnit\Runner\TestSuiteSorter::ORDER_REVERSED;
  40891. break;
  40892. case '--dump-xdebug-filter':
  40893. $xdebugFilterFile = $option[1];
  40894. break;
  40895. default:
  40896. $unrecognizedOptions[\str_replace('--', '', $option[0])] = $option[1];
  40897. }
  40898. }
  40899. if (empty($extensions)) {
  40900. $extensions = null;
  40901. }
  40902. if (empty($unavailableExtensions)) {
  40903. $unavailableExtensions = null;
  40904. }
  40905. if (empty($iniSettings)) {
  40906. $iniSettings = null;
  40907. }
  40908. if (empty($unrecognizedOptions)) {
  40909. $unrecognizedOptions = null;
  40910. }
  40911. if (empty($whitelist)) {
  40912. $whitelist = null;
  40913. }
  40914. return new \PHPUnit\TextUI\Arguments\Arguments($argument, $atLeastVersion, $backupGlobals, $backupStaticAttributes, $beStrictAboutChangesToGlobalState, $beStrictAboutResourceUsageDuringSmallTests, $bootstrap, $cacheResult, $cacheResultFile, $checkVersion, $colors, $columns, $configuration, $coverageClover, $coverageCrap4J, $coverageHtml, $coveragePhp, $coverageText, $coverageTextShowUncoveredFiles, $coverageTextShowOnlySummary, $coverageXml, $debug, $defaultTimeLimit, $disableCodeCoverageIgnore, $disallowTestOutput, $disallowTodoAnnotatedTests, $enforceTimeLimit, $excludeGroups, $executionOrder, $executionOrderDefects, $extensions, $unavailableExtensions, $failOnIncomplete, $failOnRisky, $failOnSkipped, $failOnWarning, $filter, $generateConfiguration, $groups, $help, $includePath, $iniSettings, $junitLogfile, $listGroups, $listSuites, $listTests, $listTestsXml, $loader, $noCoverage, $noExtensions, $noInteraction, $noLogging, $printer, $processIsolation, $randomOrderSeed, $repeat, $reportUselessTests, $resolveDependencies, $reverseList, $stderr, $strictCoverage, $stopOnDefect, $stopOnError, $stopOnFailure, $stopOnIncomplete, $stopOnRisky, $stopOnSkipped, $stopOnWarning, $teamcityLogfile, $testdoxExcludeGroups, $testdoxGroups, $testdoxHtmlFile, $testdoxTextFile, $testdoxXmlFile, $testSuffixes, $testSuite, $unrecognizedOptions, $unrecognizedOrderBy, $useDefaultConfiguration, $verbose, $version, $whitelist, $xdebugFilterFile);
  40915. }
  40916. }
  40917. <?php
  40918. declare (strict_types=1);
  40919. /*
  40920. * This file is part of PHPUnit.
  40921. *
  40922. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  40923. *
  40924. * For the full copyright and license information, please view the LICENSE
  40925. * file that was distributed with this source code.
  40926. */
  40927. namespace PHPUnit\TextUI\Arguments;
  40928. /**
  40929. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  40930. */
  40931. final class Exception extends \RuntimeException implements \PHPUnit\Exception
  40932. {
  40933. }
  40934. <?php
  40935. declare (strict_types=1);
  40936. /*
  40937. * This file is part of PHPUnit.
  40938. *
  40939. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  40940. *
  40941. * For the full copyright and license information, please view the LICENSE
  40942. * file that was distributed with this source code.
  40943. */
  40944. namespace PHPUnit\TextUI\Arguments;
  40945. /**
  40946. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  40947. */
  40948. final class ArgumentsMapper
  40949. {
  40950. public function mapToLegacyArray(\PHPUnit\TextUI\Arguments\Arguments $arguments) : array
  40951. {
  40952. $result = ['extensions' => [], 'listGroups' => \false, 'listSuites' => \false, 'listTests' => \false, 'listTestsXml' => \false, 'loader' => null, 'useDefaultConfiguration' => \true, 'loadedExtensions' => [], 'unavailableExtensions' => [], 'notLoadedExtensions' => []];
  40953. if ($arguments->hasColors()) {
  40954. $result['colors'] = $arguments->colors();
  40955. }
  40956. if ($arguments->hasBootstrap()) {
  40957. $result['bootstrap'] = $arguments->bootstrap();
  40958. }
  40959. if ($arguments->hasCacheResult()) {
  40960. $result['cacheResult'] = $arguments->cacheResult();
  40961. }
  40962. if ($arguments->hasCacheResultFile()) {
  40963. $result['cacheResultFile'] = $arguments->cacheResultFile();
  40964. }
  40965. if ($arguments->hasColumns()) {
  40966. $result['columns'] = $arguments->columns();
  40967. }
  40968. if ($arguments->hasConfiguration()) {
  40969. $result['configuration'] = $arguments->configuration();
  40970. }
  40971. if ($arguments->hasCoverageClover()) {
  40972. $result['coverageClover'] = $arguments->coverageClover();
  40973. }
  40974. if ($arguments->hasCoverageCrap4J()) {
  40975. $result['coverageCrap4J'] = $arguments->coverageCrap4J();
  40976. }
  40977. if ($arguments->hasCoverageHtml()) {
  40978. $result['coverageHtml'] = $arguments->coverageHtml();
  40979. }
  40980. if ($arguments->hasCoveragePhp()) {
  40981. $result['coveragePHP'] = $arguments->coveragePhp();
  40982. }
  40983. if ($arguments->hasCoverageText()) {
  40984. $result['coverageText'] = $arguments->coverageText();
  40985. }
  40986. if ($arguments->hasCoverageTextShowUncoveredFiles()) {
  40987. $result['coverageTextShowUncoveredFiles'] = $arguments->hasCoverageTextShowUncoveredFiles();
  40988. }
  40989. if ($arguments->hasCoverageTextShowOnlySummary()) {
  40990. $result['coverageTextShowOnlySummary'] = $arguments->coverageTextShowOnlySummary();
  40991. }
  40992. if ($arguments->hasCoverageXml()) {
  40993. $result['coverageXml'] = $arguments->coverageXml();
  40994. }
  40995. if ($arguments->hasDebug()) {
  40996. $result['debug'] = $arguments->debug();
  40997. }
  40998. if ($arguments->hasHelp()) {
  40999. $result['help'] = $arguments->help();
  41000. }
  41001. if ($arguments->hasFilter()) {
  41002. $result['filter'] = $arguments->filter();
  41003. }
  41004. if ($arguments->hasTestSuite()) {
  41005. $result['testsuite'] = $arguments->testSuite();
  41006. }
  41007. if ($arguments->hasGroups()) {
  41008. $result['groups'] = $arguments->groups();
  41009. }
  41010. if ($arguments->hasExcludeGroups()) {
  41011. $result['excludeGroups'] = $arguments->excludeGroups();
  41012. }
  41013. if ($arguments->hasTestSuffixes()) {
  41014. $result['testSuffixes'] = $arguments->testSuffixes();
  41015. }
  41016. if ($arguments->hasIncludePath()) {
  41017. $result['includePath'] = $arguments->includePath();
  41018. }
  41019. if ($arguments->hasListGroups()) {
  41020. $result['listGroups'] = $arguments->listGroups();
  41021. }
  41022. if ($arguments->hasListSuites()) {
  41023. $result['listSuites'] = $arguments->listSuites();
  41024. }
  41025. if ($arguments->hasListTests()) {
  41026. $result['listTests'] = $arguments->listTests();
  41027. }
  41028. if ($arguments->hasListTestsXml()) {
  41029. $result['listTestsXml'] = $arguments->listTestsXml();
  41030. }
  41031. if ($arguments->hasPrinter()) {
  41032. $result['printer'] = $arguments->printer();
  41033. }
  41034. if ($arguments->hasLoader()) {
  41035. $result['loader'] = $arguments->loader();
  41036. }
  41037. if ($arguments->hasJunitLogfile()) {
  41038. $result['junitLogfile'] = $arguments->junitLogfile();
  41039. }
  41040. if ($arguments->hasTeamcityLogfile()) {
  41041. $result['teamcityLogfile'] = $arguments->teamcityLogfile();
  41042. }
  41043. if ($arguments->hasExecutionOrder()) {
  41044. $result['executionOrder'] = $arguments->executionOrder();
  41045. }
  41046. if ($arguments->hasExecutionOrderDefects()) {
  41047. $result['executionOrderDefects'] = $arguments->executionOrderDefects();
  41048. }
  41049. if ($arguments->hasExtensions()) {
  41050. $result['extensions'] = $arguments->extensions();
  41051. }
  41052. if ($arguments->hasUnavailableExtensions()) {
  41053. $result['unavailableExtensions'] = $arguments->unavailableExtensions();
  41054. }
  41055. if ($arguments->hasResolveDependencies()) {
  41056. $result['resolveDependencies'] = $arguments->resolveDependencies();
  41057. }
  41058. if ($arguments->hasProcessIsolation()) {
  41059. $result['processIsolation'] = $arguments->processIsolation();
  41060. }
  41061. if ($arguments->hasRepeat()) {
  41062. $result['repeat'] = $arguments->repeat();
  41063. }
  41064. if ($arguments->hasStderr()) {
  41065. $result['stderr'] = $arguments->stderr();
  41066. }
  41067. if ($arguments->hasStopOnDefect()) {
  41068. $result['stopOnDefect'] = $arguments->stopOnDefect();
  41069. }
  41070. if ($arguments->hasStopOnError()) {
  41071. $result['stopOnError'] = $arguments->stopOnError();
  41072. }
  41073. if ($arguments->hasStopOnFailure()) {
  41074. $result['stopOnFailure'] = $arguments->stopOnFailure();
  41075. }
  41076. if ($arguments->hasStopOnWarning()) {
  41077. $result['stopOnWarning'] = $arguments->stopOnWarning();
  41078. }
  41079. if ($arguments->hasStopOnIncomplete()) {
  41080. $result['stopOnIncomplete'] = $arguments->stopOnIncomplete();
  41081. }
  41082. if ($arguments->hasStopOnRisky()) {
  41083. $result['stopOnRisky'] = $arguments->stopOnRisky();
  41084. }
  41085. if ($arguments->hasStopOnSkipped()) {
  41086. $result['stopOnSkipped'] = $arguments->stopOnSkipped();
  41087. }
  41088. if ($arguments->hasFailOnIncomplete()) {
  41089. $result['failOnIncomplete'] = $arguments->failOnIncomplete();
  41090. }
  41091. if ($arguments->hasFailOnRisky()) {
  41092. $result['failOnRisky'] = $arguments->failOnRisky();
  41093. }
  41094. if ($arguments->hasFailOnSkipped()) {
  41095. $result['failOnSkipped'] = $arguments->failOnSkipped();
  41096. }
  41097. if ($arguments->hasFailOnWarning()) {
  41098. $result['failOnWarning'] = $arguments->failOnWarning();
  41099. }
  41100. if ($arguments->hasTestdoxGroups()) {
  41101. $result['testdoxGroups'] = $arguments->testdoxGroups();
  41102. }
  41103. if ($arguments->hasTestdoxExcludeGroups()) {
  41104. $result['testdoxExcludeGroups'] = $arguments->testdoxExcludeGroups();
  41105. }
  41106. if ($arguments->hasTestdoxHtmlFile()) {
  41107. $result['testdoxHTMLFile'] = $arguments->testdoxHtmlFile();
  41108. }
  41109. if ($arguments->hasTestdoxTextFile()) {
  41110. $result['testdoxTextFile'] = $arguments->testdoxTextFile();
  41111. }
  41112. if ($arguments->hasTestdoxXmlFile()) {
  41113. $result['testdoxXMLFile'] = $arguments->testdoxXmlFile();
  41114. }
  41115. if ($arguments->hasUseDefaultConfiguration()) {
  41116. $result['useDefaultConfiguration'] = $arguments->useDefaultConfiguration();
  41117. }
  41118. if ($arguments->hasNoExtensions()) {
  41119. $result['noExtensions'] = $arguments->noExtensions();
  41120. }
  41121. if ($arguments->hasNoCoverage()) {
  41122. $result['noCoverage'] = $arguments->noCoverage();
  41123. }
  41124. if ($arguments->hasNoLogging()) {
  41125. $result['notLogging'] = $arguments->noLogging();
  41126. }
  41127. if ($arguments->hasNoInteraction()) {
  41128. $result['noInteraction'] = $arguments->noInteraction();
  41129. }
  41130. if ($arguments->hasBackupGlobals()) {
  41131. $result['backupGlobals'] = $arguments->backupGlobals();
  41132. }
  41133. if ($arguments->hasBackupStaticAttributes()) {
  41134. $result['backupStaticAttributes'] = $arguments->backupStaticAttributes();
  41135. }
  41136. if ($arguments->hasVerbose()) {
  41137. $result['verbose'] = $arguments->verbose();
  41138. }
  41139. if ($arguments->hasReportUselessTests()) {
  41140. $result['reportUselessTests'] = $arguments->reportUselessTests();
  41141. }
  41142. if ($arguments->hasStrictCoverage()) {
  41143. $result['strictCoverage'] = $arguments->strictCoverage();
  41144. }
  41145. if ($arguments->hasDisableCodeCoverageIgnore()) {
  41146. $result['disableCodeCoverageIgnore'] = $arguments->disableCodeCoverageIgnore();
  41147. }
  41148. if ($arguments->hasBeStrictAboutChangesToGlobalState()) {
  41149. $result['beStrictAboutChangesToGlobalState'] = $arguments->beStrictAboutChangesToGlobalState();
  41150. }
  41151. if ($arguments->hasDisallowTestOutput()) {
  41152. $result['disallowTestOutput'] = $arguments->disallowTestOutput();
  41153. }
  41154. if ($arguments->hasBeStrictAboutResourceUsageDuringSmallTests()) {
  41155. $result['beStrictAboutResourceUsageDuringSmallTests'] = $arguments->beStrictAboutResourceUsageDuringSmallTests();
  41156. }
  41157. if ($arguments->hasDefaultTimeLimit()) {
  41158. $result['defaultTimeLimit'] = $arguments->defaultTimeLimit();
  41159. }
  41160. if ($arguments->hasEnforceTimeLimit()) {
  41161. $result['enforceTimeLimit'] = $arguments->enforceTimeLimit();
  41162. }
  41163. if ($arguments->hasDisallowTodoAnnotatedTests()) {
  41164. $result['disallowTodoAnnotatedTests'] = $arguments->disallowTodoAnnotatedTests();
  41165. }
  41166. if ($arguments->hasReverseList()) {
  41167. $result['reverseList'] = $arguments->reverseList();
  41168. }
  41169. if ($arguments->hasWhitelist()) {
  41170. $result['whitelist'] = $arguments->whitelist();
  41171. }
  41172. if ($arguments->hasRandomOrderSeer()) {
  41173. $result['randomOrderSeed'] = $arguments->randomOrderSeed();
  41174. }
  41175. if ($arguments->hasXdebugFilterFile()) {
  41176. $result['xdebugFilterFile'] = $arguments->xdebugFilterFile();
  41177. }
  41178. return $result;
  41179. }
  41180. }
  41181. <?php
  41182. declare (strict_types=1);
  41183. /*
  41184. * This file is part of PHPUnit.
  41185. *
  41186. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  41187. *
  41188. * For the full copyright and license information, please view the LICENSE
  41189. * file that was distributed with this source code.
  41190. */
  41191. namespace PHPUnit\Framework;
  41192. /**
  41193. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  41194. */
  41195. interface SkippedTest extends \Throwable
  41196. {
  41197. }
  41198. <?php
  41199. declare (strict_types=1);
  41200. /*
  41201. * This file is part of PHPUnit.
  41202. *
  41203. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  41204. *
  41205. * For the full copyright and license information, please view the LICENSE
  41206. * file that was distributed with this source code.
  41207. */
  41208. namespace PHPUnit\Framework;
  41209. use PHPUnit\Runner\BaseTestRunner;
  41210. use PHPUnit\Runner\Filter\Factory;
  41211. use PHPUnit\Runner\PhptTestCase;
  41212. use PHPUnit\Util\FileLoader;
  41213. use PHPUnit\Util\Test as TestUtil;
  41214. /**
  41215. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  41216. */
  41217. class TestSuite implements \IteratorAggregate, \PHPUnit\Framework\SelfDescribing, \PHPUnit\Framework\Test
  41218. {
  41219. /**
  41220. * Enable or disable the backup and restoration of the $GLOBALS array.
  41221. *
  41222. * @var bool
  41223. */
  41224. protected $backupGlobals;
  41225. /**
  41226. * Enable or disable the backup and restoration of static attributes.
  41227. *
  41228. * @var bool
  41229. */
  41230. protected $backupStaticAttributes;
  41231. /**
  41232. * @var bool
  41233. */
  41234. protected $runTestInSeparateProcess = \false;
  41235. /**
  41236. * The name of the test suite.
  41237. *
  41238. * @var string
  41239. */
  41240. protected $name = '';
  41241. /**
  41242. * The test groups of the test suite.
  41243. *
  41244. * @var array
  41245. */
  41246. protected $groups = [];
  41247. /**
  41248. * The tests in the test suite.
  41249. *
  41250. * @var Test[]
  41251. */
  41252. protected $tests = [];
  41253. /**
  41254. * The number of tests in the test suite.
  41255. *
  41256. * @var int
  41257. */
  41258. protected $numTests = -1;
  41259. /**
  41260. * @var bool
  41261. */
  41262. protected $testCase = \false;
  41263. /**
  41264. * @var string[]
  41265. */
  41266. protected $foundClasses = [];
  41267. /**
  41268. * Last count of tests in this suite.
  41269. *
  41270. * @var null|int
  41271. */
  41272. private $cachedNumTests;
  41273. /**
  41274. * @var bool
  41275. */
  41276. private $beStrictAboutChangesToGlobalState;
  41277. /**
  41278. * @var Factory
  41279. */
  41280. private $iteratorFilter;
  41281. /**
  41282. * @var string[]
  41283. */
  41284. private $declaredClasses;
  41285. /**
  41286. * @psalm-var array<int,string>
  41287. */
  41288. private $warnings = [];
  41289. /**
  41290. * Constructs a new TestSuite:
  41291. *
  41292. * - PHPUnit\Framework\TestSuite() constructs an empty TestSuite.
  41293. *
  41294. * - PHPUnit\Framework\TestSuite(ReflectionClass) constructs a
  41295. * TestSuite from the given class.
  41296. *
  41297. * - PHPUnit\Framework\TestSuite(ReflectionClass, String)
  41298. * constructs a TestSuite from the given class with the given
  41299. * name.
  41300. *
  41301. * - PHPUnit\Framework\TestSuite(String) either constructs a
  41302. * TestSuite from the given class (if the passed string is the
  41303. * name of an existing class) or constructs an empty TestSuite
  41304. * with the given name.
  41305. *
  41306. * @param \ReflectionClass|string $theClass
  41307. *
  41308. * @throws Exception
  41309. */
  41310. public function __construct($theClass = '', string $name = '')
  41311. {
  41312. if (!\is_string($theClass) && !$theClass instanceof \ReflectionClass) {
  41313. throw \PHPUnit\Framework\InvalidArgumentException::create(1, 'ReflectionClass object or string');
  41314. }
  41315. $this->declaredClasses = \get_declared_classes();
  41316. if (!$theClass instanceof \ReflectionClass) {
  41317. if (\class_exists($theClass, \true)) {
  41318. if ($name === '') {
  41319. $name = $theClass;
  41320. }
  41321. try {
  41322. $theClass = new \ReflectionClass($theClass);
  41323. // @codeCoverageIgnoreStart
  41324. } catch (\ReflectionException $e) {
  41325. throw new \PHPUnit\Framework\Exception($e->getMessage(), (int) $e->getCode(), $e);
  41326. }
  41327. // @codeCoverageIgnoreEnd
  41328. } else {
  41329. $this->setName($theClass);
  41330. return;
  41331. }
  41332. }
  41333. if (!$theClass->isSubclassOf(\PHPUnit\Framework\TestCase::class)) {
  41334. $this->setName((string) $theClass);
  41335. return;
  41336. }
  41337. if ($name !== '') {
  41338. $this->setName($name);
  41339. } else {
  41340. $this->setName($theClass->getName());
  41341. }
  41342. $constructor = $theClass->getConstructor();
  41343. if ($constructor !== null && !$constructor->isPublic()) {
  41344. $this->addTest(new \PHPUnit\Framework\WarningTestCase(\sprintf('Class "%s" has no public constructor.', $theClass->getName())));
  41345. return;
  41346. }
  41347. foreach ($theClass->getMethods() as $method) {
  41348. if ($method->getDeclaringClass()->getName() === \PHPUnit\Framework\Assert::class) {
  41349. continue;
  41350. }
  41351. if ($method->getDeclaringClass()->getName() === \PHPUnit\Framework\TestCase::class) {
  41352. continue;
  41353. }
  41354. $this->addTestMethod($theClass, $method);
  41355. }
  41356. if (empty($this->tests)) {
  41357. $this->addTest(new \PHPUnit\Framework\WarningTestCase(\sprintf('No tests found in class "%s".', $theClass->getName())));
  41358. }
  41359. $this->testCase = \true;
  41360. }
  41361. /**
  41362. * Returns a string representation of the test suite.
  41363. */
  41364. public function toString() : string
  41365. {
  41366. return $this->getName();
  41367. }
  41368. /**
  41369. * Adds a test to the suite.
  41370. *
  41371. * @param array $groups
  41372. */
  41373. public function addTest(\PHPUnit\Framework\Test $test, $groups = []) : void
  41374. {
  41375. try {
  41376. $class = new \ReflectionClass($test);
  41377. // @codeCoverageIgnoreStart
  41378. } catch (\ReflectionException $e) {
  41379. throw new \PHPUnit\Framework\Exception($e->getMessage(), (int) $e->getCode(), $e);
  41380. }
  41381. // @codeCoverageIgnoreEnd
  41382. if (!$class->isAbstract()) {
  41383. $this->tests[] = $test;
  41384. $this->numTests = -1;
  41385. if ($test instanceof self && empty($groups)) {
  41386. $groups = $test->getGroups();
  41387. }
  41388. if (empty($groups)) {
  41389. $groups = ['default'];
  41390. }
  41391. foreach ($groups as $group) {
  41392. if (!isset($this->groups[$group])) {
  41393. $this->groups[$group] = [$test];
  41394. } else {
  41395. $this->groups[$group][] = $test;
  41396. }
  41397. }
  41398. if ($test instanceof \PHPUnit\Framework\TestCase) {
  41399. $test->setGroups($groups);
  41400. }
  41401. }
  41402. }
  41403. /**
  41404. * Adds the tests from the given class to the suite.
  41405. *
  41406. * @param object|string $testClass
  41407. *
  41408. * @throws Exception
  41409. */
  41410. public function addTestSuite($testClass) : void
  41411. {
  41412. if (!(\is_object($testClass) || \is_string($testClass) && \class_exists($testClass))) {
  41413. throw \PHPUnit\Framework\InvalidArgumentException::create(1, 'class name or object');
  41414. }
  41415. if (!\is_object($testClass)) {
  41416. try {
  41417. $testClass = new \ReflectionClass($testClass);
  41418. // @codeCoverageIgnoreStart
  41419. } catch (\ReflectionException $e) {
  41420. throw new \PHPUnit\Framework\Exception($e->getMessage(), (int) $e->getCode(), $e);
  41421. }
  41422. // @codeCoverageIgnoreEnd
  41423. }
  41424. if ($testClass instanceof self) {
  41425. $this->addTest($testClass);
  41426. } elseif ($testClass instanceof \ReflectionClass) {
  41427. $suiteMethod = \false;
  41428. if (!$testClass->isAbstract() && $testClass->hasMethod(\PHPUnit\Runner\BaseTestRunner::SUITE_METHODNAME)) {
  41429. try {
  41430. $method = $testClass->getMethod(\PHPUnit\Runner\BaseTestRunner::SUITE_METHODNAME);
  41431. // @codeCoverageIgnoreStart
  41432. } catch (\ReflectionException $e) {
  41433. throw new \PHPUnit\Framework\Exception($e->getMessage(), (int) $e->getCode(), $e);
  41434. }
  41435. // @codeCoverageIgnoreEnd
  41436. if ($method->isStatic()) {
  41437. $this->addTest($method->invoke(null, $testClass->getName()));
  41438. $suiteMethod = \true;
  41439. }
  41440. }
  41441. if (!$suiteMethod && !$testClass->isAbstract() && $testClass->isSubclassOf(\PHPUnit\Framework\TestCase::class)) {
  41442. $this->addTest(new self($testClass));
  41443. }
  41444. } else {
  41445. throw new \PHPUnit\Framework\Exception();
  41446. }
  41447. }
  41448. public function addWarning(string $warning) : void
  41449. {
  41450. $this->warnings[] = $warning;
  41451. }
  41452. /**
  41453. * Wraps both <code>addTest()</code> and <code>addTestSuite</code>
  41454. * as well as the separate import statements for the user's convenience.
  41455. *
  41456. * If the named file cannot be read or there are no new tests that can be
  41457. * added, a <code>PHPUnit\Framework\WarningTestCase</code> will be created instead,
  41458. * leaving the current test run untouched.
  41459. *
  41460. * @throws Exception
  41461. */
  41462. public function addTestFile(string $filename) : void
  41463. {
  41464. if (\file_exists($filename) && \substr($filename, -5) === '.phpt') {
  41465. $this->addTest(new \PHPUnit\Runner\PhptTestCase($filename));
  41466. $this->declaredClasses = \get_declared_classes();
  41467. return;
  41468. }
  41469. $numTests = \count($this->tests);
  41470. // The given file may contain further stub classes in addition to the
  41471. // test class itself. Figure out the actual test class.
  41472. $filename = \PHPUnit\Util\FileLoader::checkAndLoad($filename);
  41473. $newClasses = \array_diff(\get_declared_classes(), $this->declaredClasses);
  41474. // The diff is empty in case a parent class (with test methods) is added
  41475. // AFTER a child class that inherited from it. To account for that case,
  41476. // accumulate all discovered classes, so the parent class may be found in
  41477. // a later invocation.
  41478. if (!empty($newClasses)) {
  41479. // On the assumption that test classes are defined first in files,
  41480. // process discovered classes in approximate LIFO order, so as to
  41481. // avoid unnecessary reflection.
  41482. $this->foundClasses = \array_merge($newClasses, $this->foundClasses);
  41483. $this->declaredClasses = \get_declared_classes();
  41484. }
  41485. // The test class's name must match the filename, either in full, or as
  41486. // a PEAR/PSR-0 prefixed short name ('NameSpace_ShortName'), or as a
  41487. // PSR-1 local short name ('NameSpace\ShortName'). The comparison must be
  41488. // anchored to prevent false-positive matches (e.g., 'OtherShortName').
  41489. $shortName = \basename($filename, '.php');
  41490. $shortNameRegEx = '/(?:^|_|\\\\)' . \preg_quote($shortName, '/') . '$/';
  41491. foreach ($this->foundClasses as $i => $className) {
  41492. if (\preg_match($shortNameRegEx, $className)) {
  41493. try {
  41494. $class = new \ReflectionClass($className);
  41495. // @codeCoverageIgnoreStart
  41496. } catch (\ReflectionException $e) {
  41497. throw new \PHPUnit\Framework\Exception($e->getMessage(), (int) $e->getCode(), $e);
  41498. }
  41499. // @codeCoverageIgnoreEnd
  41500. if ($class->getFileName() == $filename) {
  41501. $newClasses = [$className];
  41502. unset($this->foundClasses[$i]);
  41503. break;
  41504. }
  41505. }
  41506. }
  41507. foreach ($newClasses as $className) {
  41508. try {
  41509. $class = new \ReflectionClass($className);
  41510. // @codeCoverageIgnoreStart
  41511. } catch (\ReflectionException $e) {
  41512. throw new \PHPUnit\Framework\Exception($e->getMessage(), (int) $e->getCode(), $e);
  41513. }
  41514. // @codeCoverageIgnoreEnd
  41515. if (\dirname($class->getFileName()) === __DIR__) {
  41516. continue;
  41517. }
  41518. if (!$class->isAbstract()) {
  41519. if ($class->hasMethod(\PHPUnit\Runner\BaseTestRunner::SUITE_METHODNAME)) {
  41520. try {
  41521. $method = $class->getMethod(\PHPUnit\Runner\BaseTestRunner::SUITE_METHODNAME);
  41522. // @codeCoverageIgnoreStart
  41523. } catch (\ReflectionException $e) {
  41524. throw new \PHPUnit\Framework\Exception($e->getMessage(), (int) $e->getCode(), $e);
  41525. }
  41526. // @codeCoverageIgnoreEnd
  41527. if ($method->isStatic()) {
  41528. $this->addTest($method->invoke(null, $className));
  41529. }
  41530. } elseif ($class->implementsInterface(\PHPUnit\Framework\Test::class)) {
  41531. $expectedClassName = $shortName;
  41532. if (($pos = \strpos($expectedClassName, '.')) !== \false) {
  41533. $expectedClassName = \substr($expectedClassName, 0, $pos);
  41534. }
  41535. if ($class->getShortName() !== $expectedClassName) {
  41536. $this->addWarning(\sprintf("Test case class not matching filename is deprecated\n in %s\n Class name was '%s', expected '%s'", $filename, $class->getShortName(), $expectedClassName));
  41537. }
  41538. $this->addTestSuite($class);
  41539. }
  41540. }
  41541. }
  41542. if (\count($this->tests) > ++$numTests) {
  41543. $this->addWarning(\sprintf("Multiple test case classes per file is deprecated\n in %s", $filename));
  41544. }
  41545. $this->numTests = -1;
  41546. }
  41547. /**
  41548. * Wrapper for addTestFile() that adds multiple test files.
  41549. *
  41550. * @throws Exception
  41551. */
  41552. public function addTestFiles(iterable $fileNames) : void
  41553. {
  41554. foreach ($fileNames as $filename) {
  41555. $this->addTestFile((string) $filename);
  41556. }
  41557. }
  41558. /**
  41559. * Counts the number of test cases that will be run by this test.
  41560. */
  41561. public function count(bool $preferCache = \false) : int
  41562. {
  41563. if ($preferCache && $this->cachedNumTests !== null) {
  41564. return $this->cachedNumTests;
  41565. }
  41566. $numTests = 0;
  41567. foreach ($this as $test) {
  41568. $numTests += \count($test);
  41569. }
  41570. $this->cachedNumTests = $numTests;
  41571. return $numTests;
  41572. }
  41573. /**
  41574. * Returns the name of the suite.
  41575. */
  41576. public function getName() : string
  41577. {
  41578. return $this->name;
  41579. }
  41580. /**
  41581. * Returns the test groups of the suite.
  41582. */
  41583. public function getGroups() : array
  41584. {
  41585. return \array_keys($this->groups);
  41586. }
  41587. public function getGroupDetails() : array
  41588. {
  41589. return $this->groups;
  41590. }
  41591. /**
  41592. * Set tests groups of the test case
  41593. */
  41594. public function setGroupDetails(array $groups) : void
  41595. {
  41596. $this->groups = $groups;
  41597. }
  41598. /**
  41599. * Runs the tests and collects their result in a TestResult.
  41600. *
  41601. * @throws \PHPUnit\Framework\CodeCoverageException
  41602. * @throws \SebastianBergmann\CodeCoverage\CoveredCodeNotExecutedException
  41603. * @throws \SebastianBergmann\CodeCoverage\InvalidArgumentException
  41604. * @throws \SebastianBergmann\CodeCoverage\RuntimeException
  41605. * @throws \SebastianBergmann\CodeCoverage\UnintentionallyCoveredCodeException
  41606. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  41607. * @throws Warning
  41608. */
  41609. public function run(\PHPUnit\Framework\TestResult $result = null) : \PHPUnit\Framework\TestResult
  41610. {
  41611. if ($result === null) {
  41612. $result = $this->createResult();
  41613. }
  41614. if (\count($this) === 0) {
  41615. return $result;
  41616. }
  41617. /** @psalm-var class-string $className */
  41618. $className = $this->name;
  41619. $hookMethods = \PHPUnit\Util\Test::getHookMethods($className);
  41620. $result->startTestSuite($this);
  41621. try {
  41622. foreach ($hookMethods['beforeClass'] as $beforeClassMethod) {
  41623. if ($this->testCase && \class_exists($this->name, \false) && \method_exists($this->name, $beforeClassMethod)) {
  41624. if ($missingRequirements = \PHPUnit\Util\Test::getMissingRequirements($this->name, $beforeClassMethod)) {
  41625. $this->markTestSuiteSkipped(\implode(\PHP_EOL, $missingRequirements));
  41626. }
  41627. \call_user_func([$this->name, $beforeClassMethod]);
  41628. }
  41629. }
  41630. } catch (\PHPUnit\Framework\SkippedTestSuiteError $error) {
  41631. foreach ($this->tests() as $test) {
  41632. $result->startTest($test);
  41633. $result->addFailure($test, $error, 0);
  41634. $result->endTest($test, 0);
  41635. }
  41636. $result->endTestSuite($this);
  41637. return $result;
  41638. } catch (\Throwable $t) {
  41639. $errorAdded = \false;
  41640. foreach ($this->tests() as $test) {
  41641. if ($result->shouldStop()) {
  41642. break;
  41643. }
  41644. $result->startTest($test);
  41645. if (!$errorAdded) {
  41646. $result->addError($test, $t, 0);
  41647. $errorAdded = \true;
  41648. } else {
  41649. $result->addFailure($test, new \PHPUnit\Framework\SkippedTestError('Test skipped because of an error in hook method'), 0);
  41650. }
  41651. $result->endTest($test, 0);
  41652. }
  41653. $result->endTestSuite($this);
  41654. return $result;
  41655. }
  41656. foreach ($this as $test) {
  41657. if ($result->shouldStop()) {
  41658. break;
  41659. }
  41660. if ($test instanceof \PHPUnit\Framework\TestCase || $test instanceof self) {
  41661. $test->setBeStrictAboutChangesToGlobalState($this->beStrictAboutChangesToGlobalState);
  41662. $test->setBackupGlobals($this->backupGlobals);
  41663. $test->setBackupStaticAttributes($this->backupStaticAttributes);
  41664. $test->setRunTestInSeparateProcess($this->runTestInSeparateProcess);
  41665. }
  41666. $test->run($result);
  41667. }
  41668. try {
  41669. foreach ($hookMethods['afterClass'] as $afterClassMethod) {
  41670. if ($this->testCase && \class_exists($this->name, \false) && \method_exists($this->name, $afterClassMethod)) {
  41671. \call_user_func([$this->name, $afterClassMethod]);
  41672. }
  41673. }
  41674. } catch (\Throwable $t) {
  41675. $message = "Exception in {$this->name}::{$afterClassMethod}" . \PHP_EOL . $t->getMessage();
  41676. $error = new \PHPUnit\Framework\SyntheticError($message, 0, $t->getFile(), $t->getLine(), $t->getTrace());
  41677. $placeholderTest = clone $test;
  41678. $placeholderTest->setName($afterClassMethod);
  41679. $result->startTest($placeholderTest);
  41680. $result->addFailure($placeholderTest, $error, 0);
  41681. $result->endTest($placeholderTest, 0);
  41682. }
  41683. $result->endTestSuite($this);
  41684. return $result;
  41685. }
  41686. public function setRunTestInSeparateProcess(bool $runTestInSeparateProcess) : void
  41687. {
  41688. $this->runTestInSeparateProcess = $runTestInSeparateProcess;
  41689. }
  41690. public function setName(string $name) : void
  41691. {
  41692. $this->name = $name;
  41693. }
  41694. /**
  41695. * Returns the test at the given index.
  41696. *
  41697. * @return false|Test
  41698. */
  41699. public function testAt(int $index)
  41700. {
  41701. return $this->tests[$index] ?? \false;
  41702. }
  41703. /**
  41704. * Returns the tests as an enumeration.
  41705. *
  41706. * @return Test[]
  41707. */
  41708. public function tests() : array
  41709. {
  41710. return $this->tests;
  41711. }
  41712. /**
  41713. * Set tests of the test suite
  41714. *
  41715. * @param Test[] $tests
  41716. */
  41717. public function setTests(array $tests) : void
  41718. {
  41719. $this->tests = $tests;
  41720. }
  41721. /**
  41722. * Mark the test suite as skipped.
  41723. *
  41724. * @param string $message
  41725. *
  41726. * @throws SkippedTestSuiteError
  41727. *
  41728. * @psalm-return never-return
  41729. */
  41730. public function markTestSuiteSkipped($message = '') : void
  41731. {
  41732. throw new \PHPUnit\Framework\SkippedTestSuiteError($message);
  41733. }
  41734. /**
  41735. * @param bool $beStrictAboutChangesToGlobalState
  41736. */
  41737. public function setBeStrictAboutChangesToGlobalState($beStrictAboutChangesToGlobalState) : void
  41738. {
  41739. if (null === $this->beStrictAboutChangesToGlobalState && \is_bool($beStrictAboutChangesToGlobalState)) {
  41740. $this->beStrictAboutChangesToGlobalState = $beStrictAboutChangesToGlobalState;
  41741. }
  41742. }
  41743. /**
  41744. * @param bool $backupGlobals
  41745. */
  41746. public function setBackupGlobals($backupGlobals) : void
  41747. {
  41748. if (null === $this->backupGlobals && \is_bool($backupGlobals)) {
  41749. $this->backupGlobals = $backupGlobals;
  41750. }
  41751. }
  41752. /**
  41753. * @param bool $backupStaticAttributes
  41754. */
  41755. public function setBackupStaticAttributes($backupStaticAttributes) : void
  41756. {
  41757. if (null === $this->backupStaticAttributes && \is_bool($backupStaticAttributes)) {
  41758. $this->backupStaticAttributes = $backupStaticAttributes;
  41759. }
  41760. }
  41761. /**
  41762. * Returns an iterator for this test suite.
  41763. */
  41764. public function getIterator() : \Iterator
  41765. {
  41766. $iterator = new \PHPUnit\Framework\TestSuiteIterator($this);
  41767. if ($this->iteratorFilter !== null) {
  41768. $iterator = $this->iteratorFilter->factory($iterator, $this);
  41769. }
  41770. return $iterator;
  41771. }
  41772. public function injectFilter(\PHPUnit\Runner\Filter\Factory $filter) : void
  41773. {
  41774. $this->iteratorFilter = $filter;
  41775. foreach ($this as $test) {
  41776. if ($test instanceof self) {
  41777. $test->injectFilter($filter);
  41778. }
  41779. }
  41780. }
  41781. /**
  41782. * @psalm-return array<int,string>
  41783. */
  41784. public function warnings() : array
  41785. {
  41786. return \array_unique($this->warnings);
  41787. }
  41788. /**
  41789. * Creates a default TestResult object.
  41790. */
  41791. protected function createResult() : \PHPUnit\Framework\TestResult
  41792. {
  41793. return new \PHPUnit\Framework\TestResult();
  41794. }
  41795. /**
  41796. * @throws Exception
  41797. */
  41798. protected function addTestMethod(\ReflectionClass $class, \ReflectionMethod $method) : void
  41799. {
  41800. if (!\PHPUnit\Util\Test::isTestMethod($method)) {
  41801. return;
  41802. }
  41803. $methodName = $method->getName();
  41804. if (!$method->isPublic()) {
  41805. $this->addTest(new \PHPUnit\Framework\WarningTestCase(\sprintf('Test method "%s" in test class "%s" is not public.', $methodName, $class->getName())));
  41806. return;
  41807. }
  41808. $test = (new \PHPUnit\Framework\TestBuilder())->build($class, $methodName);
  41809. if ($test instanceof \PHPUnit\Framework\TestCase || $test instanceof \PHPUnit\Framework\DataProviderTestSuite) {
  41810. $test->setDependencies(\PHPUnit\Util\Test::getDependencies($class->getName(), $methodName));
  41811. }
  41812. $this->addTest($test, \PHPUnit\Util\Test::getGroups($class->getName(), $methodName));
  41813. }
  41814. }
  41815. <?php
  41816. declare (strict_types=1);
  41817. /*
  41818. * This file is part of PHPUnit.
  41819. *
  41820. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  41821. *
  41822. * For the full copyright and license information, please view the LICENSE
  41823. * file that was distributed with this source code.
  41824. */
  41825. namespace PHPUnit\Framework;
  41826. use PHPUnit\Util\Test as TestUtil;
  41827. /**
  41828. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  41829. */
  41830. final class DataProviderTestSuite extends \PHPUnit\Framework\TestSuite
  41831. {
  41832. /**
  41833. * @var string[]
  41834. */
  41835. private $dependencies = [];
  41836. /**
  41837. * @param string[] $dependencies
  41838. */
  41839. public function setDependencies(array $dependencies) : void
  41840. {
  41841. $this->dependencies = $dependencies;
  41842. foreach ($this->tests as $test) {
  41843. if (!$test instanceof \PHPUnit\Framework\TestCase) {
  41844. continue;
  41845. }
  41846. $test->setDependencies($dependencies);
  41847. }
  41848. }
  41849. public function getDependencies() : array
  41850. {
  41851. return $this->dependencies;
  41852. }
  41853. public function hasDependencies() : bool
  41854. {
  41855. return \count($this->dependencies) > 0;
  41856. }
  41857. /**
  41858. * Returns the size of the each test created using the data provider(s)
  41859. *
  41860. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  41861. */
  41862. public function getSize() : int
  41863. {
  41864. [$className, $methodName] = \explode('::', $this->getName());
  41865. return \PHPUnit\Util\Test::getSize($className, $methodName);
  41866. }
  41867. }
  41868. <?php
  41869. declare (strict_types=1);
  41870. /*
  41871. * This file is part of PHPUnit.
  41872. *
  41873. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  41874. *
  41875. * For the full copyright and license information, please view the LICENSE
  41876. * file that was distributed with this source code.
  41877. */
  41878. namespace PHPUnit\Framework;
  41879. /**
  41880. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  41881. */
  41882. interface IncompleteTest extends \Throwable
  41883. {
  41884. }
  41885. <?php
  41886. declare (strict_types=1);
  41887. /*
  41888. * This file is part of PHPUnit.
  41889. *
  41890. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  41891. *
  41892. * For the full copyright and license information, please view the LICENSE
  41893. * file that was distributed with this source code.
  41894. */
  41895. namespace PHPUnit\Framework;
  41896. use PHPUnit\Framework\Error\Error;
  41897. /**
  41898. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  41899. */
  41900. final class TestFailure
  41901. {
  41902. /**
  41903. * @var null|Test
  41904. */
  41905. private $failedTest;
  41906. /**
  41907. * @var \Throwable
  41908. */
  41909. private $thrownException;
  41910. /**
  41911. * @var string
  41912. */
  41913. private $testName;
  41914. /**
  41915. * Returns a description for an exception.
  41916. */
  41917. public static function exceptionToString(\Throwable $e) : string
  41918. {
  41919. if ($e instanceof \PHPUnit\Framework\SelfDescribing) {
  41920. $buffer = $e->toString();
  41921. if ($e instanceof \PHPUnit\Framework\ExpectationFailedException && $e->getComparisonFailure()) {
  41922. $buffer .= $e->getComparisonFailure()->getDiff();
  41923. }
  41924. if ($e instanceof \PHPUnit\Framework\PHPTAssertionFailedError) {
  41925. $buffer .= $e->getDiff();
  41926. }
  41927. if (!empty($buffer)) {
  41928. $buffer = \trim($buffer) . "\n";
  41929. }
  41930. return $buffer;
  41931. }
  41932. if ($e instanceof \PHPUnit\Framework\Error\Error) {
  41933. return $e->getMessage() . "\n";
  41934. }
  41935. if ($e instanceof \PHPUnit\Framework\ExceptionWrapper) {
  41936. return $e->getClassName() . ': ' . $e->getMessage() . "\n";
  41937. }
  41938. return \get_class($e) . ': ' . $e->getMessage() . "\n";
  41939. }
  41940. /**
  41941. * Constructs a TestFailure with the given test and exception.
  41942. */
  41943. public function __construct(\PHPUnit\Framework\Test $failedTest, \Throwable $t)
  41944. {
  41945. if ($failedTest instanceof \PHPUnit\Framework\SelfDescribing) {
  41946. $this->testName = $failedTest->toString();
  41947. } else {
  41948. $this->testName = \get_class($failedTest);
  41949. }
  41950. if (!$failedTest instanceof \PHPUnit\Framework\TestCase || !$failedTest->isInIsolation()) {
  41951. $this->failedTest = $failedTest;
  41952. }
  41953. $this->thrownException = $t;
  41954. }
  41955. /**
  41956. * Returns a short description of the failure.
  41957. */
  41958. public function toString() : string
  41959. {
  41960. return \sprintf('%s: %s', $this->testName, $this->thrownException->getMessage());
  41961. }
  41962. /**
  41963. * Returns a description for the thrown exception.
  41964. */
  41965. public function getExceptionAsString() : string
  41966. {
  41967. return self::exceptionToString($this->thrownException);
  41968. }
  41969. /**
  41970. * Returns the name of the failing test (including data set, if any).
  41971. */
  41972. public function getTestName() : string
  41973. {
  41974. return $this->testName;
  41975. }
  41976. /**
  41977. * Returns the failing test.
  41978. *
  41979. * Note: The test object is not set when the test is executed in process
  41980. * isolation.
  41981. *
  41982. * @see Exception
  41983. */
  41984. public function failedTest() : ?\PHPUnit\Framework\Test
  41985. {
  41986. return $this->failedTest;
  41987. }
  41988. /**
  41989. * Gets the thrown exception.
  41990. */
  41991. public function thrownException() : \Throwable
  41992. {
  41993. return $this->thrownException;
  41994. }
  41995. /**
  41996. * Returns the exception's message.
  41997. */
  41998. public function exceptionMessage() : string
  41999. {
  42000. return $this->thrownException()->getMessage();
  42001. }
  42002. /**
  42003. * Returns true if the thrown exception
  42004. * is of type AssertionFailedError.
  42005. */
  42006. public function isFailure() : bool
  42007. {
  42008. return $this->thrownException() instanceof \PHPUnit\Framework\AssertionFailedError;
  42009. }
  42010. }
  42011. <?php
  42012. declare (strict_types=1);
  42013. /*
  42014. * This file is part of PHPUnit.
  42015. *
  42016. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  42017. *
  42018. * For the full copyright and license information, please view the LICENSE
  42019. * file that was distributed with this source code.
  42020. */
  42021. namespace PHPUnit\Framework;
  42022. /**
  42023. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  42024. */
  42025. final class SkippedTestCase extends \PHPUnit\Framework\TestCase
  42026. {
  42027. /**
  42028. * @var bool
  42029. */
  42030. protected $backupGlobals = \false;
  42031. /**
  42032. * @var bool
  42033. */
  42034. protected $backupStaticAttributes = \false;
  42035. /**
  42036. * @var bool
  42037. */
  42038. protected $runTestInSeparateProcess = \false;
  42039. /**
  42040. * @var bool
  42041. */
  42042. protected $useErrorHandler = \false;
  42043. /**
  42044. * @var string
  42045. */
  42046. private $message;
  42047. public function __construct(string $className, string $methodName, string $message = '')
  42048. {
  42049. parent::__construct($className . '::' . $methodName);
  42050. $this->message = $message;
  42051. }
  42052. public function getMessage() : string
  42053. {
  42054. return $this->message;
  42055. }
  42056. /**
  42057. * Returns a string representation of the test case.
  42058. *
  42059. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  42060. */
  42061. public function toString() : string
  42062. {
  42063. return $this->getName();
  42064. }
  42065. /**
  42066. * @throws Exception
  42067. */
  42068. protected function runTest() : void
  42069. {
  42070. $this->markTestSkipped($this->message);
  42071. }
  42072. }
  42073. <?php
  42074. declare (strict_types=1);
  42075. /*
  42076. * This file is part of PHPUnit.
  42077. *
  42078. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  42079. *
  42080. * For the full copyright and license information, please view the LICENSE
  42081. * file that was distributed with this source code.
  42082. */
  42083. namespace PHPUnit\Framework;
  42084. /**
  42085. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  42086. */
  42087. final class PHPTAssertionFailedError extends \PHPUnit\Framework\SyntheticError
  42088. {
  42089. /**
  42090. * @var string
  42091. */
  42092. private $diff;
  42093. public function __construct(string $message, int $code, string $file, int $line, array $trace, string $diff)
  42094. {
  42095. parent::__construct($message, $code, $file, $line, $trace);
  42096. $this->diff = $diff;
  42097. }
  42098. public function getDiff() : string
  42099. {
  42100. return $this->diff;
  42101. }
  42102. }
  42103. <?php
  42104. declare (strict_types=1);
  42105. /*
  42106. * This file is part of PHPUnit.
  42107. *
  42108. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  42109. *
  42110. * For the full copyright and license information, please view the LICENSE
  42111. * file that was distributed with this source code.
  42112. */
  42113. namespace PHPUnit\Framework;
  42114. /**
  42115. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  42116. */
  42117. final class SyntheticSkippedError extends \PHPUnit\Framework\SyntheticError implements \PHPUnit\Framework\SkippedTest
  42118. {
  42119. }
  42120. <?php
  42121. declare (strict_types=1);
  42122. /*
  42123. * This file is part of PHPUnit.
  42124. *
  42125. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  42126. *
  42127. * For the full copyright and license information, please view the LICENSE
  42128. * file that was distributed with this source code.
  42129. */
  42130. namespace PHPUnit\Framework;
  42131. /**
  42132. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  42133. */
  42134. final class OutputError extends \PHPUnit\Framework\AssertionFailedError
  42135. {
  42136. }
  42137. <?php
  42138. declare (strict_types=1);
  42139. /*
  42140. * This file is part of PHPUnit.
  42141. *
  42142. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  42143. *
  42144. * For the full copyright and license information, please view the LICENSE
  42145. * file that was distributed with this source code.
  42146. */
  42147. namespace PHPUnit\Framework;
  42148. /**
  42149. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  42150. */
  42151. final class IncompleteTestError extends \PHPUnit\Framework\AssertionFailedError implements \PHPUnit\Framework\IncompleteTest
  42152. {
  42153. }
  42154. <?php
  42155. declare (strict_types=1);
  42156. /*
  42157. * This file is part of PHPUnit.
  42158. *
  42159. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  42160. *
  42161. * For the full copyright and license information, please view the LICENSE
  42162. * file that was distributed with this source code.
  42163. */
  42164. namespace PHPUnit\Framework;
  42165. /**
  42166. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  42167. */
  42168. class CodeCoverageException extends \PHPUnit\Framework\Exception
  42169. {
  42170. }
  42171. <?php
  42172. declare (strict_types=1);
  42173. /*
  42174. * This file is part of PHPUnit.
  42175. *
  42176. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  42177. *
  42178. * For the full copyright and license information, please view the LICENSE
  42179. * file that was distributed with this source code.
  42180. */
  42181. namespace PHPUnit\Framework;
  42182. /**
  42183. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  42184. */
  42185. class RiskyTestError extends \PHPUnit\Framework\AssertionFailedError
  42186. {
  42187. }
  42188. <?php
  42189. declare (strict_types=1);
  42190. /*
  42191. * This file is part of PHPUnit.
  42192. *
  42193. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  42194. *
  42195. * For the full copyright and license information, please view the LICENSE
  42196. * file that was distributed with this source code.
  42197. */
  42198. namespace PHPUnit\Framework;
  42199. /**
  42200. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  42201. */
  42202. final class SkippedTestError extends \PHPUnit\Framework\AssertionFailedError implements \PHPUnit\Framework\SkippedTest
  42203. {
  42204. }
  42205. <?php
  42206. declare (strict_types=1);
  42207. /*
  42208. * This file is part of PHPUnit.
  42209. *
  42210. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  42211. *
  42212. * For the full copyright and license information, please view the LICENSE
  42213. * file that was distributed with this source code.
  42214. */
  42215. namespace PHPUnit\Framework;
  42216. /**
  42217. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  42218. */
  42219. final class CoveredCodeNotExecutedException extends \PHPUnit\Framework\RiskyTestError
  42220. {
  42221. }
  42222. <?php
  42223. declare (strict_types=1);
  42224. /*
  42225. * This file is part of PHPUnit.
  42226. *
  42227. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  42228. *
  42229. * For the full copyright and license information, please view the LICENSE
  42230. * file that was distributed with this source code.
  42231. */
  42232. namespace PHPUnit\Framework;
  42233. /**
  42234. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  42235. */
  42236. final class NoChildTestSuiteException extends \PHPUnit\Framework\Exception
  42237. {
  42238. }
  42239. <?php
  42240. declare (strict_types=1);
  42241. /*
  42242. * This file is part of PHPUnit.
  42243. *
  42244. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  42245. *
  42246. * For the full copyright and license information, please view the LICENSE
  42247. * file that was distributed with this source code.
  42248. */
  42249. namespace PHPUnit\Framework;
  42250. /**
  42251. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  42252. */
  42253. final class Warning extends \PHPUnit\Framework\Exception implements \PHPUnit\Framework\SelfDescribing
  42254. {
  42255. /**
  42256. * Wrapper for getMessage() which is declared as final.
  42257. */
  42258. public function toString() : string
  42259. {
  42260. return $this->getMessage();
  42261. }
  42262. }
  42263. <?php
  42264. declare (strict_types=1);
  42265. /*
  42266. * This file is part of PHPUnit.
  42267. *
  42268. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  42269. *
  42270. * For the full copyright and license information, please view the LICENSE
  42271. * file that was distributed with this source code.
  42272. */
  42273. namespace PHPUnit\Framework;
  42274. use PHPUnit\SebastianBergmann\Comparator\ComparisonFailure;
  42275. /**
  42276. * Exception for expectations which failed their check.
  42277. *
  42278. * The exception contains the error message and optionally a
  42279. * SebastianBergmann\Comparator\ComparisonFailure which is used to
  42280. * generate diff output of the failed expectations.
  42281. *
  42282. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  42283. */
  42284. final class ExpectationFailedException extends \PHPUnit\Framework\AssertionFailedError
  42285. {
  42286. /**
  42287. * @var ComparisonFailure
  42288. */
  42289. protected $comparisonFailure;
  42290. public function __construct(string $message, \PHPUnit\SebastianBergmann\Comparator\ComparisonFailure $comparisonFailure = null, \Exception $previous = null)
  42291. {
  42292. $this->comparisonFailure = $comparisonFailure;
  42293. parent::__construct($message, 0, $previous);
  42294. }
  42295. public function getComparisonFailure() : ?\PHPUnit\SebastianBergmann\Comparator\ComparisonFailure
  42296. {
  42297. return $this->comparisonFailure;
  42298. }
  42299. }
  42300. <?php
  42301. declare (strict_types=1);
  42302. /*
  42303. * This file is part of PHPUnit.
  42304. *
  42305. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  42306. *
  42307. * For the full copyright and license information, please view the LICENSE
  42308. * file that was distributed with this source code.
  42309. */
  42310. namespace PHPUnit\Framework;
  42311. /**
  42312. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  42313. */
  42314. final class SkippedTestSuiteError extends \PHPUnit\Framework\AssertionFailedError implements \PHPUnit\Framework\SkippedTest
  42315. {
  42316. }
  42317. <?php
  42318. declare (strict_types=1);
  42319. /*
  42320. * This file is part of PHPUnit.
  42321. *
  42322. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  42323. *
  42324. * For the full copyright and license information, please view the LICENSE
  42325. * file that was distributed with this source code.
  42326. */
  42327. namespace PHPUnit\Framework;
  42328. /**
  42329. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  42330. */
  42331. final class MissingCoversAnnotationException extends \PHPUnit\Framework\RiskyTestError
  42332. {
  42333. }
  42334. <?php
  42335. declare (strict_types=1);
  42336. /*
  42337. * This file is part of PHPUnit.
  42338. *
  42339. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  42340. *
  42341. * For the full copyright and license information, please view the LICENSE
  42342. * file that was distributed with this source code.
  42343. */
  42344. namespace PHPUnit\Framework;
  42345. /**
  42346. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  42347. */
  42348. class SyntheticError extends \PHPUnit\Framework\AssertionFailedError
  42349. {
  42350. /**
  42351. * The synthetic file.
  42352. *
  42353. * @var string
  42354. */
  42355. protected $syntheticFile = '';
  42356. /**
  42357. * The synthetic line number.
  42358. *
  42359. * @var int
  42360. */
  42361. protected $syntheticLine = 0;
  42362. /**
  42363. * The synthetic trace.
  42364. *
  42365. * @var array
  42366. */
  42367. protected $syntheticTrace = [];
  42368. public function __construct(string $message, int $code, string $file, int $line, array $trace)
  42369. {
  42370. parent::__construct($message, $code);
  42371. $this->syntheticFile = $file;
  42372. $this->syntheticLine = $line;
  42373. $this->syntheticTrace = $trace;
  42374. }
  42375. public function getSyntheticFile() : string
  42376. {
  42377. return $this->syntheticFile;
  42378. }
  42379. public function getSyntheticLine() : int
  42380. {
  42381. return $this->syntheticLine;
  42382. }
  42383. public function getSyntheticTrace() : array
  42384. {
  42385. return $this->syntheticTrace;
  42386. }
  42387. }
  42388. <?php
  42389. declare (strict_types=1);
  42390. /*
  42391. * This file is part of PHPUnit.
  42392. *
  42393. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  42394. *
  42395. * For the full copyright and license information, please view the LICENSE
  42396. * file that was distributed with this source code.
  42397. */
  42398. namespace PHPUnit\Framework;
  42399. /**
  42400. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  42401. */
  42402. final class UnintentionallyCoveredCodeError extends \PHPUnit\Framework\RiskyTestError
  42403. {
  42404. }
  42405. <?php
  42406. declare (strict_types=1);
  42407. /*
  42408. * This file is part of PHPUnit.
  42409. *
  42410. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  42411. *
  42412. * For the full copyright and license information, please view the LICENSE
  42413. * file that was distributed with this source code.
  42414. */
  42415. namespace PHPUnit\Framework;
  42416. /**
  42417. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  42418. */
  42419. final class InvalidDataProviderException extends \PHPUnit\Framework\Exception
  42420. {
  42421. }
  42422. <?php
  42423. declare (strict_types=1);
  42424. /*
  42425. * This file is part of PHPUnit.
  42426. *
  42427. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  42428. *
  42429. * For the full copyright and license information, please view the LICENSE
  42430. * file that was distributed with this source code.
  42431. */
  42432. namespace PHPUnit\Framework;
  42433. use PHPUnit\Util\Filter;
  42434. /**
  42435. * Base class for all PHPUnit Framework exceptions.
  42436. *
  42437. * Ensures that exceptions thrown during a test run do not leave stray
  42438. * references behind.
  42439. *
  42440. * Every Exception contains a stack trace. Each stack frame contains the 'args'
  42441. * of the called function. The function arguments can contain references to
  42442. * instantiated objects. The references prevent the objects from being
  42443. * destructed (until test results are eventually printed), so memory cannot be
  42444. * freed up.
  42445. *
  42446. * With enabled process isolation, test results are serialized in the child
  42447. * process and unserialized in the parent process. The stack trace of Exceptions
  42448. * may contain objects that cannot be serialized or unserialized (e.g., PDO
  42449. * connections). Unserializing user-space objects from the child process into
  42450. * the parent would break the intended encapsulation of process isolation.
  42451. *
  42452. * @see http://fabien.potencier.org/article/9/php-serialization-stack-traces-and-exceptions
  42453. *
  42454. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  42455. */
  42456. class Exception extends \RuntimeException implements \PHPUnit\Exception
  42457. {
  42458. /**
  42459. * @var array
  42460. */
  42461. protected $serializableTrace;
  42462. public function __construct($message = '', $code = 0, \Throwable $previous = null)
  42463. {
  42464. parent::__construct($message, $code, $previous);
  42465. $this->serializableTrace = $this->getTrace();
  42466. foreach (\array_keys($this->serializableTrace) as $key) {
  42467. unset($this->serializableTrace[$key]['args']);
  42468. }
  42469. }
  42470. public function __toString() : string
  42471. {
  42472. $string = \PHPUnit\Framework\TestFailure::exceptionToString($this);
  42473. if ($trace = \PHPUnit\Util\Filter::getFilteredStacktrace($this)) {
  42474. $string .= "\n" . $trace;
  42475. }
  42476. return $string;
  42477. }
  42478. public function __sleep() : array
  42479. {
  42480. return \array_keys(\get_object_vars($this));
  42481. }
  42482. /**
  42483. * Returns the serializable trace (without 'args').
  42484. */
  42485. public function getSerializableTrace() : array
  42486. {
  42487. return $this->serializableTrace;
  42488. }
  42489. }
  42490. <?php
  42491. declare (strict_types=1);
  42492. /*
  42493. * This file is part of PHPUnit.
  42494. *
  42495. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  42496. *
  42497. * For the full copyright and license information, please view the LICENSE
  42498. * file that was distributed with this source code.
  42499. */
  42500. namespace PHPUnit\Framework;
  42501. /**
  42502. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  42503. */
  42504. class AssertionFailedError extends \PHPUnit\Framework\Exception implements \PHPUnit\Framework\SelfDescribing
  42505. {
  42506. /**
  42507. * Wrapper for getMessage() which is declared as final.
  42508. */
  42509. public function toString() : string
  42510. {
  42511. return $this->getMessage();
  42512. }
  42513. }
  42514. <?php
  42515. declare (strict_types=1);
  42516. /*
  42517. * This file is part of PHPUnit.
  42518. *
  42519. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  42520. *
  42521. * For the full copyright and license information, please view the LICENSE
  42522. * file that was distributed with this source code.
  42523. */
  42524. namespace PHPUnit\Framework;
  42525. /**
  42526. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  42527. */
  42528. final class InvalidCoversTargetException extends \PHPUnit\Framework\CodeCoverageException
  42529. {
  42530. }
  42531. <?php
  42532. declare (strict_types=1);
  42533. /*
  42534. * This file is part of PHPUnit.
  42535. *
  42536. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  42537. *
  42538. * For the full copyright and license information, please view the LICENSE
  42539. * file that was distributed with this source code.
  42540. */
  42541. namespace PHPUnit\Framework;
  42542. /**
  42543. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  42544. */
  42545. final class InvalidArgumentException extends \PHPUnit\Framework\Exception
  42546. {
  42547. public static function create(int $argument, string $type) : self
  42548. {
  42549. $stack = \debug_backtrace();
  42550. return new self(\sprintf('Argument #%d of %s::%s() must be %s %s', $argument, $stack[1]['class'], $stack[1]['function'], \in_array(\lcfirst($type)[0], ['a', 'e', 'i', 'o', 'u']) ? 'an' : 'a', $type));
  42551. }
  42552. private function __construct(string $message = '', int $code = 0, \Exception $previous = null)
  42553. {
  42554. parent::__construct($message, $code, $previous);
  42555. }
  42556. }
  42557. <?php
  42558. declare (strict_types=1);
  42559. /*
  42560. * This file is part of PHPUnit.
  42561. *
  42562. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  42563. *
  42564. * For the full copyright and license information, please view the LICENSE
  42565. * file that was distributed with this source code.
  42566. */
  42567. namespace PHPUnit\Framework;
  42568. use PHPUnit\Framework\Constraint\ArrayHasKey;
  42569. use PHPUnit\Framework\Constraint\Callback;
  42570. use PHPUnit\Framework\Constraint\ClassHasAttribute;
  42571. use PHPUnit\Framework\Constraint\ClassHasStaticAttribute;
  42572. use PHPUnit\Framework\Constraint\Constraint;
  42573. use PHPUnit\Framework\Constraint\Count;
  42574. use PHPUnit\Framework\Constraint\DirectoryExists;
  42575. use PHPUnit\Framework\Constraint\FileExists;
  42576. use PHPUnit\Framework\Constraint\GreaterThan;
  42577. use PHPUnit\Framework\Constraint\IsAnything;
  42578. use PHPUnit\Framework\Constraint\IsEmpty;
  42579. use PHPUnit\Framework\Constraint\IsEqual;
  42580. use PHPUnit\Framework\Constraint\IsEqualCanonicalizing;
  42581. use PHPUnit\Framework\Constraint\IsEqualIgnoringCase;
  42582. use PHPUnit\Framework\Constraint\IsEqualWithDelta;
  42583. use PHPUnit\Framework\Constraint\IsFalse;
  42584. use PHPUnit\Framework\Constraint\IsFinite;
  42585. use PHPUnit\Framework\Constraint\IsIdentical;
  42586. use PHPUnit\Framework\Constraint\IsInfinite;
  42587. use PHPUnit\Framework\Constraint\IsInstanceOf;
  42588. use PHPUnit\Framework\Constraint\IsJson;
  42589. use PHPUnit\Framework\Constraint\IsNan;
  42590. use PHPUnit\Framework\Constraint\IsNull;
  42591. use PHPUnit\Framework\Constraint\IsReadable;
  42592. use PHPUnit\Framework\Constraint\IsTrue;
  42593. use PHPUnit\Framework\Constraint\IsType;
  42594. use PHPUnit\Framework\Constraint\IsWritable;
  42595. use PHPUnit\Framework\Constraint\LessThan;
  42596. use PHPUnit\Framework\Constraint\LogicalAnd;
  42597. use PHPUnit\Framework\Constraint\LogicalNot;
  42598. use PHPUnit\Framework\Constraint\LogicalOr;
  42599. use PHPUnit\Framework\Constraint\LogicalXor;
  42600. use PHPUnit\Framework\Constraint\ObjectHasAttribute;
  42601. use PHPUnit\Framework\Constraint\RegularExpression;
  42602. use PHPUnit\Framework\Constraint\StringContains;
  42603. use PHPUnit\Framework\Constraint\StringEndsWith;
  42604. use PHPUnit\Framework\Constraint\StringMatchesFormatDescription;
  42605. use PHPUnit\Framework\Constraint\StringStartsWith;
  42606. use PHPUnit\Framework\Constraint\TraversableContainsEqual;
  42607. use PHPUnit\Framework\Constraint\TraversableContainsIdentical;
  42608. use PHPUnit\Framework\Constraint\TraversableContainsOnly;
  42609. use PHPUnit\Framework\MockObject\Rule\AnyInvokedCount as AnyInvokedCountMatcher;
  42610. use PHPUnit\Framework\MockObject\Rule\InvokedAtIndex as InvokedAtIndexMatcher;
  42611. use PHPUnit\Framework\MockObject\Rule\InvokedAtLeastCount as InvokedAtLeastCountMatcher;
  42612. use PHPUnit\Framework\MockObject\Rule\InvokedAtLeastOnce as InvokedAtLeastOnceMatcher;
  42613. use PHPUnit\Framework\MockObject\Rule\InvokedAtMostCount as InvokedAtMostCountMatcher;
  42614. use PHPUnit\Framework\MockObject\Rule\InvokedCount as InvokedCountMatcher;
  42615. use PHPUnit\Framework\MockObject\Stub\ConsecutiveCalls as ConsecutiveCallsStub;
  42616. use PHPUnit\Framework\MockObject\Stub\Exception as ExceptionStub;
  42617. use PHPUnit\Framework\MockObject\Stub\ReturnArgument as ReturnArgumentStub;
  42618. use PHPUnit\Framework\MockObject\Stub\ReturnCallback as ReturnCallbackStub;
  42619. use PHPUnit\Framework\MockObject\Stub\ReturnSelf as ReturnSelfStub;
  42620. use PHPUnit\Framework\MockObject\Stub\ReturnStub;
  42621. use PHPUnit\Framework\MockObject\Stub\ReturnValueMap as ReturnValueMapStub;
  42622. /**
  42623. * Asserts that an array has a specified key.
  42624. *
  42625. * @param int|string $key
  42626. * @param array|\ArrayAccess $array
  42627. *
  42628. * @throws ExpectationFailedException
  42629. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  42630. * @throws Exception
  42631. *
  42632. * @see Assert::assertArrayHasKey
  42633. */
  42634. function assertArrayHasKey($key, $array, string $message = '') : void
  42635. {
  42636. \PHPUnit\Framework\Assert::assertArrayHasKey(...\func_get_args());
  42637. }
  42638. /**
  42639. * Asserts that an array does not have a specified key.
  42640. *
  42641. * @param int|string $key
  42642. * @param array|\ArrayAccess $array
  42643. *
  42644. * @throws ExpectationFailedException
  42645. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  42646. * @throws Exception
  42647. *
  42648. * @see Assert::assertArrayNotHasKey
  42649. */
  42650. function assertArrayNotHasKey($key, $array, string $message = '') : void
  42651. {
  42652. \PHPUnit\Framework\Assert::assertArrayNotHasKey(...\func_get_args());
  42653. }
  42654. /**
  42655. * Asserts that a haystack contains a needle.
  42656. *
  42657. * @throws ExpectationFailedException
  42658. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  42659. * @throws Exception
  42660. *
  42661. * @see Assert::assertContains
  42662. */
  42663. function assertContains($needle, iterable $haystack, string $message = '') : void
  42664. {
  42665. \PHPUnit\Framework\Assert::assertContains(...\func_get_args());
  42666. }
  42667. function assertContainsEquals($needle, iterable $haystack, string $message = '') : void
  42668. {
  42669. \PHPUnit\Framework\Assert::assertContainsEquals(...\func_get_args());
  42670. }
  42671. /**
  42672. * Asserts that a haystack does not contain a needle.
  42673. *
  42674. * @throws ExpectationFailedException
  42675. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  42676. * @throws Exception
  42677. *
  42678. * @see Assert::assertNotContains
  42679. */
  42680. function assertNotContains($needle, iterable $haystack, string $message = '') : void
  42681. {
  42682. \PHPUnit\Framework\Assert::assertNotContains(...\func_get_args());
  42683. }
  42684. function assertNotContainsEquals($needle, iterable $haystack, string $message = '') : void
  42685. {
  42686. \PHPUnit\Framework\Assert::assertNotContainsEquals(...\func_get_args());
  42687. }
  42688. /**
  42689. * Asserts that a haystack contains only values of a given type.
  42690. *
  42691. * @throws ExpectationFailedException
  42692. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  42693. *
  42694. * @see Assert::assertContainsOnly
  42695. */
  42696. function assertContainsOnly(string $type, iterable $haystack, ?bool $isNativeType = null, string $message = '') : void
  42697. {
  42698. \PHPUnit\Framework\Assert::assertContainsOnly(...\func_get_args());
  42699. }
  42700. /**
  42701. * Asserts that a haystack contains only instances of a given class name.
  42702. *
  42703. * @throws ExpectationFailedException
  42704. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  42705. *
  42706. * @see Assert::assertContainsOnlyInstancesOf
  42707. */
  42708. function assertContainsOnlyInstancesOf(string $className, iterable $haystack, string $message = '') : void
  42709. {
  42710. \PHPUnit\Framework\Assert::assertContainsOnlyInstancesOf(...\func_get_args());
  42711. }
  42712. /**
  42713. * Asserts that a haystack does not contain only values of a given type.
  42714. *
  42715. * @throws ExpectationFailedException
  42716. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  42717. *
  42718. * @see Assert::assertNotContainsOnly
  42719. */
  42720. function assertNotContainsOnly(string $type, iterable $haystack, ?bool $isNativeType = null, string $message = '') : void
  42721. {
  42722. \PHPUnit\Framework\Assert::assertNotContainsOnly(...\func_get_args());
  42723. }
  42724. /**
  42725. * Asserts the number of elements of an array, Countable or Traversable.
  42726. *
  42727. * @param \Countable|iterable $haystack
  42728. *
  42729. * @throws ExpectationFailedException
  42730. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  42731. * @throws Exception
  42732. *
  42733. * @see Assert::assertCount
  42734. */
  42735. function assertCount(int $expectedCount, $haystack, string $message = '') : void
  42736. {
  42737. \PHPUnit\Framework\Assert::assertCount(...\func_get_args());
  42738. }
  42739. /**
  42740. * Asserts the number of elements of an array, Countable or Traversable.
  42741. *
  42742. * @param \Countable|iterable $haystack
  42743. *
  42744. * @throws ExpectationFailedException
  42745. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  42746. * @throws Exception
  42747. *
  42748. * @see Assert::assertNotCount
  42749. */
  42750. function assertNotCount(int $expectedCount, $haystack, string $message = '') : void
  42751. {
  42752. \PHPUnit\Framework\Assert::assertNotCount(...\func_get_args());
  42753. }
  42754. /**
  42755. * Asserts that two variables are equal.
  42756. *
  42757. * @throws ExpectationFailedException
  42758. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  42759. *
  42760. * @see Assert::assertEquals
  42761. */
  42762. function assertEquals($expected, $actual, string $message = '') : void
  42763. {
  42764. \PHPUnit\Framework\Assert::assertEquals(...\func_get_args());
  42765. }
  42766. /**
  42767. * Asserts that two variables are equal (canonicalizing).
  42768. *
  42769. * @throws ExpectationFailedException
  42770. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  42771. *
  42772. * @see Assert::assertEqualsCanonicalizing
  42773. */
  42774. function assertEqualsCanonicalizing($expected, $actual, string $message = '') : void
  42775. {
  42776. \PHPUnit\Framework\Assert::assertEqualsCanonicalizing(...\func_get_args());
  42777. }
  42778. /**
  42779. * Asserts that two variables are equal (ignoring case).
  42780. *
  42781. * @throws ExpectationFailedException
  42782. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  42783. *
  42784. * @see Assert::assertEqualsIgnoringCase
  42785. */
  42786. function assertEqualsIgnoringCase($expected, $actual, string $message = '') : void
  42787. {
  42788. \PHPUnit\Framework\Assert::assertEqualsIgnoringCase(...\func_get_args());
  42789. }
  42790. /**
  42791. * Asserts that two variables are equal (with delta).
  42792. *
  42793. * @throws ExpectationFailedException
  42794. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  42795. *
  42796. * @see Assert::assertEqualsWithDelta
  42797. */
  42798. function assertEqualsWithDelta($expected, $actual, float $delta, string $message = '') : void
  42799. {
  42800. \PHPUnit\Framework\Assert::assertEqualsWithDelta(...\func_get_args());
  42801. }
  42802. /**
  42803. * Asserts that two variables are not equal.
  42804. *
  42805. * @throws ExpectationFailedException
  42806. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  42807. *
  42808. * @see Assert::assertNotEquals
  42809. */
  42810. function assertNotEquals($expected, $actual, string $message = '') : void
  42811. {
  42812. \PHPUnit\Framework\Assert::assertNotEquals(...\func_get_args());
  42813. }
  42814. /**
  42815. * Asserts that two variables are not equal (canonicalizing).
  42816. *
  42817. * @throws ExpectationFailedException
  42818. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  42819. *
  42820. * @see Assert::assertNotEqualsCanonicalizing
  42821. */
  42822. function assertNotEqualsCanonicalizing($expected, $actual, string $message = '') : void
  42823. {
  42824. \PHPUnit\Framework\Assert::assertNotEqualsCanonicalizing(...\func_get_args());
  42825. }
  42826. /**
  42827. * Asserts that two variables are not equal (ignoring case).
  42828. *
  42829. * @throws ExpectationFailedException
  42830. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  42831. *
  42832. * @see Assert::assertNotEqualsIgnoringCase
  42833. */
  42834. function assertNotEqualsIgnoringCase($expected, $actual, string $message = '') : void
  42835. {
  42836. \PHPUnit\Framework\Assert::assertNotEqualsIgnoringCase(...\func_get_args());
  42837. }
  42838. /**
  42839. * Asserts that two variables are not equal (with delta).
  42840. *
  42841. * @throws ExpectationFailedException
  42842. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  42843. *
  42844. * @see Assert::assertNotEqualsWithDelta
  42845. */
  42846. function assertNotEqualsWithDelta($expected, $actual, float $delta, string $message = '') : void
  42847. {
  42848. \PHPUnit\Framework\Assert::assertNotEqualsWithDelta(...\func_get_args());
  42849. }
  42850. /**
  42851. * Asserts that a variable is empty.
  42852. *
  42853. * @throws ExpectationFailedException
  42854. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  42855. *
  42856. * @psalm-assert empty $actual
  42857. *
  42858. * @see Assert::assertEmpty
  42859. */
  42860. function assertEmpty($actual, string $message = '') : void
  42861. {
  42862. \PHPUnit\Framework\Assert::assertEmpty(...\func_get_args());
  42863. }
  42864. /**
  42865. * Asserts that a variable is not empty.
  42866. *
  42867. * @throws ExpectationFailedException
  42868. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  42869. *
  42870. * @psalm-assert !empty $actual
  42871. *
  42872. * @see Assert::assertNotEmpty
  42873. */
  42874. function assertNotEmpty($actual, string $message = '') : void
  42875. {
  42876. \PHPUnit\Framework\Assert::assertNotEmpty(...\func_get_args());
  42877. }
  42878. /**
  42879. * Asserts that a value is greater than another value.
  42880. *
  42881. * @throws ExpectationFailedException
  42882. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  42883. *
  42884. * @see Assert::assertGreaterThan
  42885. */
  42886. function assertGreaterThan($expected, $actual, string $message = '') : void
  42887. {
  42888. \PHPUnit\Framework\Assert::assertGreaterThan(...\func_get_args());
  42889. }
  42890. /**
  42891. * Asserts that a value is greater than or equal to another value.
  42892. *
  42893. * @throws ExpectationFailedException
  42894. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  42895. *
  42896. * @see Assert::assertGreaterThanOrEqual
  42897. */
  42898. function assertGreaterThanOrEqual($expected, $actual, string $message = '') : void
  42899. {
  42900. \PHPUnit\Framework\Assert::assertGreaterThanOrEqual(...\func_get_args());
  42901. }
  42902. /**
  42903. * Asserts that a value is smaller than another value.
  42904. *
  42905. * @throws ExpectationFailedException
  42906. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  42907. *
  42908. * @see Assert::assertLessThan
  42909. */
  42910. function assertLessThan($expected, $actual, string $message = '') : void
  42911. {
  42912. \PHPUnit\Framework\Assert::assertLessThan(...\func_get_args());
  42913. }
  42914. /**
  42915. * Asserts that a value is smaller than or equal to another value.
  42916. *
  42917. * @throws ExpectationFailedException
  42918. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  42919. *
  42920. * @see Assert::assertLessThanOrEqual
  42921. */
  42922. function assertLessThanOrEqual($expected, $actual, string $message = '') : void
  42923. {
  42924. \PHPUnit\Framework\Assert::assertLessThanOrEqual(...\func_get_args());
  42925. }
  42926. /**
  42927. * Asserts that the contents of one file is equal to the contents of another
  42928. * file.
  42929. *
  42930. * @throws ExpectationFailedException
  42931. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  42932. *
  42933. * @see Assert::assertFileEquals
  42934. */
  42935. function assertFileEquals(string $expected, string $actual, string $message = '') : void
  42936. {
  42937. \PHPUnit\Framework\Assert::assertFileEquals(...\func_get_args());
  42938. }
  42939. /**
  42940. * Asserts that the contents of one file is equal to the contents of another
  42941. * file (canonicalizing).
  42942. *
  42943. * @throws ExpectationFailedException
  42944. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  42945. *
  42946. * @see Assert::assertFileEqualsCanonicalizing
  42947. */
  42948. function assertFileEqualsCanonicalizing(string $expected, string $actual, string $message = '') : void
  42949. {
  42950. \PHPUnit\Framework\Assert::assertFileEqualsCanonicalizing(...\func_get_args());
  42951. }
  42952. /**
  42953. * Asserts that the contents of one file is equal to the contents of another
  42954. * file (ignoring case).
  42955. *
  42956. * @throws ExpectationFailedException
  42957. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  42958. *
  42959. * @see Assert::assertFileEqualsIgnoringCase
  42960. */
  42961. function assertFileEqualsIgnoringCase(string $expected, string $actual, string $message = '') : void
  42962. {
  42963. \PHPUnit\Framework\Assert::assertFileEqualsIgnoringCase(...\func_get_args());
  42964. }
  42965. /**
  42966. * Asserts that the contents of one file is not equal to the contents of
  42967. * another file.
  42968. *
  42969. * @throws ExpectationFailedException
  42970. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  42971. *
  42972. * @see Assert::assertFileNotEquals
  42973. */
  42974. function assertFileNotEquals(string $expected, string $actual, string $message = '') : void
  42975. {
  42976. \PHPUnit\Framework\Assert::assertFileNotEquals(...\func_get_args());
  42977. }
  42978. /**
  42979. * Asserts that the contents of one file is not equal to the contents of another
  42980. * file (canonicalizing).
  42981. *
  42982. * @throws ExpectationFailedException
  42983. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  42984. *
  42985. * @see Assert::assertFileNotEqualsCanonicalizing
  42986. */
  42987. function assertFileNotEqualsCanonicalizing(string $expected, string $actual, string $message = '') : void
  42988. {
  42989. \PHPUnit\Framework\Assert::assertFileNotEqualsCanonicalizing(...\func_get_args());
  42990. }
  42991. /**
  42992. * Asserts that the contents of one file is not equal to the contents of another
  42993. * file (ignoring case).
  42994. *
  42995. * @throws ExpectationFailedException
  42996. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  42997. *
  42998. * @see Assert::assertFileNotEqualsIgnoringCase
  42999. */
  43000. function assertFileNotEqualsIgnoringCase(string $expected, string $actual, string $message = '') : void
  43001. {
  43002. \PHPUnit\Framework\Assert::assertFileNotEqualsIgnoringCase(...\func_get_args());
  43003. }
  43004. /**
  43005. * Asserts that the contents of a string is equal
  43006. * to the contents of a file.
  43007. *
  43008. * @throws ExpectationFailedException
  43009. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  43010. *
  43011. * @see Assert::assertStringEqualsFile
  43012. */
  43013. function assertStringEqualsFile(string $expectedFile, string $actualString, string $message = '') : void
  43014. {
  43015. \PHPUnit\Framework\Assert::assertStringEqualsFile(...\func_get_args());
  43016. }
  43017. /**
  43018. * Asserts that the contents of a string is equal
  43019. * to the contents of a file (canonicalizing).
  43020. *
  43021. * @throws ExpectationFailedException
  43022. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  43023. *
  43024. * @see Assert::assertStringEqualsFileCanonicalizing
  43025. */
  43026. function assertStringEqualsFileCanonicalizing(string $expectedFile, string $actualString, string $message = '') : void
  43027. {
  43028. \PHPUnit\Framework\Assert::assertStringEqualsFileCanonicalizing(...\func_get_args());
  43029. }
  43030. /**
  43031. * Asserts that the contents of a string is equal
  43032. * to the contents of a file (ignoring case).
  43033. *
  43034. * @throws ExpectationFailedException
  43035. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  43036. *
  43037. * @see Assert::assertStringEqualsFileIgnoringCase
  43038. */
  43039. function assertStringEqualsFileIgnoringCase(string $expectedFile, string $actualString, string $message = '') : void
  43040. {
  43041. \PHPUnit\Framework\Assert::assertStringEqualsFileIgnoringCase(...\func_get_args());
  43042. }
  43043. /**
  43044. * Asserts that the contents of a string is not equal
  43045. * to the contents of a file.
  43046. *
  43047. * @throws ExpectationFailedException
  43048. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  43049. *
  43050. * @see Assert::assertStringNotEqualsFile
  43051. */
  43052. function assertStringNotEqualsFile(string $expectedFile, string $actualString, string $message = '') : void
  43053. {
  43054. \PHPUnit\Framework\Assert::assertStringNotEqualsFile(...\func_get_args());
  43055. }
  43056. /**
  43057. * Asserts that the contents of a string is not equal
  43058. * to the contents of a file (canonicalizing).
  43059. *
  43060. * @throws ExpectationFailedException
  43061. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  43062. *
  43063. * @see Assert::assertStringNotEqualsFileCanonicalizing
  43064. */
  43065. function assertStringNotEqualsFileCanonicalizing(string $expectedFile, string $actualString, string $message = '') : void
  43066. {
  43067. \PHPUnit\Framework\Assert::assertStringNotEqualsFileCanonicalizing(...\func_get_args());
  43068. }
  43069. /**
  43070. * Asserts that the contents of a string is not equal
  43071. * to the contents of a file (ignoring case).
  43072. *
  43073. * @throws ExpectationFailedException
  43074. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  43075. *
  43076. * @see Assert::assertStringNotEqualsFileIgnoringCase
  43077. */
  43078. function assertStringNotEqualsFileIgnoringCase(string $expectedFile, string $actualString, string $message = '') : void
  43079. {
  43080. \PHPUnit\Framework\Assert::assertStringNotEqualsFileIgnoringCase(...\func_get_args());
  43081. }
  43082. /**
  43083. * Asserts that a file/dir is readable.
  43084. *
  43085. * @throws ExpectationFailedException
  43086. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  43087. *
  43088. * @see Assert::assertIsReadable
  43089. */
  43090. function assertIsReadable(string $filename, string $message = '') : void
  43091. {
  43092. \PHPUnit\Framework\Assert::assertIsReadable(...\func_get_args());
  43093. }
  43094. /**
  43095. * Asserts that a file/dir exists and is not readable.
  43096. *
  43097. * @throws ExpectationFailedException
  43098. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  43099. *
  43100. * @see Assert::assertIsNotReadable
  43101. */
  43102. function assertIsNotReadable(string $filename, string $message = '') : void
  43103. {
  43104. \PHPUnit\Framework\Assert::assertIsNotReadable(...\func_get_args());
  43105. }
  43106. /**
  43107. * Asserts that a file/dir exists and is not readable.
  43108. *
  43109. * @throws ExpectationFailedException
  43110. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  43111. *
  43112. * @codeCoverageIgnore
  43113. *
  43114. * @deprecated https://github.com/sebastianbergmann/phpunit/issues/4062
  43115. * @see Assert::assertNotIsReadable
  43116. */
  43117. function assertNotIsReadable(string $filename, string $message = '') : void
  43118. {
  43119. \PHPUnit\Framework\Assert::assertNotIsReadable(...\func_get_args());
  43120. }
  43121. /**
  43122. * Asserts that a file/dir exists and is writable.
  43123. *
  43124. * @throws ExpectationFailedException
  43125. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  43126. *
  43127. * @see Assert::assertIsWritable
  43128. */
  43129. function assertIsWritable(string $filename, string $message = '') : void
  43130. {
  43131. \PHPUnit\Framework\Assert::assertIsWritable(...\func_get_args());
  43132. }
  43133. /**
  43134. * Asserts that a file/dir exists and is not writable.
  43135. *
  43136. * @throws ExpectationFailedException
  43137. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  43138. *
  43139. * @see Assert::assertIsNotWritable
  43140. */
  43141. function assertIsNotWritable(string $filename, string $message = '') : void
  43142. {
  43143. \PHPUnit\Framework\Assert::assertIsNotWritable(...\func_get_args());
  43144. }
  43145. /**
  43146. * Asserts that a file/dir exists and is not writable.
  43147. *
  43148. * @throws ExpectationFailedException
  43149. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  43150. *
  43151. * @codeCoverageIgnore
  43152. *
  43153. * @deprecated https://github.com/sebastianbergmann/phpunit/issues/4065
  43154. * @see Assert::assertNotIsWritable
  43155. */
  43156. function assertNotIsWritable(string $filename, string $message = '') : void
  43157. {
  43158. \PHPUnit\Framework\Assert::assertNotIsWritable(...\func_get_args());
  43159. }
  43160. /**
  43161. * Asserts that a directory exists.
  43162. *
  43163. * @throws ExpectationFailedException
  43164. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  43165. *
  43166. * @see Assert::assertDirectoryExists
  43167. */
  43168. function assertDirectoryExists(string $directory, string $message = '') : void
  43169. {
  43170. \PHPUnit\Framework\Assert::assertDirectoryExists(...\func_get_args());
  43171. }
  43172. /**
  43173. * Asserts that a directory does not exist.
  43174. *
  43175. * @throws ExpectationFailedException
  43176. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  43177. *
  43178. * @see Assert::assertDirectoryDoesNotExist
  43179. */
  43180. function assertDirectoryDoesNotExist(string $directory, string $message = '') : void
  43181. {
  43182. \PHPUnit\Framework\Assert::assertDirectoryDoesNotExist(...\func_get_args());
  43183. }
  43184. /**
  43185. * Asserts that a directory does not exist.
  43186. *
  43187. * @throws ExpectationFailedException
  43188. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  43189. *
  43190. * @codeCoverageIgnore
  43191. *
  43192. * @deprecated https://github.com/sebastianbergmann/phpunit/issues/4068
  43193. * @see Assert::assertDirectoryNotExists
  43194. */
  43195. function assertDirectoryNotExists(string $directory, string $message = '') : void
  43196. {
  43197. \PHPUnit\Framework\Assert::assertDirectoryNotExists(...\func_get_args());
  43198. }
  43199. /**
  43200. * Asserts that a directory exists and is readable.
  43201. *
  43202. * @throws ExpectationFailedException
  43203. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  43204. *
  43205. * @see Assert::assertDirectoryIsReadable
  43206. */
  43207. function assertDirectoryIsReadable(string $directory, string $message = '') : void
  43208. {
  43209. \PHPUnit\Framework\Assert::assertDirectoryIsReadable(...\func_get_args());
  43210. }
  43211. /**
  43212. * Asserts that a directory exists and is not readable.
  43213. *
  43214. * @throws ExpectationFailedException
  43215. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  43216. *
  43217. * @see Assert::assertDirectoryIsNotReadable
  43218. */
  43219. function assertDirectoryIsNotReadable(string $directory, string $message = '') : void
  43220. {
  43221. \PHPUnit\Framework\Assert::assertDirectoryIsNotReadable(...\func_get_args());
  43222. }
  43223. /**
  43224. * Asserts that a directory exists and is not readable.
  43225. *
  43226. * @throws ExpectationFailedException
  43227. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  43228. *
  43229. * @codeCoverageIgnore
  43230. *
  43231. * @deprecated https://github.com/sebastianbergmann/phpunit/issues/4071
  43232. * @see Assert::assertDirectoryNotIsReadable
  43233. */
  43234. function assertDirectoryNotIsReadable(string $directory, string $message = '') : void
  43235. {
  43236. \PHPUnit\Framework\Assert::assertDirectoryNotIsReadable(...\func_get_args());
  43237. }
  43238. /**
  43239. * Asserts that a directory exists and is writable.
  43240. *
  43241. * @throws ExpectationFailedException
  43242. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  43243. *
  43244. * @see Assert::assertDirectoryIsWritable
  43245. */
  43246. function assertDirectoryIsWritable(string $directory, string $message = '') : void
  43247. {
  43248. \PHPUnit\Framework\Assert::assertDirectoryIsWritable(...\func_get_args());
  43249. }
  43250. /**
  43251. * Asserts that a directory exists and is not writable.
  43252. *
  43253. * @throws ExpectationFailedException
  43254. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  43255. *
  43256. * @see Assert::assertDirectoryIsNotWritable
  43257. */
  43258. function assertDirectoryIsNotWritable(string $directory, string $message = '') : void
  43259. {
  43260. \PHPUnit\Framework\Assert::assertDirectoryIsNotWritable(...\func_get_args());
  43261. }
  43262. /**
  43263. * Asserts that a directory exists and is not writable.
  43264. *
  43265. * @throws ExpectationFailedException
  43266. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  43267. *
  43268. * @codeCoverageIgnore
  43269. *
  43270. * @deprecated https://github.com/sebastianbergmann/phpunit/issues/4074
  43271. * @see Assert::assertDirectoryNotIsWritable
  43272. */
  43273. function assertDirectoryNotIsWritable(string $directory, string $message = '') : void
  43274. {
  43275. \PHPUnit\Framework\Assert::assertDirectoryNotIsWritable(...\func_get_args());
  43276. }
  43277. /**
  43278. * Asserts that a file exists.
  43279. *
  43280. * @throws ExpectationFailedException
  43281. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  43282. *
  43283. * @see Assert::assertFileExists
  43284. */
  43285. function assertFileExists(string $filename, string $message = '') : void
  43286. {
  43287. \PHPUnit\Framework\Assert::assertFileExists(...\func_get_args());
  43288. }
  43289. /**
  43290. * Asserts that a file does not exist.
  43291. *
  43292. * @throws ExpectationFailedException
  43293. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  43294. *
  43295. * @see Assert::assertFileDoesNotExist
  43296. */
  43297. function assertFileDoesNotExist(string $filename, string $message = '') : void
  43298. {
  43299. \PHPUnit\Framework\Assert::assertFileDoesNotExist(...\func_get_args());
  43300. }
  43301. /**
  43302. * Asserts that a file does not exist.
  43303. *
  43304. * @throws ExpectationFailedException
  43305. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  43306. *
  43307. * @codeCoverageIgnore
  43308. *
  43309. * @deprecated https://github.com/sebastianbergmann/phpunit/issues/4077
  43310. * @see Assert::assertFileNotExists
  43311. */
  43312. function assertFileNotExists(string $filename, string $message = '') : void
  43313. {
  43314. \PHPUnit\Framework\Assert::assertFileNotExists(...\func_get_args());
  43315. }
  43316. /**
  43317. * Asserts that a file exists and is readable.
  43318. *
  43319. * @throws ExpectationFailedException
  43320. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  43321. *
  43322. * @see Assert::assertFileIsReadable
  43323. */
  43324. function assertFileIsReadable(string $file, string $message = '') : void
  43325. {
  43326. \PHPUnit\Framework\Assert::assertFileIsReadable(...\func_get_args());
  43327. }
  43328. /**
  43329. * Asserts that a file exists and is not readable.
  43330. *
  43331. * @throws ExpectationFailedException
  43332. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  43333. *
  43334. * @see Assert::assertFileIsNotReadable
  43335. */
  43336. function assertFileIsNotReadable(string $file, string $message = '') : void
  43337. {
  43338. \PHPUnit\Framework\Assert::assertFileIsNotReadable(...\func_get_args());
  43339. }
  43340. /**
  43341. * Asserts that a file exists and is not readable.
  43342. *
  43343. * @throws ExpectationFailedException
  43344. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  43345. *
  43346. * @codeCoverageIgnore
  43347. *
  43348. * @deprecated https://github.com/sebastianbergmann/phpunit/issues/4080
  43349. * @see Assert::assertFileNotIsReadable
  43350. */
  43351. function assertFileNotIsReadable(string $file, string $message = '') : void
  43352. {
  43353. \PHPUnit\Framework\Assert::assertFileNotIsReadable(...\func_get_args());
  43354. }
  43355. /**
  43356. * Asserts that a file exists and is writable.
  43357. *
  43358. * @throws ExpectationFailedException
  43359. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  43360. *
  43361. * @see Assert::assertFileIsWritable
  43362. */
  43363. function assertFileIsWritable(string $file, string $message = '') : void
  43364. {
  43365. \PHPUnit\Framework\Assert::assertFileIsWritable(...\func_get_args());
  43366. }
  43367. /**
  43368. * Asserts that a file exists and is not writable.
  43369. *
  43370. * @throws ExpectationFailedException
  43371. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  43372. *
  43373. * @see Assert::assertFileIsNotWritable
  43374. */
  43375. function assertFileIsNotWritable(string $file, string $message = '') : void
  43376. {
  43377. \PHPUnit\Framework\Assert::assertFileIsNotWritable(...\func_get_args());
  43378. }
  43379. /**
  43380. * Asserts that a file exists and is not writable.
  43381. *
  43382. * @throws ExpectationFailedException
  43383. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  43384. *
  43385. * @codeCoverageIgnore
  43386. *
  43387. * @deprecated https://github.com/sebastianbergmann/phpunit/issues/4083
  43388. * @see Assert::assertFileNotIsWritable
  43389. */
  43390. function assertFileNotIsWritable(string $file, string $message = '') : void
  43391. {
  43392. \PHPUnit\Framework\Assert::assertFileNotIsWritable(...\func_get_args());
  43393. }
  43394. /**
  43395. * Asserts that a condition is true.
  43396. *
  43397. * @throws ExpectationFailedException
  43398. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  43399. *
  43400. * @psalm-assert true $condition
  43401. *
  43402. * @see Assert::assertTrue
  43403. */
  43404. function assertTrue($condition, string $message = '') : void
  43405. {
  43406. \PHPUnit\Framework\Assert::assertTrue(...\func_get_args());
  43407. }
  43408. /**
  43409. * Asserts that a condition is not true.
  43410. *
  43411. * @throws ExpectationFailedException
  43412. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  43413. *
  43414. * @psalm-assert !true $condition
  43415. *
  43416. * @see Assert::assertNotTrue
  43417. */
  43418. function assertNotTrue($condition, string $message = '') : void
  43419. {
  43420. \PHPUnit\Framework\Assert::assertNotTrue(...\func_get_args());
  43421. }
  43422. /**
  43423. * Asserts that a condition is false.
  43424. *
  43425. * @throws ExpectationFailedException
  43426. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  43427. *
  43428. * @psalm-assert false $condition
  43429. *
  43430. * @see Assert::assertFalse
  43431. */
  43432. function assertFalse($condition, string $message = '') : void
  43433. {
  43434. \PHPUnit\Framework\Assert::assertFalse(...\func_get_args());
  43435. }
  43436. /**
  43437. * Asserts that a condition is not false.
  43438. *
  43439. * @throws ExpectationFailedException
  43440. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  43441. *
  43442. * @psalm-assert !false $condition
  43443. *
  43444. * @see Assert::assertNotFalse
  43445. */
  43446. function assertNotFalse($condition, string $message = '') : void
  43447. {
  43448. \PHPUnit\Framework\Assert::assertNotFalse(...\func_get_args());
  43449. }
  43450. /**
  43451. * Asserts that a variable is null.
  43452. *
  43453. * @throws ExpectationFailedException
  43454. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  43455. *
  43456. * @psalm-assert null $actual
  43457. *
  43458. * @see Assert::assertNull
  43459. */
  43460. function assertNull($actual, string $message = '') : void
  43461. {
  43462. \PHPUnit\Framework\Assert::assertNull(...\func_get_args());
  43463. }
  43464. /**
  43465. * Asserts that a variable is not null.
  43466. *
  43467. * @throws ExpectationFailedException
  43468. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  43469. *
  43470. * @psalm-assert !null $actual
  43471. *
  43472. * @see Assert::assertNotNull
  43473. */
  43474. function assertNotNull($actual, string $message = '') : void
  43475. {
  43476. \PHPUnit\Framework\Assert::assertNotNull(...\func_get_args());
  43477. }
  43478. /**
  43479. * Asserts that a variable is finite.
  43480. *
  43481. * @throws ExpectationFailedException
  43482. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  43483. *
  43484. * @see Assert::assertFinite
  43485. */
  43486. function assertFinite($actual, string $message = '') : void
  43487. {
  43488. \PHPUnit\Framework\Assert::assertFinite(...\func_get_args());
  43489. }
  43490. /**
  43491. * Asserts that a variable is infinite.
  43492. *
  43493. * @throws ExpectationFailedException
  43494. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  43495. *
  43496. * @see Assert::assertInfinite
  43497. */
  43498. function assertInfinite($actual, string $message = '') : void
  43499. {
  43500. \PHPUnit\Framework\Assert::assertInfinite(...\func_get_args());
  43501. }
  43502. /**
  43503. * Asserts that a variable is nan.
  43504. *
  43505. * @throws ExpectationFailedException
  43506. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  43507. *
  43508. * @see Assert::assertNan
  43509. */
  43510. function assertNan($actual, string $message = '') : void
  43511. {
  43512. \PHPUnit\Framework\Assert::assertNan(...\func_get_args());
  43513. }
  43514. /**
  43515. * Asserts that a class has a specified attribute.
  43516. *
  43517. * @throws ExpectationFailedException
  43518. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  43519. * @throws Exception
  43520. *
  43521. * @see Assert::assertClassHasAttribute
  43522. */
  43523. function assertClassHasAttribute(string $attributeName, string $className, string $message = '') : void
  43524. {
  43525. \PHPUnit\Framework\Assert::assertClassHasAttribute(...\func_get_args());
  43526. }
  43527. /**
  43528. * Asserts that a class does not have a specified attribute.
  43529. *
  43530. * @throws ExpectationFailedException
  43531. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  43532. * @throws Exception
  43533. *
  43534. * @see Assert::assertClassNotHasAttribute
  43535. */
  43536. function assertClassNotHasAttribute(string $attributeName, string $className, string $message = '') : void
  43537. {
  43538. \PHPUnit\Framework\Assert::assertClassNotHasAttribute(...\func_get_args());
  43539. }
  43540. /**
  43541. * Asserts that a class has a specified static attribute.
  43542. *
  43543. * @throws ExpectationFailedException
  43544. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  43545. * @throws Exception
  43546. *
  43547. * @see Assert::assertClassHasStaticAttribute
  43548. */
  43549. function assertClassHasStaticAttribute(string $attributeName, string $className, string $message = '') : void
  43550. {
  43551. \PHPUnit\Framework\Assert::assertClassHasStaticAttribute(...\func_get_args());
  43552. }
  43553. /**
  43554. * Asserts that a class does not have a specified static attribute.
  43555. *
  43556. * @throws ExpectationFailedException
  43557. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  43558. * @throws Exception
  43559. *
  43560. * @see Assert::assertClassNotHasStaticAttribute
  43561. */
  43562. function assertClassNotHasStaticAttribute(string $attributeName, string $className, string $message = '') : void
  43563. {
  43564. \PHPUnit\Framework\Assert::assertClassNotHasStaticAttribute(...\func_get_args());
  43565. }
  43566. /**
  43567. * Asserts that an object has a specified attribute.
  43568. *
  43569. * @param object $object
  43570. *
  43571. * @throws ExpectationFailedException
  43572. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  43573. * @throws Exception
  43574. *
  43575. * @see Assert::assertObjectHasAttribute
  43576. */
  43577. function assertObjectHasAttribute(string $attributeName, $object, string $message = '') : void
  43578. {
  43579. \PHPUnit\Framework\Assert::assertObjectHasAttribute(...\func_get_args());
  43580. }
  43581. /**
  43582. * Asserts that an object does not have a specified attribute.
  43583. *
  43584. * @param object $object
  43585. *
  43586. * @throws ExpectationFailedException
  43587. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  43588. * @throws Exception
  43589. *
  43590. * @see Assert::assertObjectNotHasAttribute
  43591. */
  43592. function assertObjectNotHasAttribute(string $attributeName, $object, string $message = '') : void
  43593. {
  43594. \PHPUnit\Framework\Assert::assertObjectNotHasAttribute(...\func_get_args());
  43595. }
  43596. /**
  43597. * Asserts that two variables have the same type and value.
  43598. * Used on objects, it asserts that two variables reference
  43599. * the same object.
  43600. *
  43601. * @throws ExpectationFailedException
  43602. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  43603. *
  43604. * @psalm-template ExpectedType
  43605. * @psalm-param ExpectedType $expected
  43606. * @psalm-assert =ExpectedType $actual
  43607. *
  43608. * @see Assert::assertSame
  43609. */
  43610. function assertSame($expected, $actual, string $message = '') : void
  43611. {
  43612. \PHPUnit\Framework\Assert::assertSame(...\func_get_args());
  43613. }
  43614. /**
  43615. * Asserts that two variables do not have the same type and value.
  43616. * Used on objects, it asserts that two variables do not reference
  43617. * the same object.
  43618. *
  43619. * @throws ExpectationFailedException
  43620. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  43621. *
  43622. * @see Assert::assertNotSame
  43623. */
  43624. function assertNotSame($expected, $actual, string $message = '') : void
  43625. {
  43626. \PHPUnit\Framework\Assert::assertNotSame(...\func_get_args());
  43627. }
  43628. /**
  43629. * Asserts that a variable is of a given type.
  43630. *
  43631. * @throws ExpectationFailedException
  43632. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  43633. * @throws Exception
  43634. *
  43635. * @psalm-template ExpectedType of object
  43636. * @psalm-param class-string<ExpectedType> $expected
  43637. * @psalm-assert ExpectedType $actual
  43638. *
  43639. * @see Assert::assertInstanceOf
  43640. */
  43641. function assertInstanceOf(string $expected, $actual, string $message = '') : void
  43642. {
  43643. \PHPUnit\Framework\Assert::assertInstanceOf(...\func_get_args());
  43644. }
  43645. /**
  43646. * Asserts that a variable is not of a given type.
  43647. *
  43648. * @throws ExpectationFailedException
  43649. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  43650. * @throws Exception
  43651. *
  43652. * @psalm-template ExpectedType of object
  43653. * @psalm-param class-string<ExpectedType> $expected
  43654. * @psalm-assert !ExpectedType $actual
  43655. *
  43656. * @see Assert::assertNotInstanceOf
  43657. */
  43658. function assertNotInstanceOf(string $expected, $actual, string $message = '') : void
  43659. {
  43660. \PHPUnit\Framework\Assert::assertNotInstanceOf(...\func_get_args());
  43661. }
  43662. /**
  43663. * Asserts that a variable is of type array.
  43664. *
  43665. * @throws ExpectationFailedException
  43666. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  43667. *
  43668. * @psalm-assert array $actual
  43669. *
  43670. * @see Assert::assertIsArray
  43671. */
  43672. function assertIsArray($actual, string $message = '') : void
  43673. {
  43674. \PHPUnit\Framework\Assert::assertIsArray(...\func_get_args());
  43675. }
  43676. /**
  43677. * Asserts that a variable is of type bool.
  43678. *
  43679. * @throws ExpectationFailedException
  43680. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  43681. *
  43682. * @psalm-assert bool $actual
  43683. *
  43684. * @see Assert::assertIsBool
  43685. */
  43686. function assertIsBool($actual, string $message = '') : void
  43687. {
  43688. \PHPUnit\Framework\Assert::assertIsBool(...\func_get_args());
  43689. }
  43690. /**
  43691. * Asserts that a variable is of type float.
  43692. *
  43693. * @throws ExpectationFailedException
  43694. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  43695. *
  43696. * @psalm-assert float $actual
  43697. *
  43698. * @see Assert::assertIsFloat
  43699. */
  43700. function assertIsFloat($actual, string $message = '') : void
  43701. {
  43702. \PHPUnit\Framework\Assert::assertIsFloat(...\func_get_args());
  43703. }
  43704. /**
  43705. * Asserts that a variable is of type int.
  43706. *
  43707. * @throws ExpectationFailedException
  43708. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  43709. *
  43710. * @psalm-assert int $actual
  43711. *
  43712. * @see Assert::assertIsInt
  43713. */
  43714. function assertIsInt($actual, string $message = '') : void
  43715. {
  43716. \PHPUnit\Framework\Assert::assertIsInt(...\func_get_args());
  43717. }
  43718. /**
  43719. * Asserts that a variable is of type numeric.
  43720. *
  43721. * @throws ExpectationFailedException
  43722. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  43723. *
  43724. * @psalm-assert numeric $actual
  43725. *
  43726. * @see Assert::assertIsNumeric
  43727. */
  43728. function assertIsNumeric($actual, string $message = '') : void
  43729. {
  43730. \PHPUnit\Framework\Assert::assertIsNumeric(...\func_get_args());
  43731. }
  43732. /**
  43733. * Asserts that a variable is of type object.
  43734. *
  43735. * @throws ExpectationFailedException
  43736. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  43737. *
  43738. * @psalm-assert object $actual
  43739. *
  43740. * @see Assert::assertIsObject
  43741. */
  43742. function assertIsObject($actual, string $message = '') : void
  43743. {
  43744. \PHPUnit\Framework\Assert::assertIsObject(...\func_get_args());
  43745. }
  43746. /**
  43747. * Asserts that a variable is of type resource.
  43748. *
  43749. * @throws ExpectationFailedException
  43750. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  43751. *
  43752. * @psalm-assert resource $actual
  43753. *
  43754. * @see Assert::assertIsResource
  43755. */
  43756. function assertIsResource($actual, string $message = '') : void
  43757. {
  43758. \PHPUnit\Framework\Assert::assertIsResource(...\func_get_args());
  43759. }
  43760. /**
  43761. * Asserts that a variable is of type string.
  43762. *
  43763. * @throws ExpectationFailedException
  43764. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  43765. *
  43766. * @psalm-assert string $actual
  43767. *
  43768. * @see Assert::assertIsString
  43769. */
  43770. function assertIsString($actual, string $message = '') : void
  43771. {
  43772. \PHPUnit\Framework\Assert::assertIsString(...\func_get_args());
  43773. }
  43774. /**
  43775. * Asserts that a variable is of type scalar.
  43776. *
  43777. * @throws ExpectationFailedException
  43778. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  43779. *
  43780. * @psalm-assert scalar $actual
  43781. *
  43782. * @see Assert::assertIsScalar
  43783. */
  43784. function assertIsScalar($actual, string $message = '') : void
  43785. {
  43786. \PHPUnit\Framework\Assert::assertIsScalar(...\func_get_args());
  43787. }
  43788. /**
  43789. * Asserts that a variable is of type callable.
  43790. *
  43791. * @throws ExpectationFailedException
  43792. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  43793. *
  43794. * @psalm-assert callable $actual
  43795. *
  43796. * @see Assert::assertIsCallable
  43797. */
  43798. function assertIsCallable($actual, string $message = '') : void
  43799. {
  43800. \PHPUnit\Framework\Assert::assertIsCallable(...\func_get_args());
  43801. }
  43802. /**
  43803. * Asserts that a variable is of type iterable.
  43804. *
  43805. * @throws ExpectationFailedException
  43806. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  43807. *
  43808. * @psalm-assert iterable $actual
  43809. *
  43810. * @see Assert::assertIsIterable
  43811. */
  43812. function assertIsIterable($actual, string $message = '') : void
  43813. {
  43814. \PHPUnit\Framework\Assert::assertIsIterable(...\func_get_args());
  43815. }
  43816. /**
  43817. * Asserts that a variable is not of type array.
  43818. *
  43819. * @throws ExpectationFailedException
  43820. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  43821. *
  43822. * @psalm-assert !array $actual
  43823. *
  43824. * @see Assert::assertIsNotArray
  43825. */
  43826. function assertIsNotArray($actual, string $message = '') : void
  43827. {
  43828. \PHPUnit\Framework\Assert::assertIsNotArray(...\func_get_args());
  43829. }
  43830. /**
  43831. * Asserts that a variable is not of type bool.
  43832. *
  43833. * @throws ExpectationFailedException
  43834. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  43835. *
  43836. * @psalm-assert !bool $actual
  43837. *
  43838. * @see Assert::assertIsNotBool
  43839. */
  43840. function assertIsNotBool($actual, string $message = '') : void
  43841. {
  43842. \PHPUnit\Framework\Assert::assertIsNotBool(...\func_get_args());
  43843. }
  43844. /**
  43845. * Asserts that a variable is not of type float.
  43846. *
  43847. * @throws ExpectationFailedException
  43848. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  43849. *
  43850. * @psalm-assert !float $actual
  43851. *
  43852. * @see Assert::assertIsNotFloat
  43853. */
  43854. function assertIsNotFloat($actual, string $message = '') : void
  43855. {
  43856. \PHPUnit\Framework\Assert::assertIsNotFloat(...\func_get_args());
  43857. }
  43858. /**
  43859. * Asserts that a variable is not of type int.
  43860. *
  43861. * @throws ExpectationFailedException
  43862. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  43863. *
  43864. * @psalm-assert !int $actual
  43865. *
  43866. * @see Assert::assertIsNotInt
  43867. */
  43868. function assertIsNotInt($actual, string $message = '') : void
  43869. {
  43870. \PHPUnit\Framework\Assert::assertIsNotInt(...\func_get_args());
  43871. }
  43872. /**
  43873. * Asserts that a variable is not of type numeric.
  43874. *
  43875. * @throws ExpectationFailedException
  43876. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  43877. *
  43878. * @psalm-assert !numeric $actual
  43879. *
  43880. * @see Assert::assertIsNotNumeric
  43881. */
  43882. function assertIsNotNumeric($actual, string $message = '') : void
  43883. {
  43884. \PHPUnit\Framework\Assert::assertIsNotNumeric(...\func_get_args());
  43885. }
  43886. /**
  43887. * Asserts that a variable is not of type object.
  43888. *
  43889. * @throws ExpectationFailedException
  43890. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  43891. *
  43892. * @psalm-assert !object $actual
  43893. *
  43894. * @see Assert::assertIsNotObject
  43895. */
  43896. function assertIsNotObject($actual, string $message = '') : void
  43897. {
  43898. \PHPUnit\Framework\Assert::assertIsNotObject(...\func_get_args());
  43899. }
  43900. /**
  43901. * Asserts that a variable is not of type resource.
  43902. *
  43903. * @throws ExpectationFailedException
  43904. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  43905. *
  43906. * @psalm-assert !resource $actual
  43907. *
  43908. * @see Assert::assertIsNotResource
  43909. */
  43910. function assertIsNotResource($actual, string $message = '') : void
  43911. {
  43912. \PHPUnit\Framework\Assert::assertIsNotResource(...\func_get_args());
  43913. }
  43914. /**
  43915. * Asserts that a variable is not of type string.
  43916. *
  43917. * @throws ExpectationFailedException
  43918. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  43919. *
  43920. * @psalm-assert !string $actual
  43921. *
  43922. * @see Assert::assertIsNotString
  43923. */
  43924. function assertIsNotString($actual, string $message = '') : void
  43925. {
  43926. \PHPUnit\Framework\Assert::assertIsNotString(...\func_get_args());
  43927. }
  43928. /**
  43929. * Asserts that a variable is not of type scalar.
  43930. *
  43931. * @throws ExpectationFailedException
  43932. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  43933. *
  43934. * @psalm-assert !scalar $actual
  43935. *
  43936. * @see Assert::assertIsNotScalar
  43937. */
  43938. function assertIsNotScalar($actual, string $message = '') : void
  43939. {
  43940. \PHPUnit\Framework\Assert::assertIsNotScalar(...\func_get_args());
  43941. }
  43942. /**
  43943. * Asserts that a variable is not of type callable.
  43944. *
  43945. * @throws ExpectationFailedException
  43946. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  43947. *
  43948. * @psalm-assert !callable $actual
  43949. *
  43950. * @see Assert::assertIsNotCallable
  43951. */
  43952. function assertIsNotCallable($actual, string $message = '') : void
  43953. {
  43954. \PHPUnit\Framework\Assert::assertIsNotCallable(...\func_get_args());
  43955. }
  43956. /**
  43957. * Asserts that a variable is not of type iterable.
  43958. *
  43959. * @throws ExpectationFailedException
  43960. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  43961. *
  43962. * @psalm-assert !iterable $actual
  43963. *
  43964. * @see Assert::assertIsNotIterable
  43965. */
  43966. function assertIsNotIterable($actual, string $message = '') : void
  43967. {
  43968. \PHPUnit\Framework\Assert::assertIsNotIterable(...\func_get_args());
  43969. }
  43970. /**
  43971. * Asserts that a string matches a given regular expression.
  43972. *
  43973. * @throws ExpectationFailedException
  43974. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  43975. *
  43976. * @see Assert::assertMatchesRegularExpression
  43977. */
  43978. function assertMatchesRegularExpression(string $pattern, string $string, string $message = '') : void
  43979. {
  43980. \PHPUnit\Framework\Assert::assertMatchesRegularExpression(...\func_get_args());
  43981. }
  43982. /**
  43983. * Asserts that a string matches a given regular expression.
  43984. *
  43985. * @throws ExpectationFailedException
  43986. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  43987. *
  43988. * @codeCoverageIgnore
  43989. *
  43990. * @deprecated https://github.com/sebastianbergmann/phpunit/issues/4086
  43991. * @see Assert::assertRegExp
  43992. */
  43993. function assertRegExp(string $pattern, string $string, string $message = '') : void
  43994. {
  43995. \PHPUnit\Framework\Assert::assertRegExp(...\func_get_args());
  43996. }
  43997. /**
  43998. * Asserts that a string does not match a given regular expression.
  43999. *
  44000. * @throws ExpectationFailedException
  44001. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  44002. *
  44003. * @see Assert::assertDoesNotMatchRegularExpression
  44004. */
  44005. function assertDoesNotMatchRegularExpression(string $pattern, string $string, string $message = '') : void
  44006. {
  44007. \PHPUnit\Framework\Assert::assertDoesNotMatchRegularExpression(...\func_get_args());
  44008. }
  44009. /**
  44010. * Asserts that a string does not match a given regular expression.
  44011. *
  44012. * @throws ExpectationFailedException
  44013. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  44014. *
  44015. * @codeCoverageIgnore
  44016. *
  44017. * @deprecated https://github.com/sebastianbergmann/phpunit/issues/4089
  44018. * @see Assert::assertNotRegExp
  44019. */
  44020. function assertNotRegExp(string $pattern, string $string, string $message = '') : void
  44021. {
  44022. \PHPUnit\Framework\Assert::assertNotRegExp(...\func_get_args());
  44023. }
  44024. /**
  44025. * Assert that the size of two arrays (or `Countable` or `Traversable` objects)
  44026. * is the same.
  44027. *
  44028. * @param \Countable|iterable $expected
  44029. * @param \Countable|iterable $actual
  44030. *
  44031. * @throws ExpectationFailedException
  44032. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  44033. * @throws Exception
  44034. *
  44035. * @see Assert::assertSameSize
  44036. */
  44037. function assertSameSize($expected, $actual, string $message = '') : void
  44038. {
  44039. \PHPUnit\Framework\Assert::assertSameSize(...\func_get_args());
  44040. }
  44041. /**
  44042. * Assert that the size of two arrays (or `Countable` or `Traversable` objects)
  44043. * is not the same.
  44044. *
  44045. * @param \Countable|iterable $expected
  44046. * @param \Countable|iterable $actual
  44047. *
  44048. * @throws ExpectationFailedException
  44049. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  44050. * @throws Exception
  44051. *
  44052. * @see Assert::assertNotSameSize
  44053. */
  44054. function assertNotSameSize($expected, $actual, string $message = '') : void
  44055. {
  44056. \PHPUnit\Framework\Assert::assertNotSameSize(...\func_get_args());
  44057. }
  44058. /**
  44059. * Asserts that a string matches a given format string.
  44060. *
  44061. * @throws ExpectationFailedException
  44062. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  44063. *
  44064. * @see Assert::assertStringMatchesFormat
  44065. */
  44066. function assertStringMatchesFormat(string $format, string $string, string $message = '') : void
  44067. {
  44068. \PHPUnit\Framework\Assert::assertStringMatchesFormat(...\func_get_args());
  44069. }
  44070. /**
  44071. * Asserts that a string does not match a given format string.
  44072. *
  44073. * @throws ExpectationFailedException
  44074. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  44075. *
  44076. * @see Assert::assertStringNotMatchesFormat
  44077. */
  44078. function assertStringNotMatchesFormat(string $format, string $string, string $message = '') : void
  44079. {
  44080. \PHPUnit\Framework\Assert::assertStringNotMatchesFormat(...\func_get_args());
  44081. }
  44082. /**
  44083. * Asserts that a string matches a given format file.
  44084. *
  44085. * @throws ExpectationFailedException
  44086. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  44087. *
  44088. * @see Assert::assertStringMatchesFormatFile
  44089. */
  44090. function assertStringMatchesFormatFile(string $formatFile, string $string, string $message = '') : void
  44091. {
  44092. \PHPUnit\Framework\Assert::assertStringMatchesFormatFile(...\func_get_args());
  44093. }
  44094. /**
  44095. * Asserts that a string does not match a given format string.
  44096. *
  44097. * @throws ExpectationFailedException
  44098. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  44099. *
  44100. * @see Assert::assertStringNotMatchesFormatFile
  44101. */
  44102. function assertStringNotMatchesFormatFile(string $formatFile, string $string, string $message = '') : void
  44103. {
  44104. \PHPUnit\Framework\Assert::assertStringNotMatchesFormatFile(...\func_get_args());
  44105. }
  44106. /**
  44107. * Asserts that a string starts with a given prefix.
  44108. *
  44109. * @throws ExpectationFailedException
  44110. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  44111. *
  44112. * @see Assert::assertStringStartsWith
  44113. */
  44114. function assertStringStartsWith(string $prefix, string $string, string $message = '') : void
  44115. {
  44116. \PHPUnit\Framework\Assert::assertStringStartsWith(...\func_get_args());
  44117. }
  44118. /**
  44119. * Asserts that a string starts not with a given prefix.
  44120. *
  44121. * @param string $prefix
  44122. * @param string $string
  44123. *
  44124. * @throws ExpectationFailedException
  44125. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  44126. *
  44127. * @see Assert::assertStringStartsNotWith
  44128. */
  44129. function assertStringStartsNotWith($prefix, $string, string $message = '') : void
  44130. {
  44131. \PHPUnit\Framework\Assert::assertStringStartsNotWith(...\func_get_args());
  44132. }
  44133. /**
  44134. * @throws ExpectationFailedException
  44135. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  44136. *
  44137. * @see Assert::assertStringContainsString
  44138. */
  44139. function assertStringContainsString(string $needle, string $haystack, string $message = '') : void
  44140. {
  44141. \PHPUnit\Framework\Assert::assertStringContainsString(...\func_get_args());
  44142. }
  44143. /**
  44144. * @throws ExpectationFailedException
  44145. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  44146. *
  44147. * @see Assert::assertStringContainsStringIgnoringCase
  44148. */
  44149. function assertStringContainsStringIgnoringCase(string $needle, string $haystack, string $message = '') : void
  44150. {
  44151. \PHPUnit\Framework\Assert::assertStringContainsStringIgnoringCase(...\func_get_args());
  44152. }
  44153. /**
  44154. * @throws ExpectationFailedException
  44155. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  44156. *
  44157. * @see Assert::assertStringNotContainsString
  44158. */
  44159. function assertStringNotContainsString(string $needle, string $haystack, string $message = '') : void
  44160. {
  44161. \PHPUnit\Framework\Assert::assertStringNotContainsString(...\func_get_args());
  44162. }
  44163. /**
  44164. * @throws ExpectationFailedException
  44165. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  44166. *
  44167. * @see Assert::assertStringNotContainsStringIgnoringCase
  44168. */
  44169. function assertStringNotContainsStringIgnoringCase(string $needle, string $haystack, string $message = '') : void
  44170. {
  44171. \PHPUnit\Framework\Assert::assertStringNotContainsStringIgnoringCase(...\func_get_args());
  44172. }
  44173. /**
  44174. * Asserts that a string ends with a given suffix.
  44175. *
  44176. * @throws ExpectationFailedException
  44177. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  44178. *
  44179. * @see Assert::assertStringEndsWith
  44180. */
  44181. function assertStringEndsWith(string $suffix, string $string, string $message = '') : void
  44182. {
  44183. \PHPUnit\Framework\Assert::assertStringEndsWith(...\func_get_args());
  44184. }
  44185. /**
  44186. * Asserts that a string ends not with a given suffix.
  44187. *
  44188. * @throws ExpectationFailedException
  44189. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  44190. *
  44191. * @see Assert::assertStringEndsNotWith
  44192. */
  44193. function assertStringEndsNotWith(string $suffix, string $string, string $message = '') : void
  44194. {
  44195. \PHPUnit\Framework\Assert::assertStringEndsNotWith(...\func_get_args());
  44196. }
  44197. /**
  44198. * Asserts that two XML files are equal.
  44199. *
  44200. * @throws ExpectationFailedException
  44201. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  44202. * @throws Exception
  44203. *
  44204. * @see Assert::assertXmlFileEqualsXmlFile
  44205. */
  44206. function assertXmlFileEqualsXmlFile(string $expectedFile, string $actualFile, string $message = '') : void
  44207. {
  44208. \PHPUnit\Framework\Assert::assertXmlFileEqualsXmlFile(...\func_get_args());
  44209. }
  44210. /**
  44211. * Asserts that two XML files are not equal.
  44212. *
  44213. * @throws ExpectationFailedException
  44214. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  44215. * @throws Exception
  44216. *
  44217. * @see Assert::assertXmlFileNotEqualsXmlFile
  44218. */
  44219. function assertXmlFileNotEqualsXmlFile(string $expectedFile, string $actualFile, string $message = '') : void
  44220. {
  44221. \PHPUnit\Framework\Assert::assertXmlFileNotEqualsXmlFile(...\func_get_args());
  44222. }
  44223. /**
  44224. * Asserts that two XML documents are equal.
  44225. *
  44226. * @param \DOMDocument|string $actualXml
  44227. *
  44228. * @throws ExpectationFailedException
  44229. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  44230. * @throws Exception
  44231. *
  44232. * @see Assert::assertXmlStringEqualsXmlFile
  44233. */
  44234. function assertXmlStringEqualsXmlFile(string $expectedFile, $actualXml, string $message = '') : void
  44235. {
  44236. \PHPUnit\Framework\Assert::assertXmlStringEqualsXmlFile(...\func_get_args());
  44237. }
  44238. /**
  44239. * Asserts that two XML documents are not equal.
  44240. *
  44241. * @param \DOMDocument|string $actualXml
  44242. *
  44243. * @throws ExpectationFailedException
  44244. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  44245. * @throws Exception
  44246. *
  44247. * @see Assert::assertXmlStringNotEqualsXmlFile
  44248. */
  44249. function assertXmlStringNotEqualsXmlFile(string $expectedFile, $actualXml, string $message = '') : void
  44250. {
  44251. \PHPUnit\Framework\Assert::assertXmlStringNotEqualsXmlFile(...\func_get_args());
  44252. }
  44253. /**
  44254. * Asserts that two XML documents are equal.
  44255. *
  44256. * @param \DOMDocument|string $expectedXml
  44257. * @param \DOMDocument|string $actualXml
  44258. *
  44259. * @throws ExpectationFailedException
  44260. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  44261. * @throws Exception
  44262. *
  44263. * @see Assert::assertXmlStringEqualsXmlString
  44264. */
  44265. function assertXmlStringEqualsXmlString($expectedXml, $actualXml, string $message = '') : void
  44266. {
  44267. \PHPUnit\Framework\Assert::assertXmlStringEqualsXmlString(...\func_get_args());
  44268. }
  44269. /**
  44270. * Asserts that two XML documents are not equal.
  44271. *
  44272. * @param \DOMDocument|string $expectedXml
  44273. * @param \DOMDocument|string $actualXml
  44274. *
  44275. * @throws ExpectationFailedException
  44276. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  44277. * @throws Exception
  44278. *
  44279. * @see Assert::assertXmlStringNotEqualsXmlString
  44280. */
  44281. function assertXmlStringNotEqualsXmlString($expectedXml, $actualXml, string $message = '') : void
  44282. {
  44283. \PHPUnit\Framework\Assert::assertXmlStringNotEqualsXmlString(...\func_get_args());
  44284. }
  44285. /**
  44286. * Asserts that a hierarchy of DOMElements matches.
  44287. *
  44288. * @throws AssertionFailedError
  44289. * @throws ExpectationFailedException
  44290. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  44291. *
  44292. * @codeCoverageIgnore
  44293. *
  44294. * @deprecated https://github.com/sebastianbergmann/phpunit/issues/4091
  44295. * @see Assert::assertEqualXMLStructure
  44296. */
  44297. function assertEqualXMLStructure(\DOMElement $expectedElement, \DOMElement $actualElement, bool $checkAttributes = \false, string $message = '') : void
  44298. {
  44299. \PHPUnit\Framework\Assert::assertEqualXMLStructure(...\func_get_args());
  44300. }
  44301. /**
  44302. * Evaluates a PHPUnit\Framework\Constraint matcher object.
  44303. *
  44304. * @throws ExpectationFailedException
  44305. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  44306. *
  44307. * @see Assert::assertThat
  44308. */
  44309. function assertThat($value, \PHPUnit\Framework\Constraint\Constraint $constraint, string $message = '') : void
  44310. {
  44311. \PHPUnit\Framework\Assert::assertThat(...\func_get_args());
  44312. }
  44313. /**
  44314. * Asserts that a string is a valid JSON string.
  44315. *
  44316. * @throws ExpectationFailedException
  44317. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  44318. *
  44319. * @see Assert::assertJson
  44320. */
  44321. function assertJson(string $actualJson, string $message = '') : void
  44322. {
  44323. \PHPUnit\Framework\Assert::assertJson(...\func_get_args());
  44324. }
  44325. /**
  44326. * Asserts that two given JSON encoded objects or arrays are equal.
  44327. *
  44328. * @throws ExpectationFailedException
  44329. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  44330. *
  44331. * @see Assert::assertJsonStringEqualsJsonString
  44332. */
  44333. function assertJsonStringEqualsJsonString(string $expectedJson, string $actualJson, string $message = '') : void
  44334. {
  44335. \PHPUnit\Framework\Assert::assertJsonStringEqualsJsonString(...\func_get_args());
  44336. }
  44337. /**
  44338. * Asserts that two given JSON encoded objects or arrays are not equal.
  44339. *
  44340. * @param string $expectedJson
  44341. * @param string $actualJson
  44342. *
  44343. * @throws ExpectationFailedException
  44344. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  44345. *
  44346. * @see Assert::assertJsonStringNotEqualsJsonString
  44347. */
  44348. function assertJsonStringNotEqualsJsonString($expectedJson, $actualJson, string $message = '') : void
  44349. {
  44350. \PHPUnit\Framework\Assert::assertJsonStringNotEqualsJsonString(...\func_get_args());
  44351. }
  44352. /**
  44353. * Asserts that the generated JSON encoded object and the content of the given file are equal.
  44354. *
  44355. * @throws ExpectationFailedException
  44356. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  44357. *
  44358. * @see Assert::assertJsonStringEqualsJsonFile
  44359. */
  44360. function assertJsonStringEqualsJsonFile(string $expectedFile, string $actualJson, string $message = '') : void
  44361. {
  44362. \PHPUnit\Framework\Assert::assertJsonStringEqualsJsonFile(...\func_get_args());
  44363. }
  44364. /**
  44365. * Asserts that the generated JSON encoded object and the content of the given file are not equal.
  44366. *
  44367. * @throws ExpectationFailedException
  44368. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  44369. *
  44370. * @see Assert::assertJsonStringNotEqualsJsonFile
  44371. */
  44372. function assertJsonStringNotEqualsJsonFile(string $expectedFile, string $actualJson, string $message = '') : void
  44373. {
  44374. \PHPUnit\Framework\Assert::assertJsonStringNotEqualsJsonFile(...\func_get_args());
  44375. }
  44376. /**
  44377. * Asserts that two JSON files are equal.
  44378. *
  44379. * @throws ExpectationFailedException
  44380. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  44381. *
  44382. * @see Assert::assertJsonFileEqualsJsonFile
  44383. */
  44384. function assertJsonFileEqualsJsonFile(string $expectedFile, string $actualFile, string $message = '') : void
  44385. {
  44386. \PHPUnit\Framework\Assert::assertJsonFileEqualsJsonFile(...\func_get_args());
  44387. }
  44388. /**
  44389. * Asserts that two JSON files are not equal.
  44390. *
  44391. * @throws ExpectationFailedException
  44392. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  44393. *
  44394. * @see Assert::assertJsonFileNotEqualsJsonFile
  44395. */
  44396. function assertJsonFileNotEqualsJsonFile(string $expectedFile, string $actualFile, string $message = '') : void
  44397. {
  44398. \PHPUnit\Framework\Assert::assertJsonFileNotEqualsJsonFile(...\func_get_args());
  44399. }
  44400. function logicalAnd() : \PHPUnit\Framework\Constraint\LogicalAnd
  44401. {
  44402. return \PHPUnit\Framework\Assert::logicalAnd(...\func_get_args());
  44403. }
  44404. function logicalOr() : \PHPUnit\Framework\Constraint\LogicalOr
  44405. {
  44406. return \PHPUnit\Framework\Assert::logicalOr(...\func_get_args());
  44407. }
  44408. function logicalNot(\PHPUnit\Framework\Constraint\Constraint $constraint) : \PHPUnit\Framework\Constraint\LogicalNot
  44409. {
  44410. return \PHPUnit\Framework\Assert::logicalNot(...\func_get_args());
  44411. }
  44412. function logicalXor() : \PHPUnit\Framework\Constraint\LogicalXor
  44413. {
  44414. return \PHPUnit\Framework\Assert::logicalXor(...\func_get_args());
  44415. }
  44416. function anything() : \PHPUnit\Framework\Constraint\IsAnything
  44417. {
  44418. return \PHPUnit\Framework\Assert::anything(...\func_get_args());
  44419. }
  44420. function isTrue() : \PHPUnit\Framework\Constraint\IsTrue
  44421. {
  44422. return \PHPUnit\Framework\Assert::isTrue(...\func_get_args());
  44423. }
  44424. function callback(callable $callback) : \PHPUnit\Framework\Constraint\Callback
  44425. {
  44426. return \PHPUnit\Framework\Assert::callback(...\func_get_args());
  44427. }
  44428. function isFalse() : \PHPUnit\Framework\Constraint\IsFalse
  44429. {
  44430. return \PHPUnit\Framework\Assert::isFalse(...\func_get_args());
  44431. }
  44432. function isJson() : \PHPUnit\Framework\Constraint\IsJson
  44433. {
  44434. return \PHPUnit\Framework\Assert::isJson(...\func_get_args());
  44435. }
  44436. function isNull() : \PHPUnit\Framework\Constraint\IsNull
  44437. {
  44438. return \PHPUnit\Framework\Assert::isNull(...\func_get_args());
  44439. }
  44440. function isFinite() : \PHPUnit\Framework\Constraint\IsFinite
  44441. {
  44442. return \PHPUnit\Framework\Assert::isFinite(...\func_get_args());
  44443. }
  44444. function isInfinite() : \PHPUnit\Framework\Constraint\IsInfinite
  44445. {
  44446. return \PHPUnit\Framework\Assert::isInfinite(...\func_get_args());
  44447. }
  44448. function isNan() : \PHPUnit\Framework\Constraint\IsNan
  44449. {
  44450. return \PHPUnit\Framework\Assert::isNan(...\func_get_args());
  44451. }
  44452. function containsEqual($value) : \PHPUnit\Framework\Constraint\TraversableContainsEqual
  44453. {
  44454. return \PHPUnit\Framework\Assert::containsEqual(...\func_get_args());
  44455. }
  44456. function containsIdentical($value) : \PHPUnit\Framework\Constraint\TraversableContainsIdentical
  44457. {
  44458. return \PHPUnit\Framework\Assert::containsIdentical(...\func_get_args());
  44459. }
  44460. function containsOnly(string $type) : \PHPUnit\Framework\Constraint\TraversableContainsOnly
  44461. {
  44462. return \PHPUnit\Framework\Assert::containsOnly(...\func_get_args());
  44463. }
  44464. function containsOnlyInstancesOf(string $className) : \PHPUnit\Framework\Constraint\TraversableContainsOnly
  44465. {
  44466. return \PHPUnit\Framework\Assert::containsOnlyInstancesOf(...\func_get_args());
  44467. }
  44468. function arrayHasKey($key) : \PHPUnit\Framework\Constraint\ArrayHasKey
  44469. {
  44470. return \PHPUnit\Framework\Assert::arrayHasKey(...\func_get_args());
  44471. }
  44472. function equalTo($value) : \PHPUnit\Framework\Constraint\IsEqual
  44473. {
  44474. return \PHPUnit\Framework\Assert::equalTo(...\func_get_args());
  44475. }
  44476. function equalToCanonicalizing($value) : \PHPUnit\Framework\Constraint\IsEqualCanonicalizing
  44477. {
  44478. return \PHPUnit\Framework\Assert::equalToCanonicalizing(...\func_get_args());
  44479. }
  44480. function equalToIgnoringCase($value) : \PHPUnit\Framework\Constraint\IsEqualIgnoringCase
  44481. {
  44482. return \PHPUnit\Framework\Assert::equalToIgnoringCase(...\func_get_args());
  44483. }
  44484. function equalToWithDelta($value, float $delta) : \PHPUnit\Framework\Constraint\IsEqualWithDelta
  44485. {
  44486. return \PHPUnit\Framework\Assert::equalToWithDelta(...\func_get_args());
  44487. }
  44488. function isEmpty() : \PHPUnit\Framework\Constraint\IsEmpty
  44489. {
  44490. return \PHPUnit\Framework\Assert::isEmpty(...\func_get_args());
  44491. }
  44492. function isWritable() : \PHPUnit\Framework\Constraint\IsWritable
  44493. {
  44494. return \PHPUnit\Framework\Assert::isWritable(...\func_get_args());
  44495. }
  44496. function isReadable() : \PHPUnit\Framework\Constraint\IsReadable
  44497. {
  44498. return \PHPUnit\Framework\Assert::isReadable(...\func_get_args());
  44499. }
  44500. function directoryExists() : \PHPUnit\Framework\Constraint\DirectoryExists
  44501. {
  44502. return \PHPUnit\Framework\Assert::directoryExists(...\func_get_args());
  44503. }
  44504. function fileExists() : \PHPUnit\Framework\Constraint\FileExists
  44505. {
  44506. return \PHPUnit\Framework\Assert::fileExists(...\func_get_args());
  44507. }
  44508. function greaterThan($value) : \PHPUnit\Framework\Constraint\GreaterThan
  44509. {
  44510. return \PHPUnit\Framework\Assert::greaterThan(...\func_get_args());
  44511. }
  44512. function greaterThanOrEqual($value) : \PHPUnit\Framework\Constraint\LogicalOr
  44513. {
  44514. return \PHPUnit\Framework\Assert::greaterThanOrEqual(...\func_get_args());
  44515. }
  44516. function classHasAttribute(string $attributeName) : \PHPUnit\Framework\Constraint\ClassHasAttribute
  44517. {
  44518. return \PHPUnit\Framework\Assert::classHasAttribute(...\func_get_args());
  44519. }
  44520. function classHasStaticAttribute(string $attributeName) : \PHPUnit\Framework\Constraint\ClassHasStaticAttribute
  44521. {
  44522. return \PHPUnit\Framework\Assert::classHasStaticAttribute(...\func_get_args());
  44523. }
  44524. function objectHasAttribute($attributeName) : \PHPUnit\Framework\Constraint\ObjectHasAttribute
  44525. {
  44526. return \PHPUnit\Framework\Assert::objectHasAttribute(...\func_get_args());
  44527. }
  44528. function identicalTo($value) : \PHPUnit\Framework\Constraint\IsIdentical
  44529. {
  44530. return \PHPUnit\Framework\Assert::identicalTo(...\func_get_args());
  44531. }
  44532. function isInstanceOf(string $className) : \PHPUnit\Framework\Constraint\IsInstanceOf
  44533. {
  44534. return \PHPUnit\Framework\Assert::isInstanceOf(...\func_get_args());
  44535. }
  44536. function isType(string $type) : \PHPUnit\Framework\Constraint\IsType
  44537. {
  44538. return \PHPUnit\Framework\Assert::isType(...\func_get_args());
  44539. }
  44540. function lessThan($value) : \PHPUnit\Framework\Constraint\LessThan
  44541. {
  44542. return \PHPUnit\Framework\Assert::lessThan(...\func_get_args());
  44543. }
  44544. function lessThanOrEqual($value) : \PHPUnit\Framework\Constraint\LogicalOr
  44545. {
  44546. return \PHPUnit\Framework\Assert::lessThanOrEqual(...\func_get_args());
  44547. }
  44548. function matchesRegularExpression(string $pattern) : \PHPUnit\Framework\Constraint\RegularExpression
  44549. {
  44550. return \PHPUnit\Framework\Assert::matchesRegularExpression(...\func_get_args());
  44551. }
  44552. function matches(string $string) : \PHPUnit\Framework\Constraint\StringMatchesFormatDescription
  44553. {
  44554. return \PHPUnit\Framework\Assert::matches(...\func_get_args());
  44555. }
  44556. function stringStartsWith($prefix) : \PHPUnit\Framework\Constraint\StringStartsWith
  44557. {
  44558. return \PHPUnit\Framework\Assert::stringStartsWith(...\func_get_args());
  44559. }
  44560. function stringContains(string $string, bool $case = \true) : \PHPUnit\Framework\Constraint\StringContains
  44561. {
  44562. return \PHPUnit\Framework\Assert::stringContains(...\func_get_args());
  44563. }
  44564. function stringEndsWith(string $suffix) : \PHPUnit\Framework\Constraint\StringEndsWith
  44565. {
  44566. return \PHPUnit\Framework\Assert::stringEndsWith(...\func_get_args());
  44567. }
  44568. function countOf(int $count) : \PHPUnit\Framework\Constraint\Count
  44569. {
  44570. return \PHPUnit\Framework\Assert::countOf(...\func_get_args());
  44571. }
  44572. /**
  44573. * Returns a matcher that matches when the method is executed
  44574. * zero or more times.
  44575. */
  44576. function any() : \PHPUnit\Framework\MockObject\Rule\AnyInvokedCount
  44577. {
  44578. return new \PHPUnit\Framework\MockObject\Rule\AnyInvokedCount();
  44579. }
  44580. /**
  44581. * Returns a matcher that matches when the method is never executed.
  44582. */
  44583. function never() : \PHPUnit\Framework\MockObject\Rule\InvokedCount
  44584. {
  44585. return new \PHPUnit\Framework\MockObject\Rule\InvokedCount(0);
  44586. }
  44587. /**
  44588. * Returns a matcher that matches when the method is executed
  44589. * at least N times.
  44590. */
  44591. function atLeast(int $requiredInvocations) : \PHPUnit\Framework\MockObject\Rule\InvokedAtLeastCount
  44592. {
  44593. return new \PHPUnit\Framework\MockObject\Rule\InvokedAtLeastCount($requiredInvocations);
  44594. }
  44595. /**
  44596. * Returns a matcher that matches when the method is executed at least once.
  44597. */
  44598. function atLeastOnce() : \PHPUnit\Framework\MockObject\Rule\InvokedAtLeastOnce
  44599. {
  44600. return new \PHPUnit\Framework\MockObject\Rule\InvokedAtLeastOnce();
  44601. }
  44602. /**
  44603. * Returns a matcher that matches when the method is executed exactly once.
  44604. */
  44605. function once() : \PHPUnit\Framework\MockObject\Rule\InvokedCount
  44606. {
  44607. return new \PHPUnit\Framework\MockObject\Rule\InvokedCount(1);
  44608. }
  44609. /**
  44610. * Returns a matcher that matches when the method is executed
  44611. * exactly $count times.
  44612. */
  44613. function exactly(int $count) : \PHPUnit\Framework\MockObject\Rule\InvokedCount
  44614. {
  44615. return new \PHPUnit\Framework\MockObject\Rule\InvokedCount($count);
  44616. }
  44617. /**
  44618. * Returns a matcher that matches when the method is executed
  44619. * at most N times.
  44620. */
  44621. function atMost(int $allowedInvocations) : \PHPUnit\Framework\MockObject\Rule\InvokedAtMostCount
  44622. {
  44623. return new \PHPUnit\Framework\MockObject\Rule\InvokedAtMostCount($allowedInvocations);
  44624. }
  44625. /**
  44626. * Returns a matcher that matches when the method is executed
  44627. * at the given index.
  44628. */
  44629. function at(int $index) : \PHPUnit\Framework\MockObject\Rule\InvokedAtIndex
  44630. {
  44631. return new \PHPUnit\Framework\MockObject\Rule\InvokedAtIndex($index);
  44632. }
  44633. function returnValue($value) : \PHPUnit\Framework\MockObject\Stub\ReturnStub
  44634. {
  44635. return new \PHPUnit\Framework\MockObject\Stub\ReturnStub($value);
  44636. }
  44637. function returnValueMap(array $valueMap) : \PHPUnit\Framework\MockObject\Stub\ReturnValueMap
  44638. {
  44639. return new \PHPUnit\Framework\MockObject\Stub\ReturnValueMap($valueMap);
  44640. }
  44641. function returnArgument(int $argumentIndex) : \PHPUnit\Framework\MockObject\Stub\ReturnArgument
  44642. {
  44643. return new \PHPUnit\Framework\MockObject\Stub\ReturnArgument($argumentIndex);
  44644. }
  44645. function returnCallback($callback) : \PHPUnit\Framework\MockObject\Stub\ReturnCallback
  44646. {
  44647. return new \PHPUnit\Framework\MockObject\Stub\ReturnCallback($callback);
  44648. }
  44649. /**
  44650. * Returns the current object.
  44651. *
  44652. * This method is useful when mocking a fluent interface.
  44653. */
  44654. function returnSelf() : \PHPUnit\Framework\MockObject\Stub\ReturnSelf
  44655. {
  44656. return new \PHPUnit\Framework\MockObject\Stub\ReturnSelf();
  44657. }
  44658. function throwException(\Throwable $exception) : \PHPUnit\Framework\MockObject\Stub\Exception
  44659. {
  44660. return new \PHPUnit\Framework\MockObject\Stub\Exception($exception);
  44661. }
  44662. function onConsecutiveCalls() : \PHPUnit\Framework\MockObject\Stub\ConsecutiveCalls
  44663. {
  44664. $args = \func_get_args();
  44665. return new \PHPUnit\Framework\MockObject\Stub\ConsecutiveCalls($args);
  44666. }
  44667. <?php
  44668. declare (strict_types=1);
  44669. /*
  44670. * This file is part of PHPUnit.
  44671. *
  44672. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  44673. *
  44674. * For the full copyright and license information, please view the LICENSE
  44675. * file that was distributed with this source code.
  44676. */
  44677. namespace PHPUnit\Framework;
  44678. /**
  44679. * A Test can be run and collect its results.
  44680. */
  44681. interface Test extends \Countable
  44682. {
  44683. /**
  44684. * Runs a test and collects its result in a TestResult instance.
  44685. */
  44686. public function run(\PHPUnit\Framework\TestResult $result = null) : \PHPUnit\Framework\TestResult;
  44687. }
  44688. <?php
  44689. declare (strict_types=1);
  44690. /*
  44691. * This file is part of PHPUnit.
  44692. *
  44693. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  44694. *
  44695. * For the full copyright and license information, please view the LICENSE
  44696. * file that was distributed with this source code.
  44697. */
  44698. namespace PHPUnit\Framework;
  44699. use PHPUnit\Framework\Constraint\ArrayHasKey;
  44700. use PHPUnit\Framework\Constraint\Callback;
  44701. use PHPUnit\Framework\Constraint\ClassHasAttribute;
  44702. use PHPUnit\Framework\Constraint\ClassHasStaticAttribute;
  44703. use PHPUnit\Framework\Constraint\Constraint;
  44704. use PHPUnit\Framework\Constraint\Count;
  44705. use PHPUnit\Framework\Constraint\DirectoryExists;
  44706. use PHPUnit\Framework\Constraint\FileExists;
  44707. use PHPUnit\Framework\Constraint\GreaterThan;
  44708. use PHPUnit\Framework\Constraint\IsAnything;
  44709. use PHPUnit\Framework\Constraint\IsEmpty;
  44710. use PHPUnit\Framework\Constraint\IsEqual;
  44711. use PHPUnit\Framework\Constraint\IsEqualCanonicalizing;
  44712. use PHPUnit\Framework\Constraint\IsEqualIgnoringCase;
  44713. use PHPUnit\Framework\Constraint\IsEqualWithDelta;
  44714. use PHPUnit\Framework\Constraint\IsFalse;
  44715. use PHPUnit\Framework\Constraint\IsFinite;
  44716. use PHPUnit\Framework\Constraint\IsIdentical;
  44717. use PHPUnit\Framework\Constraint\IsInfinite;
  44718. use PHPUnit\Framework\Constraint\IsInstanceOf;
  44719. use PHPUnit\Framework\Constraint\IsJson;
  44720. use PHPUnit\Framework\Constraint\IsNan;
  44721. use PHPUnit\Framework\Constraint\IsNull;
  44722. use PHPUnit\Framework\Constraint\IsReadable;
  44723. use PHPUnit\Framework\Constraint\IsTrue;
  44724. use PHPUnit\Framework\Constraint\IsType;
  44725. use PHPUnit\Framework\Constraint\IsWritable;
  44726. use PHPUnit\Framework\Constraint\JsonMatches;
  44727. use PHPUnit\Framework\Constraint\LessThan;
  44728. use PHPUnit\Framework\Constraint\LogicalAnd;
  44729. use PHPUnit\Framework\Constraint\LogicalNot;
  44730. use PHPUnit\Framework\Constraint\LogicalOr;
  44731. use PHPUnit\Framework\Constraint\LogicalXor;
  44732. use PHPUnit\Framework\Constraint\ObjectHasAttribute;
  44733. use PHPUnit\Framework\Constraint\RegularExpression;
  44734. use PHPUnit\Framework\Constraint\SameSize;
  44735. use PHPUnit\Framework\Constraint\StringContains;
  44736. use PHPUnit\Framework\Constraint\StringEndsWith;
  44737. use PHPUnit\Framework\Constraint\StringMatchesFormatDescription;
  44738. use PHPUnit\Framework\Constraint\StringStartsWith;
  44739. use PHPUnit\Framework\Constraint\TraversableContainsEqual;
  44740. use PHPUnit\Framework\Constraint\TraversableContainsIdentical;
  44741. use PHPUnit\Framework\Constraint\TraversableContainsOnly;
  44742. use PHPUnit\Util\Type;
  44743. use PHPUnit\Util\Xml;
  44744. /**
  44745. * A set of assertion methods.
  44746. */
  44747. abstract class Assert
  44748. {
  44749. /**
  44750. * @var int
  44751. */
  44752. private static $count = 0;
  44753. /**
  44754. * Asserts that an array has a specified key.
  44755. *
  44756. * @param int|string $key
  44757. * @param array|\ArrayAccess $array
  44758. *
  44759. * @throws ExpectationFailedException
  44760. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  44761. * @throws Exception
  44762. */
  44763. public static function assertArrayHasKey($key, $array, string $message = '') : void
  44764. {
  44765. if (!(\is_int($key) || \is_string($key))) {
  44766. throw \PHPUnit\Framework\InvalidArgumentException::create(1, 'integer or string');
  44767. }
  44768. if (!(\is_array($array) || $array instanceof \ArrayAccess)) {
  44769. throw \PHPUnit\Framework\InvalidArgumentException::create(2, 'array or ArrayAccess');
  44770. }
  44771. $constraint = new \PHPUnit\Framework\Constraint\ArrayHasKey($key);
  44772. static::assertThat($array, $constraint, $message);
  44773. }
  44774. /**
  44775. * Asserts that an array does not have a specified key.
  44776. *
  44777. * @param int|string $key
  44778. * @param array|\ArrayAccess $array
  44779. *
  44780. * @throws ExpectationFailedException
  44781. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  44782. * @throws Exception
  44783. */
  44784. public static function assertArrayNotHasKey($key, $array, string $message = '') : void
  44785. {
  44786. if (!(\is_int($key) || \is_string($key))) {
  44787. throw \PHPUnit\Framework\InvalidArgumentException::create(1, 'integer or string');
  44788. }
  44789. if (!(\is_array($array) || $array instanceof \ArrayAccess)) {
  44790. throw \PHPUnit\Framework\InvalidArgumentException::create(2, 'array or ArrayAccess');
  44791. }
  44792. $constraint = new \PHPUnit\Framework\Constraint\LogicalNot(new \PHPUnit\Framework\Constraint\ArrayHasKey($key));
  44793. static::assertThat($array, $constraint, $message);
  44794. }
  44795. /**
  44796. * Asserts that a haystack contains a needle.
  44797. *
  44798. * @throws ExpectationFailedException
  44799. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  44800. * @throws Exception
  44801. */
  44802. public static function assertContains($needle, iterable $haystack, string $message = '') : void
  44803. {
  44804. $constraint = new \PHPUnit\Framework\Constraint\TraversableContainsIdentical($needle);
  44805. static::assertThat($haystack, $constraint, $message);
  44806. }
  44807. public static function assertContainsEquals($needle, iterable $haystack, string $message = '') : void
  44808. {
  44809. $constraint = new \PHPUnit\Framework\Constraint\TraversableContainsEqual($needle);
  44810. static::assertThat($haystack, $constraint, $message);
  44811. }
  44812. /**
  44813. * Asserts that a haystack does not contain a needle.
  44814. *
  44815. * @throws ExpectationFailedException
  44816. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  44817. * @throws Exception
  44818. */
  44819. public static function assertNotContains($needle, iterable $haystack, string $message = '') : void
  44820. {
  44821. $constraint = new \PHPUnit\Framework\Constraint\LogicalNot(new \PHPUnit\Framework\Constraint\TraversableContainsIdentical($needle));
  44822. static::assertThat($haystack, $constraint, $message);
  44823. }
  44824. public static function assertNotContainsEquals($needle, iterable $haystack, string $message = '') : void
  44825. {
  44826. $constraint = new \PHPUnit\Framework\Constraint\LogicalNot(new \PHPUnit\Framework\Constraint\TraversableContainsEqual($needle));
  44827. static::assertThat($haystack, $constraint, $message);
  44828. }
  44829. /**
  44830. * Asserts that a haystack contains only values of a given type.
  44831. *
  44832. * @throws ExpectationFailedException
  44833. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  44834. */
  44835. public static function assertContainsOnly(string $type, iterable $haystack, ?bool $isNativeType = null, string $message = '') : void
  44836. {
  44837. if ($isNativeType === null) {
  44838. $isNativeType = \PHPUnit\Util\Type::isType($type);
  44839. }
  44840. static::assertThat($haystack, new \PHPUnit\Framework\Constraint\TraversableContainsOnly($type, $isNativeType), $message);
  44841. }
  44842. /**
  44843. * Asserts that a haystack contains only instances of a given class name.
  44844. *
  44845. * @throws ExpectationFailedException
  44846. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  44847. */
  44848. public static function assertContainsOnlyInstancesOf(string $className, iterable $haystack, string $message = '') : void
  44849. {
  44850. static::assertThat($haystack, new \PHPUnit\Framework\Constraint\TraversableContainsOnly($className, \false), $message);
  44851. }
  44852. /**
  44853. * Asserts that a haystack does not contain only values of a given type.
  44854. *
  44855. * @throws ExpectationFailedException
  44856. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  44857. */
  44858. public static function assertNotContainsOnly(string $type, iterable $haystack, ?bool $isNativeType = null, string $message = '') : void
  44859. {
  44860. if ($isNativeType === null) {
  44861. $isNativeType = \PHPUnit\Util\Type::isType($type);
  44862. }
  44863. static::assertThat($haystack, new \PHPUnit\Framework\Constraint\LogicalNot(new \PHPUnit\Framework\Constraint\TraversableContainsOnly($type, $isNativeType)), $message);
  44864. }
  44865. /**
  44866. * Asserts the number of elements of an array, Countable or Traversable.
  44867. *
  44868. * @param \Countable|iterable $haystack
  44869. *
  44870. * @throws ExpectationFailedException
  44871. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  44872. * @throws Exception
  44873. */
  44874. public static function assertCount(int $expectedCount, $haystack, string $message = '') : void
  44875. {
  44876. if (!$haystack instanceof \Countable && !\is_iterable($haystack)) {
  44877. throw \PHPUnit\Framework\InvalidArgumentException::create(2, 'countable or iterable');
  44878. }
  44879. static::assertThat($haystack, new \PHPUnit\Framework\Constraint\Count($expectedCount), $message);
  44880. }
  44881. /**
  44882. * Asserts the number of elements of an array, Countable or Traversable.
  44883. *
  44884. * @param \Countable|iterable $haystack
  44885. *
  44886. * @throws ExpectationFailedException
  44887. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  44888. * @throws Exception
  44889. */
  44890. public static function assertNotCount(int $expectedCount, $haystack, string $message = '') : void
  44891. {
  44892. if (!$haystack instanceof \Countable && !\is_iterable($haystack)) {
  44893. throw \PHPUnit\Framework\InvalidArgumentException::create(2, 'countable or iterable');
  44894. }
  44895. $constraint = new \PHPUnit\Framework\Constraint\LogicalNot(new \PHPUnit\Framework\Constraint\Count($expectedCount));
  44896. static::assertThat($haystack, $constraint, $message);
  44897. }
  44898. /**
  44899. * Asserts that two variables are equal.
  44900. *
  44901. * @throws ExpectationFailedException
  44902. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  44903. */
  44904. public static function assertEquals($expected, $actual, string $message = '') : void
  44905. {
  44906. $constraint = new \PHPUnit\Framework\Constraint\IsEqual($expected);
  44907. static::assertThat($actual, $constraint, $message);
  44908. }
  44909. /**
  44910. * Asserts that two variables are equal (canonicalizing).
  44911. *
  44912. * @throws ExpectationFailedException
  44913. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  44914. */
  44915. public static function assertEqualsCanonicalizing($expected, $actual, string $message = '') : void
  44916. {
  44917. $constraint = new \PHPUnit\Framework\Constraint\IsEqualCanonicalizing($expected);
  44918. static::assertThat($actual, $constraint, $message);
  44919. }
  44920. /**
  44921. * Asserts that two variables are equal (ignoring case).
  44922. *
  44923. * @throws ExpectationFailedException
  44924. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  44925. */
  44926. public static function assertEqualsIgnoringCase($expected, $actual, string $message = '') : void
  44927. {
  44928. $constraint = new \PHPUnit\Framework\Constraint\IsEqualIgnoringCase($expected);
  44929. static::assertThat($actual, $constraint, $message);
  44930. }
  44931. /**
  44932. * Asserts that two variables are equal (with delta).
  44933. *
  44934. * @throws ExpectationFailedException
  44935. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  44936. */
  44937. public static function assertEqualsWithDelta($expected, $actual, float $delta, string $message = '') : void
  44938. {
  44939. $constraint = new \PHPUnit\Framework\Constraint\IsEqualWithDelta($expected, $delta);
  44940. static::assertThat($actual, $constraint, $message);
  44941. }
  44942. /**
  44943. * Asserts that two variables are not equal.
  44944. *
  44945. * @throws ExpectationFailedException
  44946. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  44947. */
  44948. public static function assertNotEquals($expected, $actual, string $message = '') : void
  44949. {
  44950. $constraint = new \PHPUnit\Framework\Constraint\LogicalNot(new \PHPUnit\Framework\Constraint\IsEqual($expected));
  44951. static::assertThat($actual, $constraint, $message);
  44952. }
  44953. /**
  44954. * Asserts that two variables are not equal (canonicalizing).
  44955. *
  44956. * @throws ExpectationFailedException
  44957. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  44958. */
  44959. public static function assertNotEqualsCanonicalizing($expected, $actual, string $message = '') : void
  44960. {
  44961. $constraint = new \PHPUnit\Framework\Constraint\LogicalNot(new \PHPUnit\Framework\Constraint\IsEqualCanonicalizing($expected));
  44962. static::assertThat($actual, $constraint, $message);
  44963. }
  44964. /**
  44965. * Asserts that two variables are not equal (ignoring case).
  44966. *
  44967. * @throws ExpectationFailedException
  44968. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  44969. */
  44970. public static function assertNotEqualsIgnoringCase($expected, $actual, string $message = '') : void
  44971. {
  44972. $constraint = new \PHPUnit\Framework\Constraint\LogicalNot(new \PHPUnit\Framework\Constraint\IsEqualIgnoringCase($expected));
  44973. static::assertThat($actual, $constraint, $message);
  44974. }
  44975. /**
  44976. * Asserts that two variables are not equal (with delta).
  44977. *
  44978. * @throws ExpectationFailedException
  44979. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  44980. */
  44981. public static function assertNotEqualsWithDelta($expected, $actual, float $delta, string $message = '') : void
  44982. {
  44983. $constraint = new \PHPUnit\Framework\Constraint\LogicalNot(new \PHPUnit\Framework\Constraint\IsEqualWithDelta($expected, $delta));
  44984. static::assertThat($actual, $constraint, $message);
  44985. }
  44986. /**
  44987. * Asserts that a variable is empty.
  44988. *
  44989. * @throws ExpectationFailedException
  44990. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  44991. *
  44992. * @psalm-assert empty $actual
  44993. */
  44994. public static function assertEmpty($actual, string $message = '') : void
  44995. {
  44996. static::assertThat($actual, static::isEmpty(), $message);
  44997. }
  44998. /**
  44999. * Asserts that a variable is not empty.
  45000. *
  45001. * @throws ExpectationFailedException
  45002. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  45003. *
  45004. * @psalm-assert !empty $actual
  45005. */
  45006. public static function assertNotEmpty($actual, string $message = '') : void
  45007. {
  45008. static::assertThat($actual, static::logicalNot(static::isEmpty()), $message);
  45009. }
  45010. /**
  45011. * Asserts that a value is greater than another value.
  45012. *
  45013. * @throws ExpectationFailedException
  45014. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  45015. */
  45016. public static function assertGreaterThan($expected, $actual, string $message = '') : void
  45017. {
  45018. static::assertThat($actual, static::greaterThan($expected), $message);
  45019. }
  45020. /**
  45021. * Asserts that a value is greater than or equal to another value.
  45022. *
  45023. * @throws ExpectationFailedException
  45024. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  45025. */
  45026. public static function assertGreaterThanOrEqual($expected, $actual, string $message = '') : void
  45027. {
  45028. static::assertThat($actual, static::greaterThanOrEqual($expected), $message);
  45029. }
  45030. /**
  45031. * Asserts that a value is smaller than another value.
  45032. *
  45033. * @throws ExpectationFailedException
  45034. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  45035. */
  45036. public static function assertLessThan($expected, $actual, string $message = '') : void
  45037. {
  45038. static::assertThat($actual, static::lessThan($expected), $message);
  45039. }
  45040. /**
  45041. * Asserts that a value is smaller than or equal to another value.
  45042. *
  45043. * @throws ExpectationFailedException
  45044. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  45045. */
  45046. public static function assertLessThanOrEqual($expected, $actual, string $message = '') : void
  45047. {
  45048. static::assertThat($actual, static::lessThanOrEqual($expected), $message);
  45049. }
  45050. /**
  45051. * Asserts that the contents of one file is equal to the contents of another
  45052. * file.
  45053. *
  45054. * @throws ExpectationFailedException
  45055. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  45056. */
  45057. public static function assertFileEquals(string $expected, string $actual, string $message = '') : void
  45058. {
  45059. static::assertFileExists($expected, $message);
  45060. static::assertFileExists($actual, $message);
  45061. $constraint = new \PHPUnit\Framework\Constraint\IsEqual(\file_get_contents($expected));
  45062. static::assertThat(\file_get_contents($actual), $constraint, $message);
  45063. }
  45064. /**
  45065. * Asserts that the contents of one file is equal to the contents of another
  45066. * file (canonicalizing).
  45067. *
  45068. * @throws ExpectationFailedException
  45069. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  45070. */
  45071. public static function assertFileEqualsCanonicalizing(string $expected, string $actual, string $message = '') : void
  45072. {
  45073. static::assertFileExists($expected, $message);
  45074. static::assertFileExists($actual, $message);
  45075. $constraint = new \PHPUnit\Framework\Constraint\IsEqualCanonicalizing(\file_get_contents($expected));
  45076. static::assertThat(\file_get_contents($actual), $constraint, $message);
  45077. }
  45078. /**
  45079. * Asserts that the contents of one file is equal to the contents of another
  45080. * file (ignoring case).
  45081. *
  45082. * @throws ExpectationFailedException
  45083. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  45084. */
  45085. public static function assertFileEqualsIgnoringCase(string $expected, string $actual, string $message = '') : void
  45086. {
  45087. static::assertFileExists($expected, $message);
  45088. static::assertFileExists($actual, $message);
  45089. $constraint = new \PHPUnit\Framework\Constraint\IsEqualIgnoringCase(\file_get_contents($expected));
  45090. static::assertThat(\file_get_contents($actual), $constraint, $message);
  45091. }
  45092. /**
  45093. * Asserts that the contents of one file is not equal to the contents of
  45094. * another file.
  45095. *
  45096. * @throws ExpectationFailedException
  45097. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  45098. */
  45099. public static function assertFileNotEquals(string $expected, string $actual, string $message = '') : void
  45100. {
  45101. static::assertFileExists($expected, $message);
  45102. static::assertFileExists($actual, $message);
  45103. $constraint = new \PHPUnit\Framework\Constraint\LogicalNot(new \PHPUnit\Framework\Constraint\IsEqual(\file_get_contents($expected)));
  45104. static::assertThat(\file_get_contents($actual), $constraint, $message);
  45105. }
  45106. /**
  45107. * Asserts that the contents of one file is not equal to the contents of another
  45108. * file (canonicalizing).
  45109. *
  45110. * @throws ExpectationFailedException
  45111. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  45112. */
  45113. public static function assertFileNotEqualsCanonicalizing(string $expected, string $actual, string $message = '') : void
  45114. {
  45115. static::assertFileExists($expected, $message);
  45116. static::assertFileExists($actual, $message);
  45117. $constraint = new \PHPUnit\Framework\Constraint\LogicalNot(new \PHPUnit\Framework\Constraint\IsEqualCanonicalizing(\file_get_contents($expected)));
  45118. static::assertThat(\file_get_contents($actual), $constraint, $message);
  45119. }
  45120. /**
  45121. * Asserts that the contents of one file is not equal to the contents of another
  45122. * file (ignoring case).
  45123. *
  45124. * @throws ExpectationFailedException
  45125. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  45126. */
  45127. public static function assertFileNotEqualsIgnoringCase(string $expected, string $actual, string $message = '') : void
  45128. {
  45129. static::assertFileExists($expected, $message);
  45130. static::assertFileExists($actual, $message);
  45131. $constraint = new \PHPUnit\Framework\Constraint\LogicalNot(new \PHPUnit\Framework\Constraint\IsEqualIgnoringCase(\file_get_contents($expected)));
  45132. static::assertThat(\file_get_contents($actual), $constraint, $message);
  45133. }
  45134. /**
  45135. * Asserts that the contents of a string is equal
  45136. * to the contents of a file.
  45137. *
  45138. * @throws ExpectationFailedException
  45139. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  45140. */
  45141. public static function assertStringEqualsFile(string $expectedFile, string $actualString, string $message = '') : void
  45142. {
  45143. static::assertFileExists($expectedFile, $message);
  45144. $constraint = new \PHPUnit\Framework\Constraint\IsEqual(\file_get_contents($expectedFile));
  45145. static::assertThat($actualString, $constraint, $message);
  45146. }
  45147. /**
  45148. * Asserts that the contents of a string is equal
  45149. * to the contents of a file (canonicalizing).
  45150. *
  45151. * @throws ExpectationFailedException
  45152. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  45153. */
  45154. public static function assertStringEqualsFileCanonicalizing(string $expectedFile, string $actualString, string $message = '') : void
  45155. {
  45156. static::assertFileExists($expectedFile, $message);
  45157. $constraint = new \PHPUnit\Framework\Constraint\IsEqualCanonicalizing(\file_get_contents($expectedFile));
  45158. static::assertThat($actualString, $constraint, $message);
  45159. }
  45160. /**
  45161. * Asserts that the contents of a string is equal
  45162. * to the contents of a file (ignoring case).
  45163. *
  45164. * @throws ExpectationFailedException
  45165. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  45166. */
  45167. public static function assertStringEqualsFileIgnoringCase(string $expectedFile, string $actualString, string $message = '') : void
  45168. {
  45169. static::assertFileExists($expectedFile, $message);
  45170. $constraint = new \PHPUnit\Framework\Constraint\IsEqualIgnoringCase(\file_get_contents($expectedFile));
  45171. static::assertThat($actualString, $constraint, $message);
  45172. }
  45173. /**
  45174. * Asserts that the contents of a string is not equal
  45175. * to the contents of a file.
  45176. *
  45177. * @throws ExpectationFailedException
  45178. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  45179. */
  45180. public static function assertStringNotEqualsFile(string $expectedFile, string $actualString, string $message = '') : void
  45181. {
  45182. static::assertFileExists($expectedFile, $message);
  45183. $constraint = new \PHPUnit\Framework\Constraint\LogicalNot(new \PHPUnit\Framework\Constraint\IsEqual(\file_get_contents($expectedFile)));
  45184. static::assertThat($actualString, $constraint, $message);
  45185. }
  45186. /**
  45187. * Asserts that the contents of a string is not equal
  45188. * to the contents of a file (canonicalizing).
  45189. *
  45190. * @throws ExpectationFailedException
  45191. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  45192. */
  45193. public static function assertStringNotEqualsFileCanonicalizing(string $expectedFile, string $actualString, string $message = '') : void
  45194. {
  45195. static::assertFileExists($expectedFile, $message);
  45196. $constraint = new \PHPUnit\Framework\Constraint\LogicalNot(new \PHPUnit\Framework\Constraint\IsEqualCanonicalizing(\file_get_contents($expectedFile)));
  45197. static::assertThat($actualString, $constraint, $message);
  45198. }
  45199. /**
  45200. * Asserts that the contents of a string is not equal
  45201. * to the contents of a file (ignoring case).
  45202. *
  45203. * @throws ExpectationFailedException
  45204. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  45205. */
  45206. public static function assertStringNotEqualsFileIgnoringCase(string $expectedFile, string $actualString, string $message = '') : void
  45207. {
  45208. static::assertFileExists($expectedFile, $message);
  45209. $constraint = new \PHPUnit\Framework\Constraint\LogicalNot(new \PHPUnit\Framework\Constraint\IsEqualIgnoringCase(\file_get_contents($expectedFile)));
  45210. static::assertThat($actualString, $constraint, $message);
  45211. }
  45212. /**
  45213. * Asserts that a file/dir is readable.
  45214. *
  45215. * @throws ExpectationFailedException
  45216. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  45217. */
  45218. public static function assertIsReadable(string $filename, string $message = '') : void
  45219. {
  45220. static::assertThat($filename, new \PHPUnit\Framework\Constraint\IsReadable(), $message);
  45221. }
  45222. /**
  45223. * Asserts that a file/dir exists and is not readable.
  45224. *
  45225. * @throws ExpectationFailedException
  45226. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  45227. */
  45228. public static function assertIsNotReadable(string $filename, string $message = '') : void
  45229. {
  45230. static::assertThat($filename, new \PHPUnit\Framework\Constraint\LogicalNot(new \PHPUnit\Framework\Constraint\IsReadable()), $message);
  45231. }
  45232. /**
  45233. * Asserts that a file/dir exists and is not readable.
  45234. *
  45235. * @throws ExpectationFailedException
  45236. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  45237. *
  45238. * @codeCoverageIgnore
  45239. *
  45240. * @deprecated https://github.com/sebastianbergmann/phpunit/issues/4062
  45241. */
  45242. public static function assertNotIsReadable(string $filename, string $message = '') : void
  45243. {
  45244. self::createWarning('assertNotIsReadable() is deprecated and will be removed in PHPUnit 10. Refactor your code to use assertIsNotReadable() instead.');
  45245. static::assertThat($filename, new \PHPUnit\Framework\Constraint\LogicalNot(new \PHPUnit\Framework\Constraint\IsReadable()), $message);
  45246. }
  45247. /**
  45248. * Asserts that a file/dir exists and is writable.
  45249. *
  45250. * @throws ExpectationFailedException
  45251. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  45252. */
  45253. public static function assertIsWritable(string $filename, string $message = '') : void
  45254. {
  45255. static::assertThat($filename, new \PHPUnit\Framework\Constraint\IsWritable(), $message);
  45256. }
  45257. /**
  45258. * Asserts that a file/dir exists and is not writable.
  45259. *
  45260. * @throws ExpectationFailedException
  45261. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  45262. */
  45263. public static function assertIsNotWritable(string $filename, string $message = '') : void
  45264. {
  45265. static::assertThat($filename, new \PHPUnit\Framework\Constraint\LogicalNot(new \PHPUnit\Framework\Constraint\IsWritable()), $message);
  45266. }
  45267. /**
  45268. * Asserts that a file/dir exists and is not writable.
  45269. *
  45270. * @throws ExpectationFailedException
  45271. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  45272. *
  45273. * @codeCoverageIgnore
  45274. *
  45275. * @deprecated https://github.com/sebastianbergmann/phpunit/issues/4065
  45276. */
  45277. public static function assertNotIsWritable(string $filename, string $message = '') : void
  45278. {
  45279. self::createWarning('assertNotIsWritable() is deprecated and will be removed in PHPUnit 10. Refactor your code to use assertIsNotWritable() instead.');
  45280. static::assertThat($filename, new \PHPUnit\Framework\Constraint\LogicalNot(new \PHPUnit\Framework\Constraint\IsWritable()), $message);
  45281. }
  45282. /**
  45283. * Asserts that a directory exists.
  45284. *
  45285. * @throws ExpectationFailedException
  45286. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  45287. */
  45288. public static function assertDirectoryExists(string $directory, string $message = '') : void
  45289. {
  45290. static::assertThat($directory, new \PHPUnit\Framework\Constraint\DirectoryExists(), $message);
  45291. }
  45292. /**
  45293. * Asserts that a directory does not exist.
  45294. *
  45295. * @throws ExpectationFailedException
  45296. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  45297. */
  45298. public static function assertDirectoryDoesNotExist(string $directory, string $message = '') : void
  45299. {
  45300. static::assertThat($directory, new \PHPUnit\Framework\Constraint\LogicalNot(new \PHPUnit\Framework\Constraint\DirectoryExists()), $message);
  45301. }
  45302. /**
  45303. * Asserts that a directory does not exist.
  45304. *
  45305. * @throws ExpectationFailedException
  45306. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  45307. *
  45308. * @codeCoverageIgnore
  45309. *
  45310. * @deprecated https://github.com/sebastianbergmann/phpunit/issues/4068
  45311. */
  45312. public static function assertDirectoryNotExists(string $directory, string $message = '') : void
  45313. {
  45314. self::createWarning('assertDirectoryNotExists() is deprecated and will be removed in PHPUnit 10. Refactor your code to use assertDirectoryDoesNotExist() instead.');
  45315. static::assertThat($directory, new \PHPUnit\Framework\Constraint\LogicalNot(new \PHPUnit\Framework\Constraint\DirectoryExists()), $message);
  45316. }
  45317. /**
  45318. * Asserts that a directory exists and is readable.
  45319. *
  45320. * @throws ExpectationFailedException
  45321. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  45322. */
  45323. public static function assertDirectoryIsReadable(string $directory, string $message = '') : void
  45324. {
  45325. self::assertDirectoryExists($directory, $message);
  45326. self::assertIsReadable($directory, $message);
  45327. }
  45328. /**
  45329. * Asserts that a directory exists and is not readable.
  45330. *
  45331. * @throws ExpectationFailedException
  45332. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  45333. */
  45334. public static function assertDirectoryIsNotReadable(string $directory, string $message = '') : void
  45335. {
  45336. self::assertDirectoryExists($directory, $message);
  45337. self::assertIsNotReadable($directory, $message);
  45338. }
  45339. /**
  45340. * Asserts that a directory exists and is not readable.
  45341. *
  45342. * @throws ExpectationFailedException
  45343. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  45344. *
  45345. * @codeCoverageIgnore
  45346. *
  45347. * @deprecated https://github.com/sebastianbergmann/phpunit/issues/4071
  45348. */
  45349. public static function assertDirectoryNotIsReadable(string $directory, string $message = '') : void
  45350. {
  45351. self::createWarning('assertDirectoryNotIsReadable() is deprecated and will be removed in PHPUnit 10. Refactor your code to use assertDirectoryIsNotReadable() instead.');
  45352. self::assertDirectoryExists($directory, $message);
  45353. self::assertIsNotReadable($directory, $message);
  45354. }
  45355. /**
  45356. * Asserts that a directory exists and is writable.
  45357. *
  45358. * @throws ExpectationFailedException
  45359. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  45360. */
  45361. public static function assertDirectoryIsWritable(string $directory, string $message = '') : void
  45362. {
  45363. self::assertDirectoryExists($directory, $message);
  45364. self::assertIsWritable($directory, $message);
  45365. }
  45366. /**
  45367. * Asserts that a directory exists and is not writable.
  45368. *
  45369. * @throws ExpectationFailedException
  45370. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  45371. */
  45372. public static function assertDirectoryIsNotWritable(string $directory, string $message = '') : void
  45373. {
  45374. self::assertDirectoryExists($directory, $message);
  45375. self::assertIsNotWritable($directory, $message);
  45376. }
  45377. /**
  45378. * Asserts that a directory exists and is not writable.
  45379. *
  45380. * @throws ExpectationFailedException
  45381. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  45382. *
  45383. * @codeCoverageIgnore
  45384. *
  45385. * @deprecated https://github.com/sebastianbergmann/phpunit/issues/4074
  45386. */
  45387. public static function assertDirectoryNotIsWritable(string $directory, string $message = '') : void
  45388. {
  45389. self::createWarning('assertDirectoryNotIsWritable() is deprecated and will be removed in PHPUnit 10. Refactor your code to use assertDirectoryIsNotWritable() instead.');
  45390. self::assertDirectoryExists($directory, $message);
  45391. self::assertIsNotWritable($directory, $message);
  45392. }
  45393. /**
  45394. * Asserts that a file exists.
  45395. *
  45396. * @throws ExpectationFailedException
  45397. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  45398. */
  45399. public static function assertFileExists(string $filename, string $message = '') : void
  45400. {
  45401. static::assertThat($filename, new \PHPUnit\Framework\Constraint\FileExists(), $message);
  45402. }
  45403. /**
  45404. * Asserts that a file does not exist.
  45405. *
  45406. * @throws ExpectationFailedException
  45407. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  45408. */
  45409. public static function assertFileDoesNotExist(string $filename, string $message = '') : void
  45410. {
  45411. static::assertThat($filename, new \PHPUnit\Framework\Constraint\LogicalNot(new \PHPUnit\Framework\Constraint\FileExists()), $message);
  45412. }
  45413. /**
  45414. * Asserts that a file does not exist.
  45415. *
  45416. * @throws ExpectationFailedException
  45417. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  45418. *
  45419. * @codeCoverageIgnore
  45420. *
  45421. * @deprecated https://github.com/sebastianbergmann/phpunit/issues/4077
  45422. */
  45423. public static function assertFileNotExists(string $filename, string $message = '') : void
  45424. {
  45425. self::createWarning('assertFileNotExists() is deprecated and will be removed in PHPUnit 10. Refactor your code to use assertFileDoesNotExist() instead.');
  45426. static::assertThat($filename, new \PHPUnit\Framework\Constraint\LogicalNot(new \PHPUnit\Framework\Constraint\FileExists()), $message);
  45427. }
  45428. /**
  45429. * Asserts that a file exists and is readable.
  45430. *
  45431. * @throws ExpectationFailedException
  45432. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  45433. */
  45434. public static function assertFileIsReadable(string $file, string $message = '') : void
  45435. {
  45436. self::assertFileExists($file, $message);
  45437. self::assertIsReadable($file, $message);
  45438. }
  45439. /**
  45440. * Asserts that a file exists and is not readable.
  45441. *
  45442. * @throws ExpectationFailedException
  45443. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  45444. */
  45445. public static function assertFileIsNotReadable(string $file, string $message = '') : void
  45446. {
  45447. self::assertFileExists($file, $message);
  45448. self::assertIsNotReadable($file, $message);
  45449. }
  45450. /**
  45451. * Asserts that a file exists and is not readable.
  45452. *
  45453. * @throws ExpectationFailedException
  45454. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  45455. *
  45456. * @codeCoverageIgnore
  45457. *
  45458. * @deprecated https://github.com/sebastianbergmann/phpunit/issues/4080
  45459. */
  45460. public static function assertFileNotIsReadable(string $file, string $message = '') : void
  45461. {
  45462. self::createWarning('assertFileNotIsReadable() is deprecated and will be removed in PHPUnit 10. Refactor your code to use assertFileIsNotReadable() instead.');
  45463. self::assertFileExists($file, $message);
  45464. self::assertIsNotReadable($file, $message);
  45465. }
  45466. /**
  45467. * Asserts that a file exists and is writable.
  45468. *
  45469. * @throws ExpectationFailedException
  45470. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  45471. */
  45472. public static function assertFileIsWritable(string $file, string $message = '') : void
  45473. {
  45474. self::assertFileExists($file, $message);
  45475. self::assertIsWritable($file, $message);
  45476. }
  45477. /**
  45478. * Asserts that a file exists and is not writable.
  45479. *
  45480. * @throws ExpectationFailedException
  45481. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  45482. */
  45483. public static function assertFileIsNotWritable(string $file, string $message = '') : void
  45484. {
  45485. self::assertFileExists($file, $message);
  45486. self::assertIsNotWritable($file, $message);
  45487. }
  45488. /**
  45489. * Asserts that a file exists and is not writable.
  45490. *
  45491. * @throws ExpectationFailedException
  45492. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  45493. *
  45494. * @codeCoverageIgnore
  45495. *
  45496. * @deprecated https://github.com/sebastianbergmann/phpunit/issues/4083
  45497. */
  45498. public static function assertFileNotIsWritable(string $file, string $message = '') : void
  45499. {
  45500. self::createWarning('assertFileNotIsWritable() is deprecated and will be removed in PHPUnit 10. Refactor your code to use assertFileIsNotWritable() instead.');
  45501. self::assertFileExists($file, $message);
  45502. self::assertIsNotWritable($file, $message);
  45503. }
  45504. /**
  45505. * Asserts that a condition is true.
  45506. *
  45507. * @throws ExpectationFailedException
  45508. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  45509. *
  45510. * @psalm-assert true $condition
  45511. */
  45512. public static function assertTrue($condition, string $message = '') : void
  45513. {
  45514. static::assertThat($condition, static::isTrue(), $message);
  45515. }
  45516. /**
  45517. * Asserts that a condition is not true.
  45518. *
  45519. * @throws ExpectationFailedException
  45520. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  45521. *
  45522. * @psalm-assert !true $condition
  45523. */
  45524. public static function assertNotTrue($condition, string $message = '') : void
  45525. {
  45526. static::assertThat($condition, static::logicalNot(static::isTrue()), $message);
  45527. }
  45528. /**
  45529. * Asserts that a condition is false.
  45530. *
  45531. * @throws ExpectationFailedException
  45532. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  45533. *
  45534. * @psalm-assert false $condition
  45535. */
  45536. public static function assertFalse($condition, string $message = '') : void
  45537. {
  45538. static::assertThat($condition, static::isFalse(), $message);
  45539. }
  45540. /**
  45541. * Asserts that a condition is not false.
  45542. *
  45543. * @throws ExpectationFailedException
  45544. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  45545. *
  45546. * @psalm-assert !false $condition
  45547. */
  45548. public static function assertNotFalse($condition, string $message = '') : void
  45549. {
  45550. static::assertThat($condition, static::logicalNot(static::isFalse()), $message);
  45551. }
  45552. /**
  45553. * Asserts that a variable is null.
  45554. *
  45555. * @throws ExpectationFailedException
  45556. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  45557. *
  45558. * @psalm-assert null $actual
  45559. */
  45560. public static function assertNull($actual, string $message = '') : void
  45561. {
  45562. static::assertThat($actual, static::isNull(), $message);
  45563. }
  45564. /**
  45565. * Asserts that a variable is not null.
  45566. *
  45567. * @throws ExpectationFailedException
  45568. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  45569. *
  45570. * @psalm-assert !null $actual
  45571. */
  45572. public static function assertNotNull($actual, string $message = '') : void
  45573. {
  45574. static::assertThat($actual, static::logicalNot(static::isNull()), $message);
  45575. }
  45576. /**
  45577. * Asserts that a variable is finite.
  45578. *
  45579. * @throws ExpectationFailedException
  45580. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  45581. */
  45582. public static function assertFinite($actual, string $message = '') : void
  45583. {
  45584. static::assertThat($actual, static::isFinite(), $message);
  45585. }
  45586. /**
  45587. * Asserts that a variable is infinite.
  45588. *
  45589. * @throws ExpectationFailedException
  45590. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  45591. */
  45592. public static function assertInfinite($actual, string $message = '') : void
  45593. {
  45594. static::assertThat($actual, static::isInfinite(), $message);
  45595. }
  45596. /**
  45597. * Asserts that a variable is nan.
  45598. *
  45599. * @throws ExpectationFailedException
  45600. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  45601. */
  45602. public static function assertNan($actual, string $message = '') : void
  45603. {
  45604. static::assertThat($actual, static::isNan(), $message);
  45605. }
  45606. /**
  45607. * Asserts that a class has a specified attribute.
  45608. *
  45609. * @throws ExpectationFailedException
  45610. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  45611. * @throws Exception
  45612. */
  45613. public static function assertClassHasAttribute(string $attributeName, string $className, string $message = '') : void
  45614. {
  45615. if (!self::isValidClassAttributeName($attributeName)) {
  45616. throw \PHPUnit\Framework\InvalidArgumentException::create(1, 'valid attribute name');
  45617. }
  45618. if (!\class_exists($className)) {
  45619. throw \PHPUnit\Framework\InvalidArgumentException::create(2, 'class name');
  45620. }
  45621. static::assertThat($className, new \PHPUnit\Framework\Constraint\ClassHasAttribute($attributeName), $message);
  45622. }
  45623. /**
  45624. * Asserts that a class does not have a specified attribute.
  45625. *
  45626. * @throws ExpectationFailedException
  45627. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  45628. * @throws Exception
  45629. */
  45630. public static function assertClassNotHasAttribute(string $attributeName, string $className, string $message = '') : void
  45631. {
  45632. if (!self::isValidClassAttributeName($attributeName)) {
  45633. throw \PHPUnit\Framework\InvalidArgumentException::create(1, 'valid attribute name');
  45634. }
  45635. if (!\class_exists($className)) {
  45636. throw \PHPUnit\Framework\InvalidArgumentException::create(2, 'class name');
  45637. }
  45638. static::assertThat($className, new \PHPUnit\Framework\Constraint\LogicalNot(new \PHPUnit\Framework\Constraint\ClassHasAttribute($attributeName)), $message);
  45639. }
  45640. /**
  45641. * Asserts that a class has a specified static attribute.
  45642. *
  45643. * @throws ExpectationFailedException
  45644. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  45645. * @throws Exception
  45646. */
  45647. public static function assertClassHasStaticAttribute(string $attributeName, string $className, string $message = '') : void
  45648. {
  45649. if (!self::isValidClassAttributeName($attributeName)) {
  45650. throw \PHPUnit\Framework\InvalidArgumentException::create(1, 'valid attribute name');
  45651. }
  45652. if (!\class_exists($className)) {
  45653. throw \PHPUnit\Framework\InvalidArgumentException::create(2, 'class name');
  45654. }
  45655. static::assertThat($className, new \PHPUnit\Framework\Constraint\ClassHasStaticAttribute($attributeName), $message);
  45656. }
  45657. /**
  45658. * Asserts that a class does not have a specified static attribute.
  45659. *
  45660. * @throws ExpectationFailedException
  45661. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  45662. * @throws Exception
  45663. */
  45664. public static function assertClassNotHasStaticAttribute(string $attributeName, string $className, string $message = '') : void
  45665. {
  45666. if (!self::isValidClassAttributeName($attributeName)) {
  45667. throw \PHPUnit\Framework\InvalidArgumentException::create(1, 'valid attribute name');
  45668. }
  45669. if (!\class_exists($className)) {
  45670. throw \PHPUnit\Framework\InvalidArgumentException::create(2, 'class name');
  45671. }
  45672. static::assertThat($className, new \PHPUnit\Framework\Constraint\LogicalNot(new \PHPUnit\Framework\Constraint\ClassHasStaticAttribute($attributeName)), $message);
  45673. }
  45674. /**
  45675. * Asserts that an object has a specified attribute.
  45676. *
  45677. * @param object $object
  45678. *
  45679. * @throws ExpectationFailedException
  45680. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  45681. * @throws Exception
  45682. */
  45683. public static function assertObjectHasAttribute(string $attributeName, $object, string $message = '') : void
  45684. {
  45685. if (!self::isValidObjectAttributeName($attributeName)) {
  45686. throw \PHPUnit\Framework\InvalidArgumentException::create(1, 'valid attribute name');
  45687. }
  45688. if (!\is_object($object)) {
  45689. throw \PHPUnit\Framework\InvalidArgumentException::create(2, 'object');
  45690. }
  45691. static::assertThat($object, new \PHPUnit\Framework\Constraint\ObjectHasAttribute($attributeName), $message);
  45692. }
  45693. /**
  45694. * Asserts that an object does not have a specified attribute.
  45695. *
  45696. * @param object $object
  45697. *
  45698. * @throws ExpectationFailedException
  45699. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  45700. * @throws Exception
  45701. */
  45702. public static function assertObjectNotHasAttribute(string $attributeName, $object, string $message = '') : void
  45703. {
  45704. if (!self::isValidObjectAttributeName($attributeName)) {
  45705. throw \PHPUnit\Framework\InvalidArgumentException::create(1, 'valid attribute name');
  45706. }
  45707. if (!\is_object($object)) {
  45708. throw \PHPUnit\Framework\InvalidArgumentException::create(2, 'object');
  45709. }
  45710. static::assertThat($object, new \PHPUnit\Framework\Constraint\LogicalNot(new \PHPUnit\Framework\Constraint\ObjectHasAttribute($attributeName)), $message);
  45711. }
  45712. /**
  45713. * Asserts that two variables have the same type and value.
  45714. * Used on objects, it asserts that two variables reference
  45715. * the same object.
  45716. *
  45717. * @throws ExpectationFailedException
  45718. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  45719. *
  45720. * @psalm-template ExpectedType
  45721. * @psalm-param ExpectedType $expected
  45722. * @psalm-assert =ExpectedType $actual
  45723. */
  45724. public static function assertSame($expected, $actual, string $message = '') : void
  45725. {
  45726. static::assertThat($actual, new \PHPUnit\Framework\Constraint\IsIdentical($expected), $message);
  45727. }
  45728. /**
  45729. * Asserts that two variables do not have the same type and value.
  45730. * Used on objects, it asserts that two variables do not reference
  45731. * the same object.
  45732. *
  45733. * @throws ExpectationFailedException
  45734. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  45735. */
  45736. public static function assertNotSame($expected, $actual, string $message = '') : void
  45737. {
  45738. if (\is_bool($expected) && \is_bool($actual)) {
  45739. static::assertNotEquals($expected, $actual, $message);
  45740. }
  45741. static::assertThat($actual, new \PHPUnit\Framework\Constraint\LogicalNot(new \PHPUnit\Framework\Constraint\IsIdentical($expected)), $message);
  45742. }
  45743. /**
  45744. * Asserts that a variable is of a given type.
  45745. *
  45746. * @throws ExpectationFailedException
  45747. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  45748. * @throws Exception
  45749. *
  45750. * @psalm-template ExpectedType of object
  45751. * @psalm-param class-string<ExpectedType> $expected
  45752. * @psalm-assert ExpectedType $actual
  45753. */
  45754. public static function assertInstanceOf(string $expected, $actual, string $message = '') : void
  45755. {
  45756. if (!\class_exists($expected) && !\interface_exists($expected)) {
  45757. throw \PHPUnit\Framework\InvalidArgumentException::create(1, 'class or interface name');
  45758. }
  45759. static::assertThat($actual, new \PHPUnit\Framework\Constraint\IsInstanceOf($expected), $message);
  45760. }
  45761. /**
  45762. * Asserts that a variable is not of a given type.
  45763. *
  45764. * @throws ExpectationFailedException
  45765. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  45766. * @throws Exception
  45767. *
  45768. * @psalm-template ExpectedType of object
  45769. * @psalm-param class-string<ExpectedType> $expected
  45770. * @psalm-assert !ExpectedType $actual
  45771. */
  45772. public static function assertNotInstanceOf(string $expected, $actual, string $message = '') : void
  45773. {
  45774. if (!\class_exists($expected) && !\interface_exists($expected)) {
  45775. throw \PHPUnit\Framework\InvalidArgumentException::create(1, 'class or interface name');
  45776. }
  45777. static::assertThat($actual, new \PHPUnit\Framework\Constraint\LogicalNot(new \PHPUnit\Framework\Constraint\IsInstanceOf($expected)), $message);
  45778. }
  45779. /**
  45780. * Asserts that a variable is of type array.
  45781. *
  45782. * @throws ExpectationFailedException
  45783. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  45784. *
  45785. * @psalm-assert array $actual
  45786. */
  45787. public static function assertIsArray($actual, string $message = '') : void
  45788. {
  45789. static::assertThat($actual, new \PHPUnit\Framework\Constraint\IsType(\PHPUnit\Framework\Constraint\IsType::TYPE_ARRAY), $message);
  45790. }
  45791. /**
  45792. * Asserts that a variable is of type bool.
  45793. *
  45794. * @throws ExpectationFailedException
  45795. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  45796. *
  45797. * @psalm-assert bool $actual
  45798. */
  45799. public static function assertIsBool($actual, string $message = '') : void
  45800. {
  45801. static::assertThat($actual, new \PHPUnit\Framework\Constraint\IsType(\PHPUnit\Framework\Constraint\IsType::TYPE_BOOL), $message);
  45802. }
  45803. /**
  45804. * Asserts that a variable is of type float.
  45805. *
  45806. * @throws ExpectationFailedException
  45807. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  45808. *
  45809. * @psalm-assert float $actual
  45810. */
  45811. public static function assertIsFloat($actual, string $message = '') : void
  45812. {
  45813. static::assertThat($actual, new \PHPUnit\Framework\Constraint\IsType(\PHPUnit\Framework\Constraint\IsType::TYPE_FLOAT), $message);
  45814. }
  45815. /**
  45816. * Asserts that a variable is of type int.
  45817. *
  45818. * @throws ExpectationFailedException
  45819. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  45820. *
  45821. * @psalm-assert int $actual
  45822. */
  45823. public static function assertIsInt($actual, string $message = '') : void
  45824. {
  45825. static::assertThat($actual, new \PHPUnit\Framework\Constraint\IsType(\PHPUnit\Framework\Constraint\IsType::TYPE_INT), $message);
  45826. }
  45827. /**
  45828. * Asserts that a variable is of type numeric.
  45829. *
  45830. * @throws ExpectationFailedException
  45831. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  45832. *
  45833. * @psalm-assert numeric $actual
  45834. */
  45835. public static function assertIsNumeric($actual, string $message = '') : void
  45836. {
  45837. static::assertThat($actual, new \PHPUnit\Framework\Constraint\IsType(\PHPUnit\Framework\Constraint\IsType::TYPE_NUMERIC), $message);
  45838. }
  45839. /**
  45840. * Asserts that a variable is of type object.
  45841. *
  45842. * @throws ExpectationFailedException
  45843. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  45844. *
  45845. * @psalm-assert object $actual
  45846. */
  45847. public static function assertIsObject($actual, string $message = '') : void
  45848. {
  45849. static::assertThat($actual, new \PHPUnit\Framework\Constraint\IsType(\PHPUnit\Framework\Constraint\IsType::TYPE_OBJECT), $message);
  45850. }
  45851. /**
  45852. * Asserts that a variable is of type resource.
  45853. *
  45854. * @throws ExpectationFailedException
  45855. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  45856. *
  45857. * @psalm-assert resource $actual
  45858. */
  45859. public static function assertIsResource($actual, string $message = '') : void
  45860. {
  45861. static::assertThat($actual, new \PHPUnit\Framework\Constraint\IsType(\PHPUnit\Framework\Constraint\IsType::TYPE_RESOURCE), $message);
  45862. }
  45863. /**
  45864. * Asserts that a variable is of type string.
  45865. *
  45866. * @throws ExpectationFailedException
  45867. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  45868. *
  45869. * @psalm-assert string $actual
  45870. */
  45871. public static function assertIsString($actual, string $message = '') : void
  45872. {
  45873. static::assertThat($actual, new \PHPUnit\Framework\Constraint\IsType(\PHPUnit\Framework\Constraint\IsType::TYPE_STRING), $message);
  45874. }
  45875. /**
  45876. * Asserts that a variable is of type scalar.
  45877. *
  45878. * @throws ExpectationFailedException
  45879. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  45880. *
  45881. * @psalm-assert scalar $actual
  45882. */
  45883. public static function assertIsScalar($actual, string $message = '') : void
  45884. {
  45885. static::assertThat($actual, new \PHPUnit\Framework\Constraint\IsType(\PHPUnit\Framework\Constraint\IsType::TYPE_SCALAR), $message);
  45886. }
  45887. /**
  45888. * Asserts that a variable is of type callable.
  45889. *
  45890. * @throws ExpectationFailedException
  45891. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  45892. *
  45893. * @psalm-assert callable $actual
  45894. */
  45895. public static function assertIsCallable($actual, string $message = '') : void
  45896. {
  45897. static::assertThat($actual, new \PHPUnit\Framework\Constraint\IsType(\PHPUnit\Framework\Constraint\IsType::TYPE_CALLABLE), $message);
  45898. }
  45899. /**
  45900. * Asserts that a variable is of type iterable.
  45901. *
  45902. * @throws ExpectationFailedException
  45903. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  45904. *
  45905. * @psalm-assert iterable $actual
  45906. */
  45907. public static function assertIsIterable($actual, string $message = '') : void
  45908. {
  45909. static::assertThat($actual, new \PHPUnit\Framework\Constraint\IsType(\PHPUnit\Framework\Constraint\IsType::TYPE_ITERABLE), $message);
  45910. }
  45911. /**
  45912. * Asserts that a variable is not of type array.
  45913. *
  45914. * @throws ExpectationFailedException
  45915. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  45916. *
  45917. * @psalm-assert !array $actual
  45918. */
  45919. public static function assertIsNotArray($actual, string $message = '') : void
  45920. {
  45921. static::assertThat($actual, new \PHPUnit\Framework\Constraint\LogicalNot(new \PHPUnit\Framework\Constraint\IsType(\PHPUnit\Framework\Constraint\IsType::TYPE_ARRAY)), $message);
  45922. }
  45923. /**
  45924. * Asserts that a variable is not of type bool.
  45925. *
  45926. * @throws ExpectationFailedException
  45927. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  45928. *
  45929. * @psalm-assert !bool $actual
  45930. */
  45931. public static function assertIsNotBool($actual, string $message = '') : void
  45932. {
  45933. static::assertThat($actual, new \PHPUnit\Framework\Constraint\LogicalNot(new \PHPUnit\Framework\Constraint\IsType(\PHPUnit\Framework\Constraint\IsType::TYPE_BOOL)), $message);
  45934. }
  45935. /**
  45936. * Asserts that a variable is not of type float.
  45937. *
  45938. * @throws ExpectationFailedException
  45939. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  45940. *
  45941. * @psalm-assert !float $actual
  45942. */
  45943. public static function assertIsNotFloat($actual, string $message = '') : void
  45944. {
  45945. static::assertThat($actual, new \PHPUnit\Framework\Constraint\LogicalNot(new \PHPUnit\Framework\Constraint\IsType(\PHPUnit\Framework\Constraint\IsType::TYPE_FLOAT)), $message);
  45946. }
  45947. /**
  45948. * Asserts that a variable is not of type int.
  45949. *
  45950. * @throws ExpectationFailedException
  45951. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  45952. *
  45953. * @psalm-assert !int $actual
  45954. */
  45955. public static function assertIsNotInt($actual, string $message = '') : void
  45956. {
  45957. static::assertThat($actual, new \PHPUnit\Framework\Constraint\LogicalNot(new \PHPUnit\Framework\Constraint\IsType(\PHPUnit\Framework\Constraint\IsType::TYPE_INT)), $message);
  45958. }
  45959. /**
  45960. * Asserts that a variable is not of type numeric.
  45961. *
  45962. * @throws ExpectationFailedException
  45963. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  45964. *
  45965. * @psalm-assert !numeric $actual
  45966. */
  45967. public static function assertIsNotNumeric($actual, string $message = '') : void
  45968. {
  45969. static::assertThat($actual, new \PHPUnit\Framework\Constraint\LogicalNot(new \PHPUnit\Framework\Constraint\IsType(\PHPUnit\Framework\Constraint\IsType::TYPE_NUMERIC)), $message);
  45970. }
  45971. /**
  45972. * Asserts that a variable is not of type object.
  45973. *
  45974. * @throws ExpectationFailedException
  45975. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  45976. *
  45977. * @psalm-assert !object $actual
  45978. */
  45979. public static function assertIsNotObject($actual, string $message = '') : void
  45980. {
  45981. static::assertThat($actual, new \PHPUnit\Framework\Constraint\LogicalNot(new \PHPUnit\Framework\Constraint\IsType(\PHPUnit\Framework\Constraint\IsType::TYPE_OBJECT)), $message);
  45982. }
  45983. /**
  45984. * Asserts that a variable is not of type resource.
  45985. *
  45986. * @throws ExpectationFailedException
  45987. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  45988. *
  45989. * @psalm-assert !resource $actual
  45990. */
  45991. public static function assertIsNotResource($actual, string $message = '') : void
  45992. {
  45993. static::assertThat($actual, new \PHPUnit\Framework\Constraint\LogicalNot(new \PHPUnit\Framework\Constraint\IsType(\PHPUnit\Framework\Constraint\IsType::TYPE_RESOURCE)), $message);
  45994. }
  45995. /**
  45996. * Asserts that a variable is not of type string.
  45997. *
  45998. * @throws ExpectationFailedException
  45999. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  46000. *
  46001. * @psalm-assert !string $actual
  46002. */
  46003. public static function assertIsNotString($actual, string $message = '') : void
  46004. {
  46005. static::assertThat($actual, new \PHPUnit\Framework\Constraint\LogicalNot(new \PHPUnit\Framework\Constraint\IsType(\PHPUnit\Framework\Constraint\IsType::TYPE_STRING)), $message);
  46006. }
  46007. /**
  46008. * Asserts that a variable is not of type scalar.
  46009. *
  46010. * @throws ExpectationFailedException
  46011. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  46012. *
  46013. * @psalm-assert !scalar $actual
  46014. */
  46015. public static function assertIsNotScalar($actual, string $message = '') : void
  46016. {
  46017. static::assertThat($actual, new \PHPUnit\Framework\Constraint\LogicalNot(new \PHPUnit\Framework\Constraint\IsType(\PHPUnit\Framework\Constraint\IsType::TYPE_SCALAR)), $message);
  46018. }
  46019. /**
  46020. * Asserts that a variable is not of type callable.
  46021. *
  46022. * @throws ExpectationFailedException
  46023. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  46024. *
  46025. * @psalm-assert !callable $actual
  46026. */
  46027. public static function assertIsNotCallable($actual, string $message = '') : void
  46028. {
  46029. static::assertThat($actual, new \PHPUnit\Framework\Constraint\LogicalNot(new \PHPUnit\Framework\Constraint\IsType(\PHPUnit\Framework\Constraint\IsType::TYPE_CALLABLE)), $message);
  46030. }
  46031. /**
  46032. * Asserts that a variable is not of type iterable.
  46033. *
  46034. * @throws ExpectationFailedException
  46035. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  46036. *
  46037. * @psalm-assert !iterable $actual
  46038. */
  46039. public static function assertIsNotIterable($actual, string $message = '') : void
  46040. {
  46041. static::assertThat($actual, new \PHPUnit\Framework\Constraint\LogicalNot(new \PHPUnit\Framework\Constraint\IsType(\PHPUnit\Framework\Constraint\IsType::TYPE_ITERABLE)), $message);
  46042. }
  46043. /**
  46044. * Asserts that a string matches a given regular expression.
  46045. *
  46046. * @throws ExpectationFailedException
  46047. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  46048. */
  46049. public static function assertMatchesRegularExpression(string $pattern, string $string, string $message = '') : void
  46050. {
  46051. static::assertThat($string, new \PHPUnit\Framework\Constraint\RegularExpression($pattern), $message);
  46052. }
  46053. /**
  46054. * Asserts that a string matches a given regular expression.
  46055. *
  46056. * @throws ExpectationFailedException
  46057. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  46058. *
  46059. * @codeCoverageIgnore
  46060. *
  46061. * @deprecated https://github.com/sebastianbergmann/phpunit/issues/4086
  46062. */
  46063. public static function assertRegExp(string $pattern, string $string, string $message = '') : void
  46064. {
  46065. self::createWarning('assertRegExp() is deprecated and will be removed in PHPUnit 10. Refactor your code to use assertMatchesRegularExpression() instead.');
  46066. static::assertThat($string, new \PHPUnit\Framework\Constraint\RegularExpression($pattern), $message);
  46067. }
  46068. /**
  46069. * Asserts that a string does not match a given regular expression.
  46070. *
  46071. * @throws ExpectationFailedException
  46072. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  46073. */
  46074. public static function assertDoesNotMatchRegularExpression(string $pattern, string $string, string $message = '') : void
  46075. {
  46076. static::assertThat($string, new \PHPUnit\Framework\Constraint\LogicalNot(new \PHPUnit\Framework\Constraint\RegularExpression($pattern)), $message);
  46077. }
  46078. /**
  46079. * Asserts that a string does not match a given regular expression.
  46080. *
  46081. * @throws ExpectationFailedException
  46082. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  46083. *
  46084. * @codeCoverageIgnore
  46085. *
  46086. * @deprecated https://github.com/sebastianbergmann/phpunit/issues/4089
  46087. */
  46088. public static function assertNotRegExp(string $pattern, string $string, string $message = '') : void
  46089. {
  46090. self::createWarning('assertNotRegExp() is deprecated and will be removed in PHPUnit 10. Refactor your code to use assertDoesNotMatchRegularExpression() instead.');
  46091. static::assertThat($string, new \PHPUnit\Framework\Constraint\LogicalNot(new \PHPUnit\Framework\Constraint\RegularExpression($pattern)), $message);
  46092. }
  46093. /**
  46094. * Assert that the size of two arrays (or `Countable` or `Traversable` objects)
  46095. * is the same.
  46096. *
  46097. * @param \Countable|iterable $expected
  46098. * @param \Countable|iterable $actual
  46099. *
  46100. * @throws ExpectationFailedException
  46101. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  46102. * @throws Exception
  46103. */
  46104. public static function assertSameSize($expected, $actual, string $message = '') : void
  46105. {
  46106. if (!$expected instanceof \Countable && !\is_iterable($expected)) {
  46107. throw \PHPUnit\Framework\InvalidArgumentException::create(1, 'countable or iterable');
  46108. }
  46109. if (!$actual instanceof \Countable && !\is_iterable($actual)) {
  46110. throw \PHPUnit\Framework\InvalidArgumentException::create(2, 'countable or iterable');
  46111. }
  46112. static::assertThat($actual, new \PHPUnit\Framework\Constraint\SameSize($expected), $message);
  46113. }
  46114. /**
  46115. * Assert that the size of two arrays (or `Countable` or `Traversable` objects)
  46116. * is not the same.
  46117. *
  46118. * @param \Countable|iterable $expected
  46119. * @param \Countable|iterable $actual
  46120. *
  46121. * @throws ExpectationFailedException
  46122. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  46123. * @throws Exception
  46124. */
  46125. public static function assertNotSameSize($expected, $actual, string $message = '') : void
  46126. {
  46127. if (!$expected instanceof \Countable && !\is_iterable($expected)) {
  46128. throw \PHPUnit\Framework\InvalidArgumentException::create(1, 'countable or iterable');
  46129. }
  46130. if (!$actual instanceof \Countable && !\is_iterable($actual)) {
  46131. throw \PHPUnit\Framework\InvalidArgumentException::create(2, 'countable or iterable');
  46132. }
  46133. static::assertThat($actual, new \PHPUnit\Framework\Constraint\LogicalNot(new \PHPUnit\Framework\Constraint\SameSize($expected)), $message);
  46134. }
  46135. /**
  46136. * Asserts that a string matches a given format string.
  46137. *
  46138. * @throws ExpectationFailedException
  46139. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  46140. */
  46141. public static function assertStringMatchesFormat(string $format, string $string, string $message = '') : void
  46142. {
  46143. static::assertThat($string, new \PHPUnit\Framework\Constraint\StringMatchesFormatDescription($format), $message);
  46144. }
  46145. /**
  46146. * Asserts that a string does not match a given format string.
  46147. *
  46148. * @throws ExpectationFailedException
  46149. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  46150. */
  46151. public static function assertStringNotMatchesFormat(string $format, string $string, string $message = '') : void
  46152. {
  46153. static::assertThat($string, new \PHPUnit\Framework\Constraint\LogicalNot(new \PHPUnit\Framework\Constraint\StringMatchesFormatDescription($format)), $message);
  46154. }
  46155. /**
  46156. * Asserts that a string matches a given format file.
  46157. *
  46158. * @throws ExpectationFailedException
  46159. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  46160. */
  46161. public static function assertStringMatchesFormatFile(string $formatFile, string $string, string $message = '') : void
  46162. {
  46163. static::assertFileExists($formatFile, $message);
  46164. static::assertThat($string, new \PHPUnit\Framework\Constraint\StringMatchesFormatDescription(\file_get_contents($formatFile)), $message);
  46165. }
  46166. /**
  46167. * Asserts that a string does not match a given format string.
  46168. *
  46169. * @throws ExpectationFailedException
  46170. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  46171. */
  46172. public static function assertStringNotMatchesFormatFile(string $formatFile, string $string, string $message = '') : void
  46173. {
  46174. static::assertFileExists($formatFile, $message);
  46175. static::assertThat($string, new \PHPUnit\Framework\Constraint\LogicalNot(new \PHPUnit\Framework\Constraint\StringMatchesFormatDescription(\file_get_contents($formatFile))), $message);
  46176. }
  46177. /**
  46178. * Asserts that a string starts with a given prefix.
  46179. *
  46180. * @throws ExpectationFailedException
  46181. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  46182. */
  46183. public static function assertStringStartsWith(string $prefix, string $string, string $message = '') : void
  46184. {
  46185. static::assertThat($string, new \PHPUnit\Framework\Constraint\StringStartsWith($prefix), $message);
  46186. }
  46187. /**
  46188. * Asserts that a string starts not with a given prefix.
  46189. *
  46190. * @param string $prefix
  46191. * @param string $string
  46192. *
  46193. * @throws ExpectationFailedException
  46194. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  46195. */
  46196. public static function assertStringStartsNotWith($prefix, $string, string $message = '') : void
  46197. {
  46198. static::assertThat($string, new \PHPUnit\Framework\Constraint\LogicalNot(new \PHPUnit\Framework\Constraint\StringStartsWith($prefix)), $message);
  46199. }
  46200. /**
  46201. * @throws ExpectationFailedException
  46202. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  46203. */
  46204. public static function assertStringContainsString(string $needle, string $haystack, string $message = '') : void
  46205. {
  46206. $constraint = new \PHPUnit\Framework\Constraint\StringContains($needle, \false);
  46207. static::assertThat($haystack, $constraint, $message);
  46208. }
  46209. /**
  46210. * @throws ExpectationFailedException
  46211. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  46212. */
  46213. public static function assertStringContainsStringIgnoringCase(string $needle, string $haystack, string $message = '') : void
  46214. {
  46215. $constraint = new \PHPUnit\Framework\Constraint\StringContains($needle, \true);
  46216. static::assertThat($haystack, $constraint, $message);
  46217. }
  46218. /**
  46219. * @throws ExpectationFailedException
  46220. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  46221. */
  46222. public static function assertStringNotContainsString(string $needle, string $haystack, string $message = '') : void
  46223. {
  46224. $constraint = new \PHPUnit\Framework\Constraint\LogicalNot(new \PHPUnit\Framework\Constraint\StringContains($needle));
  46225. static::assertThat($haystack, $constraint, $message);
  46226. }
  46227. /**
  46228. * @throws ExpectationFailedException
  46229. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  46230. */
  46231. public static function assertStringNotContainsStringIgnoringCase(string $needle, string $haystack, string $message = '') : void
  46232. {
  46233. $constraint = new \PHPUnit\Framework\Constraint\LogicalNot(new \PHPUnit\Framework\Constraint\StringContains($needle, \true));
  46234. static::assertThat($haystack, $constraint, $message);
  46235. }
  46236. /**
  46237. * Asserts that a string ends with a given suffix.
  46238. *
  46239. * @throws ExpectationFailedException
  46240. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  46241. */
  46242. public static function assertStringEndsWith(string $suffix, string $string, string $message = '') : void
  46243. {
  46244. static::assertThat($string, new \PHPUnit\Framework\Constraint\StringEndsWith($suffix), $message);
  46245. }
  46246. /**
  46247. * Asserts that a string ends not with a given suffix.
  46248. *
  46249. * @throws ExpectationFailedException
  46250. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  46251. */
  46252. public static function assertStringEndsNotWith(string $suffix, string $string, string $message = '') : void
  46253. {
  46254. static::assertThat($string, new \PHPUnit\Framework\Constraint\LogicalNot(new \PHPUnit\Framework\Constraint\StringEndsWith($suffix)), $message);
  46255. }
  46256. /**
  46257. * Asserts that two XML files are equal.
  46258. *
  46259. * @throws ExpectationFailedException
  46260. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  46261. * @throws Exception
  46262. */
  46263. public static function assertXmlFileEqualsXmlFile(string $expectedFile, string $actualFile, string $message = '') : void
  46264. {
  46265. $expected = \PHPUnit\Util\Xml::loadFile($expectedFile);
  46266. $actual = \PHPUnit\Util\Xml::loadFile($actualFile);
  46267. static::assertEquals($expected, $actual, $message);
  46268. }
  46269. /**
  46270. * Asserts that two XML files are not equal.
  46271. *
  46272. * @throws ExpectationFailedException
  46273. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  46274. * @throws Exception
  46275. */
  46276. public static function assertXmlFileNotEqualsXmlFile(string $expectedFile, string $actualFile, string $message = '') : void
  46277. {
  46278. $expected = \PHPUnit\Util\Xml::loadFile($expectedFile);
  46279. $actual = \PHPUnit\Util\Xml::loadFile($actualFile);
  46280. static::assertNotEquals($expected, $actual, $message);
  46281. }
  46282. /**
  46283. * Asserts that two XML documents are equal.
  46284. *
  46285. * @param \DOMDocument|string $actualXml
  46286. *
  46287. * @throws ExpectationFailedException
  46288. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  46289. * @throws Exception
  46290. */
  46291. public static function assertXmlStringEqualsXmlFile(string $expectedFile, $actualXml, string $message = '') : void
  46292. {
  46293. $expected = \PHPUnit\Util\Xml::loadFile($expectedFile);
  46294. $actual = \PHPUnit\Util\Xml::load($actualXml);
  46295. static::assertEquals($expected, $actual, $message);
  46296. }
  46297. /**
  46298. * Asserts that two XML documents are not equal.
  46299. *
  46300. * @param \DOMDocument|string $actualXml
  46301. *
  46302. * @throws ExpectationFailedException
  46303. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  46304. * @throws Exception
  46305. */
  46306. public static function assertXmlStringNotEqualsXmlFile(string $expectedFile, $actualXml, string $message = '') : void
  46307. {
  46308. $expected = \PHPUnit\Util\Xml::loadFile($expectedFile);
  46309. $actual = \PHPUnit\Util\Xml::load($actualXml);
  46310. static::assertNotEquals($expected, $actual, $message);
  46311. }
  46312. /**
  46313. * Asserts that two XML documents are equal.
  46314. *
  46315. * @param \DOMDocument|string $expectedXml
  46316. * @param \DOMDocument|string $actualXml
  46317. *
  46318. * @throws ExpectationFailedException
  46319. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  46320. * @throws Exception
  46321. */
  46322. public static function assertXmlStringEqualsXmlString($expectedXml, $actualXml, string $message = '') : void
  46323. {
  46324. $expected = \PHPUnit\Util\Xml::load($expectedXml);
  46325. $actual = \PHPUnit\Util\Xml::load($actualXml);
  46326. static::assertEquals($expected, $actual, $message);
  46327. }
  46328. /**
  46329. * Asserts that two XML documents are not equal.
  46330. *
  46331. * @param \DOMDocument|string $expectedXml
  46332. * @param \DOMDocument|string $actualXml
  46333. *
  46334. * @throws ExpectationFailedException
  46335. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  46336. * @throws Exception
  46337. */
  46338. public static function assertXmlStringNotEqualsXmlString($expectedXml, $actualXml, string $message = '') : void
  46339. {
  46340. $expected = \PHPUnit\Util\Xml::load($expectedXml);
  46341. $actual = \PHPUnit\Util\Xml::load($actualXml);
  46342. static::assertNotEquals($expected, $actual, $message);
  46343. }
  46344. /**
  46345. * Asserts that a hierarchy of DOMElements matches.
  46346. *
  46347. * @throws AssertionFailedError
  46348. * @throws ExpectationFailedException
  46349. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  46350. *
  46351. * @codeCoverageIgnore
  46352. *
  46353. * @deprecated https://github.com/sebastianbergmann/phpunit/issues/4091
  46354. */
  46355. public static function assertEqualXMLStructure(\DOMElement $expectedElement, \DOMElement $actualElement, bool $checkAttributes = \false, string $message = '') : void
  46356. {
  46357. self::createWarning('assertEqualXMLStructure() is deprecated and will be removed in PHPUnit 10.');
  46358. $expectedElement = \PHPUnit\Util\Xml::import($expectedElement);
  46359. $actualElement = \PHPUnit\Util\Xml::import($actualElement);
  46360. static::assertSame($expectedElement->tagName, $actualElement->tagName, $message);
  46361. if ($checkAttributes) {
  46362. static::assertSame($expectedElement->attributes->length, $actualElement->attributes->length, \sprintf('%s%sNumber of attributes on node "%s" does not match', $message, !empty($message) ? "\n" : '', $expectedElement->tagName));
  46363. for ($i = 0; $i < $expectedElement->attributes->length; $i++) {
  46364. $expectedAttribute = $expectedElement->attributes->item($i);
  46365. $actualAttribute = $actualElement->attributes->getNamedItem($expectedAttribute->name);
  46366. \assert($expectedAttribute instanceof \DOMAttr);
  46367. if (!$actualAttribute) {
  46368. static::fail(\sprintf('%s%sCould not find attribute "%s" on node "%s"', $message, !empty($message) ? "\n" : '', $expectedAttribute->name, $expectedElement->tagName));
  46369. }
  46370. }
  46371. }
  46372. \PHPUnit\Util\Xml::removeCharacterDataNodes($expectedElement);
  46373. \PHPUnit\Util\Xml::removeCharacterDataNodes($actualElement);
  46374. static::assertSame($expectedElement->childNodes->length, $actualElement->childNodes->length, \sprintf('%s%sNumber of child nodes of "%s" differs', $message, !empty($message) ? "\n" : '', $expectedElement->tagName));
  46375. for ($i = 0; $i < $expectedElement->childNodes->length; $i++) {
  46376. static::assertEqualXMLStructure($expectedElement->childNodes->item($i), $actualElement->childNodes->item($i), $checkAttributes, $message);
  46377. }
  46378. }
  46379. /**
  46380. * Evaluates a PHPUnit\Framework\Constraint matcher object.
  46381. *
  46382. * @throws ExpectationFailedException
  46383. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  46384. */
  46385. public static function assertThat($value, \PHPUnit\Framework\Constraint\Constraint $constraint, string $message = '') : void
  46386. {
  46387. self::$count += \count($constraint);
  46388. $constraint->evaluate($value, $message);
  46389. }
  46390. /**
  46391. * Asserts that a string is a valid JSON string.
  46392. *
  46393. * @throws ExpectationFailedException
  46394. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  46395. */
  46396. public static function assertJson(string $actualJson, string $message = '') : void
  46397. {
  46398. static::assertThat($actualJson, static::isJson(), $message);
  46399. }
  46400. /**
  46401. * Asserts that two given JSON encoded objects or arrays are equal.
  46402. *
  46403. * @throws ExpectationFailedException
  46404. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  46405. */
  46406. public static function assertJsonStringEqualsJsonString(string $expectedJson, string $actualJson, string $message = '') : void
  46407. {
  46408. static::assertJson($expectedJson, $message);
  46409. static::assertJson($actualJson, $message);
  46410. static::assertThat($actualJson, new \PHPUnit\Framework\Constraint\JsonMatches($expectedJson), $message);
  46411. }
  46412. /**
  46413. * Asserts that two given JSON encoded objects or arrays are not equal.
  46414. *
  46415. * @param string $expectedJson
  46416. * @param string $actualJson
  46417. *
  46418. * @throws ExpectationFailedException
  46419. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  46420. */
  46421. public static function assertJsonStringNotEqualsJsonString($expectedJson, $actualJson, string $message = '') : void
  46422. {
  46423. static::assertJson($expectedJson, $message);
  46424. static::assertJson($actualJson, $message);
  46425. static::assertThat($actualJson, new \PHPUnit\Framework\Constraint\LogicalNot(new \PHPUnit\Framework\Constraint\JsonMatches($expectedJson)), $message);
  46426. }
  46427. /**
  46428. * Asserts that the generated JSON encoded object and the content of the given file are equal.
  46429. *
  46430. * @throws ExpectationFailedException
  46431. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  46432. */
  46433. public static function assertJsonStringEqualsJsonFile(string $expectedFile, string $actualJson, string $message = '') : void
  46434. {
  46435. static::assertFileExists($expectedFile, $message);
  46436. $expectedJson = \file_get_contents($expectedFile);
  46437. static::assertJson($expectedJson, $message);
  46438. static::assertJson($actualJson, $message);
  46439. static::assertThat($actualJson, new \PHPUnit\Framework\Constraint\JsonMatches($expectedJson), $message);
  46440. }
  46441. /**
  46442. * Asserts that the generated JSON encoded object and the content of the given file are not equal.
  46443. *
  46444. * @throws ExpectationFailedException
  46445. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  46446. */
  46447. public static function assertJsonStringNotEqualsJsonFile(string $expectedFile, string $actualJson, string $message = '') : void
  46448. {
  46449. static::assertFileExists($expectedFile, $message);
  46450. $expectedJson = \file_get_contents($expectedFile);
  46451. static::assertJson($expectedJson, $message);
  46452. static::assertJson($actualJson, $message);
  46453. static::assertThat($actualJson, new \PHPUnit\Framework\Constraint\LogicalNot(new \PHPUnit\Framework\Constraint\JsonMatches($expectedJson)), $message);
  46454. }
  46455. /**
  46456. * Asserts that two JSON files are equal.
  46457. *
  46458. * @throws ExpectationFailedException
  46459. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  46460. */
  46461. public static function assertJsonFileEqualsJsonFile(string $expectedFile, string $actualFile, string $message = '') : void
  46462. {
  46463. static::assertFileExists($expectedFile, $message);
  46464. static::assertFileExists($actualFile, $message);
  46465. $actualJson = \file_get_contents($actualFile);
  46466. $expectedJson = \file_get_contents($expectedFile);
  46467. static::assertJson($expectedJson, $message);
  46468. static::assertJson($actualJson, $message);
  46469. $constraintExpected = new \PHPUnit\Framework\Constraint\JsonMatches($expectedJson);
  46470. $constraintActual = new \PHPUnit\Framework\Constraint\JsonMatches($actualJson);
  46471. static::assertThat($expectedJson, $constraintActual, $message);
  46472. static::assertThat($actualJson, $constraintExpected, $message);
  46473. }
  46474. /**
  46475. * Asserts that two JSON files are not equal.
  46476. *
  46477. * @throws ExpectationFailedException
  46478. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  46479. */
  46480. public static function assertJsonFileNotEqualsJsonFile(string $expectedFile, string $actualFile, string $message = '') : void
  46481. {
  46482. static::assertFileExists($expectedFile, $message);
  46483. static::assertFileExists($actualFile, $message);
  46484. $actualJson = \file_get_contents($actualFile);
  46485. $expectedJson = \file_get_contents($expectedFile);
  46486. static::assertJson($expectedJson, $message);
  46487. static::assertJson($actualJson, $message);
  46488. $constraintExpected = new \PHPUnit\Framework\Constraint\JsonMatches($expectedJson);
  46489. $constraintActual = new \PHPUnit\Framework\Constraint\JsonMatches($actualJson);
  46490. static::assertThat($expectedJson, new \PHPUnit\Framework\Constraint\LogicalNot($constraintActual), $message);
  46491. static::assertThat($actualJson, new \PHPUnit\Framework\Constraint\LogicalNot($constraintExpected), $message);
  46492. }
  46493. /**
  46494. * @throws Exception
  46495. */
  46496. public static function logicalAnd() : \PHPUnit\Framework\Constraint\LogicalAnd
  46497. {
  46498. $constraints = \func_get_args();
  46499. $constraint = new \PHPUnit\Framework\Constraint\LogicalAnd();
  46500. $constraint->setConstraints($constraints);
  46501. return $constraint;
  46502. }
  46503. public static function logicalOr() : \PHPUnit\Framework\Constraint\LogicalOr
  46504. {
  46505. $constraints = \func_get_args();
  46506. $constraint = new \PHPUnit\Framework\Constraint\LogicalOr();
  46507. $constraint->setConstraints($constraints);
  46508. return $constraint;
  46509. }
  46510. public static function logicalNot(\PHPUnit\Framework\Constraint\Constraint $constraint) : \PHPUnit\Framework\Constraint\LogicalNot
  46511. {
  46512. return new \PHPUnit\Framework\Constraint\LogicalNot($constraint);
  46513. }
  46514. public static function logicalXor() : \PHPUnit\Framework\Constraint\LogicalXor
  46515. {
  46516. $constraints = \func_get_args();
  46517. $constraint = new \PHPUnit\Framework\Constraint\LogicalXor();
  46518. $constraint->setConstraints($constraints);
  46519. return $constraint;
  46520. }
  46521. public static function anything() : \PHPUnit\Framework\Constraint\IsAnything
  46522. {
  46523. return new \PHPUnit\Framework\Constraint\IsAnything();
  46524. }
  46525. public static function isTrue() : \PHPUnit\Framework\Constraint\IsTrue
  46526. {
  46527. return new \PHPUnit\Framework\Constraint\IsTrue();
  46528. }
  46529. public static function callback(callable $callback) : \PHPUnit\Framework\Constraint\Callback
  46530. {
  46531. return new \PHPUnit\Framework\Constraint\Callback($callback);
  46532. }
  46533. public static function isFalse() : \PHPUnit\Framework\Constraint\IsFalse
  46534. {
  46535. return new \PHPUnit\Framework\Constraint\IsFalse();
  46536. }
  46537. public static function isJson() : \PHPUnit\Framework\Constraint\IsJson
  46538. {
  46539. return new \PHPUnit\Framework\Constraint\IsJson();
  46540. }
  46541. public static function isNull() : \PHPUnit\Framework\Constraint\IsNull
  46542. {
  46543. return new \PHPUnit\Framework\Constraint\IsNull();
  46544. }
  46545. public static function isFinite() : \PHPUnit\Framework\Constraint\IsFinite
  46546. {
  46547. return new \PHPUnit\Framework\Constraint\IsFinite();
  46548. }
  46549. public static function isInfinite() : \PHPUnit\Framework\Constraint\IsInfinite
  46550. {
  46551. return new \PHPUnit\Framework\Constraint\IsInfinite();
  46552. }
  46553. public static function isNan() : \PHPUnit\Framework\Constraint\IsNan
  46554. {
  46555. return new \PHPUnit\Framework\Constraint\IsNan();
  46556. }
  46557. public static function containsEqual($value) : \PHPUnit\Framework\Constraint\TraversableContainsEqual
  46558. {
  46559. return new \PHPUnit\Framework\Constraint\TraversableContainsEqual($value);
  46560. }
  46561. public static function containsIdentical($value) : \PHPUnit\Framework\Constraint\TraversableContainsIdentical
  46562. {
  46563. return new \PHPUnit\Framework\Constraint\TraversableContainsIdentical($value);
  46564. }
  46565. public static function containsOnly(string $type) : \PHPUnit\Framework\Constraint\TraversableContainsOnly
  46566. {
  46567. return new \PHPUnit\Framework\Constraint\TraversableContainsOnly($type);
  46568. }
  46569. public static function containsOnlyInstancesOf(string $className) : \PHPUnit\Framework\Constraint\TraversableContainsOnly
  46570. {
  46571. return new \PHPUnit\Framework\Constraint\TraversableContainsOnly($className, \false);
  46572. }
  46573. /**
  46574. * @param int|string $key
  46575. */
  46576. public static function arrayHasKey($key) : \PHPUnit\Framework\Constraint\ArrayHasKey
  46577. {
  46578. return new \PHPUnit\Framework\Constraint\ArrayHasKey($key);
  46579. }
  46580. public static function equalTo($value) : \PHPUnit\Framework\Constraint\IsEqual
  46581. {
  46582. return new \PHPUnit\Framework\Constraint\IsEqual($value, 0.0, \false, \false);
  46583. }
  46584. public static function equalToCanonicalizing($value) : \PHPUnit\Framework\Constraint\IsEqualCanonicalizing
  46585. {
  46586. return new \PHPUnit\Framework\Constraint\IsEqualCanonicalizing($value);
  46587. }
  46588. public static function equalToIgnoringCase($value) : \PHPUnit\Framework\Constraint\IsEqualIgnoringCase
  46589. {
  46590. return new \PHPUnit\Framework\Constraint\IsEqualIgnoringCase($value);
  46591. }
  46592. public static function equalToWithDelta($value, float $delta) : \PHPUnit\Framework\Constraint\IsEqualWithDelta
  46593. {
  46594. return new \PHPUnit\Framework\Constraint\IsEqualWithDelta($value, $delta);
  46595. }
  46596. public static function isEmpty() : \PHPUnit\Framework\Constraint\IsEmpty
  46597. {
  46598. return new \PHPUnit\Framework\Constraint\IsEmpty();
  46599. }
  46600. public static function isWritable() : \PHPUnit\Framework\Constraint\IsWritable
  46601. {
  46602. return new \PHPUnit\Framework\Constraint\IsWritable();
  46603. }
  46604. public static function isReadable() : \PHPUnit\Framework\Constraint\IsReadable
  46605. {
  46606. return new \PHPUnit\Framework\Constraint\IsReadable();
  46607. }
  46608. public static function directoryExists() : \PHPUnit\Framework\Constraint\DirectoryExists
  46609. {
  46610. return new \PHPUnit\Framework\Constraint\DirectoryExists();
  46611. }
  46612. public static function fileExists() : \PHPUnit\Framework\Constraint\FileExists
  46613. {
  46614. return new \PHPUnit\Framework\Constraint\FileExists();
  46615. }
  46616. public static function greaterThan($value) : \PHPUnit\Framework\Constraint\GreaterThan
  46617. {
  46618. return new \PHPUnit\Framework\Constraint\GreaterThan($value);
  46619. }
  46620. public static function greaterThanOrEqual($value) : \PHPUnit\Framework\Constraint\LogicalOr
  46621. {
  46622. return static::logicalOr(new \PHPUnit\Framework\Constraint\IsEqual($value), new \PHPUnit\Framework\Constraint\GreaterThan($value));
  46623. }
  46624. public static function classHasAttribute(string $attributeName) : \PHPUnit\Framework\Constraint\ClassHasAttribute
  46625. {
  46626. return new \PHPUnit\Framework\Constraint\ClassHasAttribute($attributeName);
  46627. }
  46628. public static function classHasStaticAttribute(string $attributeName) : \PHPUnit\Framework\Constraint\ClassHasStaticAttribute
  46629. {
  46630. return new \PHPUnit\Framework\Constraint\ClassHasStaticAttribute($attributeName);
  46631. }
  46632. public static function objectHasAttribute($attributeName) : \PHPUnit\Framework\Constraint\ObjectHasAttribute
  46633. {
  46634. return new \PHPUnit\Framework\Constraint\ObjectHasAttribute($attributeName);
  46635. }
  46636. public static function identicalTo($value) : \PHPUnit\Framework\Constraint\IsIdentical
  46637. {
  46638. return new \PHPUnit\Framework\Constraint\IsIdentical($value);
  46639. }
  46640. public static function isInstanceOf(string $className) : \PHPUnit\Framework\Constraint\IsInstanceOf
  46641. {
  46642. return new \PHPUnit\Framework\Constraint\IsInstanceOf($className);
  46643. }
  46644. public static function isType(string $type) : \PHPUnit\Framework\Constraint\IsType
  46645. {
  46646. return new \PHPUnit\Framework\Constraint\IsType($type);
  46647. }
  46648. public static function lessThan($value) : \PHPUnit\Framework\Constraint\LessThan
  46649. {
  46650. return new \PHPUnit\Framework\Constraint\LessThan($value);
  46651. }
  46652. public static function lessThanOrEqual($value) : \PHPUnit\Framework\Constraint\LogicalOr
  46653. {
  46654. return static::logicalOr(new \PHPUnit\Framework\Constraint\IsEqual($value), new \PHPUnit\Framework\Constraint\LessThan($value));
  46655. }
  46656. public static function matchesRegularExpression(string $pattern) : \PHPUnit\Framework\Constraint\RegularExpression
  46657. {
  46658. return new \PHPUnit\Framework\Constraint\RegularExpression($pattern);
  46659. }
  46660. public static function matches(string $string) : \PHPUnit\Framework\Constraint\StringMatchesFormatDescription
  46661. {
  46662. return new \PHPUnit\Framework\Constraint\StringMatchesFormatDescription($string);
  46663. }
  46664. public static function stringStartsWith($prefix) : \PHPUnit\Framework\Constraint\StringStartsWith
  46665. {
  46666. return new \PHPUnit\Framework\Constraint\StringStartsWith($prefix);
  46667. }
  46668. public static function stringContains(string $string, bool $case = \true) : \PHPUnit\Framework\Constraint\StringContains
  46669. {
  46670. return new \PHPUnit\Framework\Constraint\StringContains($string, $case);
  46671. }
  46672. public static function stringEndsWith(string $suffix) : \PHPUnit\Framework\Constraint\StringEndsWith
  46673. {
  46674. return new \PHPUnit\Framework\Constraint\StringEndsWith($suffix);
  46675. }
  46676. public static function countOf(int $count) : \PHPUnit\Framework\Constraint\Count
  46677. {
  46678. return new \PHPUnit\Framework\Constraint\Count($count);
  46679. }
  46680. /**
  46681. * Fails a test with the given message.
  46682. *
  46683. * @throws AssertionFailedError
  46684. *
  46685. * @psalm-return never-return
  46686. */
  46687. public static function fail(string $message = '') : void
  46688. {
  46689. self::$count++;
  46690. throw new \PHPUnit\Framework\AssertionFailedError($message);
  46691. }
  46692. /**
  46693. * Mark the test as incomplete.
  46694. *
  46695. * @throws IncompleteTestError
  46696. *
  46697. * @psalm-return never-return
  46698. */
  46699. public static function markTestIncomplete(string $message = '') : void
  46700. {
  46701. throw new \PHPUnit\Framework\IncompleteTestError($message);
  46702. }
  46703. /**
  46704. * Mark the test as skipped.
  46705. *
  46706. * @throws SkippedTestError
  46707. * @throws SyntheticSkippedError
  46708. *
  46709. * @psalm-return never-return
  46710. */
  46711. public static function markTestSkipped(string $message = '') : void
  46712. {
  46713. if ($hint = self::detectLocationHint($message)) {
  46714. $trace = \debug_backtrace(\DEBUG_BACKTRACE_IGNORE_ARGS);
  46715. \array_unshift($trace, $hint);
  46716. throw new \PHPUnit\Framework\SyntheticSkippedError($hint['message'], 0, $hint['file'], (int) $hint['line'], $trace);
  46717. }
  46718. throw new \PHPUnit\Framework\SkippedTestError($message);
  46719. }
  46720. /**
  46721. * Return the current assertion count.
  46722. */
  46723. public static function getCount() : int
  46724. {
  46725. return self::$count;
  46726. }
  46727. /**
  46728. * Reset the assertion counter.
  46729. */
  46730. public static function resetCount() : void
  46731. {
  46732. self::$count = 0;
  46733. }
  46734. private static function detectLocationHint(string $message) : ?array
  46735. {
  46736. $hint = null;
  46737. $lines = \preg_split('/\\r\\n|\\r|\\n/', $message);
  46738. while (\strpos($lines[0], '__OFFSET') !== \false) {
  46739. $offset = \explode('=', \array_shift($lines));
  46740. if ($offset[0] === '__OFFSET_FILE') {
  46741. $hint['file'] = $offset[1];
  46742. }
  46743. if ($offset[0] === '__OFFSET_LINE') {
  46744. $hint['line'] = $offset[1];
  46745. }
  46746. }
  46747. if ($hint) {
  46748. $hint['message'] = \implode(\PHP_EOL, $lines);
  46749. }
  46750. return $hint;
  46751. }
  46752. private static function isValidObjectAttributeName(string $attributeName) : bool
  46753. {
  46754. return (bool) \preg_match('/[^\\x00-\\x1f\\x7f-\\x9f]+/', $attributeName);
  46755. }
  46756. private static function isValidClassAttributeName(string $attributeName) : bool
  46757. {
  46758. return (bool) \preg_match('/[a-zA-Z_\\x7f-\\xff][a-zA-Z0-9_\\x7f-\\xff]*/', $attributeName);
  46759. }
  46760. /**
  46761. * @codeCoverageIgnore
  46762. */
  46763. private static function createWarning(string $warning) : void
  46764. {
  46765. foreach (\debug_backtrace() as $step) {
  46766. if (isset($step['object']) && $step['object'] instanceof \PHPUnit\Framework\TestCase) {
  46767. \assert($step['object'] instanceof \PHPUnit\Framework\TestCase);
  46768. $step['object']->addWarning($warning);
  46769. break;
  46770. }
  46771. }
  46772. }
  46773. }
  46774. <?php
  46775. declare (strict_types=1);
  46776. /*
  46777. * This file is part of PHPUnit.
  46778. *
  46779. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  46780. *
  46781. * For the full copyright and license information, please view the LICENSE
  46782. * file that was distributed with this source code.
  46783. */
  46784. namespace PHPUnit\Framework;
  46785. /**
  46786. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  46787. */
  46788. final class TestSuiteIterator implements \RecursiveIterator
  46789. {
  46790. /**
  46791. * @var int
  46792. */
  46793. private $position = 0;
  46794. /**
  46795. * @var Test[]
  46796. */
  46797. private $tests;
  46798. public function __construct(\PHPUnit\Framework\TestSuite $testSuite)
  46799. {
  46800. $this->tests = $testSuite->tests();
  46801. }
  46802. public function rewind() : void
  46803. {
  46804. $this->position = 0;
  46805. }
  46806. public function valid() : bool
  46807. {
  46808. return $this->position < \count($this->tests);
  46809. }
  46810. public function key() : int
  46811. {
  46812. return $this->position;
  46813. }
  46814. public function current() : \PHPUnit\Framework\Test
  46815. {
  46816. return $this->tests[$this->position];
  46817. }
  46818. public function next() : void
  46819. {
  46820. $this->position++;
  46821. }
  46822. /**
  46823. * @throws NoChildTestSuiteException
  46824. */
  46825. public function getChildren() : self
  46826. {
  46827. if (!$this->hasChildren()) {
  46828. throw new \PHPUnit\Framework\NoChildTestSuiteException('The current item is not a TestSuite instance and therefore does not have any children.');
  46829. }
  46830. $current = $this->current();
  46831. \assert($current instanceof \PHPUnit\Framework\TestSuite);
  46832. return new self($current);
  46833. }
  46834. public function hasChildren() : bool
  46835. {
  46836. return $this->valid() && $this->current() instanceof \PHPUnit\Framework\TestSuite;
  46837. }
  46838. }
  46839. <?php
  46840. declare (strict_types=1);
  46841. /*
  46842. * This file is part of PHPUnit.
  46843. *
  46844. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  46845. *
  46846. * For the full copyright and license information, please view the LICENSE
  46847. * file that was distributed with this source code.
  46848. */
  46849. namespace PHPUnit\Framework\MockObject;
  46850. use PHPUnit\Framework\MockObject\Builder\InvocationStubber;
  46851. /**
  46852. * @method InvocationStubber method($constraint)
  46853. */
  46854. interface Stub
  46855. {
  46856. public function __phpunit_getInvocationHandler() : \PHPUnit\Framework\MockObject\InvocationHandler;
  46857. public function __phpunit_hasMatchers() : bool;
  46858. public function __phpunit_setReturnValueGeneration(bool $returnValueGeneration) : void;
  46859. }
  46860. <?php
  46861. declare (strict_types=1);
  46862. /*
  46863. * This file is part of PHPUnit.
  46864. *
  46865. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  46866. *
  46867. * For the full copyright and license information, please view the LICENSE
  46868. * file that was distributed with this source code.
  46869. */
  46870. namespace PHPUnit\Framework\MockObject;
  46871. /**
  46872. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  46873. */
  46874. final class MockClass implements \PHPUnit\Framework\MockObject\MockType
  46875. {
  46876. /**
  46877. * @var string
  46878. */
  46879. private $classCode;
  46880. /**
  46881. * @var string
  46882. */
  46883. private $mockName;
  46884. /**
  46885. * @var ConfigurableMethod[]
  46886. */
  46887. private $configurableMethods;
  46888. public function __construct(string $classCode, string $mockName, array $configurableMethods)
  46889. {
  46890. $this->classCode = $classCode;
  46891. $this->mockName = $mockName;
  46892. $this->configurableMethods = $configurableMethods;
  46893. }
  46894. public function generate() : string
  46895. {
  46896. if (!\class_exists($this->mockName, \false)) {
  46897. eval($this->classCode);
  46898. \call_user_func([$this->mockName, '__phpunit_initConfigurableMethods'], ...$this->configurableMethods);
  46899. }
  46900. return $this->mockName;
  46901. }
  46902. public function getClassCode() : string
  46903. {
  46904. return $this->classCode;
  46905. }
  46906. }
  46907. <?php
  46908. declare (strict_types=1);
  46909. /*
  46910. * This file is part of PHPUnit.
  46911. *
  46912. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  46913. *
  46914. * For the full copyright and license information, please view the LICENSE
  46915. * file that was distributed with this source code.
  46916. */
  46917. namespace PHPUnit\Framework\MockObject;
  46918. /**
  46919. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  46920. */
  46921. interface MockType
  46922. {
  46923. public function generate() : string;
  46924. }
  46925. <?php
  46926. declare (strict_types=1);
  46927. /*
  46928. * This file is part of PHPUnit.
  46929. *
  46930. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  46931. *
  46932. * For the full copyright and license information, please view the LICENSE
  46933. * file that was distributed with this source code.
  46934. */
  46935. namespace PHPUnit\Framework\MockObject\Builder;
  46936. /**
  46937. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  46938. */
  46939. interface MethodNameMatch extends \PHPUnit\Framework\MockObject\Builder\ParametersMatch
  46940. {
  46941. /**
  46942. * Adds a new method name match and returns the parameter match object for
  46943. * further matching possibilities.
  46944. *
  46945. * @param \PHPUnit\Framework\Constraint\Constraint $name Constraint for matching method, if a string is passed it will use the PHPUnit_Framework_Constraint_IsEqual
  46946. *
  46947. * @return ParametersMatch
  46948. */
  46949. public function method($name);
  46950. }
  46951. <?php
  46952. declare (strict_types=1);
  46953. /*
  46954. * This file is part of PHPUnit.
  46955. *
  46956. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  46957. *
  46958. * For the full copyright and license information, please view the LICENSE
  46959. * file that was distributed with this source code.
  46960. */
  46961. namespace PHPUnit\Framework\MockObject\Builder;
  46962. use PHPUnit\Framework\MockObject\Stub\Stub as BaseStub;
  46963. /**
  46964. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  46965. */
  46966. interface Stub extends \PHPUnit\Framework\MockObject\Builder\Identity
  46967. {
  46968. /**
  46969. * Stubs the matching method with the stub object $stub. Any invocations of
  46970. * the matched method will now be handled by the stub instead.
  46971. */
  46972. public function will(\PHPUnit\Framework\MockObject\Stub\Stub $stub) : \PHPUnit\Framework\MockObject\Builder\Identity;
  46973. }
  46974. <?php
  46975. declare (strict_types=1);
  46976. /*
  46977. * This file is part of PHPUnit.
  46978. *
  46979. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  46980. *
  46981. * For the full copyright and license information, please view the LICENSE
  46982. * file that was distributed with this source code.
  46983. */
  46984. namespace PHPUnit\Framework\MockObject\Builder;
  46985. use PHPUnit\Framework\MockObject\Stub\Stub;
  46986. interface InvocationStubber
  46987. {
  46988. public function will(\PHPUnit\Framework\MockObject\Stub\Stub $stub) : \PHPUnit\Framework\MockObject\Builder\Identity;
  46989. /** @return self */
  46990. public function willReturn($value, ...$nextValues);
  46991. /**
  46992. * @param mixed $reference
  46993. *
  46994. * @return self
  46995. */
  46996. public function willReturnReference(&$reference);
  46997. /**
  46998. * @param array<int, array<int, mixed>> $valueMap
  46999. *
  47000. * @return self
  47001. */
  47002. public function willReturnMap(array $valueMap);
  47003. /**
  47004. * @param int $argumentIndex
  47005. *
  47006. * @return self
  47007. */
  47008. public function willReturnArgument($argumentIndex);
  47009. /**
  47010. * @param callable $callback
  47011. *
  47012. * @return self
  47013. */
  47014. public function willReturnCallback($callback);
  47015. /** @return self */
  47016. public function willReturnSelf();
  47017. /**
  47018. * @param mixed $values
  47019. *
  47020. * @return self
  47021. */
  47022. public function willReturnOnConsecutiveCalls(...$values);
  47023. /** @return self */
  47024. public function willThrowException(\Throwable $exception);
  47025. }
  47026. <?php
  47027. declare (strict_types=1);
  47028. /*
  47029. * This file is part of PHPUnit.
  47030. *
  47031. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  47032. *
  47033. * For the full copyright and license information, please view the LICENSE
  47034. * file that was distributed with this source code.
  47035. */
  47036. namespace PHPUnit\Framework\MockObject\Builder;
  47037. /**
  47038. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  47039. */
  47040. interface Identity
  47041. {
  47042. /**
  47043. * Sets the identification of the expectation to $id.
  47044. *
  47045. * @note The identifier is unique per mock object.
  47046. *
  47047. * @param string $id unique identification of expectation
  47048. */
  47049. public function id($id);
  47050. }
  47051. <?php
  47052. declare (strict_types=1);
  47053. /*
  47054. * This file is part of PHPUnit.
  47055. *
  47056. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  47057. *
  47058. * For the full copyright and license information, please view the LICENSE
  47059. * file that was distributed with this source code.
  47060. */
  47061. namespace PHPUnit\Framework\MockObject\Builder;
  47062. /**
  47063. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  47064. */
  47065. interface ParametersMatch extends \PHPUnit\Framework\MockObject\Builder\Match
  47066. {
  47067. /**
  47068. * Sets the parameters to match for, each parameter to this function will
  47069. * be part of match. To perform specific matches or constraints create a
  47070. * new PHPUnit\Framework\Constraint\Constraint and use it for the parameter.
  47071. * If the parameter value is not a constraint it will use the
  47072. * PHPUnit\Framework\Constraint\IsEqual for the value.
  47073. *
  47074. * Some examples:
  47075. * <code>
  47076. * // match first parameter with value 2
  47077. * $b->with(2);
  47078. * // match first parameter with value 'smock' and second identical to 42
  47079. * $b->with('smock', new PHPUnit\Framework\Constraint\IsEqual(42));
  47080. * </code>
  47081. *
  47082. * @return ParametersMatch
  47083. */
  47084. public function with(...$arguments);
  47085. /**
  47086. * Sets a rule which allows any kind of parameters.
  47087. *
  47088. * Some examples:
  47089. * <code>
  47090. * // match any number of parameters
  47091. * $b->withAnyParameters();
  47092. * </code>
  47093. *
  47094. * @return ParametersMatch
  47095. */
  47096. public function withAnyParameters();
  47097. }
  47098. <?php
  47099. declare (strict_types=1);
  47100. /*
  47101. * This file is part of PHPUnit.
  47102. *
  47103. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  47104. *
  47105. * For the full copyright and license information, please view the LICENSE
  47106. * file that was distributed with this source code.
  47107. */
  47108. namespace PHPUnit\Framework\MockObject\Builder;
  47109. /**
  47110. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  47111. */
  47112. interface Match extends \PHPUnit\Framework\MockObject\Builder\Stub
  47113. {
  47114. /**
  47115. * Defines the expectation which must occur before the current is valid.
  47116. *
  47117. * @param string $id the identification of the expectation that should
  47118. * occur before this one
  47119. *
  47120. * @return Stub
  47121. */
  47122. public function after($id);
  47123. }
  47124. <?php
  47125. declare (strict_types=1);
  47126. /*
  47127. * This file is part of PHPUnit.
  47128. *
  47129. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  47130. *
  47131. * For the full copyright and license information, please view the LICENSE
  47132. * file that was distributed with this source code.
  47133. */
  47134. namespace PHPUnit\Framework\MockObject\Builder;
  47135. use PHPUnit\Framework\Constraint\Constraint;
  47136. use PHPUnit\Framework\MockObject\ConfigurableMethod;
  47137. use PHPUnit\Framework\MockObject\IncompatibleReturnValueException;
  47138. use PHPUnit\Framework\MockObject\InvocationHandler;
  47139. use PHPUnit\Framework\MockObject\Matcher;
  47140. use PHPUnit\Framework\MockObject\Rule;
  47141. use PHPUnit\Framework\MockObject\RuntimeException;
  47142. use PHPUnit\Framework\MockObject\Stub\ConsecutiveCalls;
  47143. use PHPUnit\Framework\MockObject\Stub\Exception;
  47144. use PHPUnit\Framework\MockObject\Stub\ReturnArgument;
  47145. use PHPUnit\Framework\MockObject\Stub\ReturnCallback;
  47146. use PHPUnit\Framework\MockObject\Stub\ReturnReference;
  47147. use PHPUnit\Framework\MockObject\Stub\ReturnSelf;
  47148. use PHPUnit\Framework\MockObject\Stub\ReturnStub;
  47149. use PHPUnit\Framework\MockObject\Stub\ReturnValueMap;
  47150. use PHPUnit\Framework\MockObject\Stub\Stub;
  47151. /**
  47152. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  47153. */
  47154. final class InvocationMocker implements \PHPUnit\Framework\MockObject\Builder\InvocationStubber, \PHPUnit\Framework\MockObject\Builder\MethodNameMatch
  47155. {
  47156. /**
  47157. * @var InvocationHandler
  47158. */
  47159. private $invocationHandler;
  47160. /**
  47161. * @var Matcher
  47162. */
  47163. private $matcher;
  47164. /**
  47165. * @var ConfigurableMethod[]
  47166. */
  47167. private $configurableMethods;
  47168. public function __construct(\PHPUnit\Framework\MockObject\InvocationHandler $handler, \PHPUnit\Framework\MockObject\Matcher $matcher, \PHPUnit\Framework\MockObject\ConfigurableMethod ...$configurableMethods)
  47169. {
  47170. $this->invocationHandler = $handler;
  47171. $this->matcher = $matcher;
  47172. $this->configurableMethods = $configurableMethods;
  47173. }
  47174. /**
  47175. * @return $this
  47176. */
  47177. public function id($id) : self
  47178. {
  47179. $this->invocationHandler->registerMatcher($id, $this->matcher);
  47180. return $this;
  47181. }
  47182. /**
  47183. * @return $this
  47184. */
  47185. public function will(\PHPUnit\Framework\MockObject\Stub\Stub $stub) : \PHPUnit\Framework\MockObject\Builder\Identity
  47186. {
  47187. $this->matcher->setStub($stub);
  47188. return $this;
  47189. }
  47190. public function willReturn($value, ...$nextValues) : self
  47191. {
  47192. if (\count($nextValues) === 0) {
  47193. $this->ensureTypeOfReturnValues([$value]);
  47194. $stub = $value instanceof \PHPUnit\Framework\MockObject\Stub\Stub ? $value : new \PHPUnit\Framework\MockObject\Stub\ReturnStub($value);
  47195. } else {
  47196. $values = \array_merge([$value], $nextValues);
  47197. $this->ensureTypeOfReturnValues($values);
  47198. $stub = new \PHPUnit\Framework\MockObject\Stub\ConsecutiveCalls($values);
  47199. }
  47200. return $this->will($stub);
  47201. }
  47202. /** {@inheritDoc} */
  47203. public function willReturnReference(&$reference) : self
  47204. {
  47205. $stub = new \PHPUnit\Framework\MockObject\Stub\ReturnReference($reference);
  47206. return $this->will($stub);
  47207. }
  47208. public function willReturnMap(array $valueMap) : self
  47209. {
  47210. $stub = new \PHPUnit\Framework\MockObject\Stub\ReturnValueMap($valueMap);
  47211. return $this->will($stub);
  47212. }
  47213. public function willReturnArgument($argumentIndex) : self
  47214. {
  47215. $stub = new \PHPUnit\Framework\MockObject\Stub\ReturnArgument($argumentIndex);
  47216. return $this->will($stub);
  47217. }
  47218. /** {@inheritDoc} */
  47219. public function willReturnCallback($callback) : self
  47220. {
  47221. $stub = new \PHPUnit\Framework\MockObject\Stub\ReturnCallback($callback);
  47222. return $this->will($stub);
  47223. }
  47224. public function willReturnSelf() : self
  47225. {
  47226. $stub = new \PHPUnit\Framework\MockObject\Stub\ReturnSelf();
  47227. return $this->will($stub);
  47228. }
  47229. public function willReturnOnConsecutiveCalls(...$values) : self
  47230. {
  47231. $stub = new \PHPUnit\Framework\MockObject\Stub\ConsecutiveCalls($values);
  47232. return $this->will($stub);
  47233. }
  47234. public function willThrowException(\Throwable $exception) : self
  47235. {
  47236. $stub = new \PHPUnit\Framework\MockObject\Stub\Exception($exception);
  47237. return $this->will($stub);
  47238. }
  47239. /**
  47240. * @return $this
  47241. */
  47242. public function after($id) : self
  47243. {
  47244. $this->matcher->setAfterMatchBuilderId($id);
  47245. return $this;
  47246. }
  47247. /**
  47248. * @throws RuntimeException
  47249. *
  47250. * @return $this
  47251. */
  47252. public function with(...$arguments) : self
  47253. {
  47254. $this->canDefineParameters();
  47255. $this->matcher->setParametersRule(new \PHPUnit\Framework\MockObject\Rule\Parameters($arguments));
  47256. return $this;
  47257. }
  47258. /**
  47259. * @param array ...$arguments
  47260. *
  47261. * @throws RuntimeException
  47262. *
  47263. * @return $this
  47264. */
  47265. public function withConsecutive(...$arguments) : self
  47266. {
  47267. $this->canDefineParameters();
  47268. $this->matcher->setParametersRule(new \PHPUnit\Framework\MockObject\Rule\ConsecutiveParameters($arguments));
  47269. return $this;
  47270. }
  47271. /**
  47272. * @throws RuntimeException
  47273. *
  47274. * @return $this
  47275. */
  47276. public function withAnyParameters() : self
  47277. {
  47278. $this->canDefineParameters();
  47279. $this->matcher->setParametersRule(new \PHPUnit\Framework\MockObject\Rule\AnyParameters());
  47280. return $this;
  47281. }
  47282. /**
  47283. * @param Constraint|string $constraint
  47284. *
  47285. * @throws RuntimeException
  47286. *
  47287. * @return $this
  47288. */
  47289. public function method($constraint) : self
  47290. {
  47291. if ($this->matcher->hasMethodNameRule()) {
  47292. throw new \PHPUnit\Framework\MockObject\RuntimeException('Rule for method name is already defined, cannot redefine');
  47293. }
  47294. $configurableMethodNames = \array_map(static function (\PHPUnit\Framework\MockObject\ConfigurableMethod $configurable) {
  47295. return \strtolower($configurable->getName());
  47296. }, $this->configurableMethods);
  47297. if (\is_string($constraint) && !\in_array(\strtolower($constraint), $configurableMethodNames, \true)) {
  47298. throw new \PHPUnit\Framework\MockObject\RuntimeException(\sprintf('Trying to configure method "%s" which cannot be configured because it does not exist, has not been specified, is final, or is static', $constraint));
  47299. }
  47300. $this->matcher->setMethodNameRule(new \PHPUnit\Framework\MockObject\Rule\MethodName($constraint));
  47301. return $this;
  47302. }
  47303. /**
  47304. * Validate that a parameters rule can be defined, throw exceptions otherwise.
  47305. *
  47306. * @throws RuntimeException
  47307. */
  47308. private function canDefineParameters() : void
  47309. {
  47310. if (!$this->matcher->hasMethodNameRule()) {
  47311. throw new \PHPUnit\Framework\MockObject\RuntimeException('Rule for method name is not defined, cannot define rule for parameters ' . 'without one');
  47312. }
  47313. if ($this->matcher->hasParametersRule()) {
  47314. throw new \PHPUnit\Framework\MockObject\RuntimeException('Rule for parameters is already defined, cannot redefine');
  47315. }
  47316. }
  47317. private function getConfiguredMethod() : ?\PHPUnit\Framework\MockObject\ConfigurableMethod
  47318. {
  47319. $configuredMethod = null;
  47320. foreach ($this->configurableMethods as $configurableMethod) {
  47321. if ($this->matcher->getMethodNameRule()->matchesName($configurableMethod->getName())) {
  47322. if ($configuredMethod !== null) {
  47323. return null;
  47324. }
  47325. $configuredMethod = $configurableMethod;
  47326. }
  47327. }
  47328. return $configuredMethod;
  47329. }
  47330. private function ensureTypeOfReturnValues(array $values) : void
  47331. {
  47332. $configuredMethod = $this->getConfiguredMethod();
  47333. if ($configuredMethod === null) {
  47334. return;
  47335. }
  47336. foreach ($values as $value) {
  47337. if (!$configuredMethod->mayReturn($value)) {
  47338. throw new \PHPUnit\Framework\MockObject\IncompatibleReturnValueException(\sprintf('Method %s may not return value of type %s, its return declaration is "%s"', $configuredMethod->getName(), \is_object($value) ? \get_class($value) : \gettype($value), $configuredMethod->getReturnTypeDeclaration()));
  47339. }
  47340. }
  47341. }
  47342. }
  47343. <?php
  47344. declare (strict_types=1);
  47345. /*
  47346. * This file is part of PHPUnit.
  47347. *
  47348. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  47349. *
  47350. * For the full copyright and license information, please view the LICENSE
  47351. * file that was distributed with this source code.
  47352. */
  47353. namespace PHPUnit\Framework\MockObject;
  47354. /**
  47355. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  47356. */
  47357. final class ConfigurableMethodsAlreadyInitializedException extends \PHPUnit\Framework\Exception implements \PHPUnit\Framework\MockObject\Exception
  47358. {
  47359. }
  47360. <?php
  47361. declare (strict_types=1);
  47362. /*
  47363. * This file is part of PHPUnit.
  47364. *
  47365. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  47366. *
  47367. * For the full copyright and license information, please view the LICENSE
  47368. * file that was distributed with this source code.
  47369. */
  47370. namespace PHPUnit\Framework\MockObject;
  47371. /**
  47372. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  47373. */
  47374. final class IncompatibleReturnValueException extends \PHPUnit\Framework\Exception implements \PHPUnit\Framework\MockObject\Exception
  47375. {
  47376. }
  47377. <?php
  47378. declare (strict_types=1);
  47379. /*
  47380. * This file is part of PHPUnit.
  47381. *
  47382. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  47383. *
  47384. * For the full copyright and license information, please view the LICENSE
  47385. * file that was distributed with this source code.
  47386. */
  47387. namespace PHPUnit\Framework\MockObject;
  47388. /**
  47389. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  47390. */
  47391. final class RuntimeException extends \RuntimeException implements \PHPUnit\Framework\MockObject\Exception
  47392. {
  47393. }
  47394. <?php
  47395. declare (strict_types=1);
  47396. /*
  47397. * This file is part of PHPUnit.
  47398. *
  47399. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  47400. *
  47401. * For the full copyright and license information, please view the LICENSE
  47402. * file that was distributed with this source code.
  47403. */
  47404. namespace PHPUnit\Framework\MockObject;
  47405. /**
  47406. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  47407. */
  47408. final class BadMethodCallException extends \BadMethodCallException implements \PHPUnit\Framework\MockObject\Exception
  47409. {
  47410. }
  47411. <?php
  47412. declare (strict_types=1);
  47413. /*
  47414. * This file is part of PHPUnit.
  47415. *
  47416. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  47417. *
  47418. * For the full copyright and license information, please view the LICENSE
  47419. * file that was distributed with this source code.
  47420. */
  47421. namespace PHPUnit\Framework\MockObject;
  47422. /**
  47423. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  47424. */
  47425. interface Exception extends \Throwable
  47426. {
  47427. }
  47428. <?php
  47429. declare (strict_types=1);
  47430. /*
  47431. * This file is part of PHPUnit.
  47432. *
  47433. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  47434. *
  47435. * For the full copyright and license information, please view the LICENSE
  47436. * file that was distributed with this source code.
  47437. */
  47438. namespace PHPUnit\Framework\MockObject\Stub;
  47439. use PHPUnit\Framework\MockObject\Invocation;
  47440. use PHPUnit\SebastianBergmann\Exporter\Exporter;
  47441. /**
  47442. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  47443. */
  47444. final class ReturnReference implements \PHPUnit\Framework\MockObject\Stub\Stub
  47445. {
  47446. /**
  47447. * @var mixed
  47448. */
  47449. private $reference;
  47450. public function __construct(&$reference)
  47451. {
  47452. $this->reference =& $reference;
  47453. }
  47454. public function invoke(\PHPUnit\Framework\MockObject\Invocation $invocation)
  47455. {
  47456. return $this->reference;
  47457. }
  47458. public function toString() : string
  47459. {
  47460. $exporter = new \PHPUnit\SebastianBergmann\Exporter\Exporter();
  47461. return \sprintf('return user-specified reference %s', $exporter->export($this->reference));
  47462. }
  47463. }
  47464. <?php
  47465. declare (strict_types=1);
  47466. /*
  47467. * This file is part of PHPUnit.
  47468. *
  47469. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  47470. *
  47471. * For the full copyright and license information, please view the LICENSE
  47472. * file that was distributed with this source code.
  47473. */
  47474. namespace PHPUnit\Framework\MockObject\Stub;
  47475. use PHPUnit\Framework\MockObject\Invocation;
  47476. use PHPUnit\Framework\SelfDescribing;
  47477. /**
  47478. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  47479. */
  47480. interface Stub extends \PHPUnit\Framework\SelfDescribing
  47481. {
  47482. /**
  47483. * Fakes the processing of the invocation $invocation by returning a
  47484. * specific value.
  47485. *
  47486. * @param Invocation $invocation The invocation which was mocked and matched by the current method and argument matchers
  47487. */
  47488. public function invoke(\PHPUnit\Framework\MockObject\Invocation $invocation);
  47489. }
  47490. <?php
  47491. declare (strict_types=1);
  47492. /*
  47493. * This file is part of PHPUnit.
  47494. *
  47495. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  47496. *
  47497. * For the full copyright and license information, please view the LICENSE
  47498. * file that was distributed with this source code.
  47499. */
  47500. namespace PHPUnit\Framework\MockObject\Stub;
  47501. use PHPUnit\Framework\MockObject\Invocation;
  47502. /**
  47503. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  47504. */
  47505. final class ReturnValueMap implements \PHPUnit\Framework\MockObject\Stub\Stub
  47506. {
  47507. /**
  47508. * @var array
  47509. */
  47510. private $valueMap;
  47511. public function __construct(array $valueMap)
  47512. {
  47513. $this->valueMap = $valueMap;
  47514. }
  47515. public function invoke(\PHPUnit\Framework\MockObject\Invocation $invocation)
  47516. {
  47517. $parameterCount = \count($invocation->getParameters());
  47518. foreach ($this->valueMap as $map) {
  47519. if (!\is_array($map) || $parameterCount !== \count($map) - 1) {
  47520. continue;
  47521. }
  47522. $return = \array_pop($map);
  47523. if ($invocation->getParameters() === $map) {
  47524. return $return;
  47525. }
  47526. }
  47527. }
  47528. public function toString() : string
  47529. {
  47530. return 'return value from a map';
  47531. }
  47532. }
  47533. <?php
  47534. declare (strict_types=1);
  47535. /*
  47536. * This file is part of PHPUnit.
  47537. *
  47538. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  47539. *
  47540. * For the full copyright and license information, please view the LICENSE
  47541. * file that was distributed with this source code.
  47542. */
  47543. namespace PHPUnit\Framework\MockObject\Stub;
  47544. use PHPUnit\Framework\MockObject\Invocation;
  47545. /**
  47546. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  47547. */
  47548. final class ReturnCallback implements \PHPUnit\Framework\MockObject\Stub\Stub
  47549. {
  47550. private $callback;
  47551. public function __construct($callback)
  47552. {
  47553. $this->callback = $callback;
  47554. }
  47555. public function invoke(\PHPUnit\Framework\MockObject\Invocation $invocation)
  47556. {
  47557. return \call_user_func_array($this->callback, $invocation->getParameters());
  47558. }
  47559. public function toString() : string
  47560. {
  47561. if (\is_array($this->callback)) {
  47562. if (\is_object($this->callback[0])) {
  47563. $class = \get_class($this->callback[0]);
  47564. $type = '->';
  47565. } else {
  47566. $class = $this->callback[0];
  47567. $type = '::';
  47568. }
  47569. return \sprintf('return result of user defined callback %s%s%s() with the ' . 'passed arguments', $class, $type, $this->callback[1]);
  47570. }
  47571. return 'return result of user defined callback ' . $this->callback . ' with the passed arguments';
  47572. }
  47573. }
  47574. <?php
  47575. declare (strict_types=1);
  47576. /*
  47577. * This file is part of PHPUnit.
  47578. *
  47579. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  47580. *
  47581. * For the full copyright and license information, please view the LICENSE
  47582. * file that was distributed with this source code.
  47583. */
  47584. namespace PHPUnit\Framework\MockObject\Stub;
  47585. use PHPUnit\Framework\MockObject\Invocation;
  47586. use PHPUnit\Framework\MockObject\RuntimeException;
  47587. /**
  47588. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  47589. */
  47590. final class ReturnSelf implements \PHPUnit\Framework\MockObject\Stub\Stub
  47591. {
  47592. /**
  47593. * @throws RuntimeException
  47594. */
  47595. public function invoke(\PHPUnit\Framework\MockObject\Invocation $invocation)
  47596. {
  47597. return $invocation->getObject();
  47598. }
  47599. public function toString() : string
  47600. {
  47601. return 'return the current object';
  47602. }
  47603. }
  47604. <?php
  47605. declare (strict_types=1);
  47606. /*
  47607. * This file is part of PHPUnit.
  47608. *
  47609. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  47610. *
  47611. * For the full copyright and license information, please view the LICENSE
  47612. * file that was distributed with this source code.
  47613. */
  47614. namespace PHPUnit\Framework\MockObject\Stub;
  47615. use PHPUnit\Framework\MockObject\Invocation;
  47616. use PHPUnit\SebastianBergmann\Exporter\Exporter;
  47617. /**
  47618. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  47619. */
  47620. final class Exception implements \PHPUnit\Framework\MockObject\Stub\Stub
  47621. {
  47622. private $exception;
  47623. public function __construct(\Throwable $exception)
  47624. {
  47625. $this->exception = $exception;
  47626. }
  47627. /**
  47628. * @throws \Throwable
  47629. */
  47630. public function invoke(\PHPUnit\Framework\MockObject\Invocation $invocation) : void
  47631. {
  47632. throw $this->exception;
  47633. }
  47634. public function toString() : string
  47635. {
  47636. $exporter = new \PHPUnit\SebastianBergmann\Exporter\Exporter();
  47637. return \sprintf('raise user-specified exception %s', $exporter->export($this->exception));
  47638. }
  47639. }
  47640. <?php
  47641. declare (strict_types=1);
  47642. /*
  47643. * This file is part of PHPUnit.
  47644. *
  47645. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  47646. *
  47647. * For the full copyright and license information, please view the LICENSE
  47648. * file that was distributed with this source code.
  47649. */
  47650. namespace PHPUnit\Framework\MockObject\Stub;
  47651. use PHPUnit\Framework\MockObject\Invocation;
  47652. /**
  47653. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  47654. */
  47655. final class ReturnArgument implements \PHPUnit\Framework\MockObject\Stub\Stub
  47656. {
  47657. /**
  47658. * @var int
  47659. */
  47660. private $argumentIndex;
  47661. public function __construct($argumentIndex)
  47662. {
  47663. $this->argumentIndex = $argumentIndex;
  47664. }
  47665. public function invoke(\PHPUnit\Framework\MockObject\Invocation $invocation)
  47666. {
  47667. if (isset($invocation->getParameters()[$this->argumentIndex])) {
  47668. return $invocation->getParameters()[$this->argumentIndex];
  47669. }
  47670. }
  47671. public function toString() : string
  47672. {
  47673. return \sprintf('return argument #%d', $this->argumentIndex);
  47674. }
  47675. }
  47676. <?php
  47677. declare (strict_types=1);
  47678. /*
  47679. * This file is part of PHPUnit.
  47680. *
  47681. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  47682. *
  47683. * For the full copyright and license information, please view the LICENSE
  47684. * file that was distributed with this source code.
  47685. */
  47686. namespace PHPUnit\Framework\MockObject\Stub;
  47687. use PHPUnit\Framework\MockObject\Invocation;
  47688. use PHPUnit\SebastianBergmann\Exporter\Exporter;
  47689. /**
  47690. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  47691. */
  47692. final class ReturnStub implements \PHPUnit\Framework\MockObject\Stub\Stub
  47693. {
  47694. /**
  47695. * @var mixed
  47696. */
  47697. private $value;
  47698. public function __construct($value)
  47699. {
  47700. $this->value = $value;
  47701. }
  47702. public function invoke(\PHPUnit\Framework\MockObject\Invocation $invocation)
  47703. {
  47704. return $this->value;
  47705. }
  47706. public function toString() : string
  47707. {
  47708. $exporter = new \PHPUnit\SebastianBergmann\Exporter\Exporter();
  47709. return \sprintf('return user-specified value %s', $exporter->export($this->value));
  47710. }
  47711. }
  47712. <?php
  47713. declare (strict_types=1);
  47714. /*
  47715. * This file is part of PHPUnit.
  47716. *
  47717. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  47718. *
  47719. * For the full copyright and license information, please view the LICENSE
  47720. * file that was distributed with this source code.
  47721. */
  47722. namespace PHPUnit\Framework\MockObject\Stub;
  47723. use PHPUnit\Framework\MockObject\Invocation;
  47724. use PHPUnit\SebastianBergmann\Exporter\Exporter;
  47725. /**
  47726. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  47727. */
  47728. final class ConsecutiveCalls implements \PHPUnit\Framework\MockObject\Stub\Stub
  47729. {
  47730. /**
  47731. * @var array
  47732. */
  47733. private $stack;
  47734. /**
  47735. * @var mixed
  47736. */
  47737. private $value;
  47738. public function __construct(array $stack)
  47739. {
  47740. $this->stack = $stack;
  47741. }
  47742. public function invoke(\PHPUnit\Framework\MockObject\Invocation $invocation)
  47743. {
  47744. $this->value = \array_shift($this->stack);
  47745. if ($this->value instanceof \PHPUnit\Framework\MockObject\Stub\Stub) {
  47746. $this->value = $this->value->invoke($invocation);
  47747. }
  47748. return $this->value;
  47749. }
  47750. public function toString() : string
  47751. {
  47752. $exporter = new \PHPUnit\SebastianBergmann\Exporter\Exporter();
  47753. return \sprintf('return user-specified value %s', $exporter->export($this->value));
  47754. }
  47755. }
  47756. <?php
  47757. declare (strict_types=1);
  47758. /*
  47759. * This file is part of PHPUnit.
  47760. *
  47761. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  47762. *
  47763. * For the full copyright and license information, please view the LICENSE
  47764. * file that was distributed with this source code.
  47765. */
  47766. namespace PHPUnit\Framework\MockObject;
  47767. use PHPUnit\Doctrine\Instantiator\Exception\ExceptionInterface as InstantiatorException;
  47768. use PHPUnit\Doctrine\Instantiator\Instantiator;
  47769. use PHPUnit\Framework\InvalidArgumentException;
  47770. use PHPUnit\SebastianBergmann\Template\Template;
  47771. /**
  47772. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  47773. */
  47774. final class Generator
  47775. {
  47776. /**
  47777. * @var array
  47778. */
  47779. private const BLACKLISTED_METHOD_NAMES = ['__CLASS__' => \true, '__DIR__' => \true, '__FILE__' => \true, '__FUNCTION__' => \true, '__LINE__' => \true, '__METHOD__' => \true, '__NAMESPACE__' => \true, '__TRAIT__' => \true, '__clone' => \true, '__halt_compiler' => \true];
  47780. /**
  47781. * @var array
  47782. */
  47783. private static $cache = [];
  47784. /**
  47785. * @var Template[]
  47786. */
  47787. private static $templates = [];
  47788. /**
  47789. * Returns a mock object for the specified class.
  47790. *
  47791. * @param null|array $methods
  47792. *
  47793. * @throws RuntimeException
  47794. */
  47795. public function getMock(string $type, $methods = [], array $arguments = [], string $mockClassName = '', bool $callOriginalConstructor = \true, bool $callOriginalClone = \true, bool $callAutoload = \true, bool $cloneArguments = \true, bool $callOriginalMethods = \false, object $proxyTarget = null, bool $allowMockingUnknownTypes = \true, bool $returnValueGeneration = \true) : \PHPUnit\Framework\MockObject\MockObject
  47796. {
  47797. if (!\is_array($methods) && null !== $methods) {
  47798. throw \PHPUnit\Framework\InvalidArgumentException::create(2, 'array');
  47799. }
  47800. if ($type === 'Traversable' || $type === '\\Traversable') {
  47801. $type = 'Iterator';
  47802. }
  47803. if (!$allowMockingUnknownTypes && !\class_exists($type, $callAutoload) && !\interface_exists($type, $callAutoload)) {
  47804. throw new \PHPUnit\Framework\MockObject\RuntimeException(\sprintf('Cannot stub or mock class or interface "%s" which does not exist', $type));
  47805. }
  47806. if (null !== $methods) {
  47807. foreach ($methods as $method) {
  47808. if (!\preg_match('~[a-zA-Z_\\x7f-\\xff][a-zA-Z0-9_\\x7f-\\xff]*~', (string) $method)) {
  47809. throw new \PHPUnit\Framework\MockObject\RuntimeException(\sprintf('Cannot stub or mock method with invalid name "%s"', $method));
  47810. }
  47811. }
  47812. if ($methods !== \array_unique($methods)) {
  47813. throw new \PHPUnit\Framework\MockObject\RuntimeException(\sprintf('Cannot stub or mock using a method list that contains duplicates: "%s" (duplicate: "%s")', \implode(', ', $methods), \implode(', ', \array_unique(\array_diff_assoc($methods, \array_unique($methods))))));
  47814. }
  47815. }
  47816. if ($mockClassName !== '' && \class_exists($mockClassName, \false)) {
  47817. try {
  47818. $reflector = new \ReflectionClass($mockClassName);
  47819. // @codeCoverageIgnoreStart
  47820. } catch (\ReflectionException $e) {
  47821. throw new \PHPUnit\Framework\MockObject\RuntimeException($e->getMessage(), (int) $e->getCode(), $e);
  47822. }
  47823. // @codeCoverageIgnoreEnd
  47824. if (!$reflector->implementsInterface(\PHPUnit\Framework\MockObject\MockObject::class)) {
  47825. throw new \PHPUnit\Framework\MockObject\RuntimeException(\sprintf('Class "%s" already exists.', $mockClassName));
  47826. }
  47827. }
  47828. if (!$callOriginalConstructor && $callOriginalMethods) {
  47829. throw new \PHPUnit\Framework\MockObject\RuntimeException('Proxying to original methods requires invoking the original constructor');
  47830. }
  47831. $mock = $this->generate($type, $methods, $mockClassName, $callOriginalClone, $callAutoload, $cloneArguments, $callOriginalMethods);
  47832. return $this->getObject($mock, $type, $callOriginalConstructor, $callAutoload, $arguments, $callOriginalMethods, $proxyTarget, $returnValueGeneration);
  47833. }
  47834. /**
  47835. * Returns a mock object for the specified abstract class with all abstract
  47836. * methods of the class mocked. Concrete methods to mock can be specified with
  47837. * the $mockedMethods parameter
  47838. *
  47839. * @psalm-template RealInstanceType of object
  47840. * @psalm-param class-string<RealInstanceType> $originalClassName
  47841. * @psalm-return MockObject&RealInstanceType
  47842. *
  47843. * @throws RuntimeException
  47844. */
  47845. public function getMockForAbstractClass(string $originalClassName, array $arguments = [], string $mockClassName = '', bool $callOriginalConstructor = \true, bool $callOriginalClone = \true, bool $callAutoload = \true, array $mockedMethods = null, bool $cloneArguments = \true) : \PHPUnit\Framework\MockObject\MockObject
  47846. {
  47847. if (\class_exists($originalClassName, $callAutoload) || \interface_exists($originalClassName, $callAutoload)) {
  47848. try {
  47849. $reflector = new \ReflectionClass($originalClassName);
  47850. // @codeCoverageIgnoreStart
  47851. } catch (\ReflectionException $e) {
  47852. throw new \PHPUnit\Framework\MockObject\RuntimeException($e->getMessage(), (int) $e->getCode(), $e);
  47853. }
  47854. // @codeCoverageIgnoreEnd
  47855. $methods = $mockedMethods;
  47856. foreach ($reflector->getMethods() as $method) {
  47857. if ($method->isAbstract() && !\in_array($method->getName(), $methods ?? [], \true)) {
  47858. $methods[] = $method->getName();
  47859. }
  47860. }
  47861. if (empty($methods)) {
  47862. $methods = null;
  47863. }
  47864. return $this->getMock($originalClassName, $methods, $arguments, $mockClassName, $callOriginalConstructor, $callOriginalClone, $callAutoload, $cloneArguments);
  47865. }
  47866. throw new \PHPUnit\Framework\MockObject\RuntimeException(\sprintf('Class "%s" does not exist.', $originalClassName));
  47867. }
  47868. /**
  47869. * Returns a mock object for the specified trait with all abstract methods
  47870. * of the trait mocked. Concrete methods to mock can be specified with the
  47871. * `$mockedMethods` parameter.
  47872. *
  47873. * @throws RuntimeException
  47874. */
  47875. public function getMockForTrait(string $traitName, array $arguments = [], string $mockClassName = '', bool $callOriginalConstructor = \true, bool $callOriginalClone = \true, bool $callAutoload = \true, array $mockedMethods = null, bool $cloneArguments = \true) : \PHPUnit\Framework\MockObject\MockObject
  47876. {
  47877. if (!\trait_exists($traitName, $callAutoload)) {
  47878. throw new \PHPUnit\Framework\MockObject\RuntimeException(\sprintf('Trait "%s" does not exist.', $traitName));
  47879. }
  47880. $className = $this->generateClassName($traitName, '', 'Trait_');
  47881. $classTemplate = $this->getTemplate('trait_class.tpl');
  47882. $classTemplate->setVar(['prologue' => 'abstract ', 'class_name' => $className['className'], 'trait_name' => $traitName]);
  47883. $mockTrait = new \PHPUnit\Framework\MockObject\MockTrait($classTemplate->render(), $className['className']);
  47884. $mockTrait->generate();
  47885. return $this->getMockForAbstractClass($className['className'], $arguments, $mockClassName, $callOriginalConstructor, $callOriginalClone, $callAutoload, $mockedMethods, $cloneArguments);
  47886. }
  47887. /**
  47888. * Returns an object for the specified trait.
  47889. *
  47890. * @throws RuntimeException
  47891. */
  47892. public function getObjectForTrait(string $traitName, string $traitClassName = '', bool $callAutoload = \true, bool $callOriginalConstructor = \false, array $arguments = []) : object
  47893. {
  47894. if (!\trait_exists($traitName, $callAutoload)) {
  47895. throw new \PHPUnit\Framework\MockObject\RuntimeException(\sprintf('Trait "%s" does not exist.', $traitName));
  47896. }
  47897. $className = $this->generateClassName($traitName, $traitClassName, 'Trait_');
  47898. $classTemplate = $this->getTemplate('trait_class.tpl');
  47899. $classTemplate->setVar(['prologue' => '', 'class_name' => $className['className'], 'trait_name' => $traitName]);
  47900. return $this->getObject(new \PHPUnit\Framework\MockObject\MockTrait($classTemplate->render(), $className['className']), '', $callOriginalConstructor, $callAutoload, $arguments);
  47901. }
  47902. public function generate(string $type, array $methods = null, string $mockClassName = '', bool $callOriginalClone = \true, bool $callAutoload = \true, bool $cloneArguments = \true, bool $callOriginalMethods = \false) : \PHPUnit\Framework\MockObject\MockClass
  47903. {
  47904. if ($mockClassName !== '') {
  47905. return $this->generateMock($type, $methods, $mockClassName, $callOriginalClone, $callAutoload, $cloneArguments, $callOriginalMethods);
  47906. }
  47907. $key = \md5($type . \serialize($methods) . \serialize($callOriginalClone) . \serialize($cloneArguments) . \serialize($callOriginalMethods));
  47908. if (!isset(self::$cache[$key])) {
  47909. self::$cache[$key] = $this->generateMock($type, $methods, $mockClassName, $callOriginalClone, $callAutoload, $cloneArguments, $callOriginalMethods);
  47910. }
  47911. return self::$cache[$key];
  47912. }
  47913. /**
  47914. * @throws RuntimeException
  47915. */
  47916. public function generateClassFromWsdl(string $wsdlFile, string $className, array $methods = [], array $options = []) : string
  47917. {
  47918. if (!\extension_loaded('soap')) {
  47919. throw new \PHPUnit\Framework\MockObject\RuntimeException('The SOAP extension is required to generate a mock object from WSDL.');
  47920. }
  47921. $options = \array_merge($options, ['cache_wsdl' => \WSDL_CACHE_NONE]);
  47922. try {
  47923. $client = new \SoapClient($wsdlFile, $options);
  47924. $_methods = \array_unique($client->__getFunctions());
  47925. unset($client);
  47926. } catch (\SoapFault $e) {
  47927. throw new \PHPUnit\Framework\MockObject\RuntimeException($e->getMessage(), (int) $e->getCode(), $e);
  47928. }
  47929. \sort($_methods);
  47930. $methodTemplate = $this->getTemplate('wsdl_method.tpl');
  47931. $methodsBuffer = '';
  47932. foreach ($_methods as $method) {
  47933. \preg_match_all('/[a-zA-Z_\\x7f-\\xff][a-zA-Z0-9_\\x7f-\\xff]*\\(/', $method, $matches, \PREG_OFFSET_CAPTURE);
  47934. $lastFunction = \array_pop($matches[0]);
  47935. $nameStart = $lastFunction[1];
  47936. $nameEnd = $nameStart + \strlen($lastFunction[0]) - 1;
  47937. $name = \str_replace('(', '', $lastFunction[0]);
  47938. if (empty($methods) || \in_array($name, $methods, \true)) {
  47939. $args = \explode(',', \str_replace(')', '', \substr($method, $nameEnd + 1)));
  47940. foreach (\range(0, \count($args) - 1) as $i) {
  47941. $args[$i] = \substr($args[$i], \strpos($args[$i], '$'));
  47942. }
  47943. $methodTemplate->setVar(['method_name' => $name, 'arguments' => \implode(', ', $args)]);
  47944. $methodsBuffer .= $methodTemplate->render();
  47945. }
  47946. }
  47947. $optionsBuffer = '[';
  47948. foreach ($options as $key => $value) {
  47949. $optionsBuffer .= $key . ' => ' . $value;
  47950. }
  47951. $optionsBuffer .= ']';
  47952. $classTemplate = $this->getTemplate('wsdl_class.tpl');
  47953. $namespace = '';
  47954. if (\strpos($className, '\\') !== \false) {
  47955. $parts = \explode('\\', $className);
  47956. $className = \array_pop($parts);
  47957. $namespace = 'namespace ' . \implode('\\', $parts) . ';' . "\n\n";
  47958. }
  47959. $classTemplate->setVar(['namespace' => $namespace, 'class_name' => $className, 'wsdl' => $wsdlFile, 'options' => $optionsBuffer, 'methods' => $methodsBuffer]);
  47960. return $classTemplate->render();
  47961. }
  47962. /**
  47963. * @throws RuntimeException
  47964. *
  47965. * @return string[]
  47966. */
  47967. public function getClassMethods(string $className) : array
  47968. {
  47969. try {
  47970. $class = new \ReflectionClass($className);
  47971. // @codeCoverageIgnoreStart
  47972. } catch (\ReflectionException $e) {
  47973. throw new \PHPUnit\Framework\MockObject\RuntimeException($e->getMessage(), (int) $e->getCode(), $e);
  47974. }
  47975. // @codeCoverageIgnoreEnd
  47976. $methods = [];
  47977. foreach ($class->getMethods() as $method) {
  47978. if ($method->isPublic() || $method->isAbstract()) {
  47979. $methods[] = $method->getName();
  47980. }
  47981. }
  47982. return $methods;
  47983. }
  47984. /**
  47985. * @throws RuntimeException
  47986. *
  47987. * @return MockMethod[]
  47988. */
  47989. public function mockClassMethods(string $className, bool $callOriginalMethods, bool $cloneArguments) : array
  47990. {
  47991. try {
  47992. $class = new \ReflectionClass($className);
  47993. // @codeCoverageIgnoreStart
  47994. } catch (\ReflectionException $e) {
  47995. throw new \PHPUnit\Framework\MockObject\RuntimeException($e->getMessage(), (int) $e->getCode(), $e);
  47996. }
  47997. // @codeCoverageIgnoreEnd
  47998. $methods = [];
  47999. foreach ($class->getMethods() as $method) {
  48000. if (($method->isPublic() || $method->isAbstract()) && $this->canMockMethod($method)) {
  48001. $methods[] = \PHPUnit\Framework\MockObject\MockMethod::fromReflection($method, $callOriginalMethods, $cloneArguments);
  48002. }
  48003. }
  48004. return $methods;
  48005. }
  48006. /**
  48007. * @throws RuntimeException
  48008. *
  48009. * @return MockMethod[]
  48010. */
  48011. public function mockInterfaceMethods(string $interfaceName, bool $cloneArguments) : array
  48012. {
  48013. try {
  48014. $class = new \ReflectionClass($interfaceName);
  48015. // @codeCoverageIgnoreStart
  48016. } catch (\ReflectionException $e) {
  48017. throw new \PHPUnit\Framework\MockObject\RuntimeException($e->getMessage(), (int) $e->getCode(), $e);
  48018. }
  48019. // @codeCoverageIgnoreEnd
  48020. $methods = [];
  48021. foreach ($class->getMethods() as $method) {
  48022. $methods[] = \PHPUnit\Framework\MockObject\MockMethod::fromReflection($method, \false, $cloneArguments);
  48023. }
  48024. return $methods;
  48025. }
  48026. /**
  48027. * @psalm-param class-string $interfaceName
  48028. *
  48029. * @return \ReflectionMethod[]
  48030. */
  48031. private function userDefinedInterfaceMethods(string $interfaceName) : array
  48032. {
  48033. try {
  48034. // @codeCoverageIgnoreStart
  48035. $interface = new \ReflectionClass($interfaceName);
  48036. } catch (\ReflectionException $e) {
  48037. throw new \PHPUnit\Framework\MockObject\RuntimeException($e->getMessage(), (int) $e->getCode(), $e);
  48038. }
  48039. // @codeCoverageIgnoreEnd
  48040. $methods = [];
  48041. foreach ($interface->getMethods() as $method) {
  48042. if (!$method->isUserDefined()) {
  48043. continue;
  48044. }
  48045. $methods[] = $method;
  48046. }
  48047. return $methods;
  48048. }
  48049. private function getObject(\PHPUnit\Framework\MockObject\MockType $mockClass, $type = '', bool $callOriginalConstructor = \false, bool $callAutoload = \false, array $arguments = [], bool $callOriginalMethods = \false, object $proxyTarget = null, bool $returnValueGeneration = \true)
  48050. {
  48051. $className = $mockClass->generate();
  48052. if ($callOriginalConstructor) {
  48053. if (\count($arguments) === 0) {
  48054. $object = new $className();
  48055. } else {
  48056. try {
  48057. $class = new \ReflectionClass($className);
  48058. // @codeCoverageIgnoreStart
  48059. } catch (\ReflectionException $e) {
  48060. throw new \PHPUnit\Framework\MockObject\RuntimeException($e->getMessage(), (int) $e->getCode(), $e);
  48061. }
  48062. // @codeCoverageIgnoreEnd
  48063. $object = $class->newInstanceArgs($arguments);
  48064. }
  48065. } else {
  48066. try {
  48067. $object = (new \PHPUnit\Doctrine\Instantiator\Instantiator())->instantiate($className);
  48068. } catch (\PHPUnit\Doctrine\Instantiator\Exception\ExceptionInterface $exception) {
  48069. throw new \PHPUnit\Framework\MockObject\RuntimeException($exception->getMessage());
  48070. }
  48071. }
  48072. if ($callOriginalMethods) {
  48073. if (!\is_object($proxyTarget)) {
  48074. if (\count($arguments) === 0) {
  48075. $proxyTarget = new $type();
  48076. } else {
  48077. try {
  48078. $class = new \ReflectionClass($type);
  48079. // @codeCoverageIgnoreStart
  48080. } catch (\ReflectionException $e) {
  48081. throw new \PHPUnit\Framework\MockObject\RuntimeException($e->getMessage(), (int) $e->getCode(), $e);
  48082. }
  48083. // @codeCoverageIgnoreEnd
  48084. $proxyTarget = $class->newInstanceArgs($arguments);
  48085. }
  48086. }
  48087. $object->__phpunit_setOriginalObject($proxyTarget);
  48088. }
  48089. if ($object instanceof \PHPUnit\Framework\MockObject\MockObject) {
  48090. $object->__phpunit_setReturnValueGeneration($returnValueGeneration);
  48091. }
  48092. return $object;
  48093. }
  48094. /**
  48095. * @throws RuntimeException
  48096. */
  48097. private function generateMock(string $type, ?array $explicitMethods, string $mockClassName, bool $callOriginalClone, bool $callAutoload, bool $cloneArguments, bool $callOriginalMethods) : \PHPUnit\Framework\MockObject\MockClass
  48098. {
  48099. $classTemplate = $this->getTemplate('mocked_class.tpl');
  48100. $additionalInterfaces = [];
  48101. $mockedCloneMethod = \false;
  48102. $unmockedCloneMethod = \false;
  48103. $isClass = \false;
  48104. $isInterface = \false;
  48105. $class = null;
  48106. $mockMethods = new \PHPUnit\Framework\MockObject\MockMethodSet();
  48107. $_mockClassName = $this->generateClassName($type, $mockClassName, 'Mock_');
  48108. if (\class_exists($_mockClassName['fullClassName'], $callAutoload)) {
  48109. $isClass = \true;
  48110. } elseif (\interface_exists($_mockClassName['fullClassName'], $callAutoload)) {
  48111. $isInterface = \true;
  48112. }
  48113. if (!$isClass && !$isInterface) {
  48114. $prologue = 'class ' . $_mockClassName['originalClassName'] . "\n{\n}\n\n";
  48115. if (!empty($_mockClassName['namespaceName'])) {
  48116. $prologue = 'namespace ' . $_mockClassName['namespaceName'] . " {\n\n" . $prologue . "}\n\n" . "namespace {\n\n";
  48117. $epilogue = "\n\n}";
  48118. }
  48119. $mockedCloneMethod = \true;
  48120. } else {
  48121. try {
  48122. $class = new \ReflectionClass($_mockClassName['fullClassName']);
  48123. // @codeCoverageIgnoreStart
  48124. } catch (\ReflectionException $e) {
  48125. throw new \PHPUnit\Framework\MockObject\RuntimeException($e->getMessage(), (int) $e->getCode(), $e);
  48126. }
  48127. // @codeCoverageIgnoreEnd
  48128. if ($class->isFinal()) {
  48129. throw new \PHPUnit\Framework\MockObject\RuntimeException(\sprintf('Class "%s" is declared "final" and cannot be mocked.', $_mockClassName['fullClassName']));
  48130. }
  48131. // @see https://github.com/sebastianbergmann/phpunit/issues/2995
  48132. if ($isInterface && $class->implementsInterface(\Throwable::class)) {
  48133. $actualClassName = \Exception::class;
  48134. $additionalInterfaces[] = $class->getName();
  48135. $isInterface = \false;
  48136. try {
  48137. $class = new \ReflectionClass($actualClassName);
  48138. // @codeCoverageIgnoreStart
  48139. } catch (\ReflectionException $e) {
  48140. throw new \PHPUnit\Framework\MockObject\RuntimeException($e->getMessage(), (int) $e->getCode(), $e);
  48141. }
  48142. // @codeCoverageIgnoreEnd
  48143. foreach ($this->userDefinedInterfaceMethods($_mockClassName['fullClassName']) as $method) {
  48144. $methodName = $method->getName();
  48145. if ($class->hasMethod($methodName)) {
  48146. try {
  48147. $classMethod = $class->getMethod($methodName);
  48148. // @codeCoverageIgnoreStart
  48149. } catch (\ReflectionException $e) {
  48150. throw new \PHPUnit\Framework\MockObject\RuntimeException($e->getMessage(), (int) $e->getCode(), $e);
  48151. }
  48152. // @codeCoverageIgnoreEnd
  48153. if (!$this->canMockMethod($classMethod)) {
  48154. continue;
  48155. }
  48156. }
  48157. $mockMethods->addMethods(\PHPUnit\Framework\MockObject\MockMethod::fromReflection($method, $callOriginalMethods, $cloneArguments));
  48158. }
  48159. $_mockClassName = $this->generateClassName($actualClassName, $_mockClassName['className'], 'Mock_');
  48160. }
  48161. // @see https://github.com/sebastianbergmann/phpunit-mock-objects/issues/103
  48162. if ($isInterface && $class->implementsInterface(\Traversable::class) && !$class->implementsInterface(\Iterator::class) && !$class->implementsInterface(\IteratorAggregate::class)) {
  48163. $additionalInterfaces[] = \Iterator::class;
  48164. $mockMethods->addMethods(...$this->mockClassMethods(\Iterator::class, $callOriginalMethods, $cloneArguments));
  48165. }
  48166. if ($class->hasMethod('__clone')) {
  48167. try {
  48168. $cloneMethod = $class->getMethod('__clone');
  48169. // @codeCoverageIgnoreStart
  48170. } catch (\ReflectionException $e) {
  48171. throw new \PHPUnit\Framework\MockObject\RuntimeException($e->getMessage(), (int) $e->getCode(), $e);
  48172. }
  48173. // @codeCoverageIgnoreEnd
  48174. if (!$cloneMethod->isFinal()) {
  48175. if ($callOriginalClone && !$isInterface) {
  48176. $unmockedCloneMethod = \true;
  48177. } else {
  48178. $mockedCloneMethod = \true;
  48179. }
  48180. }
  48181. } else {
  48182. $mockedCloneMethod = \true;
  48183. }
  48184. }
  48185. if ($isClass && $explicitMethods === []) {
  48186. $mockMethods->addMethods(...$this->mockClassMethods($_mockClassName['fullClassName'], $callOriginalMethods, $cloneArguments));
  48187. }
  48188. if ($isInterface && ($explicitMethods === [] || $explicitMethods === null)) {
  48189. $mockMethods->addMethods(...$this->mockInterfaceMethods($_mockClassName['fullClassName'], $cloneArguments));
  48190. }
  48191. if (\is_array($explicitMethods)) {
  48192. foreach ($explicitMethods as $methodName) {
  48193. if ($class !== null && $class->hasMethod($methodName)) {
  48194. try {
  48195. $method = $class->getMethod($methodName);
  48196. // @codeCoverageIgnoreStart
  48197. } catch (\ReflectionException $e) {
  48198. throw new \PHPUnit\Framework\MockObject\RuntimeException($e->getMessage(), (int) $e->getCode(), $e);
  48199. }
  48200. // @codeCoverageIgnoreEnd
  48201. if ($this->canMockMethod($method)) {
  48202. $mockMethods->addMethods(\PHPUnit\Framework\MockObject\MockMethod::fromReflection($method, $callOriginalMethods, $cloneArguments));
  48203. }
  48204. } else {
  48205. $mockMethods->addMethods(\PHPUnit\Framework\MockObject\MockMethod::fromName($_mockClassName['fullClassName'], $methodName, $cloneArguments));
  48206. }
  48207. }
  48208. }
  48209. $mockedMethods = '';
  48210. $configurable = [];
  48211. foreach ($mockMethods->asArray() as $mockMethod) {
  48212. $mockedMethods .= $mockMethod->generateCode();
  48213. $configurable[] = new \PHPUnit\Framework\MockObject\ConfigurableMethod($mockMethod->getName(), $mockMethod->getReturnType());
  48214. }
  48215. $method = '';
  48216. if (!$mockMethods->hasMethod('method') && (!isset($class) || !$class->hasMethod('method'))) {
  48217. $method = \PHP_EOL . ' use \\PHPUnit\\Framework\\MockObject\\Method;';
  48218. }
  48219. $cloneTrait = '';
  48220. if ($mockedCloneMethod) {
  48221. $cloneTrait = \PHP_EOL . ' use \\PHPUnit\\Framework\\MockObject\\MockedCloneMethod;';
  48222. }
  48223. if ($unmockedCloneMethod) {
  48224. $cloneTrait = \PHP_EOL . ' use \\PHPUnit\\Framework\\MockObject\\UnmockedCloneMethod;';
  48225. }
  48226. $classTemplate->setVar(['prologue' => $prologue ?? '', 'epilogue' => $epilogue ?? '', 'class_declaration' => $this->generateMockClassDeclaration($_mockClassName, $isInterface, $additionalInterfaces), 'clone' => $cloneTrait, 'mock_class_name' => $_mockClassName['className'], 'mocked_methods' => $mockedMethods, 'method' => $method]);
  48227. return new \PHPUnit\Framework\MockObject\MockClass($classTemplate->render(), $_mockClassName['className'], $configurable);
  48228. }
  48229. private function generateClassName(string $type, string $className, string $prefix) : array
  48230. {
  48231. if ($type[0] === '\\') {
  48232. $type = \substr($type, 1);
  48233. }
  48234. $classNameParts = \explode('\\', $type);
  48235. if (\count($classNameParts) > 1) {
  48236. $type = \array_pop($classNameParts);
  48237. $namespaceName = \implode('\\', $classNameParts);
  48238. $fullClassName = $namespaceName . '\\' . $type;
  48239. } else {
  48240. $namespaceName = '';
  48241. $fullClassName = $type;
  48242. }
  48243. if ($className === '') {
  48244. do {
  48245. $className = $prefix . $type . '_' . \substr(\md5((string) \mt_rand()), 0, 8);
  48246. } while (\class_exists($className, \false));
  48247. }
  48248. return ['className' => $className, 'originalClassName' => $type, 'fullClassName' => $fullClassName, 'namespaceName' => $namespaceName];
  48249. }
  48250. private function generateMockClassDeclaration(array $mockClassName, bool $isInterface, array $additionalInterfaces = []) : string
  48251. {
  48252. $buffer = 'class ';
  48253. $additionalInterfaces[] = \PHPUnit\Framework\MockObject\MockObject::class;
  48254. $interfaces = \implode(', ', $additionalInterfaces);
  48255. if ($isInterface) {
  48256. $buffer .= \sprintf('%s implements %s', $mockClassName['className'], $interfaces);
  48257. if (!\in_array($mockClassName['originalClassName'], $additionalInterfaces, \true)) {
  48258. $buffer .= ', ';
  48259. if (!empty($mockClassName['namespaceName'])) {
  48260. $buffer .= $mockClassName['namespaceName'] . '\\';
  48261. }
  48262. $buffer .= $mockClassName['originalClassName'];
  48263. }
  48264. } else {
  48265. $buffer .= \sprintf('%s extends %s%s implements %s', $mockClassName['className'], !empty($mockClassName['namespaceName']) ? $mockClassName['namespaceName'] . '\\' : '', $mockClassName['originalClassName'], $interfaces);
  48266. }
  48267. return $buffer;
  48268. }
  48269. private function canMockMethod(\ReflectionMethod $method) : bool
  48270. {
  48271. return !($this->isConstructor($method) || $method->isFinal() || $method->isPrivate() || $this->isMethodNameBlacklisted($method->getName()));
  48272. }
  48273. private function isMethodNameBlacklisted(string $name) : bool
  48274. {
  48275. return isset(self::BLACKLISTED_METHOD_NAMES[$name]);
  48276. }
  48277. private function getTemplate(string $template) : \PHPUnit\SebastianBergmann\Template\Template
  48278. {
  48279. $filename = __DIR__ . \DIRECTORY_SEPARATOR . 'Generator' . \DIRECTORY_SEPARATOR . $template;
  48280. if (!isset(self::$templates[$filename])) {
  48281. self::$templates[$filename] = new \PHPUnit\SebastianBergmann\Template\Template($filename);
  48282. }
  48283. return self::$templates[$filename];
  48284. }
  48285. /**
  48286. * @see https://github.com/sebastianbergmann/phpunit/issues/4139#issuecomment-605409765
  48287. */
  48288. private function isConstructor(\ReflectionMethod $method) : bool
  48289. {
  48290. $methodName = \strtolower($method->getName());
  48291. if ($methodName === '__construct') {
  48292. return \true;
  48293. }
  48294. if (\PHP_MAJOR_VERSION >= 8) {
  48295. return \false;
  48296. }
  48297. $className = \strtolower($method->getDeclaringClass()->getName());
  48298. return $methodName === $className;
  48299. }
  48300. }
  48301. {modifier} function {reference}{method_name}({arguments_decl}){return_declaration}
  48302. {{deprecation}
  48303. $__phpunit_arguments = [{arguments_call}];
  48304. $__phpunit_count = func_num_args();
  48305. if ($__phpunit_count > {arguments_count}) {
  48306. $__phpunit_arguments_tmp = func_get_args();
  48307. for ($__phpunit_i = {arguments_count}; $__phpunit_i < $__phpunit_count; $__phpunit_i++) {
  48308. $__phpunit_arguments[] = $__phpunit_arguments_tmp[$__phpunit_i];
  48309. }
  48310. }
  48311. $this->__phpunit_getInvocationHandler()->invoke(
  48312. new \PHPUnit\Framework\MockObject\Invocation(
  48313. '{class_name}', '{method_name}', $__phpunit_arguments, '{return_type}', $this, {clone_arguments}
  48314. )
  48315. );
  48316. }
  48317. declare(strict_types=1);
  48318. {prologue}{class_declaration}
  48319. {
  48320. use \PHPUnit\Framework\MockObject\Api;{method}{clone}
  48321. {mocked_methods}}{epilogue}
  48322. {modifier} function {reference}{method_name}({arguments_decl}){return_declaration}
  48323. {{deprecation}
  48324. $__phpunit_arguments = [{arguments_call}];
  48325. $__phpunit_count = func_num_args();
  48326. if ($__phpunit_count > {arguments_count}) {
  48327. $__phpunit_arguments_tmp = func_get_args();
  48328. for ($__phpunit_i = {arguments_count}; $__phpunit_i < $__phpunit_count; $__phpunit_i++) {
  48329. $__phpunit_arguments[] = $__phpunit_arguments_tmp[$__phpunit_i];
  48330. }
  48331. }
  48332. $__phpunit_result = $this->__phpunit_getInvocationHandler()->invoke(
  48333. new \PHPUnit\Framework\MockObject\Invocation(
  48334. '{class_name}', '{method_name}', $__phpunit_arguments, '{return_type}', $this, {clone_arguments}
  48335. )
  48336. );
  48337. return $__phpunit_result;
  48338. }
  48339. public function {method_name}({arguments})
  48340. {
  48341. }
  48342. declare(strict_types=1);
  48343. {namespace}class {class_name} extends \SoapClient
  48344. {
  48345. public function __construct($wsdl, array $options)
  48346. {
  48347. parent::__construct('{wsdl}', $options);
  48348. }
  48349. {methods}}
  48350. {modifier} function {reference}{method_name}({arguments_decl}){return_declaration}
  48351. {
  48352. $__phpunit_arguments = [{arguments_call}];
  48353. $__phpunit_count = func_num_args();
  48354. if ($__phpunit_count > {arguments_count}) {
  48355. $__phpunit_arguments_tmp = func_get_args();
  48356. for ($__phpunit_i = {arguments_count}; $__phpunit_i < $__phpunit_count; $__phpunit_i++) {
  48357. $__phpunit_arguments[] = $__phpunit_arguments_tmp[$__phpunit_i];
  48358. }
  48359. }
  48360. $this->__phpunit_getInvocationHandler()->invoke(
  48361. new \PHPUnit\Framework\MockObject\Invocation(
  48362. '{class_name}', '{method_name}', $__phpunit_arguments, '{return_type}', $this, {clone_arguments}, true
  48363. )
  48364. );
  48365. return call_user_func_array(array($this->__phpunit_originalObject, "{method_name}"), $__phpunit_arguments);
  48366. }
  48367. {modifier} function {reference}{method_name}({arguments_decl}){return_declaration}
  48368. {
  48369. $__phpunit_arguments = [{arguments_call}];
  48370. $__phpunit_count = func_num_args();
  48371. if ($__phpunit_count > {arguments_count}) {
  48372. $__phpunit_arguments_tmp = func_get_args();
  48373. for ($__phpunit_i = {arguments_count}; $__phpunit_i < $__phpunit_count; $__phpunit_i++) {
  48374. $__phpunit_arguments[] = $__phpunit_arguments_tmp[$__phpunit_i];
  48375. }
  48376. }
  48377. $this->__phpunit_getInvocationHandler()->invoke(
  48378. new \PHPUnit\Framework\MockObject\Invocation(
  48379. '{class_name}', '{method_name}', $__phpunit_arguments, '{return_type}', $this, {clone_arguments}, true
  48380. )
  48381. );
  48382. call_user_func_array(array($this->__phpunit_originalObject, "{method_name}"), $__phpunit_arguments);
  48383. }
  48384. {modifier} function {reference}{method_name}({arguments_decl}){return_declaration}
  48385. {
  48386. throw new \PHPUnit\Framework\MockObject\BadMethodCallException('Static method "{method_name}" cannot be invoked on mock object');
  48387. }
  48388. declare(strict_types=1);
  48389. {prologue}class {class_name}
  48390. {
  48391. use {trait_name};
  48392. }
  48393. @trigger_error({deprecation}, E_USER_DEPRECATED);
  48394. <?php
  48395. declare (strict_types=1);
  48396. /*
  48397. * This file is part of PHPUnit.
  48398. *
  48399. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  48400. *
  48401. * For the full copyright and license information, please view the LICENSE
  48402. * file that was distributed with this source code.
  48403. */
  48404. namespace PHPUnit\Framework\MockObject;
  48405. use PHPUnit\Framework\TestCase;
  48406. /**
  48407. * @psalm-template MockedType
  48408. */
  48409. final class MockBuilder
  48410. {
  48411. /**
  48412. * @var TestCase
  48413. */
  48414. private $testCase;
  48415. /**
  48416. * @var string
  48417. */
  48418. private $type;
  48419. /**
  48420. * @var null|string[]
  48421. */
  48422. private $methods = [];
  48423. /**
  48424. * @var bool
  48425. */
  48426. private $emptyMethodsArray = \false;
  48427. /**
  48428. * @var string
  48429. */
  48430. private $mockClassName = '';
  48431. /**
  48432. * @var array
  48433. */
  48434. private $constructorArgs = [];
  48435. /**
  48436. * @var bool
  48437. */
  48438. private $originalConstructor = \true;
  48439. /**
  48440. * @var bool
  48441. */
  48442. private $originalClone = \true;
  48443. /**
  48444. * @var bool
  48445. */
  48446. private $autoload = \true;
  48447. /**
  48448. * @var bool
  48449. */
  48450. private $cloneArguments = \false;
  48451. /**
  48452. * @var bool
  48453. */
  48454. private $callOriginalMethods = \false;
  48455. /**
  48456. * @var ?object
  48457. */
  48458. private $proxyTarget;
  48459. /**
  48460. * @var bool
  48461. */
  48462. private $allowMockingUnknownTypes = \true;
  48463. /**
  48464. * @var bool
  48465. */
  48466. private $returnValueGeneration = \true;
  48467. /**
  48468. * @var Generator
  48469. */
  48470. private $generator;
  48471. /**
  48472. * @param string|string[] $type
  48473. *
  48474. * @psalm-param class-string<MockedType>|string|string[] $type
  48475. */
  48476. public function __construct(\PHPUnit\Framework\TestCase $testCase, $type)
  48477. {
  48478. $this->testCase = $testCase;
  48479. $this->type = $type;
  48480. $this->generator = new \PHPUnit\Framework\MockObject\Generator();
  48481. }
  48482. /**
  48483. * Creates a mock object using a fluent interface.
  48484. *
  48485. * @throws RuntimeException
  48486. *
  48487. * @psalm-return MockObject&MockedType
  48488. */
  48489. public function getMock() : \PHPUnit\Framework\MockObject\MockObject
  48490. {
  48491. $object = $this->generator->getMock($this->type, !$this->emptyMethodsArray ? $this->methods : null, $this->constructorArgs, $this->mockClassName, $this->originalConstructor, $this->originalClone, $this->autoload, $this->cloneArguments, $this->callOriginalMethods, $this->proxyTarget, $this->allowMockingUnknownTypes, $this->returnValueGeneration);
  48492. $this->testCase->registerMockObject($object);
  48493. return $object;
  48494. }
  48495. /**
  48496. * Creates a mock object for an abstract class using a fluent interface.
  48497. *
  48498. * @throws \PHPUnit\Framework\Exception
  48499. * @throws RuntimeException
  48500. *
  48501. * @psalm-return MockObject&MockedType
  48502. */
  48503. public function getMockForAbstractClass() : \PHPUnit\Framework\MockObject\MockObject
  48504. {
  48505. $object = $this->generator->getMockForAbstractClass($this->type, $this->constructorArgs, $this->mockClassName, $this->originalConstructor, $this->originalClone, $this->autoload, $this->methods, $this->cloneArguments);
  48506. $this->testCase->registerMockObject($object);
  48507. return $object;
  48508. }
  48509. /**
  48510. * Creates a mock object for a trait using a fluent interface.
  48511. *
  48512. * @throws \PHPUnit\Framework\Exception
  48513. * @throws RuntimeException
  48514. *
  48515. * @psalm-return MockObject&MockedType
  48516. */
  48517. public function getMockForTrait() : \PHPUnit\Framework\MockObject\MockObject
  48518. {
  48519. $object = $this->generator->getMockForTrait($this->type, $this->constructorArgs, $this->mockClassName, $this->originalConstructor, $this->originalClone, $this->autoload, $this->methods, $this->cloneArguments);
  48520. $this->testCase->registerMockObject($object);
  48521. return $object;
  48522. }
  48523. /**
  48524. * Specifies the subset of methods to mock. Default is to mock none of them.
  48525. *
  48526. * @deprecated https://github.com/sebastianbergmann/phpunit/pull/3687
  48527. *
  48528. * @return $this
  48529. */
  48530. public function setMethods(?array $methods = null) : self
  48531. {
  48532. if ($methods === null) {
  48533. $this->methods = $methods;
  48534. } else {
  48535. $this->methods = \array_merge($this->methods ?? [], $methods);
  48536. }
  48537. return $this;
  48538. }
  48539. /**
  48540. * Specifies the subset of methods to mock, requiring each to exist in the class
  48541. *
  48542. * @param string[] $methods
  48543. *
  48544. * @throws RuntimeException
  48545. *
  48546. * @return $this
  48547. */
  48548. public function onlyMethods(array $methods) : self
  48549. {
  48550. if (empty($methods)) {
  48551. $this->emptyMethodsArray = \true;
  48552. return $this;
  48553. }
  48554. try {
  48555. $reflector = new \ReflectionClass($this->type);
  48556. // @codeCoverageIgnoreStart
  48557. } catch (\ReflectionException $e) {
  48558. throw new \PHPUnit\Framework\MockObject\RuntimeException($e->getMessage(), (int) $e->getCode(), $e);
  48559. }
  48560. // @codeCoverageIgnoreEnd
  48561. foreach ($methods as $method) {
  48562. if (!$reflector->hasMethod($method)) {
  48563. throw new \PHPUnit\Framework\MockObject\RuntimeException(\sprintf('Trying to set mock method "%s" with onlyMethods, but it does not exist in class "%s". Use addMethods() for methods that don\'t exist in the class.', $method, $this->type));
  48564. }
  48565. }
  48566. $this->methods = \array_merge($this->methods ?? [], $methods);
  48567. return $this;
  48568. }
  48569. /**
  48570. * Specifies methods that don't exist in the class which you want to mock
  48571. *
  48572. * @param string[] $methods
  48573. *
  48574. * @throws RuntimeException
  48575. *
  48576. * @return $this
  48577. */
  48578. public function addMethods(array $methods) : self
  48579. {
  48580. if (empty($methods)) {
  48581. $this->emptyMethodsArray = \true;
  48582. return $this;
  48583. }
  48584. try {
  48585. $reflector = new \ReflectionClass($this->type);
  48586. // @codeCoverageIgnoreStart
  48587. } catch (\ReflectionException $e) {
  48588. throw new \PHPUnit\Framework\MockObject\RuntimeException($e->getMessage(), (int) $e->getCode(), $e);
  48589. }
  48590. // @codeCoverageIgnoreEnd
  48591. foreach ($methods as $method) {
  48592. if ($reflector->hasMethod($method)) {
  48593. throw new \PHPUnit\Framework\MockObject\RuntimeException(\sprintf('Trying to set mock method "%s" with addMethods(), but it exists in class "%s". Use onlyMethods() for methods that exist in the class.', $method, $this->type));
  48594. }
  48595. }
  48596. $this->methods = \array_merge($this->methods ?? [], $methods);
  48597. return $this;
  48598. }
  48599. /**
  48600. * Specifies the subset of methods to not mock. Default is to mock all of them.
  48601. */
  48602. public function setMethodsExcept(array $methods = []) : self
  48603. {
  48604. return $this->setMethods(\array_diff($this->generator->getClassMethods($this->type), $methods));
  48605. }
  48606. /**
  48607. * Specifies the arguments for the constructor.
  48608. *
  48609. * @return $this
  48610. */
  48611. public function setConstructorArgs(array $args) : self
  48612. {
  48613. $this->constructorArgs = $args;
  48614. return $this;
  48615. }
  48616. /**
  48617. * Specifies the name for the mock class.
  48618. *
  48619. * @return $this
  48620. */
  48621. public function setMockClassName(string $name) : self
  48622. {
  48623. $this->mockClassName = $name;
  48624. return $this;
  48625. }
  48626. /**
  48627. * Disables the invocation of the original constructor.
  48628. *
  48629. * @return $this
  48630. */
  48631. public function disableOriginalConstructor() : self
  48632. {
  48633. $this->originalConstructor = \false;
  48634. return $this;
  48635. }
  48636. /**
  48637. * Enables the invocation of the original constructor.
  48638. *
  48639. * @return $this
  48640. */
  48641. public function enableOriginalConstructor() : self
  48642. {
  48643. $this->originalConstructor = \true;
  48644. return $this;
  48645. }
  48646. /**
  48647. * Disables the invocation of the original clone constructor.
  48648. *
  48649. * @return $this
  48650. */
  48651. public function disableOriginalClone() : self
  48652. {
  48653. $this->originalClone = \false;
  48654. return $this;
  48655. }
  48656. /**
  48657. * Enables the invocation of the original clone constructor.
  48658. *
  48659. * @return $this
  48660. */
  48661. public function enableOriginalClone() : self
  48662. {
  48663. $this->originalClone = \true;
  48664. return $this;
  48665. }
  48666. /**
  48667. * Disables the use of class autoloading while creating the mock object.
  48668. *
  48669. * @return $this
  48670. */
  48671. public function disableAutoload() : self
  48672. {
  48673. $this->autoload = \false;
  48674. return $this;
  48675. }
  48676. /**
  48677. * Enables the use of class autoloading while creating the mock object.
  48678. *
  48679. * @return $this
  48680. */
  48681. public function enableAutoload() : self
  48682. {
  48683. $this->autoload = \true;
  48684. return $this;
  48685. }
  48686. /**
  48687. * Disables the cloning of arguments passed to mocked methods.
  48688. *
  48689. * @return $this
  48690. */
  48691. public function disableArgumentCloning() : self
  48692. {
  48693. $this->cloneArguments = \false;
  48694. return $this;
  48695. }
  48696. /**
  48697. * Enables the cloning of arguments passed to mocked methods.
  48698. *
  48699. * @return $this
  48700. */
  48701. public function enableArgumentCloning() : self
  48702. {
  48703. $this->cloneArguments = \true;
  48704. return $this;
  48705. }
  48706. /**
  48707. * Enables the invocation of the original methods.
  48708. *
  48709. * @return $this
  48710. */
  48711. public function enableProxyingToOriginalMethods() : self
  48712. {
  48713. $this->callOriginalMethods = \true;
  48714. return $this;
  48715. }
  48716. /**
  48717. * Disables the invocation of the original methods.
  48718. *
  48719. * @return $this
  48720. */
  48721. public function disableProxyingToOriginalMethods() : self
  48722. {
  48723. $this->callOriginalMethods = \false;
  48724. $this->proxyTarget = null;
  48725. return $this;
  48726. }
  48727. /**
  48728. * Sets the proxy target.
  48729. *
  48730. * @return $this
  48731. */
  48732. public function setProxyTarget(object $object) : self
  48733. {
  48734. $this->proxyTarget = $object;
  48735. return $this;
  48736. }
  48737. /**
  48738. * @return $this
  48739. */
  48740. public function allowMockingUnknownTypes() : self
  48741. {
  48742. $this->allowMockingUnknownTypes = \true;
  48743. return $this;
  48744. }
  48745. /**
  48746. * @return $this
  48747. */
  48748. public function disallowMockingUnknownTypes() : self
  48749. {
  48750. $this->allowMockingUnknownTypes = \false;
  48751. return $this;
  48752. }
  48753. /**
  48754. * @return $this
  48755. */
  48756. public function enableAutoReturnValueGeneration() : self
  48757. {
  48758. $this->returnValueGeneration = \true;
  48759. return $this;
  48760. }
  48761. /**
  48762. * @return $this
  48763. */
  48764. public function disableAutoReturnValueGeneration() : self
  48765. {
  48766. $this->returnValueGeneration = \false;
  48767. return $this;
  48768. }
  48769. }
  48770. <?php
  48771. declare (strict_types=1);
  48772. /*
  48773. * This file is part of PHPUnit.
  48774. *
  48775. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  48776. *
  48777. * For the full copyright and license information, please view the LICENSE
  48778. * file that was distributed with this source code.
  48779. */
  48780. namespace PHPUnit\Framework\MockObject;
  48781. /**
  48782. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  48783. */
  48784. final class MockMethodSet
  48785. {
  48786. /**
  48787. * @var MockMethod[]
  48788. */
  48789. private $methods = [];
  48790. public function addMethods(\PHPUnit\Framework\MockObject\MockMethod ...$methods) : void
  48791. {
  48792. foreach ($methods as $method) {
  48793. $this->methods[\strtolower($method->getName())] = $method;
  48794. }
  48795. }
  48796. /**
  48797. * @return MockMethod[]
  48798. */
  48799. public function asArray() : array
  48800. {
  48801. return \array_values($this->methods);
  48802. }
  48803. public function hasMethod(string $methodName) : bool
  48804. {
  48805. return \array_key_exists(\strtolower($methodName), $this->methods);
  48806. }
  48807. }
  48808. <?php
  48809. declare (strict_types=1);
  48810. /*
  48811. * This file is part of PHPUnit.
  48812. *
  48813. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  48814. *
  48815. * For the full copyright and license information, please view the LICENSE
  48816. * file that was distributed with this source code.
  48817. */
  48818. namespace PHPUnit\Framework\MockObject;
  48819. use PHPUnit\Framework\SelfDescribing;
  48820. use PHPUnit\Util\Type;
  48821. use PHPUnit\SebastianBergmann\Exporter\Exporter;
  48822. /**
  48823. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  48824. */
  48825. final class Invocation implements \PHPUnit\Framework\SelfDescribing
  48826. {
  48827. /**
  48828. * @var string
  48829. */
  48830. private $className;
  48831. /**
  48832. * @var string
  48833. */
  48834. private $methodName;
  48835. /**
  48836. * @var array
  48837. */
  48838. private $parameters;
  48839. /**
  48840. * @var string
  48841. */
  48842. private $returnType;
  48843. /**
  48844. * @var bool
  48845. */
  48846. private $isReturnTypeNullable = \false;
  48847. /**
  48848. * @var bool
  48849. */
  48850. private $proxiedCall;
  48851. /**
  48852. * @var object
  48853. */
  48854. private $object;
  48855. public function __construct(string $className, string $methodName, array $parameters, string $returnType, object $object, bool $cloneObjects = \false, bool $proxiedCall = \false)
  48856. {
  48857. $this->className = $className;
  48858. $this->methodName = $methodName;
  48859. $this->parameters = $parameters;
  48860. $this->object = $object;
  48861. $this->proxiedCall = $proxiedCall;
  48862. if (\strtolower($methodName) === '__tostring') {
  48863. $returnType = 'string';
  48864. }
  48865. if (\strpos($returnType, '?') === 0) {
  48866. $returnType = \substr($returnType, 1);
  48867. $this->isReturnTypeNullable = \true;
  48868. }
  48869. $this->returnType = $returnType;
  48870. if (!$cloneObjects) {
  48871. return;
  48872. }
  48873. foreach ($this->parameters as $key => $value) {
  48874. if (\is_object($value)) {
  48875. $this->parameters[$key] = $this->cloneObject($value);
  48876. }
  48877. }
  48878. }
  48879. public function getClassName() : string
  48880. {
  48881. return $this->className;
  48882. }
  48883. public function getMethodName() : string
  48884. {
  48885. return $this->methodName;
  48886. }
  48887. public function getParameters() : array
  48888. {
  48889. return $this->parameters;
  48890. }
  48891. /**
  48892. * @throws RuntimeException
  48893. *
  48894. * @return mixed Mocked return value
  48895. */
  48896. public function generateReturnValue()
  48897. {
  48898. if ($this->isReturnTypeNullable || $this->proxiedCall) {
  48899. return;
  48900. }
  48901. $returnType = $this->returnType;
  48902. if (\strpos($returnType, '|') !== \false) {
  48903. $types = \explode('|', $returnType);
  48904. $returnType = $types[0];
  48905. foreach ($types as $type) {
  48906. if ($type === 'null') {
  48907. return;
  48908. }
  48909. }
  48910. }
  48911. switch (\strtolower($returnType)) {
  48912. case '':
  48913. case 'void':
  48914. return;
  48915. case 'string':
  48916. return '';
  48917. case 'float':
  48918. return 0.0;
  48919. case 'int':
  48920. return 0;
  48921. case 'bool':
  48922. return \false;
  48923. case 'array':
  48924. return [];
  48925. case 'object':
  48926. return new \stdClass();
  48927. case 'callable':
  48928. case 'closure':
  48929. return static function () : void {
  48930. };
  48931. case 'traversable':
  48932. case 'generator':
  48933. case 'iterable':
  48934. $generator = static function () {
  48935. yield;
  48936. };
  48937. return $generator();
  48938. default:
  48939. $generator = new \PHPUnit\Framework\MockObject\Generator();
  48940. return $generator->getMock($this->returnType, [], [], '', \false);
  48941. }
  48942. }
  48943. public function toString() : string
  48944. {
  48945. $exporter = new \PHPUnit\SebastianBergmann\Exporter\Exporter();
  48946. return \sprintf('%s::%s(%s)%s', $this->className, $this->methodName, \implode(', ', \array_map([$exporter, 'shortenedExport'], $this->parameters)), $this->returnType ? \sprintf(': %s', $this->returnType) : '');
  48947. }
  48948. public function getObject() : object
  48949. {
  48950. return $this->object;
  48951. }
  48952. private function cloneObject(object $original) : object
  48953. {
  48954. if (\PHPUnit\Util\Type::isCloneable($original)) {
  48955. return clone $original;
  48956. }
  48957. return $original;
  48958. }
  48959. }
  48960. <?php
  48961. declare (strict_types=1);
  48962. /*
  48963. * This file is part of PHPUnit.
  48964. *
  48965. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  48966. *
  48967. * For the full copyright and license information, please view the LICENSE
  48968. * file that was distributed with this source code.
  48969. */
  48970. namespace PHPUnit\Framework\MockObject;
  48971. use PHPUnit\SebastianBergmann\Template\Template;
  48972. use PHPUnit\SebastianBergmann\Type\ReflectionMapper;
  48973. use PHPUnit\SebastianBergmann\Type\Type;
  48974. use PHPUnit\SebastianBergmann\Type\UnknownType;
  48975. use PHPUnit\SebastianBergmann\Type\VoidType;
  48976. /**
  48977. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  48978. */
  48979. final class MockMethod
  48980. {
  48981. /**
  48982. * @var Template[]
  48983. */
  48984. private static $templates = [];
  48985. /**
  48986. * @var string
  48987. */
  48988. private $className;
  48989. /**
  48990. * @var string
  48991. */
  48992. private $methodName;
  48993. /**
  48994. * @var bool
  48995. */
  48996. private $cloneArguments;
  48997. /**
  48998. * @var string string
  48999. */
  49000. private $modifier;
  49001. /**
  49002. * @var string
  49003. */
  49004. private $argumentsForDeclaration;
  49005. /**
  49006. * @var string
  49007. */
  49008. private $argumentsForCall;
  49009. /**
  49010. * @var Type
  49011. */
  49012. private $returnType;
  49013. /**
  49014. * @var string
  49015. */
  49016. private $reference;
  49017. /**
  49018. * @var bool
  49019. */
  49020. private $callOriginalMethod;
  49021. /**
  49022. * @var bool
  49023. */
  49024. private $static;
  49025. /**
  49026. * @var ?string
  49027. */
  49028. private $deprecation;
  49029. /**
  49030. * @var bool
  49031. */
  49032. private $allowsReturnNull;
  49033. /**
  49034. * @throws RuntimeException
  49035. */
  49036. public static function fromReflection(\ReflectionMethod $method, bool $callOriginalMethod, bool $cloneArguments) : self
  49037. {
  49038. if ($method->isPrivate()) {
  49039. $modifier = 'private';
  49040. } elseif ($method->isProtected()) {
  49041. $modifier = 'protected';
  49042. } else {
  49043. $modifier = 'public';
  49044. }
  49045. if ($method->isStatic()) {
  49046. $modifier .= ' static';
  49047. }
  49048. if ($method->returnsReference()) {
  49049. $reference = '&';
  49050. } else {
  49051. $reference = '';
  49052. }
  49053. $docComment = $method->getDocComment();
  49054. if (\is_string($docComment) && \preg_match('#\\*[ \\t]*+@deprecated[ \\t]*+(.*?)\\r?+\\n[ \\t]*+\\*(?:[ \\t]*+@|/$)#s', $docComment, $deprecation)) {
  49055. $deprecation = \trim(\preg_replace('#[ \\t]*\\r?\\n[ \\t]*+\\*[ \\t]*+#', ' ', $deprecation[1]));
  49056. } else {
  49057. $deprecation = null;
  49058. }
  49059. return new self($method->getDeclaringClass()->getName(), $method->getName(), $cloneArguments, $modifier, self::getMethodParameters($method), self::getMethodParameters($method, \true), (new \PHPUnit\SebastianBergmann\Type\ReflectionMapper())->fromMethodReturnType($method), $reference, $callOriginalMethod, $method->isStatic(), $deprecation, $method->hasReturnType() && $method->getReturnType()->allowsNull());
  49060. }
  49061. public static function fromName(string $fullClassName, string $methodName, bool $cloneArguments) : self
  49062. {
  49063. return new self($fullClassName, $methodName, $cloneArguments, 'public', '', '', new \PHPUnit\SebastianBergmann\Type\UnknownType(), '', \false, \false, null, \false);
  49064. }
  49065. public function __construct(string $className, string $methodName, bool $cloneArguments, string $modifier, string $argumentsForDeclaration, string $argumentsForCall, \PHPUnit\SebastianBergmann\Type\Type $returnType, string $reference, bool $callOriginalMethod, bool $static, ?string $deprecation, bool $allowsReturnNull)
  49066. {
  49067. $this->className = $className;
  49068. $this->methodName = $methodName;
  49069. $this->cloneArguments = $cloneArguments;
  49070. $this->modifier = $modifier;
  49071. $this->argumentsForDeclaration = $argumentsForDeclaration;
  49072. $this->argumentsForCall = $argumentsForCall;
  49073. $this->returnType = $returnType;
  49074. $this->reference = $reference;
  49075. $this->callOriginalMethod = $callOriginalMethod;
  49076. $this->static = $static;
  49077. $this->deprecation = $deprecation;
  49078. $this->allowsReturnNull = $allowsReturnNull;
  49079. }
  49080. public function getName() : string
  49081. {
  49082. return $this->methodName;
  49083. }
  49084. /**
  49085. * @throws RuntimeException
  49086. */
  49087. public function generateCode() : string
  49088. {
  49089. if ($this->static) {
  49090. $templateFile = 'mocked_static_method.tpl';
  49091. } elseif ($this->returnType instanceof \PHPUnit\SebastianBergmann\Type\VoidType) {
  49092. $templateFile = \sprintf('%s_method_void.tpl', $this->callOriginalMethod ? 'proxied' : 'mocked');
  49093. } else {
  49094. $templateFile = \sprintf('%s_method.tpl', $this->callOriginalMethod ? 'proxied' : 'mocked');
  49095. }
  49096. $deprecation = $this->deprecation;
  49097. if (null !== $this->deprecation) {
  49098. $deprecation = "The {$this->className}::{$this->methodName} method is deprecated ({$this->deprecation}).";
  49099. $deprecationTemplate = $this->getTemplate('deprecation.tpl');
  49100. $deprecationTemplate->setVar(['deprecation' => \var_export($deprecation, \true)]);
  49101. $deprecation = $deprecationTemplate->render();
  49102. }
  49103. $template = $this->getTemplate($templateFile);
  49104. $template->setVar(['arguments_decl' => $this->argumentsForDeclaration, 'arguments_call' => $this->argumentsForCall, 'return_declaration' => !empty($this->returnType->asString()) ? ': ' . $this->returnType->asString() : '', 'return_type' => $this->returnType->asString(), 'arguments_count' => !empty($this->argumentsForCall) ? \substr_count($this->argumentsForCall, ',') + 1 : 0, 'class_name' => $this->className, 'method_name' => $this->methodName, 'modifier' => $this->modifier, 'reference' => $this->reference, 'clone_arguments' => $this->cloneArguments ? 'true' : 'false', 'deprecation' => $deprecation]);
  49105. return $template->render();
  49106. }
  49107. public function getReturnType() : \PHPUnit\SebastianBergmann\Type\Type
  49108. {
  49109. return $this->returnType;
  49110. }
  49111. private function getTemplate(string $template) : \PHPUnit\SebastianBergmann\Template\Template
  49112. {
  49113. $filename = __DIR__ . \DIRECTORY_SEPARATOR . 'Generator' . \DIRECTORY_SEPARATOR . $template;
  49114. if (!isset(self::$templates[$filename])) {
  49115. self::$templates[$filename] = new \PHPUnit\SebastianBergmann\Template\Template($filename);
  49116. }
  49117. return self::$templates[$filename];
  49118. }
  49119. /**
  49120. * Returns the parameters of a function or method.
  49121. *
  49122. * @throws RuntimeException
  49123. */
  49124. private static function getMethodParameters(\ReflectionMethod $method, bool $forCall = \false) : string
  49125. {
  49126. $parameters = [];
  49127. foreach ($method->getParameters() as $i => $parameter) {
  49128. $name = '$' . $parameter->getName();
  49129. /* Note: PHP extensions may use empty names for reference arguments
  49130. * or "..." for methods taking a variable number of arguments.
  49131. */
  49132. if ($name === '$' || $name === '$...') {
  49133. $name = '$arg' . $i;
  49134. }
  49135. if ($parameter->isVariadic()) {
  49136. if ($forCall) {
  49137. continue;
  49138. }
  49139. $name = '...' . $name;
  49140. }
  49141. $nullable = '';
  49142. $default = '';
  49143. $reference = '';
  49144. $typeDeclaration = '';
  49145. if (!$forCall) {
  49146. if ($parameter->hasType() && $parameter->allowsNull()) {
  49147. $nullable = '?';
  49148. }
  49149. if ($parameter->hasType()) {
  49150. $type = $parameter->getType();
  49151. if ($type instanceof \ReflectionNamedType) {
  49152. if ($type->getName() !== 'self') {
  49153. $typeDeclaration = $type->getName() . ' ';
  49154. } else {
  49155. $typeDeclaration = $method->getDeclaringClass()->getName() . ' ';
  49156. }
  49157. } elseif ($type instanceof \ReflectionUnionType) {
  49158. $types = [];
  49159. foreach ($type->getTypes() as $_type) {
  49160. if ($_type === 'self') {
  49161. $types[] = $method->getDeclaringClass()->getName();
  49162. } else {
  49163. $types[] = $_type;
  49164. }
  49165. }
  49166. $typeDeclaration = \implode('|', $types) . ' ';
  49167. }
  49168. }
  49169. if (!$parameter->isVariadic()) {
  49170. if ($parameter->isDefaultValueAvailable()) {
  49171. try {
  49172. $value = \var_export($parameter->getDefaultValue(), \true);
  49173. // @codeCoverageIgnoreStart
  49174. } catch (\ReflectionException $e) {
  49175. throw new \PHPUnit\Framework\MockObject\RuntimeException($e->getMessage(), (int) $e->getCode(), $e);
  49176. }
  49177. // @codeCoverageIgnoreEnd
  49178. $default = ' = ' . $value;
  49179. } elseif ($parameter->isOptional()) {
  49180. $default = ' = null';
  49181. }
  49182. }
  49183. }
  49184. if ($parameter->isPassedByReference()) {
  49185. $reference = '&';
  49186. }
  49187. $parameters[] = $nullable . $typeDeclaration . $reference . $name . $default;
  49188. }
  49189. return \implode(', ', $parameters);
  49190. }
  49191. }
  49192. <?php
  49193. declare (strict_types=1);
  49194. /*
  49195. * This file is part of PHPUnit.
  49196. *
  49197. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  49198. *
  49199. * For the full copyright and license information, please view the LICENSE
  49200. * file that was distributed with this source code.
  49201. */
  49202. namespace PHPUnit\Framework\MockObject;
  49203. use PHPUnit\Framework\Constraint\Constraint;
  49204. /**
  49205. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  49206. */
  49207. final class MethodNameConstraint extends \PHPUnit\Framework\Constraint\Constraint
  49208. {
  49209. /**
  49210. * @var string
  49211. */
  49212. private $methodName;
  49213. public function __construct(string $methodName)
  49214. {
  49215. $this->methodName = $methodName;
  49216. }
  49217. public function toString() : string
  49218. {
  49219. return \sprintf('is "%s"', $this->methodName);
  49220. }
  49221. protected function matches($other) : bool
  49222. {
  49223. if (!\is_string($other)) {
  49224. return \false;
  49225. }
  49226. return \strtolower($this->methodName) === \strtolower($other);
  49227. }
  49228. }
  49229. <?php
  49230. declare (strict_types=1);
  49231. /*
  49232. * This file is part of PHPUnit.
  49233. *
  49234. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  49235. *
  49236. * For the full copyright and license information, please view the LICENSE
  49237. * file that was distributed with this source code.
  49238. */
  49239. namespace PHPUnit\Framework\MockObject\Rule;
  49240. use PHPUnit\Framework\Constraint\Constraint;
  49241. use PHPUnit\Framework\Constraint\IsEqual;
  49242. use PHPUnit\Framework\ExpectationFailedException;
  49243. use PHPUnit\Framework\InvalidParameterGroupException;
  49244. use PHPUnit\Framework\MockObject\Invocation as BaseInvocation;
  49245. /**
  49246. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  49247. */
  49248. final class ConsecutiveParameters implements \PHPUnit\Framework\MockObject\Rule\ParametersRule
  49249. {
  49250. /**
  49251. * @var array
  49252. */
  49253. private $parameterGroups = [];
  49254. /**
  49255. * @var array
  49256. */
  49257. private $invocations = [];
  49258. /**
  49259. * @throws \PHPUnit\Framework\Exception
  49260. */
  49261. public function __construct(array $parameterGroups)
  49262. {
  49263. foreach ($parameterGroups as $index => $parameters) {
  49264. if (!\is_iterable($parameters)) {
  49265. throw new \PHPUnit\Framework\InvalidParameterGroupException(\sprintf('Parameter group #%d must be an array or Traversable, got %s', $index, \gettype($parameters)));
  49266. }
  49267. foreach ($parameters as $parameter) {
  49268. if (!$parameter instanceof \PHPUnit\Framework\Constraint\Constraint) {
  49269. $parameter = new \PHPUnit\Framework\Constraint\IsEqual($parameter);
  49270. }
  49271. $this->parameterGroups[$index][] = $parameter;
  49272. }
  49273. }
  49274. }
  49275. public function toString() : string
  49276. {
  49277. return 'with consecutive parameters';
  49278. }
  49279. /**
  49280. * @throws ExpectationFailedException
  49281. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  49282. */
  49283. public function apply(\PHPUnit\Framework\MockObject\Invocation $invocation) : void
  49284. {
  49285. $this->invocations[] = $invocation;
  49286. $callIndex = \count($this->invocations) - 1;
  49287. $this->verifyInvocation($invocation, $callIndex);
  49288. }
  49289. /**
  49290. * @throws \PHPUnit\Framework\ExpectationFailedException
  49291. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  49292. */
  49293. public function verify() : void
  49294. {
  49295. foreach ($this->invocations as $callIndex => $invocation) {
  49296. $this->verifyInvocation($invocation, $callIndex);
  49297. }
  49298. }
  49299. /**
  49300. * Verify a single invocation
  49301. *
  49302. * @param int $callIndex
  49303. *
  49304. * @throws ExpectationFailedException
  49305. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  49306. */
  49307. private function verifyInvocation(\PHPUnit\Framework\MockObject\Invocation $invocation, $callIndex) : void
  49308. {
  49309. if (!isset($this->parameterGroups[$callIndex])) {
  49310. // no parameter assertion for this call index
  49311. return;
  49312. }
  49313. if ($invocation === null) {
  49314. throw new \PHPUnit\Framework\ExpectationFailedException('Mocked method does not exist.');
  49315. }
  49316. $parameters = $this->parameterGroups[$callIndex];
  49317. if (\count($invocation->getParameters()) < \count($parameters)) {
  49318. throw new \PHPUnit\Framework\ExpectationFailedException(\sprintf('Parameter count for invocation %s is too low.', $invocation->toString()));
  49319. }
  49320. foreach ($parameters as $i => $parameter) {
  49321. $parameter->evaluate($invocation->getParameters()[$i], \sprintf('Parameter %s for invocation #%d %s does not match expected ' . 'value.', $i, $callIndex, $invocation->toString()));
  49322. }
  49323. }
  49324. }
  49325. <?php
  49326. declare (strict_types=1);
  49327. /*
  49328. * This file is part of PHPUnit.
  49329. *
  49330. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  49331. *
  49332. * For the full copyright and license information, please view the LICENSE
  49333. * file that was distributed with this source code.
  49334. */
  49335. namespace PHPUnit\Framework\MockObject\Rule;
  49336. use PHPUnit\Framework\Constraint\Constraint;
  49337. use PHPUnit\Framework\InvalidArgumentException;
  49338. use PHPUnit\Framework\MockObject\Invocation as BaseInvocation;
  49339. use PHPUnit\Framework\MockObject\MethodNameConstraint;
  49340. /**
  49341. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  49342. */
  49343. final class MethodName
  49344. {
  49345. /**
  49346. * @var Constraint
  49347. */
  49348. private $constraint;
  49349. /**
  49350. * @param Constraint|string $constraint
  49351. *
  49352. * @throws InvalidArgumentException
  49353. */
  49354. public function __construct($constraint)
  49355. {
  49356. if (\is_string($constraint)) {
  49357. $constraint = new \PHPUnit\Framework\MockObject\MethodNameConstraint($constraint);
  49358. }
  49359. if (!$constraint instanceof \PHPUnit\Framework\Constraint\Constraint) {
  49360. throw \PHPUnit\Framework\InvalidArgumentException::create(1, 'PHPUnit\\Framework\\Constraint\\Constraint object or string');
  49361. }
  49362. $this->constraint = $constraint;
  49363. }
  49364. public function toString() : string
  49365. {
  49366. return 'method name ' . $this->constraint->toString();
  49367. }
  49368. /**
  49369. * @throws \PHPUnit\Framework\ExpectationFailedException
  49370. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  49371. */
  49372. public function matches(\PHPUnit\Framework\MockObject\Invocation $invocation) : bool
  49373. {
  49374. return $this->matchesName($invocation->getMethodName());
  49375. }
  49376. public function matchesName(string $methodName) : bool
  49377. {
  49378. return (bool) $this->constraint->evaluate($methodName, '', \true);
  49379. }
  49380. }
  49381. <?php
  49382. declare (strict_types=1);
  49383. /*
  49384. * This file is part of PHPUnit.
  49385. *
  49386. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  49387. *
  49388. * For the full copyright and license information, please view the LICENSE
  49389. * file that was distributed with this source code.
  49390. */
  49391. namespace PHPUnit\Framework\MockObject\Rule;
  49392. use PHPUnit\Framework\ExpectationFailedException;
  49393. use PHPUnit\Framework\MockObject\Invocation as BaseInvocation;
  49394. /**
  49395. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  49396. */
  49397. final class InvokedAtIndex extends \PHPUnit\Framework\MockObject\Rule\InvocationOrder
  49398. {
  49399. /**
  49400. * @var int
  49401. */
  49402. private $sequenceIndex;
  49403. /**
  49404. * @var int
  49405. */
  49406. private $currentIndex = -1;
  49407. /**
  49408. * @param int $sequenceIndex
  49409. */
  49410. public function __construct($sequenceIndex)
  49411. {
  49412. $this->sequenceIndex = $sequenceIndex;
  49413. }
  49414. public function toString() : string
  49415. {
  49416. return 'invoked at sequence index ' . $this->sequenceIndex;
  49417. }
  49418. public function matches(\PHPUnit\Framework\MockObject\Invocation $invocation) : bool
  49419. {
  49420. $this->currentIndex++;
  49421. return $this->currentIndex == $this->sequenceIndex;
  49422. }
  49423. /**
  49424. * Verifies that the current expectation is valid. If everything is OK the
  49425. * code should just return, if not it must throw an exception.
  49426. *
  49427. * @throws ExpectationFailedException
  49428. */
  49429. public function verify() : void
  49430. {
  49431. if ($this->currentIndex < $this->sequenceIndex) {
  49432. throw new \PHPUnit\Framework\ExpectationFailedException(\sprintf('The expected invocation at index %s was never reached.', $this->sequenceIndex));
  49433. }
  49434. }
  49435. protected function invokedDo(\PHPUnit\Framework\MockObject\Invocation $invocation) : void
  49436. {
  49437. }
  49438. }
  49439. <?php
  49440. declare (strict_types=1);
  49441. /*
  49442. * This file is part of PHPUnit.
  49443. *
  49444. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  49445. *
  49446. * For the full copyright and license information, please view the LICENSE
  49447. * file that was distributed with this source code.
  49448. */
  49449. namespace PHPUnit\Framework\MockObject\Rule;
  49450. use PHPUnit\Framework\MockObject\Invocation as BaseInvocation;
  49451. /**
  49452. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  49453. */
  49454. final class AnyParameters implements \PHPUnit\Framework\MockObject\Rule\ParametersRule
  49455. {
  49456. public function toString() : string
  49457. {
  49458. return 'with any parameters';
  49459. }
  49460. public function apply(\PHPUnit\Framework\MockObject\Invocation $invocation) : void
  49461. {
  49462. }
  49463. public function verify() : void
  49464. {
  49465. }
  49466. }
  49467. <?php
  49468. declare (strict_types=1);
  49469. /*
  49470. * This file is part of PHPUnit.
  49471. *
  49472. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  49473. *
  49474. * For the full copyright and license information, please view the LICENSE
  49475. * file that was distributed with this source code.
  49476. */
  49477. namespace PHPUnit\Framework\MockObject\Rule;
  49478. use PHPUnit\Framework\MockObject\Invocation as BaseInvocation;
  49479. use PHPUnit\Framework\MockObject\Verifiable;
  49480. use PHPUnit\Framework\SelfDescribing;
  49481. /**
  49482. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  49483. */
  49484. abstract class InvocationOrder implements \PHPUnit\Framework\SelfDescribing, \PHPUnit\Framework\MockObject\Verifiable
  49485. {
  49486. /**
  49487. * @var BaseInvocation[]
  49488. */
  49489. private $invocations = [];
  49490. public function getInvocationCount() : int
  49491. {
  49492. return \count($this->invocations);
  49493. }
  49494. public function hasBeenInvoked() : bool
  49495. {
  49496. return \count($this->invocations) > 0;
  49497. }
  49498. public final function invoked(\PHPUnit\Framework\MockObject\Invocation $invocation)
  49499. {
  49500. $this->invocations[] = $invocation;
  49501. return $this->invokedDo($invocation);
  49502. }
  49503. public abstract function matches(\PHPUnit\Framework\MockObject\Invocation $invocation) : bool;
  49504. protected abstract function invokedDo(\PHPUnit\Framework\MockObject\Invocation $invocation);
  49505. }
  49506. <?php
  49507. declare (strict_types=1);
  49508. /*
  49509. * This file is part of PHPUnit.
  49510. *
  49511. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  49512. *
  49513. * For the full copyright and license information, please view the LICENSE
  49514. * file that was distributed with this source code.
  49515. */
  49516. namespace PHPUnit\Framework\MockObject\Rule;
  49517. use PHPUnit\Framework\ExpectationFailedException;
  49518. use PHPUnit\Framework\MockObject\Invocation as BaseInvocation;
  49519. /**
  49520. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  49521. */
  49522. final class InvokedAtLeastOnce extends \PHPUnit\Framework\MockObject\Rule\InvocationOrder
  49523. {
  49524. public function toString() : string
  49525. {
  49526. return 'invoked at least once';
  49527. }
  49528. /**
  49529. * Verifies that the current expectation is valid. If everything is OK the
  49530. * code should just return, if not it must throw an exception.
  49531. *
  49532. * @throws ExpectationFailedException
  49533. */
  49534. public function verify() : void
  49535. {
  49536. $count = $this->getInvocationCount();
  49537. if ($count < 1) {
  49538. throw new \PHPUnit\Framework\ExpectationFailedException('Expected invocation at least once but it never occurred.');
  49539. }
  49540. }
  49541. public function matches(\PHPUnit\Framework\MockObject\Invocation $invocation) : bool
  49542. {
  49543. return \true;
  49544. }
  49545. protected function invokedDo(\PHPUnit\Framework\MockObject\Invocation $invocation) : void
  49546. {
  49547. }
  49548. }
  49549. <?php
  49550. declare (strict_types=1);
  49551. /*
  49552. * This file is part of PHPUnit.
  49553. *
  49554. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  49555. *
  49556. * For the full copyright and license information, please view the LICENSE
  49557. * file that was distributed with this source code.
  49558. */
  49559. namespace PHPUnit\Framework\MockObject\Rule;
  49560. use PHPUnit\Framework\ExpectationFailedException;
  49561. use PHPUnit\Framework\MockObject\Invocation as BaseInvocation;
  49562. /**
  49563. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  49564. */
  49565. final class InvokedAtMostCount extends \PHPUnit\Framework\MockObject\Rule\InvocationOrder
  49566. {
  49567. /**
  49568. * @var int
  49569. */
  49570. private $allowedInvocations;
  49571. /**
  49572. * @param int $allowedInvocations
  49573. */
  49574. public function __construct($allowedInvocations)
  49575. {
  49576. $this->allowedInvocations = $allowedInvocations;
  49577. }
  49578. public function toString() : string
  49579. {
  49580. return 'invoked at most ' . $this->allowedInvocations . ' times';
  49581. }
  49582. /**
  49583. * Verifies that the current expectation is valid. If everything is OK the
  49584. * code should just return, if not it must throw an exception.
  49585. *
  49586. * @throws ExpectationFailedException
  49587. */
  49588. public function verify() : void
  49589. {
  49590. $count = $this->getInvocationCount();
  49591. if ($count > $this->allowedInvocations) {
  49592. throw new \PHPUnit\Framework\ExpectationFailedException('Expected invocation at most ' . $this->allowedInvocations . ' times but it occurred ' . $count . ' time(s).');
  49593. }
  49594. }
  49595. public function matches(\PHPUnit\Framework\MockObject\Invocation $invocation) : bool
  49596. {
  49597. return \true;
  49598. }
  49599. protected function invokedDo(\PHPUnit\Framework\MockObject\Invocation $invocation) : void
  49600. {
  49601. }
  49602. }
  49603. <?php
  49604. declare (strict_types=1);
  49605. /*
  49606. * This file is part of PHPUnit.
  49607. *
  49608. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  49609. *
  49610. * For the full copyright and license information, please view the LICENSE
  49611. * file that was distributed with this source code.
  49612. */
  49613. namespace PHPUnit\Framework\MockObject\Rule;
  49614. use PHPUnit\Framework\ExpectationFailedException;
  49615. use PHPUnit\Framework\MockObject\Invocation as BaseInvocation;
  49616. /**
  49617. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  49618. */
  49619. final class InvokedAtLeastCount extends \PHPUnit\Framework\MockObject\Rule\InvocationOrder
  49620. {
  49621. /**
  49622. * @var int
  49623. */
  49624. private $requiredInvocations;
  49625. /**
  49626. * @param int $requiredInvocations
  49627. */
  49628. public function __construct($requiredInvocations)
  49629. {
  49630. $this->requiredInvocations = $requiredInvocations;
  49631. }
  49632. public function toString() : string
  49633. {
  49634. return 'invoked at least ' . $this->requiredInvocations . ' times';
  49635. }
  49636. /**
  49637. * Verifies that the current expectation is valid. If everything is OK the
  49638. * code should just return, if not it must throw an exception.
  49639. *
  49640. * @throws ExpectationFailedException
  49641. */
  49642. public function verify() : void
  49643. {
  49644. $count = $this->getInvocationCount();
  49645. if ($count < $this->requiredInvocations) {
  49646. throw new \PHPUnit\Framework\ExpectationFailedException('Expected invocation at least ' . $this->requiredInvocations . ' times but it occurred ' . $count . ' time(s).');
  49647. }
  49648. }
  49649. public function matches(\PHPUnit\Framework\MockObject\Invocation $invocation) : bool
  49650. {
  49651. return \true;
  49652. }
  49653. protected function invokedDo(\PHPUnit\Framework\MockObject\Invocation $invocation) : void
  49654. {
  49655. }
  49656. }
  49657. <?php
  49658. declare (strict_types=1);
  49659. /*
  49660. * This file is part of PHPUnit.
  49661. *
  49662. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  49663. *
  49664. * For the full copyright and license information, please view the LICENSE
  49665. * file that was distributed with this source code.
  49666. */
  49667. namespace PHPUnit\Framework\MockObject\Rule;
  49668. use PHPUnit\Framework\MockObject\Invocation as BaseInvocation;
  49669. /**
  49670. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  49671. */
  49672. final class AnyInvokedCount extends \PHPUnit\Framework\MockObject\Rule\InvocationOrder
  49673. {
  49674. public function toString() : string
  49675. {
  49676. return 'invoked zero or more times';
  49677. }
  49678. public function verify() : void
  49679. {
  49680. }
  49681. public function matches(\PHPUnit\Framework\MockObject\Invocation $invocation) : bool
  49682. {
  49683. return \true;
  49684. }
  49685. protected function invokedDo(\PHPUnit\Framework\MockObject\Invocation $invocation) : void
  49686. {
  49687. }
  49688. }
  49689. <?php
  49690. declare (strict_types=1);
  49691. /*
  49692. * This file is part of PHPUnit.
  49693. *
  49694. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  49695. *
  49696. * For the full copyright and license information, please view the LICENSE
  49697. * file that was distributed with this source code.
  49698. */
  49699. namespace PHPUnit\Framework\MockObject\Rule;
  49700. use PHPUnit\Framework\ExpectationFailedException;
  49701. use PHPUnit\Framework\MockObject\Invocation as BaseInvocation;
  49702. use PHPUnit\Framework\MockObject\Verifiable;
  49703. use PHPUnit\Framework\SelfDescribing;
  49704. interface ParametersRule extends \PHPUnit\Framework\SelfDescribing, \PHPUnit\Framework\MockObject\Verifiable
  49705. {
  49706. /**
  49707. * @throws ExpectationFailedException if the invocation violates the rule
  49708. */
  49709. public function apply(\PHPUnit\Framework\MockObject\Invocation $invocation) : void;
  49710. public function verify() : void;
  49711. }
  49712. <?php
  49713. declare (strict_types=1);
  49714. /*
  49715. * This file is part of PHPUnit.
  49716. *
  49717. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  49718. *
  49719. * For the full copyright and license information, please view the LICENSE
  49720. * file that was distributed with this source code.
  49721. */
  49722. namespace PHPUnit\Framework\MockObject\Rule;
  49723. use PHPUnit\Framework\ExpectationFailedException;
  49724. use PHPUnit\Framework\MockObject\Invocation as BaseInvocation;
  49725. /**
  49726. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  49727. */
  49728. final class InvokedCount extends \PHPUnit\Framework\MockObject\Rule\InvocationOrder
  49729. {
  49730. /**
  49731. * @var int
  49732. */
  49733. private $expectedCount;
  49734. /**
  49735. * @param int $expectedCount
  49736. */
  49737. public function __construct($expectedCount)
  49738. {
  49739. $this->expectedCount = $expectedCount;
  49740. }
  49741. public function isNever() : bool
  49742. {
  49743. return $this->expectedCount === 0;
  49744. }
  49745. public function toString() : string
  49746. {
  49747. return 'invoked ' . $this->expectedCount . ' time(s)';
  49748. }
  49749. public function matches(\PHPUnit\Framework\MockObject\Invocation $invocation) : bool
  49750. {
  49751. return \true;
  49752. }
  49753. /**
  49754. * Verifies that the current expectation is valid. If everything is OK the
  49755. * code should just return, if not it must throw an exception.
  49756. *
  49757. * @throws ExpectationFailedException
  49758. */
  49759. public function verify() : void
  49760. {
  49761. $count = $this->getInvocationCount();
  49762. if ($count !== $this->expectedCount) {
  49763. throw new \PHPUnit\Framework\ExpectationFailedException(\sprintf('Method was expected to be called %d times, ' . 'actually called %d times.', $this->expectedCount, $count));
  49764. }
  49765. }
  49766. /**
  49767. * @throws ExpectationFailedException
  49768. */
  49769. protected function invokedDo(\PHPUnit\Framework\MockObject\Invocation $invocation) : void
  49770. {
  49771. $count = $this->getInvocationCount();
  49772. if ($count > $this->expectedCount) {
  49773. $message = $invocation->toString() . ' ';
  49774. switch ($this->expectedCount) {
  49775. case 0:
  49776. $message .= 'was not expected to be called.';
  49777. break;
  49778. case 1:
  49779. $message .= 'was not expected to be called more than once.';
  49780. break;
  49781. default:
  49782. $message .= \sprintf('was not expected to be called more than %d times.', $this->expectedCount);
  49783. }
  49784. throw new \PHPUnit\Framework\ExpectationFailedException($message);
  49785. }
  49786. }
  49787. }
  49788. <?php
  49789. declare (strict_types=1);
  49790. /*
  49791. * This file is part of PHPUnit.
  49792. *
  49793. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  49794. *
  49795. * For the full copyright and license information, please view the LICENSE
  49796. * file that was distributed with this source code.
  49797. */
  49798. namespace PHPUnit\Framework\MockObject\Rule;
  49799. use PHPUnit\Framework\Constraint\Constraint;
  49800. use PHPUnit\Framework\Constraint\IsAnything;
  49801. use PHPUnit\Framework\Constraint\IsEqual;
  49802. use PHPUnit\Framework\ExpectationFailedException;
  49803. use PHPUnit\Framework\MockObject\Invocation as BaseInvocation;
  49804. /**
  49805. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  49806. */
  49807. final class Parameters implements \PHPUnit\Framework\MockObject\Rule\ParametersRule
  49808. {
  49809. /**
  49810. * @var Constraint[]
  49811. */
  49812. private $parameters = [];
  49813. /**
  49814. * @var BaseInvocation
  49815. */
  49816. private $invocation;
  49817. /**
  49818. * @var bool|ExpectationFailedException
  49819. */
  49820. private $parameterVerificationResult;
  49821. /**
  49822. * @throws \PHPUnit\Framework\Exception
  49823. */
  49824. public function __construct(array $parameters)
  49825. {
  49826. foreach ($parameters as $parameter) {
  49827. if (!$parameter instanceof \PHPUnit\Framework\Constraint\Constraint) {
  49828. $parameter = new \PHPUnit\Framework\Constraint\IsEqual($parameter);
  49829. }
  49830. $this->parameters[] = $parameter;
  49831. }
  49832. }
  49833. public function toString() : string
  49834. {
  49835. $text = 'with parameter';
  49836. foreach ($this->parameters as $index => $parameter) {
  49837. if ($index > 0) {
  49838. $text .= ' and';
  49839. }
  49840. $text .= ' ' . $index . ' ' . $parameter->toString();
  49841. }
  49842. return $text;
  49843. }
  49844. /**
  49845. * @throws \Exception
  49846. */
  49847. public function apply(\PHPUnit\Framework\MockObject\Invocation $invocation) : void
  49848. {
  49849. $this->invocation = $invocation;
  49850. $this->parameterVerificationResult = null;
  49851. try {
  49852. $this->parameterVerificationResult = $this->doVerify();
  49853. } catch (\PHPUnit\Framework\ExpectationFailedException $e) {
  49854. $this->parameterVerificationResult = $e;
  49855. throw $this->parameterVerificationResult;
  49856. }
  49857. }
  49858. /**
  49859. * Checks if the invocation $invocation matches the current rules. If it
  49860. * does the rule will get the invoked() method called which should check
  49861. * if an expectation is met.
  49862. *
  49863. * @throws ExpectationFailedException
  49864. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  49865. */
  49866. public function verify() : void
  49867. {
  49868. $this->doVerify();
  49869. }
  49870. /**
  49871. * @throws ExpectationFailedException
  49872. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  49873. */
  49874. private function doVerify() : bool
  49875. {
  49876. if (isset($this->parameterVerificationResult)) {
  49877. return $this->guardAgainstDuplicateEvaluationOfParameterConstraints();
  49878. }
  49879. if ($this->invocation === null) {
  49880. throw new \PHPUnit\Framework\ExpectationFailedException('Mocked method does not exist.');
  49881. }
  49882. if (\count($this->invocation->getParameters()) < \count($this->parameters)) {
  49883. $message = 'Parameter count for invocation %s is too low.';
  49884. // The user called `->with($this->anything())`, but may have meant
  49885. // `->withAnyParameters()`.
  49886. //
  49887. // @see https://github.com/sebastianbergmann/phpunit-mock-objects/issues/199
  49888. if (\count($this->parameters) === 1 && \get_class($this->parameters[0]) === \PHPUnit\Framework\Constraint\IsAnything::class) {
  49889. $message .= "\nTo allow 0 or more parameters with any value, omit ->with() or use ->withAnyParameters() instead.";
  49890. }
  49891. throw new \PHPUnit\Framework\ExpectationFailedException(\sprintf($message, $this->invocation->toString()));
  49892. }
  49893. foreach ($this->parameters as $i => $parameter) {
  49894. $parameter->evaluate($this->invocation->getParameters()[$i], \sprintf('Parameter %s for invocation %s does not match expected ' . 'value.', $i, $this->invocation->toString()));
  49895. }
  49896. return \true;
  49897. }
  49898. /**
  49899. * @throws ExpectationFailedException
  49900. */
  49901. private function guardAgainstDuplicateEvaluationOfParameterConstraints() : bool
  49902. {
  49903. if ($this->parameterVerificationResult instanceof \PHPUnit\Framework\ExpectationFailedException) {
  49904. throw $this->parameterVerificationResult;
  49905. }
  49906. return (bool) $this->parameterVerificationResult;
  49907. }
  49908. }
  49909. <?php
  49910. declare (strict_types=1);
  49911. /*
  49912. * This file is part of PHPUnit.
  49913. *
  49914. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  49915. *
  49916. * For the full copyright and license information, please view the LICENSE
  49917. * file that was distributed with this source code.
  49918. */
  49919. namespace PHPUnit\Framework\MockObject;
  49920. /**
  49921. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  49922. */
  49923. final class MockTrait implements \PHPUnit\Framework\MockObject\MockType
  49924. {
  49925. /**
  49926. * @var string
  49927. */
  49928. private $classCode;
  49929. /**
  49930. * @var string
  49931. */
  49932. private $mockName;
  49933. public function __construct(string $classCode, string $mockName)
  49934. {
  49935. $this->classCode = $classCode;
  49936. $this->mockName = $mockName;
  49937. }
  49938. public function generate() : string
  49939. {
  49940. if (!\class_exists($this->mockName, \false)) {
  49941. eval($this->classCode);
  49942. }
  49943. return $this->mockName;
  49944. }
  49945. public function getClassCode() : string
  49946. {
  49947. return $this->classCode;
  49948. }
  49949. }
  49950. <?php
  49951. declare (strict_types=1);
  49952. /*
  49953. * This file is part of PHPUnit.
  49954. *
  49955. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  49956. *
  49957. * For the full copyright and license information, please view the LICENSE
  49958. * file that was distributed with this source code.
  49959. */
  49960. namespace PHPUnit\Framework\MockObject;
  49961. use PHPUnit\SebastianBergmann\Type\Type;
  49962. /**
  49963. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  49964. */
  49965. final class ConfigurableMethod
  49966. {
  49967. /**
  49968. * @var string
  49969. */
  49970. private $name;
  49971. /**
  49972. * @var Type
  49973. */
  49974. private $returnType;
  49975. public function __construct(string $name, \PHPUnit\SebastianBergmann\Type\Type $returnType)
  49976. {
  49977. $this->name = $name;
  49978. $this->returnType = $returnType;
  49979. }
  49980. public function getName() : string
  49981. {
  49982. return $this->name;
  49983. }
  49984. public function mayReturn($value) : bool
  49985. {
  49986. if ($value === null && $this->returnType->allowsNull()) {
  49987. return \true;
  49988. }
  49989. return $this->returnType->isAssignable(\PHPUnit\SebastianBergmann\Type\Type::fromValue($value, \false));
  49990. }
  49991. public function getReturnTypeDeclaration() : string
  49992. {
  49993. return $this->returnType->asString();
  49994. }
  49995. }
  49996. <?php
  49997. declare (strict_types=1);
  49998. /*
  49999. * This file is part of PHPUnit.
  50000. *
  50001. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  50002. *
  50003. * For the full copyright and license information, please view the LICENSE
  50004. * file that was distributed with this source code.
  50005. */
  50006. namespace PHPUnit\Framework\MockObject;
  50007. use PHPUnit\Framework\ExpectationFailedException;
  50008. /**
  50009. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  50010. */
  50011. interface Verifiable
  50012. {
  50013. /**
  50014. * Verifies that the current expectation is valid. If everything is OK the
  50015. * code should just return, if not it must throw an exception.
  50016. *
  50017. * @throws ExpectationFailedException
  50018. */
  50019. public function verify() : void;
  50020. }
  50021. <?php
  50022. declare (strict_types=1);
  50023. /*
  50024. * This file is part of PHPUnit.
  50025. *
  50026. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  50027. *
  50028. * For the full copyright and license information, please view the LICENSE
  50029. * file that was distributed with this source code.
  50030. */
  50031. namespace PHPUnit\Framework\MockObject;
  50032. use PHPUnit\Framework\MockObject\Rule\AnyInvokedCount;
  50033. /**
  50034. * @internal This trait is not covered by the backward compatibility promise for PHPUnit
  50035. */
  50036. trait Method
  50037. {
  50038. public function method()
  50039. {
  50040. $expects = $this->expects(new \PHPUnit\Framework\MockObject\Rule\AnyInvokedCount());
  50041. return \call_user_func_array([$expects, 'method'], \func_get_args());
  50042. }
  50043. }
  50044. <?php
  50045. declare (strict_types=1);
  50046. /*
  50047. * This file is part of PHPUnit.
  50048. *
  50049. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  50050. *
  50051. * For the full copyright and license information, please view the LICENSE
  50052. * file that was distributed with this source code.
  50053. */
  50054. namespace PHPUnit\Framework\MockObject;
  50055. use PHPUnit\Framework\MockObject\Builder\InvocationMocker as InvocationMockerBuilder;
  50056. use PHPUnit\Framework\MockObject\Rule\InvocationOrder;
  50057. /**
  50058. * @internal This trait is not covered by the backward compatibility promise for PHPUnit
  50059. */
  50060. trait Api
  50061. {
  50062. /**
  50063. * @var ConfigurableMethod[]
  50064. */
  50065. private static $__phpunit_configurableMethods;
  50066. /**
  50067. * @var object
  50068. */
  50069. private $__phpunit_originalObject;
  50070. /**
  50071. * @var bool
  50072. */
  50073. private $__phpunit_returnValueGeneration = \true;
  50074. /**
  50075. * @var InvocationHandler
  50076. */
  50077. private $__phpunit_invocationMocker;
  50078. /** @noinspection MagicMethodsValidityInspection */
  50079. public static function __phpunit_initConfigurableMethods(\PHPUnit\Framework\MockObject\ConfigurableMethod ...$configurableMethods) : void
  50080. {
  50081. if (isset(static::$__phpunit_configurableMethods)) {
  50082. throw new \PHPUnit\Framework\MockObject\ConfigurableMethodsAlreadyInitializedException('Configurable methods is already initialized and can not be reinitialized');
  50083. }
  50084. static::$__phpunit_configurableMethods = $configurableMethods;
  50085. }
  50086. /** @noinspection MagicMethodsValidityInspection */
  50087. public function __phpunit_setOriginalObject($originalObject) : void
  50088. {
  50089. $this->__phpunit_originalObject = $originalObject;
  50090. }
  50091. /** @noinspection MagicMethodsValidityInspection */
  50092. public function __phpunit_setReturnValueGeneration(bool $returnValueGeneration) : void
  50093. {
  50094. $this->__phpunit_returnValueGeneration = $returnValueGeneration;
  50095. }
  50096. /** @noinspection MagicMethodsValidityInspection */
  50097. public function __phpunit_getInvocationHandler() : \PHPUnit\Framework\MockObject\InvocationHandler
  50098. {
  50099. if ($this->__phpunit_invocationMocker === null) {
  50100. $this->__phpunit_invocationMocker = new \PHPUnit\Framework\MockObject\InvocationHandler(static::$__phpunit_configurableMethods, $this->__phpunit_returnValueGeneration);
  50101. }
  50102. return $this->__phpunit_invocationMocker;
  50103. }
  50104. /** @noinspection MagicMethodsValidityInspection */
  50105. public function __phpunit_hasMatchers() : bool
  50106. {
  50107. return $this->__phpunit_getInvocationHandler()->hasMatchers();
  50108. }
  50109. /** @noinspection MagicMethodsValidityInspection */
  50110. public function __phpunit_verify(bool $unsetInvocationMocker = \true) : void
  50111. {
  50112. $this->__phpunit_getInvocationHandler()->verify();
  50113. if ($unsetInvocationMocker) {
  50114. $this->__phpunit_invocationMocker = null;
  50115. }
  50116. }
  50117. public function expects(\PHPUnit\Framework\MockObject\Rule\InvocationOrder $matcher) : \PHPUnit\Framework\MockObject\Builder\InvocationMocker
  50118. {
  50119. return $this->__phpunit_getInvocationHandler()->expects($matcher);
  50120. }
  50121. }
  50122. <?php
  50123. declare (strict_types=1);
  50124. /*
  50125. * This file is part of PHPUnit.
  50126. *
  50127. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  50128. *
  50129. * For the full copyright and license information, please view the LICENSE
  50130. * file that was distributed with this source code.
  50131. */
  50132. namespace PHPUnit\Framework\MockObject;
  50133. /**
  50134. * @internal This trait is not covered by the backward compatibility promise for PHPUnit
  50135. */
  50136. trait MockedCloneMethod
  50137. {
  50138. public function __clone()
  50139. {
  50140. $this->__phpunit_invocationMocker = clone $this->__phpunit_getInvocationHandler();
  50141. }
  50142. }
  50143. <?php
  50144. declare (strict_types=1);
  50145. /*
  50146. * This file is part of PHPUnit.
  50147. *
  50148. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  50149. *
  50150. * For the full copyright and license information, please view the LICENSE
  50151. * file that was distributed with this source code.
  50152. */
  50153. namespace PHPUnit\Framework\MockObject;
  50154. /**
  50155. * @internal This trait is not covered by the backward compatibility promise for PHPUnit
  50156. */
  50157. trait UnmockedCloneMethod
  50158. {
  50159. public function __clone()
  50160. {
  50161. $this->__phpunit_invocationMocker = clone $this->__phpunit_getInvocationHandler();
  50162. parent::__clone();
  50163. }
  50164. }
  50165. <?php
  50166. declare (strict_types=1);
  50167. /*
  50168. * This file is part of PHPUnit.
  50169. *
  50170. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  50171. *
  50172. * For the full copyright and license information, please view the LICENSE
  50173. * file that was distributed with this source code.
  50174. */
  50175. namespace PHPUnit\Framework\MockObject;
  50176. use PHPUnit\Framework\ExpectationFailedException;
  50177. use PHPUnit\Framework\MockObject\Rule\AnyInvokedCount;
  50178. use PHPUnit\Framework\MockObject\Rule\AnyParameters;
  50179. use PHPUnit\Framework\MockObject\Rule\InvocationOrder;
  50180. use PHPUnit\Framework\MockObject\Rule\InvokedCount;
  50181. use PHPUnit\Framework\MockObject\Rule\MethodName;
  50182. use PHPUnit\Framework\MockObject\Rule\ParametersRule;
  50183. use PHPUnit\Framework\MockObject\Stub\Stub;
  50184. use PHPUnit\Framework\TestFailure;
  50185. /**
  50186. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  50187. */
  50188. final class Matcher
  50189. {
  50190. /**
  50191. * @var InvocationOrder
  50192. */
  50193. private $invocationRule;
  50194. /**
  50195. * @var mixed
  50196. */
  50197. private $afterMatchBuilderId;
  50198. /**
  50199. * @var bool
  50200. */
  50201. private $afterMatchBuilderIsInvoked = \false;
  50202. /**
  50203. * @var MethodName
  50204. */
  50205. private $methodNameRule;
  50206. /**
  50207. * @var ParametersRule
  50208. */
  50209. private $parametersRule;
  50210. /**
  50211. * @var Stub
  50212. */
  50213. private $stub;
  50214. public function __construct(\PHPUnit\Framework\MockObject\Rule\InvocationOrder $rule)
  50215. {
  50216. $this->invocationRule = $rule;
  50217. }
  50218. public function hasMatchers() : bool
  50219. {
  50220. return !$this->invocationRule instanceof \PHPUnit\Framework\MockObject\Rule\AnyInvokedCount;
  50221. }
  50222. public function hasMethodNameRule() : bool
  50223. {
  50224. return $this->methodNameRule !== null;
  50225. }
  50226. public function getMethodNameRule() : \PHPUnit\Framework\MockObject\Rule\MethodName
  50227. {
  50228. return $this->methodNameRule;
  50229. }
  50230. public function setMethodNameRule(\PHPUnit\Framework\MockObject\Rule\MethodName $rule) : void
  50231. {
  50232. $this->methodNameRule = $rule;
  50233. }
  50234. public function hasParametersRule() : bool
  50235. {
  50236. return $this->parametersRule !== null;
  50237. }
  50238. public function setParametersRule(\PHPUnit\Framework\MockObject\Rule\ParametersRule $rule) : void
  50239. {
  50240. $this->parametersRule = $rule;
  50241. }
  50242. public function setStub(\PHPUnit\Framework\MockObject\Stub\Stub $stub) : void
  50243. {
  50244. $this->stub = $stub;
  50245. }
  50246. public function setAfterMatchBuilderId(string $id) : void
  50247. {
  50248. $this->afterMatchBuilderId = $id;
  50249. }
  50250. /**
  50251. * @throws \Exception
  50252. * @throws RuntimeException
  50253. * @throws ExpectationFailedException
  50254. */
  50255. public function invoked(\PHPUnit\Framework\MockObject\Invocation $invocation)
  50256. {
  50257. if ($this->methodNameRule === null) {
  50258. throw new \PHPUnit\Framework\MockObject\RuntimeException('No method rule is set');
  50259. }
  50260. if ($this->afterMatchBuilderId !== null) {
  50261. $matcher = $invocation->getObject()->__phpunit_getInvocationHandler()->lookupMatcher($this->afterMatchBuilderId);
  50262. if (!$matcher) {
  50263. throw new \PHPUnit\Framework\MockObject\RuntimeException(\sprintf('No builder found for match builder identification <%s>', $this->afterMatchBuilderId));
  50264. }
  50265. \assert($matcher instanceof self);
  50266. if ($matcher->invocationRule->hasBeenInvoked()) {
  50267. $this->afterMatchBuilderIsInvoked = \true;
  50268. }
  50269. }
  50270. $this->invocationRule->invoked($invocation);
  50271. try {
  50272. if ($this->parametersRule !== null) {
  50273. $this->parametersRule->apply($invocation);
  50274. }
  50275. } catch (\PHPUnit\Framework\ExpectationFailedException $e) {
  50276. throw new \PHPUnit\Framework\ExpectationFailedException(\sprintf("Expectation failed for %s when %s\n%s", $this->methodNameRule->toString(), $this->invocationRule->toString(), $e->getMessage()), $e->getComparisonFailure());
  50277. }
  50278. if ($this->stub) {
  50279. return $this->stub->invoke($invocation);
  50280. }
  50281. return $invocation->generateReturnValue();
  50282. }
  50283. /**
  50284. * @throws RuntimeException
  50285. * @throws ExpectationFailedException
  50286. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  50287. */
  50288. public function matches(\PHPUnit\Framework\MockObject\Invocation $invocation) : bool
  50289. {
  50290. if ($this->afterMatchBuilderId !== null) {
  50291. $matcher = $invocation->getObject()->__phpunit_getInvocationHandler()->lookupMatcher($this->afterMatchBuilderId);
  50292. if (!$matcher) {
  50293. throw new \PHPUnit\Framework\MockObject\RuntimeException(\sprintf('No builder found for match builder identification <%s>', $this->afterMatchBuilderId));
  50294. }
  50295. \assert($matcher instanceof self);
  50296. if (!$matcher->invocationRule->hasBeenInvoked()) {
  50297. return \false;
  50298. }
  50299. }
  50300. if ($this->methodNameRule === null) {
  50301. throw new \PHPUnit\Framework\MockObject\RuntimeException('No method rule is set');
  50302. }
  50303. if (!$this->invocationRule->matches($invocation)) {
  50304. return \false;
  50305. }
  50306. try {
  50307. if (!$this->methodNameRule->matches($invocation)) {
  50308. return \false;
  50309. }
  50310. } catch (\PHPUnit\Framework\ExpectationFailedException $e) {
  50311. throw new \PHPUnit\Framework\ExpectationFailedException(\sprintf("Expectation failed for %s when %s\n%s", $this->methodNameRule->toString(), $this->invocationRule->toString(), $e->getMessage()), $e->getComparisonFailure());
  50312. }
  50313. return \true;
  50314. }
  50315. /**
  50316. * @throws RuntimeException
  50317. * @throws ExpectationFailedException
  50318. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  50319. */
  50320. public function verify() : void
  50321. {
  50322. if ($this->methodNameRule === null) {
  50323. throw new \PHPUnit\Framework\MockObject\RuntimeException('No method rule is set');
  50324. }
  50325. try {
  50326. $this->invocationRule->verify();
  50327. if ($this->parametersRule === null) {
  50328. $this->parametersRule = new \PHPUnit\Framework\MockObject\Rule\AnyParameters();
  50329. }
  50330. $invocationIsAny = $this->invocationRule instanceof \PHPUnit\Framework\MockObject\Rule\AnyInvokedCount;
  50331. $invocationIsNever = $this->invocationRule instanceof \PHPUnit\Framework\MockObject\Rule\InvokedCount && $this->invocationRule->isNever();
  50332. if (!$invocationIsAny && !$invocationIsNever) {
  50333. $this->parametersRule->verify();
  50334. }
  50335. } catch (\PHPUnit\Framework\ExpectationFailedException $e) {
  50336. throw new \PHPUnit\Framework\ExpectationFailedException(\sprintf("Expectation failed for %s when %s.\n%s", $this->methodNameRule->toString(), $this->invocationRule->toString(), \PHPUnit\Framework\TestFailure::exceptionToString($e)));
  50337. }
  50338. }
  50339. public function toString() : string
  50340. {
  50341. $list = [];
  50342. if ($this->invocationRule !== null) {
  50343. $list[] = $this->invocationRule->toString();
  50344. }
  50345. if ($this->methodNameRule !== null) {
  50346. $list[] = 'where ' . $this->methodNameRule->toString();
  50347. }
  50348. if ($this->parametersRule !== null) {
  50349. $list[] = 'and ' . $this->parametersRule->toString();
  50350. }
  50351. if ($this->afterMatchBuilderId !== null) {
  50352. $list[] = 'after ' . $this->afterMatchBuilderId;
  50353. }
  50354. if ($this->stub !== null) {
  50355. $list[] = 'will ' . $this->stub->toString();
  50356. }
  50357. return \implode(' ', $list);
  50358. }
  50359. }
  50360. <?php
  50361. declare (strict_types=1);
  50362. /*
  50363. * This file is part of PHPUnit.
  50364. *
  50365. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  50366. *
  50367. * For the full copyright and license information, please view the LICENSE
  50368. * file that was distributed with this source code.
  50369. */
  50370. namespace PHPUnit\Framework\MockObject;
  50371. use PHPUnit\Framework\MockObject\Builder\InvocationMocker;
  50372. use PHPUnit\Framework\MockObject\Rule\InvocationOrder;
  50373. /**
  50374. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  50375. */
  50376. final class InvocationHandler
  50377. {
  50378. /**
  50379. * @var Matcher[]
  50380. */
  50381. private $matchers = [];
  50382. /**
  50383. * @var Matcher[]
  50384. */
  50385. private $matcherMap = [];
  50386. /**
  50387. * @var ConfigurableMethod[]
  50388. */
  50389. private $configurableMethods;
  50390. /**
  50391. * @var bool
  50392. */
  50393. private $returnValueGeneration;
  50394. /**
  50395. * @var \Throwable
  50396. */
  50397. private $deferredError;
  50398. public function __construct(array $configurableMethods, bool $returnValueGeneration)
  50399. {
  50400. $this->configurableMethods = $configurableMethods;
  50401. $this->returnValueGeneration = $returnValueGeneration;
  50402. }
  50403. public function hasMatchers() : bool
  50404. {
  50405. foreach ($this->matchers as $matcher) {
  50406. if ($matcher->hasMatchers()) {
  50407. return \true;
  50408. }
  50409. }
  50410. return \false;
  50411. }
  50412. /**
  50413. * Looks up the match builder with identification $id and returns it.
  50414. *
  50415. * @param string $id The identification of the match builder
  50416. */
  50417. public function lookupMatcher(string $id) : ?\PHPUnit\Framework\MockObject\Matcher
  50418. {
  50419. if (isset($this->matcherMap[$id])) {
  50420. return $this->matcherMap[$id];
  50421. }
  50422. return null;
  50423. }
  50424. /**
  50425. * Registers a matcher with the identification $id. The matcher can later be
  50426. * looked up using lookupMatcher() to figure out if it has been invoked.
  50427. *
  50428. * @param string $id The identification of the matcher
  50429. * @param Matcher $matcher The builder which is being registered
  50430. *
  50431. * @throws RuntimeException
  50432. */
  50433. public function registerMatcher(string $id, \PHPUnit\Framework\MockObject\Matcher $matcher) : void
  50434. {
  50435. if (isset($this->matcherMap[$id])) {
  50436. throw new \PHPUnit\Framework\MockObject\RuntimeException('Matcher with id <' . $id . '> is already registered.');
  50437. }
  50438. $this->matcherMap[$id] = $matcher;
  50439. }
  50440. public function expects(\PHPUnit\Framework\MockObject\Rule\InvocationOrder $rule) : \PHPUnit\Framework\MockObject\Builder\InvocationMocker
  50441. {
  50442. $matcher = new \PHPUnit\Framework\MockObject\Matcher($rule);
  50443. $this->addMatcher($matcher);
  50444. return new \PHPUnit\Framework\MockObject\Builder\InvocationMocker($this, $matcher, ...$this->configurableMethods);
  50445. }
  50446. /**
  50447. * @throws RuntimeException
  50448. * @throws \Exception
  50449. */
  50450. public function invoke(\PHPUnit\Framework\MockObject\Invocation $invocation)
  50451. {
  50452. $exception = null;
  50453. $hasReturnValue = \false;
  50454. $returnValue = null;
  50455. foreach ($this->matchers as $match) {
  50456. try {
  50457. if ($match->matches($invocation)) {
  50458. $value = $match->invoked($invocation);
  50459. if (!$hasReturnValue) {
  50460. $returnValue = $value;
  50461. $hasReturnValue = \true;
  50462. }
  50463. }
  50464. } catch (\Exception $e) {
  50465. $exception = $e;
  50466. }
  50467. }
  50468. if ($exception !== null) {
  50469. throw $exception;
  50470. }
  50471. if ($hasReturnValue) {
  50472. return $returnValue;
  50473. }
  50474. if (!$this->returnValueGeneration) {
  50475. $exception = new \PHPUnit\Framework\MockObject\RuntimeException(\sprintf('Return value inference disabled and no expectation set up for %s::%s()', $invocation->getClassName(), $invocation->getMethodName()));
  50476. if (\strtolower($invocation->getMethodName()) === '__tostring') {
  50477. $this->deferredError = $exception;
  50478. return '';
  50479. }
  50480. throw $exception;
  50481. }
  50482. return $invocation->generateReturnValue();
  50483. }
  50484. public function matches(\PHPUnit\Framework\MockObject\Invocation $invocation) : bool
  50485. {
  50486. foreach ($this->matchers as $matcher) {
  50487. if (!$matcher->matches($invocation)) {
  50488. return \false;
  50489. }
  50490. }
  50491. return \true;
  50492. }
  50493. /**
  50494. * @throws \Throwable
  50495. */
  50496. public function verify() : void
  50497. {
  50498. foreach ($this->matchers as $matcher) {
  50499. $matcher->verify();
  50500. }
  50501. if ($this->deferredError) {
  50502. throw $this->deferredError;
  50503. }
  50504. }
  50505. private function addMatcher(\PHPUnit\Framework\MockObject\Matcher $matcher) : void
  50506. {
  50507. $this->matchers[] = $matcher;
  50508. }
  50509. }
  50510. <?php
  50511. declare (strict_types=1);
  50512. /*
  50513. * This file is part of PHPUnit.
  50514. *
  50515. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  50516. *
  50517. * For the full copyright and license information, please view the LICENSE
  50518. * file that was distributed with this source code.
  50519. */
  50520. namespace PHPUnit\Framework\MockObject;
  50521. use PHPUnit\Framework\MockObject\Builder\InvocationMocker as BuilderInvocationMocker;
  50522. use PHPUnit\Framework\MockObject\Rule\InvocationOrder;
  50523. /**
  50524. * @method BuilderInvocationMocker method($constraint)
  50525. */
  50526. interface MockObject extends \PHPUnit\Framework\MockObject\Stub
  50527. {
  50528. public function __phpunit_setOriginalObject($originalObject) : void;
  50529. public function __phpunit_verify(bool $unsetInvocationMocker = \true) : void;
  50530. public function expects(\PHPUnit\Framework\MockObject\Rule\InvocationOrder $invocationRule) : \PHPUnit\Framework\MockObject\Builder\InvocationMocker;
  50531. }
  50532. <?php
  50533. declare (strict_types=1);
  50534. /*
  50535. * This file is part of PHPUnit.
  50536. *
  50537. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  50538. *
  50539. * For the full copyright and license information, please view the LICENSE
  50540. * file that was distributed with this source code.
  50541. */
  50542. namespace PHPUnit\Framework;
  50543. /**
  50544. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  50545. */
  50546. interface SelfDescribing
  50547. {
  50548. /**
  50549. * Returns a string representation of the object.
  50550. */
  50551. public function toString() : string;
  50552. }
  50553. <?php
  50554. declare (strict_types=1);
  50555. /*
  50556. * This file is part of PHPUnit.
  50557. *
  50558. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  50559. *
  50560. * For the full copyright and license information, please view the LICENSE
  50561. * file that was distributed with this source code.
  50562. */
  50563. namespace PHPUnit\Framework;
  50564. use PHPUnit\DeepCopy\DeepCopy;
  50565. use PHPUnit\Framework\Constraint\Exception as ExceptionConstraint;
  50566. use PHPUnit\Framework\Constraint\ExceptionCode;
  50567. use PHPUnit\Framework\Constraint\ExceptionMessage;
  50568. use PHPUnit\Framework\Constraint\ExceptionMessageRegularExpression;
  50569. use PHPUnit\Framework\Error\Deprecated;
  50570. use PHPUnit\Framework\Error\Error;
  50571. use PHPUnit\Framework\Error\Notice;
  50572. use PHPUnit\Framework\Error\Warning as WarningError;
  50573. use PHPUnit\Framework\MockObject\Generator as MockGenerator;
  50574. use PHPUnit\Framework\MockObject\MockBuilder;
  50575. use PHPUnit\Framework\MockObject\MockObject;
  50576. use PHPUnit\Framework\MockObject\Rule\AnyInvokedCount as AnyInvokedCountMatcher;
  50577. use PHPUnit\Framework\MockObject\Rule\InvokedAtIndex as InvokedAtIndexMatcher;
  50578. use PHPUnit\Framework\MockObject\Rule\InvokedAtLeastCount as InvokedAtLeastCountMatcher;
  50579. use PHPUnit\Framework\MockObject\Rule\InvokedAtLeastOnce as InvokedAtLeastOnceMatcher;
  50580. use PHPUnit\Framework\MockObject\Rule\InvokedAtMostCount as InvokedAtMostCountMatcher;
  50581. use PHPUnit\Framework\MockObject\Rule\InvokedCount as InvokedCountMatcher;
  50582. use PHPUnit\Framework\MockObject\Stub;
  50583. use PHPUnit\Framework\MockObject\Stub\ConsecutiveCalls as ConsecutiveCallsStub;
  50584. use PHPUnit\Framework\MockObject\Stub\Exception as ExceptionStub;
  50585. use PHPUnit\Framework\MockObject\Stub\ReturnArgument as ReturnArgumentStub;
  50586. use PHPUnit\Framework\MockObject\Stub\ReturnCallback as ReturnCallbackStub;
  50587. use PHPUnit\Framework\MockObject\Stub\ReturnSelf as ReturnSelfStub;
  50588. use PHPUnit\Framework\MockObject\Stub\ReturnStub;
  50589. use PHPUnit\Framework\MockObject\Stub\ReturnValueMap as ReturnValueMapStub;
  50590. use PHPUnit\Runner\BaseTestRunner;
  50591. use PHPUnit\Runner\PhptTestCase;
  50592. use PHPUnit\Util\Exception as UtilException;
  50593. use PHPUnit\Util\GlobalState;
  50594. use PHPUnit\Util\PHP\AbstractPhpProcess;
  50595. use PHPUnit\Util\Test as TestUtil;
  50596. use PHPUnit\Util\Type;
  50597. use Prophecy\Exception\Prediction\PredictionException;
  50598. use Prophecy\Prophecy\MethodProphecy;
  50599. use Prophecy\Prophecy\ObjectProphecy;
  50600. use Prophecy\Prophet;
  50601. use PHPUnit\SebastianBergmann\Comparator\Comparator;
  50602. use PHPUnit\SebastianBergmann\Comparator\Factory as ComparatorFactory;
  50603. use PHPUnit\SebastianBergmann\Diff\Differ;
  50604. use PHPUnit\SebastianBergmann\Exporter\Exporter;
  50605. use PHPUnit\SebastianBergmann\GlobalState\Blacklist;
  50606. use PHPUnit\SebastianBergmann\GlobalState\Restorer;
  50607. use PHPUnit\SebastianBergmann\GlobalState\Snapshot;
  50608. use PHPUnit\SebastianBergmann\ObjectEnumerator\Enumerator;
  50609. use PHPUnit\SebastianBergmann\Template\Template;
  50610. abstract class TestCase extends \PHPUnit\Framework\Assert implements \PHPUnit\Framework\SelfDescribing, \PHPUnit\Framework\Test
  50611. {
  50612. private const LOCALE_CATEGORIES = [\LC_ALL, \LC_COLLATE, \LC_CTYPE, \LC_MONETARY, \LC_NUMERIC, \LC_TIME];
  50613. /**
  50614. * @var ?bool
  50615. */
  50616. protected $backupGlobals;
  50617. /**
  50618. * @var string[]
  50619. */
  50620. protected $backupGlobalsBlacklist = [];
  50621. /**
  50622. * @var bool
  50623. */
  50624. protected $backupStaticAttributes;
  50625. /**
  50626. * @var array<string,array<int,string>>
  50627. */
  50628. protected $backupStaticAttributesBlacklist = [];
  50629. /**
  50630. * @var bool
  50631. */
  50632. protected $runTestInSeparateProcess;
  50633. /**
  50634. * @var bool
  50635. */
  50636. protected $preserveGlobalState = \true;
  50637. /**
  50638. * @var bool
  50639. */
  50640. private $runClassInSeparateProcess;
  50641. /**
  50642. * @var bool
  50643. */
  50644. private $inIsolation = \false;
  50645. /**
  50646. * @var array
  50647. */
  50648. private $data;
  50649. /**
  50650. * @var int|string
  50651. */
  50652. private $dataName;
  50653. /**
  50654. * @var null|string
  50655. */
  50656. private $expectedException;
  50657. /**
  50658. * @var null|string
  50659. */
  50660. private $expectedExceptionMessage;
  50661. /**
  50662. * @var null|string
  50663. */
  50664. private $expectedExceptionMessageRegExp;
  50665. /**
  50666. * @var null|int|string
  50667. */
  50668. private $expectedExceptionCode;
  50669. /**
  50670. * @var string
  50671. */
  50672. private $name = '';
  50673. /**
  50674. * @var string[]
  50675. */
  50676. private $dependencies = [];
  50677. /**
  50678. * @var array
  50679. */
  50680. private $dependencyInput = [];
  50681. /**
  50682. * @var array<string,string>
  50683. */
  50684. private $iniSettings = [];
  50685. /**
  50686. * @var array
  50687. */
  50688. private $locale = [];
  50689. /**
  50690. * @var MockObject[]
  50691. */
  50692. private $mockObjects = [];
  50693. /**
  50694. * @var MockGenerator
  50695. */
  50696. private $mockObjectGenerator;
  50697. /**
  50698. * @var int
  50699. */
  50700. private $status = \PHPUnit\Runner\BaseTestRunner::STATUS_UNKNOWN;
  50701. /**
  50702. * @var string
  50703. */
  50704. private $statusMessage = '';
  50705. /**
  50706. * @var int
  50707. */
  50708. private $numAssertions = 0;
  50709. /**
  50710. * @var TestResult
  50711. */
  50712. private $result;
  50713. /**
  50714. * @var mixed
  50715. */
  50716. private $testResult;
  50717. /**
  50718. * @var string
  50719. */
  50720. private $output = '';
  50721. /**
  50722. * @var string
  50723. */
  50724. private $outputExpectedRegex;
  50725. /**
  50726. * @var string
  50727. */
  50728. private $outputExpectedString;
  50729. /**
  50730. * @var mixed
  50731. */
  50732. private $outputCallback = \false;
  50733. /**
  50734. * @var bool
  50735. */
  50736. private $outputBufferingActive = \false;
  50737. /**
  50738. * @var int
  50739. */
  50740. private $outputBufferingLevel;
  50741. /**
  50742. * @var bool
  50743. */
  50744. private $outputRetrievedForAssertion = \false;
  50745. /**
  50746. * @var Snapshot
  50747. */
  50748. private $snapshot;
  50749. /**
  50750. * @var \Prophecy\Prophet
  50751. */
  50752. private $prophet;
  50753. /**
  50754. * @var bool
  50755. */
  50756. private $beStrictAboutChangesToGlobalState = \false;
  50757. /**
  50758. * @var bool
  50759. */
  50760. private $registerMockObjectsFromTestArgumentsRecursively = \false;
  50761. /**
  50762. * @var string[]
  50763. */
  50764. private $warnings = [];
  50765. /**
  50766. * @var string[]
  50767. */
  50768. private $groups = [];
  50769. /**
  50770. * @var bool
  50771. */
  50772. private $doesNotPerformAssertions = \false;
  50773. /**
  50774. * @var Comparator[]
  50775. */
  50776. private $customComparators = [];
  50777. /**
  50778. * @var string[]
  50779. */
  50780. private $doubledTypes = [];
  50781. /**
  50782. * Returns a matcher that matches when the method is executed
  50783. * zero or more times.
  50784. */
  50785. public static function any() : \PHPUnit\Framework\MockObject\Rule\AnyInvokedCount
  50786. {
  50787. return new \PHPUnit\Framework\MockObject\Rule\AnyInvokedCount();
  50788. }
  50789. /**
  50790. * Returns a matcher that matches when the method is never executed.
  50791. */
  50792. public static function never() : \PHPUnit\Framework\MockObject\Rule\InvokedCount
  50793. {
  50794. return new \PHPUnit\Framework\MockObject\Rule\InvokedCount(0);
  50795. }
  50796. /**
  50797. * Returns a matcher that matches when the method is executed
  50798. * at least N times.
  50799. */
  50800. public static function atLeast(int $requiredInvocations) : \PHPUnit\Framework\MockObject\Rule\InvokedAtLeastCount
  50801. {
  50802. return new \PHPUnit\Framework\MockObject\Rule\InvokedAtLeastCount($requiredInvocations);
  50803. }
  50804. /**
  50805. * Returns a matcher that matches when the method is executed at least once.
  50806. */
  50807. public static function atLeastOnce() : \PHPUnit\Framework\MockObject\Rule\InvokedAtLeastOnce
  50808. {
  50809. return new \PHPUnit\Framework\MockObject\Rule\InvokedAtLeastOnce();
  50810. }
  50811. /**
  50812. * Returns a matcher that matches when the method is executed exactly once.
  50813. */
  50814. public static function once() : \PHPUnit\Framework\MockObject\Rule\InvokedCount
  50815. {
  50816. return new \PHPUnit\Framework\MockObject\Rule\InvokedCount(1);
  50817. }
  50818. /**
  50819. * Returns a matcher that matches when the method is executed
  50820. * exactly $count times.
  50821. */
  50822. public static function exactly(int $count) : \PHPUnit\Framework\MockObject\Rule\InvokedCount
  50823. {
  50824. return new \PHPUnit\Framework\MockObject\Rule\InvokedCount($count);
  50825. }
  50826. /**
  50827. * Returns a matcher that matches when the method is executed
  50828. * at most N times.
  50829. */
  50830. public static function atMost(int $allowedInvocations) : \PHPUnit\Framework\MockObject\Rule\InvokedAtMostCount
  50831. {
  50832. return new \PHPUnit\Framework\MockObject\Rule\InvokedAtMostCount($allowedInvocations);
  50833. }
  50834. /**
  50835. * Returns a matcher that matches when the method is executed
  50836. * at the given index.
  50837. */
  50838. public static function at(int $index) : \PHPUnit\Framework\MockObject\Rule\InvokedAtIndex
  50839. {
  50840. return new \PHPUnit\Framework\MockObject\Rule\InvokedAtIndex($index);
  50841. }
  50842. public static function returnValue($value) : \PHPUnit\Framework\MockObject\Stub\ReturnStub
  50843. {
  50844. return new \PHPUnit\Framework\MockObject\Stub\ReturnStub($value);
  50845. }
  50846. public static function returnValueMap(array $valueMap) : \PHPUnit\Framework\MockObject\Stub\ReturnValueMap
  50847. {
  50848. return new \PHPUnit\Framework\MockObject\Stub\ReturnValueMap($valueMap);
  50849. }
  50850. public static function returnArgument(int $argumentIndex) : \PHPUnit\Framework\MockObject\Stub\ReturnArgument
  50851. {
  50852. return new \PHPUnit\Framework\MockObject\Stub\ReturnArgument($argumentIndex);
  50853. }
  50854. public static function returnCallback($callback) : \PHPUnit\Framework\MockObject\Stub\ReturnCallback
  50855. {
  50856. return new \PHPUnit\Framework\MockObject\Stub\ReturnCallback($callback);
  50857. }
  50858. /**
  50859. * Returns the current object.
  50860. *
  50861. * This method is useful when mocking a fluent interface.
  50862. */
  50863. public static function returnSelf() : \PHPUnit\Framework\MockObject\Stub\ReturnSelf
  50864. {
  50865. return new \PHPUnit\Framework\MockObject\Stub\ReturnSelf();
  50866. }
  50867. public static function throwException(\Throwable $exception) : \PHPUnit\Framework\MockObject\Stub\Exception
  50868. {
  50869. return new \PHPUnit\Framework\MockObject\Stub\Exception($exception);
  50870. }
  50871. public static function onConsecutiveCalls(...$args) : \PHPUnit\Framework\MockObject\Stub\ConsecutiveCalls
  50872. {
  50873. return new \PHPUnit\Framework\MockObject\Stub\ConsecutiveCalls($args);
  50874. }
  50875. /**
  50876. * @param int|string $dataName
  50877. *
  50878. * @internal This method is not covered by the backward compatibility promise for PHPUnit
  50879. */
  50880. public function __construct(?string $name = null, array $data = [], $dataName = '')
  50881. {
  50882. if ($name !== null) {
  50883. $this->setName($name);
  50884. }
  50885. $this->data = $data;
  50886. $this->dataName = $dataName;
  50887. }
  50888. /**
  50889. * This method is called before the first test of this test class is run.
  50890. */
  50891. public static function setUpBeforeClass() : void
  50892. {
  50893. }
  50894. /**
  50895. * This method is called after the last test of this test class is run.
  50896. */
  50897. public static function tearDownAfterClass() : void
  50898. {
  50899. }
  50900. /**
  50901. * This method is called before each test.
  50902. */
  50903. protected function setUp() : void
  50904. {
  50905. }
  50906. /**
  50907. * This method is called after each test.
  50908. */
  50909. protected function tearDown() : void
  50910. {
  50911. }
  50912. /**
  50913. * Returns a string representation of the test case.
  50914. *
  50915. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  50916. * @throws Exception
  50917. */
  50918. public function toString() : string
  50919. {
  50920. try {
  50921. $class = new \ReflectionClass($this);
  50922. // @codeCoverageIgnoreStart
  50923. } catch (\ReflectionException $e) {
  50924. throw new \PHPUnit\Framework\Exception($e->getMessage(), (int) $e->getCode(), $e);
  50925. }
  50926. // @codeCoverageIgnoreEnd
  50927. $buffer = \sprintf('%s::%s', $class->name, $this->getName(\false));
  50928. return $buffer . $this->getDataSetAsString();
  50929. }
  50930. public function count() : int
  50931. {
  50932. return 1;
  50933. }
  50934. public function getActualOutputForAssertion() : string
  50935. {
  50936. $this->outputRetrievedForAssertion = \true;
  50937. return $this->getActualOutput();
  50938. }
  50939. public function expectOutputRegex(string $expectedRegex) : void
  50940. {
  50941. $this->outputExpectedRegex = $expectedRegex;
  50942. }
  50943. public function expectOutputString(string $expectedString) : void
  50944. {
  50945. $this->outputExpectedString = $expectedString;
  50946. }
  50947. /**
  50948. * @psalm-param class-string<\Throwable> $exception
  50949. */
  50950. public function expectException(string $exception) : void
  50951. {
  50952. // @codeCoverageIgnoreStart
  50953. switch ($exception) {
  50954. case \PHPUnit\Framework\Error\Deprecated::class:
  50955. $this->addWarning('Support for using expectException() with PHPUnit\\Framework\\Error\\Deprecated is deprecated and will be removed in PHPUnit 10. Use expectDeprecation() instead.');
  50956. break;
  50957. case \PHPUnit\Framework\Error\Error::class:
  50958. $this->addWarning('Support for using expectException() with PHPUnit\\Framework\\Error\\Error is deprecated and will be removed in PHPUnit 10. Use expectError() instead.');
  50959. break;
  50960. case \PHPUnit\Framework\Error\Notice::class:
  50961. $this->addWarning('Support for using expectException() with PHPUnit\\Framework\\Error\\Notice is deprecated and will be removed in PHPUnit 10. Use expectNotice() instead.');
  50962. break;
  50963. case \PHPUnit\Framework\Error\Warning::class:
  50964. $this->addWarning('Support for using expectException() with PHPUnit\\Framework\\Error\\Warning is deprecated and will be removed in PHPUnit 10. Use expectWarning() instead.');
  50965. break;
  50966. }
  50967. // @codeCoverageIgnoreEnd
  50968. $this->expectedException = $exception;
  50969. }
  50970. /**
  50971. * @param int|string $code
  50972. */
  50973. public function expectExceptionCode($code) : void
  50974. {
  50975. $this->expectedExceptionCode = $code;
  50976. }
  50977. public function expectExceptionMessage(string $message) : void
  50978. {
  50979. $this->expectedExceptionMessage = $message;
  50980. }
  50981. public function expectExceptionMessageMatches(string $regularExpression) : void
  50982. {
  50983. $this->expectedExceptionMessageRegExp = $regularExpression;
  50984. }
  50985. /**
  50986. * Sets up an expectation for an exception to be raised by the code under test.
  50987. * Information for expected exception class, expected exception message, and
  50988. * expected exception code are retrieved from a given Exception object.
  50989. */
  50990. public function expectExceptionObject(\Exception $exception) : void
  50991. {
  50992. $this->expectException(\get_class($exception));
  50993. $this->expectExceptionMessage($exception->getMessage());
  50994. $this->expectExceptionCode($exception->getCode());
  50995. }
  50996. public function expectNotToPerformAssertions() : void
  50997. {
  50998. $this->doesNotPerformAssertions = \true;
  50999. }
  51000. public function expectDeprecation() : void
  51001. {
  51002. $this->expectedException = \PHPUnit\Framework\Error\Deprecated::class;
  51003. }
  51004. public function expectDeprecationMessage(string $message) : void
  51005. {
  51006. $this->expectExceptionMessage($message);
  51007. }
  51008. public function expectDeprecationMessageMatches(string $regularExpression) : void
  51009. {
  51010. $this->expectExceptionMessageMatches($regularExpression);
  51011. }
  51012. public function expectNotice() : void
  51013. {
  51014. $this->expectedException = \PHPUnit\Framework\Error\Notice::class;
  51015. }
  51016. public function expectNoticeMessage(string $message) : void
  51017. {
  51018. $this->expectExceptionMessage($message);
  51019. }
  51020. public function expectNoticeMessageMatches(string $regularExpression) : void
  51021. {
  51022. $this->expectExceptionMessageMatches($regularExpression);
  51023. }
  51024. public function expectWarning() : void
  51025. {
  51026. $this->expectedException = \PHPUnit\Framework\Error\Warning::class;
  51027. }
  51028. public function expectWarningMessage(string $message) : void
  51029. {
  51030. $this->expectExceptionMessage($message);
  51031. }
  51032. public function expectWarningMessageMatches(string $regularExpression) : void
  51033. {
  51034. $this->expectExceptionMessageMatches($regularExpression);
  51035. }
  51036. public function expectError() : void
  51037. {
  51038. $this->expectedException = \PHPUnit\Framework\Error\Error::class;
  51039. }
  51040. public function expectErrorMessage(string $message) : void
  51041. {
  51042. $this->expectExceptionMessage($message);
  51043. }
  51044. public function expectErrorMessageMatches(string $regularExpression) : void
  51045. {
  51046. $this->expectExceptionMessageMatches($regularExpression);
  51047. }
  51048. public function getStatus() : int
  51049. {
  51050. return $this->status;
  51051. }
  51052. public function markAsRisky() : void
  51053. {
  51054. $this->status = \PHPUnit\Runner\BaseTestRunner::STATUS_RISKY;
  51055. }
  51056. public function getStatusMessage() : string
  51057. {
  51058. return $this->statusMessage;
  51059. }
  51060. public function hasFailed() : bool
  51061. {
  51062. $status = $this->getStatus();
  51063. return $status === \PHPUnit\Runner\BaseTestRunner::STATUS_FAILURE || $status === \PHPUnit\Runner\BaseTestRunner::STATUS_ERROR;
  51064. }
  51065. /**
  51066. * Runs the test case and collects the results in a TestResult object.
  51067. * If no TestResult object is passed a new one will be created.
  51068. *
  51069. * @throws CodeCoverageException
  51070. * @throws UtilException
  51071. * @throws \SebastianBergmann\CodeCoverage\CoveredCodeNotExecutedException
  51072. * @throws \SebastianBergmann\CodeCoverage\InvalidArgumentException
  51073. * @throws \SebastianBergmann\CodeCoverage\RuntimeException
  51074. * @throws \SebastianBergmann\CodeCoverage\UnintentionallyCoveredCodeException
  51075. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  51076. */
  51077. public function run(\PHPUnit\Framework\TestResult $result = null) : \PHPUnit\Framework\TestResult
  51078. {
  51079. if ($result === null) {
  51080. $result = $this->createResult();
  51081. }
  51082. if (!$this instanceof \PHPUnit\Framework\WarningTestCase) {
  51083. $this->setTestResultObject($result);
  51084. }
  51085. if (!$this instanceof \PHPUnit\Framework\WarningTestCase && !$this instanceof \PHPUnit\Framework\SkippedTestCase && !$this->handleDependencies()) {
  51086. return $result;
  51087. }
  51088. if ($this->runInSeparateProcess()) {
  51089. $runEntireClass = $this->runClassInSeparateProcess && !$this->runTestInSeparateProcess;
  51090. try {
  51091. $class = new \ReflectionClass($this);
  51092. // @codeCoverageIgnoreStart
  51093. } catch (\ReflectionException $e) {
  51094. throw new \PHPUnit\Framework\Exception($e->getMessage(), (int) $e->getCode(), $e);
  51095. }
  51096. // @codeCoverageIgnoreEnd
  51097. if ($runEntireClass) {
  51098. $template = new \PHPUnit\SebastianBergmann\Template\Template(__DIR__ . '/../Util/PHP/Template/TestCaseClass.tpl');
  51099. } else {
  51100. $template = new \PHPUnit\SebastianBergmann\Template\Template(__DIR__ . '/../Util/PHP/Template/TestCaseMethod.tpl');
  51101. }
  51102. if ($this->preserveGlobalState) {
  51103. $constants = \PHPUnit\Util\GlobalState::getConstantsAsString();
  51104. $globals = \PHPUnit\Util\GlobalState::getGlobalsAsString();
  51105. $includedFiles = \PHPUnit\Util\GlobalState::getIncludedFilesAsString();
  51106. $iniSettings = \PHPUnit\Util\GlobalState::getIniSettingsAsString();
  51107. } else {
  51108. $constants = '';
  51109. if (!empty($GLOBALS['__PHPUNIT_BOOTSTRAP'])) {
  51110. $globals = '$GLOBALS[\'__PHPUNIT_BOOTSTRAP\'] = ' . \var_export($GLOBALS['__PHPUNIT_BOOTSTRAP'], \true) . ";\n";
  51111. } else {
  51112. $globals = '';
  51113. }
  51114. $includedFiles = '';
  51115. $iniSettings = '';
  51116. }
  51117. $coverage = $result->getCollectCodeCoverageInformation() ? 'true' : 'false';
  51118. $isStrictAboutTestsThatDoNotTestAnything = $result->isStrictAboutTestsThatDoNotTestAnything() ? 'true' : 'false';
  51119. $isStrictAboutOutputDuringTests = $result->isStrictAboutOutputDuringTests() ? 'true' : 'false';
  51120. $enforcesTimeLimit = $result->enforcesTimeLimit() ? 'true' : 'false';
  51121. $isStrictAboutTodoAnnotatedTests = $result->isStrictAboutTodoAnnotatedTests() ? 'true' : 'false';
  51122. $isStrictAboutResourceUsageDuringSmallTests = $result->isStrictAboutResourceUsageDuringSmallTests() ? 'true' : 'false';
  51123. if (\defined('PHPUNIT_COMPOSER_INSTALL')) {
  51124. $composerAutoload = \var_export(PHPUNIT_COMPOSER_INSTALL, \true);
  51125. } else {
  51126. $composerAutoload = '\'\'';
  51127. }
  51128. if (\defined('__PHPUNIT_PHAR__')) {
  51129. $phar = \var_export(__PHPUNIT_PHAR__, \true);
  51130. } else {
  51131. $phar = '\'\'';
  51132. }
  51133. if ($result->getCodeCoverage()) {
  51134. $codeCoverageFilter = $result->getCodeCoverage()->filter();
  51135. } else {
  51136. $codeCoverageFilter = null;
  51137. }
  51138. $data = \var_export(\serialize($this->data), \true);
  51139. $dataName = \var_export($this->dataName, \true);
  51140. $dependencyInput = \var_export(\serialize($this->dependencyInput), \true);
  51141. $includePath = \var_export(\get_include_path(), \true);
  51142. $codeCoverageFilter = \var_export(\serialize($codeCoverageFilter), \true);
  51143. // must do these fixes because TestCaseMethod.tpl has unserialize('{data}') in it, and we can't break BC
  51144. // the lines above used to use addcslashes() rather than var_export(), which breaks null byte escape sequences
  51145. $data = "'." . $data . ".'";
  51146. $dataName = "'.(" . $dataName . ").'";
  51147. $dependencyInput = "'." . $dependencyInput . ".'";
  51148. $includePath = "'." . $includePath . ".'";
  51149. $codeCoverageFilter = "'." . $codeCoverageFilter . ".'";
  51150. $configurationFilePath = $GLOBALS['__PHPUNIT_CONFIGURATION_FILE'] ?? '';
  51151. $var = ['composerAutoload' => $composerAutoload, 'phar' => $phar, 'filename' => $class->getFileName(), 'className' => $class->getName(), 'collectCodeCoverageInformation' => $coverage, 'data' => $data, 'dataName' => $dataName, 'dependencyInput' => $dependencyInput, 'constants' => $constants, 'globals' => $globals, 'include_path' => $includePath, 'included_files' => $includedFiles, 'iniSettings' => $iniSettings, 'isStrictAboutTestsThatDoNotTestAnything' => $isStrictAboutTestsThatDoNotTestAnything, 'isStrictAboutOutputDuringTests' => $isStrictAboutOutputDuringTests, 'enforcesTimeLimit' => $enforcesTimeLimit, 'isStrictAboutTodoAnnotatedTests' => $isStrictAboutTodoAnnotatedTests, 'isStrictAboutResourceUsageDuringSmallTests' => $isStrictAboutResourceUsageDuringSmallTests, 'codeCoverageFilter' => $codeCoverageFilter, 'configurationFilePath' => $configurationFilePath, 'name' => $this->getName(\false)];
  51152. if (!$runEntireClass) {
  51153. $var['methodName'] = $this->name;
  51154. }
  51155. $template->setVar($var);
  51156. $php = \PHPUnit\Util\PHP\AbstractPhpProcess::factory();
  51157. $php->runTestJob($template->render(), $this, $result);
  51158. } else {
  51159. $result->run($this);
  51160. }
  51161. $this->result = null;
  51162. return $result;
  51163. }
  51164. /**
  51165. * Returns a builder object to create mock objects using a fluent interface.
  51166. *
  51167. * @psalm-template RealInstanceType of object
  51168. * @psalm-param class-string<RealInstanceType> $className
  51169. * @psalm-return MockBuilder<RealInstanceType>
  51170. */
  51171. public function getMockBuilder(string $className) : \PHPUnit\Framework\MockObject\MockBuilder
  51172. {
  51173. $this->recordDoubledType($className);
  51174. return new \PHPUnit\Framework\MockObject\MockBuilder($this, $className);
  51175. }
  51176. public function registerComparator(\PHPUnit\SebastianBergmann\Comparator\Comparator $comparator) : void
  51177. {
  51178. \PHPUnit\SebastianBergmann\Comparator\Factory::getInstance()->register($comparator);
  51179. $this->customComparators[] = $comparator;
  51180. }
  51181. /**
  51182. * @return string[]
  51183. *
  51184. * @internal This method is not covered by the backward compatibility promise for PHPUnit
  51185. */
  51186. public function doubledTypes() : array
  51187. {
  51188. return \array_unique($this->doubledTypes);
  51189. }
  51190. /**
  51191. * @internal This method is not covered by the backward compatibility promise for PHPUnit
  51192. */
  51193. public function getGroups() : array
  51194. {
  51195. return $this->groups;
  51196. }
  51197. /**
  51198. * @internal This method is not covered by the backward compatibility promise for PHPUnit
  51199. */
  51200. public function setGroups(array $groups) : void
  51201. {
  51202. $this->groups = $groups;
  51203. }
  51204. /**
  51205. * @internal This method is not covered by the backward compatibility promise for PHPUnit
  51206. */
  51207. public function getAnnotations() : array
  51208. {
  51209. return \PHPUnit\Util\Test::parseTestMethodAnnotations(\get_class($this), $this->name);
  51210. }
  51211. /**
  51212. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  51213. *
  51214. * @internal This method is not covered by the backward compatibility promise for PHPUnit
  51215. */
  51216. public function getName(bool $withDataSet = \true) : string
  51217. {
  51218. if ($withDataSet) {
  51219. return $this->name . $this->getDataSetAsString(\false);
  51220. }
  51221. return $this->name;
  51222. }
  51223. /**
  51224. * Returns the size of the test.
  51225. *
  51226. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  51227. *
  51228. * @internal This method is not covered by the backward compatibility promise for PHPUnit
  51229. */
  51230. public function getSize() : int
  51231. {
  51232. return \PHPUnit\Util\Test::getSize(\get_class($this), $this->getName(\false));
  51233. }
  51234. /**
  51235. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  51236. *
  51237. * @internal This method is not covered by the backward compatibility promise for PHPUnit
  51238. */
  51239. public function hasSize() : bool
  51240. {
  51241. return $this->getSize() !== \PHPUnit\Util\Test::UNKNOWN;
  51242. }
  51243. /**
  51244. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  51245. *
  51246. * @internal This method is not covered by the backward compatibility promise for PHPUnit
  51247. */
  51248. public function isSmall() : bool
  51249. {
  51250. return $this->getSize() === \PHPUnit\Util\Test::SMALL;
  51251. }
  51252. /**
  51253. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  51254. *
  51255. * @internal This method is not covered by the backward compatibility promise for PHPUnit
  51256. */
  51257. public function isMedium() : bool
  51258. {
  51259. return $this->getSize() === \PHPUnit\Util\Test::MEDIUM;
  51260. }
  51261. /**
  51262. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  51263. *
  51264. * @internal This method is not covered by the backward compatibility promise for PHPUnit
  51265. */
  51266. public function isLarge() : bool
  51267. {
  51268. return $this->getSize() === \PHPUnit\Util\Test::LARGE;
  51269. }
  51270. /**
  51271. * @internal This method is not covered by the backward compatibility promise for PHPUnit
  51272. */
  51273. public function getActualOutput() : string
  51274. {
  51275. if (!$this->outputBufferingActive) {
  51276. return $this->output;
  51277. }
  51278. return (string) \ob_get_contents();
  51279. }
  51280. /**
  51281. * @internal This method is not covered by the backward compatibility promise for PHPUnit
  51282. */
  51283. public function hasOutput() : bool
  51284. {
  51285. if ($this->output === '') {
  51286. return \false;
  51287. }
  51288. if ($this->hasExpectationOnOutput()) {
  51289. return \false;
  51290. }
  51291. return \true;
  51292. }
  51293. /**
  51294. * @internal This method is not covered by the backward compatibility promise for PHPUnit
  51295. */
  51296. public function doesNotPerformAssertions() : bool
  51297. {
  51298. return $this->doesNotPerformAssertions;
  51299. }
  51300. /**
  51301. * @internal This method is not covered by the backward compatibility promise for PHPUnit
  51302. */
  51303. public function hasExpectationOnOutput() : bool
  51304. {
  51305. return \is_string($this->outputExpectedString) || \is_string($this->outputExpectedRegex) || $this->outputRetrievedForAssertion;
  51306. }
  51307. /**
  51308. * @internal This method is not covered by the backward compatibility promise for PHPUnit
  51309. */
  51310. public function getExpectedException() : ?string
  51311. {
  51312. return $this->expectedException;
  51313. }
  51314. /**
  51315. * @return null|int|string
  51316. *
  51317. * @internal This method is not covered by the backward compatibility promise for PHPUnit
  51318. */
  51319. public function getExpectedExceptionCode()
  51320. {
  51321. return $this->expectedExceptionCode;
  51322. }
  51323. /**
  51324. * @internal This method is not covered by the backward compatibility promise for PHPUnit
  51325. */
  51326. public function getExpectedExceptionMessage() : ?string
  51327. {
  51328. return $this->expectedExceptionMessage;
  51329. }
  51330. /**
  51331. * @internal This method is not covered by the backward compatibility promise for PHPUnit
  51332. */
  51333. public function getExpectedExceptionMessageRegExp() : ?string
  51334. {
  51335. return $this->expectedExceptionMessageRegExp;
  51336. }
  51337. /**
  51338. * @internal This method is not covered by the backward compatibility promise for PHPUnit
  51339. */
  51340. public function setRegisterMockObjectsFromTestArgumentsRecursively(bool $flag) : void
  51341. {
  51342. $this->registerMockObjectsFromTestArgumentsRecursively = $flag;
  51343. }
  51344. /**
  51345. * @throws \Throwable
  51346. *
  51347. * @internal This method is not covered by the backward compatibility promise for PHPUnit
  51348. */
  51349. public function runBare() : void
  51350. {
  51351. $this->numAssertions = 0;
  51352. $this->snapshotGlobalState();
  51353. $this->startOutputBuffering();
  51354. \clearstatcache();
  51355. $currentWorkingDirectory = \getcwd();
  51356. $hookMethods = \PHPUnit\Util\Test::getHookMethods(\get_class($this));
  51357. $hasMetRequirements = \false;
  51358. try {
  51359. $this->checkRequirements();
  51360. $hasMetRequirements = \true;
  51361. if ($this->inIsolation) {
  51362. foreach ($hookMethods['beforeClass'] as $method) {
  51363. $this->{$method}();
  51364. }
  51365. }
  51366. $this->setDoesNotPerformAssertionsFromAnnotation();
  51367. foreach ($hookMethods['before'] as $method) {
  51368. $this->{$method}();
  51369. }
  51370. foreach ($hookMethods['preCondition'] as $method) {
  51371. $this->{$method}();
  51372. }
  51373. $this->testResult = $this->runTest();
  51374. $this->verifyMockObjects();
  51375. foreach ($hookMethods['postCondition'] as $method) {
  51376. $this->{$method}();
  51377. }
  51378. if (!empty($this->warnings)) {
  51379. throw new \PHPUnit\Framework\Warning(\implode("\n", \array_unique($this->warnings)));
  51380. }
  51381. $this->status = \PHPUnit\Runner\BaseTestRunner::STATUS_PASSED;
  51382. } catch (\PHPUnit\Framework\IncompleteTest $e) {
  51383. $this->status = \PHPUnit\Runner\BaseTestRunner::STATUS_INCOMPLETE;
  51384. $this->statusMessage = $e->getMessage();
  51385. } catch (\PHPUnit\Framework\SkippedTest $e) {
  51386. $this->status = \PHPUnit\Runner\BaseTestRunner::STATUS_SKIPPED;
  51387. $this->statusMessage = $e->getMessage();
  51388. } catch (\PHPUnit\Framework\Warning $e) {
  51389. $this->status = \PHPUnit\Runner\BaseTestRunner::STATUS_WARNING;
  51390. $this->statusMessage = $e->getMessage();
  51391. } catch (\PHPUnit\Framework\AssertionFailedError $e) {
  51392. $this->status = \PHPUnit\Runner\BaseTestRunner::STATUS_FAILURE;
  51393. $this->statusMessage = $e->getMessage();
  51394. } catch (\Prophecy\Exception\Prediction\PredictionException $e) {
  51395. $this->status = \PHPUnit\Runner\BaseTestRunner::STATUS_FAILURE;
  51396. $this->statusMessage = $e->getMessage();
  51397. } catch (\Throwable $_e) {
  51398. $e = $_e;
  51399. $this->status = \PHPUnit\Runner\BaseTestRunner::STATUS_ERROR;
  51400. $this->statusMessage = $_e->getMessage();
  51401. }
  51402. $this->mockObjects = [];
  51403. $this->prophet = null;
  51404. // Tear down the fixture. An exception raised in tearDown() will be
  51405. // caught and passed on when no exception was raised before.
  51406. try {
  51407. if ($hasMetRequirements) {
  51408. foreach ($hookMethods['after'] as $method) {
  51409. $this->{$method}();
  51410. }
  51411. if ($this->inIsolation) {
  51412. foreach ($hookMethods['afterClass'] as $method) {
  51413. $this->{$method}();
  51414. }
  51415. }
  51416. }
  51417. } catch (\Throwable $_e) {
  51418. $e = $e ?? $_e;
  51419. }
  51420. try {
  51421. $this->stopOutputBuffering();
  51422. } catch (\PHPUnit\Framework\RiskyTestError $_e) {
  51423. $e = $e ?? $_e;
  51424. }
  51425. if (isset($_e)) {
  51426. $this->status = \PHPUnit\Runner\BaseTestRunner::STATUS_ERROR;
  51427. $this->statusMessage = $_e->getMessage();
  51428. }
  51429. \clearstatcache();
  51430. if ($currentWorkingDirectory !== \getcwd()) {
  51431. \chdir($currentWorkingDirectory);
  51432. }
  51433. $this->restoreGlobalState();
  51434. $this->unregisterCustomComparators();
  51435. $this->cleanupIniSettings();
  51436. $this->cleanupLocaleSettings();
  51437. \libxml_clear_errors();
  51438. // Perform assertion on output.
  51439. if (!isset($e)) {
  51440. try {
  51441. if ($this->outputExpectedRegex !== null) {
  51442. $this->assertMatchesRegularExpression($this->outputExpectedRegex, $this->output);
  51443. } elseif ($this->outputExpectedString !== null) {
  51444. $this->assertEquals($this->outputExpectedString, $this->output);
  51445. }
  51446. } catch (\Throwable $_e) {
  51447. $e = $_e;
  51448. }
  51449. }
  51450. // Workaround for missing "finally".
  51451. if (isset($e)) {
  51452. if ($e instanceof \Prophecy\Exception\Prediction\PredictionException) {
  51453. $e = new \PHPUnit\Framework\AssertionFailedError($e->getMessage());
  51454. }
  51455. $this->onNotSuccessfulTest($e);
  51456. }
  51457. }
  51458. /**
  51459. * @internal This method is not covered by the backward compatibility promise for PHPUnit
  51460. */
  51461. public function setName(string $name) : void
  51462. {
  51463. $this->name = $name;
  51464. }
  51465. /**
  51466. * @param string[] $dependencies
  51467. *
  51468. * @internal This method is not covered by the backward compatibility promise for PHPUnit
  51469. */
  51470. public function setDependencies(array $dependencies) : void
  51471. {
  51472. $this->dependencies = $dependencies;
  51473. }
  51474. /**
  51475. * @internal This method is not covered by the backward compatibility promise for PHPUnit
  51476. */
  51477. public function getDependencies() : array
  51478. {
  51479. return $this->dependencies;
  51480. }
  51481. /**
  51482. * @internal This method is not covered by the backward compatibility promise for PHPUnit
  51483. */
  51484. public function hasDependencies() : bool
  51485. {
  51486. return \count($this->dependencies) > 0;
  51487. }
  51488. /**
  51489. * @internal This method is not covered by the backward compatibility promise for PHPUnit
  51490. */
  51491. public function setDependencyInput(array $dependencyInput) : void
  51492. {
  51493. $this->dependencyInput = $dependencyInput;
  51494. }
  51495. /**
  51496. * @internal This method is not covered by the backward compatibility promise for PHPUnit
  51497. */
  51498. public function getDependencyInput() : array
  51499. {
  51500. return $this->dependencyInput;
  51501. }
  51502. /**
  51503. * @internal This method is not covered by the backward compatibility promise for PHPUnit
  51504. */
  51505. public function setBeStrictAboutChangesToGlobalState(?bool $beStrictAboutChangesToGlobalState) : void
  51506. {
  51507. $this->beStrictAboutChangesToGlobalState = $beStrictAboutChangesToGlobalState;
  51508. }
  51509. /**
  51510. * @internal This method is not covered by the backward compatibility promise for PHPUnit
  51511. */
  51512. public function setBackupGlobals(?bool $backupGlobals) : void
  51513. {
  51514. if ($this->backupGlobals === null && $backupGlobals !== null) {
  51515. $this->backupGlobals = $backupGlobals;
  51516. }
  51517. }
  51518. /**
  51519. * @internal This method is not covered by the backward compatibility promise for PHPUnit
  51520. */
  51521. public function setBackupStaticAttributes(?bool $backupStaticAttributes) : void
  51522. {
  51523. if ($this->backupStaticAttributes === null && $backupStaticAttributes !== null) {
  51524. $this->backupStaticAttributes = $backupStaticAttributes;
  51525. }
  51526. }
  51527. /**
  51528. * @internal This method is not covered by the backward compatibility promise for PHPUnit
  51529. */
  51530. public function setRunTestInSeparateProcess(bool $runTestInSeparateProcess) : void
  51531. {
  51532. if ($this->runTestInSeparateProcess === null) {
  51533. $this->runTestInSeparateProcess = $runTestInSeparateProcess;
  51534. }
  51535. }
  51536. /**
  51537. * @internal This method is not covered by the backward compatibility promise for PHPUnit
  51538. */
  51539. public function setRunClassInSeparateProcess(bool $runClassInSeparateProcess) : void
  51540. {
  51541. if ($this->runClassInSeparateProcess === null) {
  51542. $this->runClassInSeparateProcess = $runClassInSeparateProcess;
  51543. }
  51544. }
  51545. /**
  51546. * @internal This method is not covered by the backward compatibility promise for PHPUnit
  51547. */
  51548. public function setPreserveGlobalState(bool $preserveGlobalState) : void
  51549. {
  51550. $this->preserveGlobalState = $preserveGlobalState;
  51551. }
  51552. /**
  51553. * @internal This method is not covered by the backward compatibility promise for PHPUnit
  51554. */
  51555. public function setInIsolation(bool $inIsolation) : void
  51556. {
  51557. $this->inIsolation = $inIsolation;
  51558. }
  51559. /**
  51560. * @internal This method is not covered by the backward compatibility promise for PHPUnit
  51561. */
  51562. public function isInIsolation() : bool
  51563. {
  51564. return $this->inIsolation;
  51565. }
  51566. /**
  51567. * @internal This method is not covered by the backward compatibility promise for PHPUnit
  51568. */
  51569. public function getResult()
  51570. {
  51571. return $this->testResult;
  51572. }
  51573. /**
  51574. * @internal This method is not covered by the backward compatibility promise for PHPUnit
  51575. */
  51576. public function setResult($result) : void
  51577. {
  51578. $this->testResult = $result;
  51579. }
  51580. /**
  51581. * @internal This method is not covered by the backward compatibility promise for PHPUnit
  51582. */
  51583. public function setOutputCallback(callable $callback) : void
  51584. {
  51585. $this->outputCallback = $callback;
  51586. }
  51587. /**
  51588. * @internal This method is not covered by the backward compatibility promise for PHPUnit
  51589. */
  51590. public function getTestResultObject() : ?\PHPUnit\Framework\TestResult
  51591. {
  51592. return $this->result;
  51593. }
  51594. /**
  51595. * @internal This method is not covered by the backward compatibility promise for PHPUnit
  51596. */
  51597. public function setTestResultObject(\PHPUnit\Framework\TestResult $result) : void
  51598. {
  51599. $this->result = $result;
  51600. }
  51601. /**
  51602. * @internal This method is not covered by the backward compatibility promise for PHPUnit
  51603. */
  51604. public function registerMockObject(\PHPUnit\Framework\MockObject\MockObject $mockObject) : void
  51605. {
  51606. $this->mockObjects[] = $mockObject;
  51607. }
  51608. /**
  51609. * @internal This method is not covered by the backward compatibility promise for PHPUnit
  51610. */
  51611. public function addToAssertionCount(int $count) : void
  51612. {
  51613. $this->numAssertions += $count;
  51614. }
  51615. /**
  51616. * Returns the number of assertions performed by this test.
  51617. *
  51618. * @internal This method is not covered by the backward compatibility promise for PHPUnit
  51619. */
  51620. public function getNumAssertions() : int
  51621. {
  51622. return $this->numAssertions;
  51623. }
  51624. /**
  51625. * @internal This method is not covered by the backward compatibility promise for PHPUnit
  51626. */
  51627. public function usesDataProvider() : bool
  51628. {
  51629. return !empty($this->data);
  51630. }
  51631. /**
  51632. * @internal This method is not covered by the backward compatibility promise for PHPUnit
  51633. */
  51634. public function dataDescription() : string
  51635. {
  51636. return \is_string($this->dataName) ? $this->dataName : '';
  51637. }
  51638. /**
  51639. * @return int|string
  51640. *
  51641. * @internal This method is not covered by the backward compatibility promise for PHPUnit
  51642. */
  51643. public function dataName()
  51644. {
  51645. return $this->dataName;
  51646. }
  51647. /**
  51648. * @internal This method is not covered by the backward compatibility promise for PHPUnit
  51649. */
  51650. public function getDataSetAsString(bool $includeData = \true) : string
  51651. {
  51652. $buffer = '';
  51653. if (!empty($this->data)) {
  51654. if (\is_int($this->dataName)) {
  51655. $buffer .= \sprintf(' with data set #%d', $this->dataName);
  51656. } else {
  51657. $buffer .= \sprintf(' with data set "%s"', $this->dataName);
  51658. }
  51659. $exporter = new \PHPUnit\SebastianBergmann\Exporter\Exporter();
  51660. if ($includeData) {
  51661. $buffer .= \sprintf(' (%s)', $exporter->shortenedRecursiveExport($this->data));
  51662. }
  51663. }
  51664. return $buffer;
  51665. }
  51666. /**
  51667. * Gets the data set of a TestCase.
  51668. *
  51669. * @internal This method is not covered by the backward compatibility promise for PHPUnit
  51670. */
  51671. public function getProvidedData() : array
  51672. {
  51673. return $this->data;
  51674. }
  51675. /**
  51676. * @internal This method is not covered by the backward compatibility promise for PHPUnit
  51677. */
  51678. public function addWarning(string $warning) : void
  51679. {
  51680. $this->warnings[] = $warning;
  51681. }
  51682. /**
  51683. * Override to run the test and assert its state.
  51684. *
  51685. * @throws AssertionFailedError
  51686. * @throws Exception
  51687. * @throws ExpectationFailedException
  51688. * @throws \SebastianBergmann\ObjectEnumerator\InvalidArgumentException
  51689. * @throws \Throwable
  51690. */
  51691. protected function runTest()
  51692. {
  51693. if (\trim($this->name) === '') {
  51694. throw new \PHPUnit\Framework\Exception('PHPUnit\\Framework\\TestCase::$name must be a non-blank string.');
  51695. }
  51696. $testArguments = \array_merge($this->data, $this->dependencyInput);
  51697. $this->registerMockObjectsFromTestArguments($testArguments);
  51698. try {
  51699. $testResult = $this->{$this->name}(...\array_values($testArguments));
  51700. } catch (\Throwable $exception) {
  51701. if (!$this->checkExceptionExpectations($exception)) {
  51702. throw $exception;
  51703. }
  51704. if ($this->expectedException !== null) {
  51705. $this->assertThat($exception, new \PHPUnit\Framework\Constraint\Exception($this->expectedException));
  51706. }
  51707. if ($this->expectedExceptionMessage !== null) {
  51708. $this->assertThat($exception, new \PHPUnit\Framework\Constraint\ExceptionMessage($this->expectedExceptionMessage));
  51709. }
  51710. if ($this->expectedExceptionMessageRegExp !== null) {
  51711. $this->assertThat($exception, new \PHPUnit\Framework\Constraint\ExceptionMessageRegularExpression($this->expectedExceptionMessageRegExp));
  51712. }
  51713. if ($this->expectedExceptionCode !== null) {
  51714. $this->assertThat($exception, new \PHPUnit\Framework\Constraint\ExceptionCode($this->expectedExceptionCode));
  51715. }
  51716. return;
  51717. }
  51718. if ($this->expectedException !== null) {
  51719. $this->assertThat(null, new \PHPUnit\Framework\Constraint\Exception($this->expectedException));
  51720. } elseif ($this->expectedExceptionMessage !== null) {
  51721. $this->numAssertions++;
  51722. throw new \PHPUnit\Framework\AssertionFailedError(\sprintf('Failed asserting that exception with message "%s" is thrown', $this->expectedExceptionMessage));
  51723. } elseif ($this->expectedExceptionMessageRegExp !== null) {
  51724. $this->numAssertions++;
  51725. throw new \PHPUnit\Framework\AssertionFailedError(\sprintf('Failed asserting that exception with message matching "%s" is thrown', $this->expectedExceptionMessageRegExp));
  51726. } elseif ($this->expectedExceptionCode !== null) {
  51727. $this->numAssertions++;
  51728. throw new \PHPUnit\Framework\AssertionFailedError(\sprintf('Failed asserting that exception with code "%s" is thrown', $this->expectedExceptionCode));
  51729. }
  51730. return $testResult;
  51731. }
  51732. /**
  51733. * This method is a wrapper for the ini_set() function that automatically
  51734. * resets the modified php.ini setting to its original value after the
  51735. * test is run.
  51736. *
  51737. * @throws Exception
  51738. */
  51739. protected function iniSet(string $varName, string $newValue) : void
  51740. {
  51741. $currentValue = \ini_set($varName, $newValue);
  51742. if ($currentValue !== \false) {
  51743. $this->iniSettings[$varName] = $currentValue;
  51744. } else {
  51745. throw new \PHPUnit\Framework\Exception(\sprintf('INI setting "%s" could not be set to "%s".', $varName, $newValue));
  51746. }
  51747. }
  51748. /**
  51749. * This method is a wrapper for the setlocale() function that automatically
  51750. * resets the locale to its original value after the test is run.
  51751. *
  51752. * @throws Exception
  51753. */
  51754. protected function setLocale(...$args) : void
  51755. {
  51756. if (\count($args) < 2) {
  51757. throw new \PHPUnit\Framework\Exception();
  51758. }
  51759. [$category, $locale] = $args;
  51760. if (\defined('LC_MESSAGES')) {
  51761. $categories[] = \LC_MESSAGES;
  51762. }
  51763. if (!\in_array($category, self::LOCALE_CATEGORIES, \true)) {
  51764. throw new \PHPUnit\Framework\Exception();
  51765. }
  51766. if (!\is_array($locale) && !\is_string($locale)) {
  51767. throw new \PHPUnit\Framework\Exception();
  51768. }
  51769. $this->locale[$category] = \setlocale($category, 0);
  51770. $result = \setlocale(...$args);
  51771. if ($result === \false) {
  51772. throw new \PHPUnit\Framework\Exception('The locale functionality is not implemented on your platform, ' . 'the specified locale does not exist or the category name is ' . 'invalid.');
  51773. }
  51774. }
  51775. /**
  51776. * Makes configurable stub for the specified class.
  51777. *
  51778. * @psalm-template RealInstanceType of object
  51779. * @psalm-param class-string<RealInstanceType> $originalClassName
  51780. * @psalm-return Stub&RealInstanceType
  51781. */
  51782. protected function createStub(string $originalClassName) : \PHPUnit\Framework\MockObject\Stub
  51783. {
  51784. return $this->createMock($originalClassName);
  51785. }
  51786. /**
  51787. * Returns a mock object for the specified class.
  51788. *
  51789. * @psalm-template RealInstanceType of object
  51790. * @psalm-param class-string<RealInstanceType> $originalClassName
  51791. * @psalm-return MockObject&RealInstanceType
  51792. */
  51793. protected function createMock(string $originalClassName) : \PHPUnit\Framework\MockObject\MockObject
  51794. {
  51795. return $this->getMockBuilder($originalClassName)->disableOriginalConstructor()->disableOriginalClone()->disableArgumentCloning()->disallowMockingUnknownTypes()->getMock();
  51796. }
  51797. /**
  51798. * Returns a configured mock object for the specified class.
  51799. *
  51800. * @psalm-template RealInstanceType of object
  51801. * @psalm-param class-string<RealInstanceType> $originalClassName
  51802. * @psalm-return MockObject&RealInstanceType
  51803. */
  51804. protected function createConfiguredMock(string $originalClassName, array $configuration) : \PHPUnit\Framework\MockObject\MockObject
  51805. {
  51806. $o = $this->createMock($originalClassName);
  51807. foreach ($configuration as $method => $return) {
  51808. $o->method($method)->willReturn($return);
  51809. }
  51810. return $o;
  51811. }
  51812. /**
  51813. * Returns a partial mock object for the specified class.
  51814. *
  51815. * @param string[] $methods
  51816. *
  51817. * @psalm-template RealInstanceType of object
  51818. * @psalm-param class-string<RealInstanceType> $originalClassName
  51819. * @psalm-return MockObject&RealInstanceType
  51820. */
  51821. protected function createPartialMock(string $originalClassName, array $methods) : \PHPUnit\Framework\MockObject\MockObject
  51822. {
  51823. try {
  51824. $reflector = new \ReflectionClass($originalClassName);
  51825. // @codeCoverageIgnoreStart
  51826. } catch (\ReflectionException $e) {
  51827. throw new \PHPUnit\Framework\Exception($e->getMessage(), (int) $e->getCode(), $e);
  51828. }
  51829. // @codeCoverageIgnoreEnd
  51830. $mockedMethodsThatDontExist = \array_filter($methods, static function (string $method) use($reflector) {
  51831. return !$reflector->hasMethod($method);
  51832. });
  51833. if ($mockedMethodsThatDontExist) {
  51834. $this->addWarning(\sprintf('createPartialMock() called with method(s) %s that do not exist in %s. This will not be allowed in future versions of PHPUnit.', \implode(', ', $mockedMethodsThatDontExist), $originalClassName));
  51835. }
  51836. return $this->getMockBuilder($originalClassName)->disableOriginalConstructor()->disableOriginalClone()->disableArgumentCloning()->disallowMockingUnknownTypes()->setMethods(empty($methods) ? null : $methods)->getMock();
  51837. }
  51838. /**
  51839. * Returns a test proxy for the specified class.
  51840. *
  51841. * @psalm-template RealInstanceType of object
  51842. * @psalm-param class-string<RealInstanceType> $originalClassName
  51843. * @psalm-return MockObject&RealInstanceType
  51844. */
  51845. protected function createTestProxy(string $originalClassName, array $constructorArguments = []) : \PHPUnit\Framework\MockObject\MockObject
  51846. {
  51847. return $this->getMockBuilder($originalClassName)->setConstructorArgs($constructorArguments)->enableProxyingToOriginalMethods()->getMock();
  51848. }
  51849. /**
  51850. * Mocks the specified class and returns the name of the mocked class.
  51851. *
  51852. * @param null|array $methods $methods
  51853. *
  51854. * @psalm-template RealInstanceType of object
  51855. * @psalm-param class-string<RealInstanceType>|string $originalClassName
  51856. * @psalm-return class-string<MockObject&RealInstanceType>
  51857. */
  51858. protected function getMockClass(string $originalClassName, $methods = [], array $arguments = [], string $mockClassName = '', bool $callOriginalConstructor = \false, bool $callOriginalClone = \true, bool $callAutoload = \true, bool $cloneArguments = \false) : string
  51859. {
  51860. $this->recordDoubledType($originalClassName);
  51861. $mock = $this->getMockObjectGenerator()->getMock($originalClassName, $methods, $arguments, $mockClassName, $callOriginalConstructor, $callOriginalClone, $callAutoload, $cloneArguments);
  51862. return \get_class($mock);
  51863. }
  51864. /**
  51865. * Returns a mock object for the specified abstract class with all abstract
  51866. * methods of the class mocked. Concrete methods are not mocked by default.
  51867. * To mock concrete methods, use the 7th parameter ($mockedMethods).
  51868. *
  51869. * @psalm-template RealInstanceType of object
  51870. * @psalm-param class-string<RealInstanceType> $originalClassName
  51871. * @psalm-return MockObject&RealInstanceType
  51872. */
  51873. protected function getMockForAbstractClass(string $originalClassName, array $arguments = [], string $mockClassName = '', bool $callOriginalConstructor = \true, bool $callOriginalClone = \true, bool $callAutoload = \true, array $mockedMethods = [], bool $cloneArguments = \false) : \PHPUnit\Framework\MockObject\MockObject
  51874. {
  51875. $this->recordDoubledType($originalClassName);
  51876. $mockObject = $this->getMockObjectGenerator()->getMockForAbstractClass($originalClassName, $arguments, $mockClassName, $callOriginalConstructor, $callOriginalClone, $callAutoload, $mockedMethods, $cloneArguments);
  51877. $this->registerMockObject($mockObject);
  51878. return $mockObject;
  51879. }
  51880. /**
  51881. * Returns a mock object based on the given WSDL file.
  51882. *
  51883. * @psalm-template RealInstanceType of object
  51884. * @psalm-param class-string<RealInstanceType>|string $originalClassName
  51885. * @psalm-return MockObject&RealInstanceType
  51886. */
  51887. protected function getMockFromWsdl(string $wsdlFile, string $originalClassName = '', string $mockClassName = '', array $methods = [], bool $callOriginalConstructor = \true, array $options = []) : \PHPUnit\Framework\MockObject\MockObject
  51888. {
  51889. $this->recordDoubledType(\SoapClient::class);
  51890. if ($originalClassName === '') {
  51891. $fileName = \pathinfo(\basename(\parse_url($wsdlFile, \PHP_URL_PATH)), \PATHINFO_FILENAME);
  51892. $originalClassName = \preg_replace('/\\W/', '', $fileName);
  51893. }
  51894. if (!\class_exists($originalClassName)) {
  51895. eval($this->getMockObjectGenerator()->generateClassFromWsdl($wsdlFile, $originalClassName, $methods, $options));
  51896. }
  51897. $mockObject = $this->getMockObjectGenerator()->getMock($originalClassName, $methods, ['', $options], $mockClassName, $callOriginalConstructor, \false, \false);
  51898. $this->registerMockObject($mockObject);
  51899. return $mockObject;
  51900. }
  51901. /**
  51902. * Returns a mock object for the specified trait with all abstract methods
  51903. * of the trait mocked. Concrete methods to mock can be specified with the
  51904. * `$mockedMethods` parameter.
  51905. */
  51906. protected function getMockForTrait(string $traitName, array $arguments = [], string $mockClassName = '', bool $callOriginalConstructor = \true, bool $callOriginalClone = \true, bool $callAutoload = \true, array $mockedMethods = [], bool $cloneArguments = \false) : \PHPUnit\Framework\MockObject\MockObject
  51907. {
  51908. $this->recordDoubledType($traitName);
  51909. $mockObject = $this->getMockObjectGenerator()->getMockForTrait($traitName, $arguments, $mockClassName, $callOriginalConstructor, $callOriginalClone, $callAutoload, $mockedMethods, $cloneArguments);
  51910. $this->registerMockObject($mockObject);
  51911. return $mockObject;
  51912. }
  51913. /**
  51914. * Returns an object for the specified trait.
  51915. */
  51916. protected function getObjectForTrait(string $traitName, array $arguments = [], string $traitClassName = '', bool $callOriginalConstructor = \true, bool $callOriginalClone = \true, bool $callAutoload = \true) : object
  51917. {
  51918. $this->recordDoubledType($traitName);
  51919. return $this->getMockObjectGenerator()->getObjectForTrait($traitName, $traitClassName, $callAutoload, $callOriginalConstructor, $arguments);
  51920. }
  51921. /**
  51922. * @throws \Prophecy\Exception\Doubler\ClassNotFoundException
  51923. * @throws \Prophecy\Exception\Doubler\DoubleException
  51924. * @throws \Prophecy\Exception\Doubler\InterfaceNotFoundException
  51925. *
  51926. * @psalm-param class-string|null $classOrInterface
  51927. */
  51928. protected function prophesize(?string $classOrInterface = null) : \Prophecy\Prophecy\ObjectProphecy
  51929. {
  51930. $this->addWarning('PHPUnit\\Framework\\TestCase::prophesize() is deprecated and will be removed in PHPUnit 10. Please use the trait provided by phpspec/prophecy-phpunit.');
  51931. if (\is_string($classOrInterface)) {
  51932. $this->recordDoubledType($classOrInterface);
  51933. }
  51934. return $this->getProphet()->prophesize($classOrInterface);
  51935. }
  51936. /**
  51937. * Creates a default TestResult object.
  51938. *
  51939. * @internal This method is not covered by the backward compatibility promise for PHPUnit
  51940. */
  51941. protected function createResult() : \PHPUnit\Framework\TestResult
  51942. {
  51943. return new \PHPUnit\Framework\TestResult();
  51944. }
  51945. /**
  51946. * Performs assertions shared by all tests of a test case.
  51947. *
  51948. * This method is called between setUp() and test.
  51949. */
  51950. protected function assertPreConditions() : void
  51951. {
  51952. }
  51953. /**
  51954. * Performs assertions shared by all tests of a test case.
  51955. *
  51956. * This method is called between test and tearDown().
  51957. */
  51958. protected function assertPostConditions() : void
  51959. {
  51960. }
  51961. /**
  51962. * This method is called when a test method did not execute successfully.
  51963. *
  51964. * @throws \Throwable
  51965. */
  51966. protected function onNotSuccessfulTest(\Throwable $t) : void
  51967. {
  51968. throw $t;
  51969. }
  51970. protected function recordDoubledType(string $originalClassName) : void
  51971. {
  51972. $this->doubledTypes[] = $originalClassName;
  51973. }
  51974. /**
  51975. * @throws \Throwable
  51976. */
  51977. private function verifyMockObjects() : void
  51978. {
  51979. foreach ($this->mockObjects as $mockObject) {
  51980. if ($mockObject->__phpunit_hasMatchers()) {
  51981. $this->numAssertions++;
  51982. }
  51983. $mockObject->__phpunit_verify($this->shouldInvocationMockerBeReset($mockObject));
  51984. }
  51985. if ($this->prophet !== null) {
  51986. try {
  51987. $this->prophet->checkPredictions();
  51988. } finally {
  51989. foreach ($this->prophet->getProphecies() as $objectProphecy) {
  51990. foreach ($objectProphecy->getMethodProphecies() as $methodProphecies) {
  51991. foreach ($methodProphecies as $methodProphecy) {
  51992. \assert($methodProphecy instanceof \Prophecy\Prophecy\MethodProphecy);
  51993. $this->numAssertions += \count($methodProphecy->getCheckedPredictions());
  51994. }
  51995. }
  51996. }
  51997. }
  51998. }
  51999. }
  52000. /**
  52001. * @throws Warning
  52002. * @throws SkippedTestError
  52003. * @throws SyntheticSkippedError
  52004. */
  52005. private function checkRequirements() : void
  52006. {
  52007. if (!$this->name || !\method_exists($this, $this->name)) {
  52008. return;
  52009. }
  52010. $missingRequirements = \PHPUnit\Util\Test::getMissingRequirements(\get_class($this), $this->name);
  52011. if (!empty($missingRequirements)) {
  52012. $this->markTestSkipped(\implode(\PHP_EOL, $missingRequirements));
  52013. }
  52014. }
  52015. private function handleDependencies() : bool
  52016. {
  52017. if (!empty($this->dependencies) && !$this->inIsolation) {
  52018. $className = \get_class($this);
  52019. $passed = $this->result->passed();
  52020. $passedKeys = \array_keys($passed);
  52021. foreach ($passedKeys as $key => $value) {
  52022. $pos = \strpos($value, ' with data set');
  52023. if ($pos !== \false) {
  52024. $passedKeys[$key] = \substr($value, 0, $pos);
  52025. }
  52026. }
  52027. $passedKeys = \array_flip(\array_unique($passedKeys));
  52028. foreach ($this->dependencies as $dependency) {
  52029. $deepClone = \false;
  52030. $shallowClone = \false;
  52031. if (empty($dependency)) {
  52032. $this->markSkippedForNotSpecifyingDependency();
  52033. return \false;
  52034. }
  52035. if (\strpos($dependency, 'clone ') === 0) {
  52036. $deepClone = \true;
  52037. $dependency = \substr($dependency, \strlen('clone '));
  52038. } elseif (\strpos($dependency, '!clone ') === 0) {
  52039. $deepClone = \false;
  52040. $dependency = \substr($dependency, \strlen('!clone '));
  52041. }
  52042. if (\strpos($dependency, 'shallowClone ') === 0) {
  52043. $shallowClone = \true;
  52044. $dependency = \substr($dependency, \strlen('shallowClone '));
  52045. } elseif (\strpos($dependency, '!shallowClone ') === 0) {
  52046. $shallowClone = \false;
  52047. $dependency = \substr($dependency, \strlen('!shallowClone '));
  52048. }
  52049. if (\strpos($dependency, '::') === \false) {
  52050. $dependency = $className . '::' . $dependency;
  52051. }
  52052. if (!isset($passedKeys[$dependency])) {
  52053. if (!$this->isCallableTestMethod($dependency)) {
  52054. $this->warnAboutDependencyThatDoesNotExist($dependency);
  52055. } else {
  52056. $this->markSkippedForMissingDependency($dependency);
  52057. }
  52058. return \false;
  52059. }
  52060. if (isset($passed[$dependency])) {
  52061. if ($passed[$dependency]['size'] !== \PHPUnit\Util\Test::UNKNOWN && $this->getSize() !== \PHPUnit\Util\Test::UNKNOWN && $passed[$dependency]['size'] > $this->getSize()) {
  52062. $this->result->addError($this, new \PHPUnit\Framework\SkippedTestError('This test depends on a test that is larger than itself.'), 0);
  52063. return \false;
  52064. }
  52065. if ($deepClone) {
  52066. $deepCopy = new \PHPUnit\DeepCopy\DeepCopy();
  52067. $deepCopy->skipUncloneable(\false);
  52068. $this->dependencyInput[$dependency] = $deepCopy->copy($passed[$dependency]['result']);
  52069. } elseif ($shallowClone) {
  52070. $this->dependencyInput[$dependency] = clone $passed[$dependency]['result'];
  52071. } else {
  52072. $this->dependencyInput[$dependency] = $passed[$dependency]['result'];
  52073. }
  52074. } else {
  52075. $this->dependencyInput[$dependency] = null;
  52076. }
  52077. }
  52078. }
  52079. return \true;
  52080. }
  52081. private function markSkippedForNotSpecifyingDependency() : void
  52082. {
  52083. $this->status = \PHPUnit\Runner\BaseTestRunner::STATUS_SKIPPED;
  52084. $this->result->startTest($this);
  52085. $this->result->addError($this, new \PHPUnit\Framework\SkippedTestError(\sprintf('This method has an invalid @depends annotation.')), 0);
  52086. $this->result->endTest($this, 0);
  52087. }
  52088. private function markSkippedForMissingDependency(string $dependency) : void
  52089. {
  52090. $this->status = \PHPUnit\Runner\BaseTestRunner::STATUS_SKIPPED;
  52091. $this->result->startTest($this);
  52092. $this->result->addError($this, new \PHPUnit\Framework\SkippedTestError(\sprintf('This test depends on "%s" to pass.', $dependency)), 0);
  52093. $this->result->endTest($this, 0);
  52094. }
  52095. private function warnAboutDependencyThatDoesNotExist(string $dependency) : void
  52096. {
  52097. $this->status = \PHPUnit\Runner\BaseTestRunner::STATUS_WARNING;
  52098. $this->result->startTest($this);
  52099. $this->result->addWarning($this, new \PHPUnit\Framework\Warning(\sprintf('This test depends on "%s" which does not exist.', $dependency)), 0);
  52100. $this->result->endTest($this, 0);
  52101. }
  52102. /**
  52103. * Get the mock object generator, creating it if it doesn't exist.
  52104. */
  52105. private function getMockObjectGenerator() : \PHPUnit\Framework\MockObject\Generator
  52106. {
  52107. if ($this->mockObjectGenerator === null) {
  52108. $this->mockObjectGenerator = new \PHPUnit\Framework\MockObject\Generator();
  52109. }
  52110. return $this->mockObjectGenerator;
  52111. }
  52112. private function startOutputBuffering() : void
  52113. {
  52114. \ob_start();
  52115. $this->outputBufferingActive = \true;
  52116. $this->outputBufferingLevel = \ob_get_level();
  52117. }
  52118. /**
  52119. * @throws RiskyTestError
  52120. */
  52121. private function stopOutputBuffering() : void
  52122. {
  52123. if (\ob_get_level() !== $this->outputBufferingLevel) {
  52124. while (\ob_get_level() >= $this->outputBufferingLevel) {
  52125. \ob_end_clean();
  52126. }
  52127. throw new \PHPUnit\Framework\RiskyTestError('Test code or tested code did not (only) close its own output buffers');
  52128. }
  52129. $this->output = \ob_get_contents();
  52130. if ($this->outputCallback !== \false) {
  52131. $this->output = (string) \call_user_func($this->outputCallback, $this->output);
  52132. }
  52133. \ob_end_clean();
  52134. $this->outputBufferingActive = \false;
  52135. $this->outputBufferingLevel = \ob_get_level();
  52136. }
  52137. private function snapshotGlobalState() : void
  52138. {
  52139. if ($this->runTestInSeparateProcess || $this->inIsolation || !$this->backupGlobals && !$this->backupStaticAttributes) {
  52140. return;
  52141. }
  52142. $this->snapshot = $this->createGlobalStateSnapshot($this->backupGlobals === \true);
  52143. }
  52144. /**
  52145. * @throws RiskyTestError
  52146. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  52147. */
  52148. private function restoreGlobalState() : void
  52149. {
  52150. if (!$this->snapshot instanceof \PHPUnit\SebastianBergmann\GlobalState\Snapshot) {
  52151. return;
  52152. }
  52153. if ($this->beStrictAboutChangesToGlobalState) {
  52154. try {
  52155. $this->compareGlobalStateSnapshots($this->snapshot, $this->createGlobalStateSnapshot($this->backupGlobals === \true));
  52156. } catch (\PHPUnit\Framework\RiskyTestError $rte) {
  52157. // Intentionally left empty
  52158. }
  52159. }
  52160. $restorer = new \PHPUnit\SebastianBergmann\GlobalState\Restorer();
  52161. if ($this->backupGlobals) {
  52162. $restorer->restoreGlobalVariables($this->snapshot);
  52163. }
  52164. if ($this->backupStaticAttributes) {
  52165. $restorer->restoreStaticAttributes($this->snapshot);
  52166. }
  52167. $this->snapshot = null;
  52168. if (isset($rte)) {
  52169. throw $rte;
  52170. }
  52171. }
  52172. private function createGlobalStateSnapshot(bool $backupGlobals) : \PHPUnit\SebastianBergmann\GlobalState\Snapshot
  52173. {
  52174. $blacklist = new \PHPUnit\SebastianBergmann\GlobalState\Blacklist();
  52175. foreach ($this->backupGlobalsBlacklist as $globalVariable) {
  52176. $blacklist->addGlobalVariable($globalVariable);
  52177. }
  52178. if (!\defined('PHPUNIT_TESTSUITE')) {
  52179. $blacklist->addClassNamePrefix('PHPUnit');
  52180. $blacklist->addClassNamePrefix('PHPUnit\\SebastianBergmann\\CodeCoverage');
  52181. $blacklist->addClassNamePrefix('PHPUnit\\SebastianBergmann\\FileIterator');
  52182. $blacklist->addClassNamePrefix('PHPUnit\\SebastianBergmann\\Invoker');
  52183. $blacklist->addClassNamePrefix('PHPUnit\\SebastianBergmann\\Template');
  52184. $blacklist->addClassNamePrefix('PHPUnit\\SebastianBergmann\\Timer');
  52185. $blacklist->addClassNamePrefix('PHP_Token');
  52186. $blacklist->addClassNamePrefix('Symfony');
  52187. $blacklist->addClassNamePrefix('PHPUnit\\Doctrine\\Instantiator');
  52188. $blacklist->addClassNamePrefix('Prophecy');
  52189. foreach ($this->backupStaticAttributesBlacklist as $class => $attributes) {
  52190. foreach ($attributes as $attribute) {
  52191. $blacklist->addStaticAttribute($class, $attribute);
  52192. }
  52193. }
  52194. }
  52195. return new \PHPUnit\SebastianBergmann\GlobalState\Snapshot($blacklist, $backupGlobals, (bool) $this->backupStaticAttributes, \false, \false, \false, \false, \false, \false, \false);
  52196. }
  52197. /**
  52198. * @throws RiskyTestError
  52199. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  52200. */
  52201. private function compareGlobalStateSnapshots(\PHPUnit\SebastianBergmann\GlobalState\Snapshot $before, \PHPUnit\SebastianBergmann\GlobalState\Snapshot $after) : void
  52202. {
  52203. $backupGlobals = $this->backupGlobals === null || $this->backupGlobals;
  52204. if ($backupGlobals) {
  52205. $this->compareGlobalStateSnapshotPart($before->globalVariables(), $after->globalVariables(), "--- Global variables before the test\n+++ Global variables after the test\n");
  52206. $this->compareGlobalStateSnapshotPart($before->superGlobalVariables(), $after->superGlobalVariables(), "--- Super-global variables before the test\n+++ Super-global variables after the test\n");
  52207. }
  52208. if ($this->backupStaticAttributes) {
  52209. $this->compareGlobalStateSnapshotPart($before->staticAttributes(), $after->staticAttributes(), "--- Static attributes before the test\n+++ Static attributes after the test\n");
  52210. }
  52211. }
  52212. /**
  52213. * @throws RiskyTestError
  52214. */
  52215. private function compareGlobalStateSnapshotPart(array $before, array $after, string $header) : void
  52216. {
  52217. if ($before != $after) {
  52218. $differ = new \PHPUnit\SebastianBergmann\Diff\Differ($header);
  52219. $exporter = new \PHPUnit\SebastianBergmann\Exporter\Exporter();
  52220. $diff = $differ->diff($exporter->export($before), $exporter->export($after));
  52221. throw new \PHPUnit\Framework\RiskyTestError($diff);
  52222. }
  52223. }
  52224. private function getProphet() : \Prophecy\Prophet
  52225. {
  52226. if ($this->prophet === null) {
  52227. $this->prophet = new \Prophecy\Prophet();
  52228. }
  52229. return $this->prophet;
  52230. }
  52231. /**
  52232. * @throws \SebastianBergmann\ObjectEnumerator\InvalidArgumentException
  52233. */
  52234. private function shouldInvocationMockerBeReset(\PHPUnit\Framework\MockObject\MockObject $mock) : bool
  52235. {
  52236. $enumerator = new \PHPUnit\SebastianBergmann\ObjectEnumerator\Enumerator();
  52237. foreach ($enumerator->enumerate($this->dependencyInput) as $object) {
  52238. if ($mock === $object) {
  52239. return \false;
  52240. }
  52241. }
  52242. if (!\is_array($this->testResult) && !\is_object($this->testResult)) {
  52243. return \true;
  52244. }
  52245. return !\in_array($mock, $enumerator->enumerate($this->testResult), \true);
  52246. }
  52247. /**
  52248. * @throws \SebastianBergmann\ObjectEnumerator\InvalidArgumentException
  52249. * @throws \SebastianBergmann\ObjectReflector\InvalidArgumentException
  52250. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  52251. */
  52252. private function registerMockObjectsFromTestArguments(array $testArguments, array &$visited = []) : void
  52253. {
  52254. if ($this->registerMockObjectsFromTestArgumentsRecursively) {
  52255. foreach ((new \PHPUnit\SebastianBergmann\ObjectEnumerator\Enumerator())->enumerate($testArguments) as $object) {
  52256. if ($object instanceof \PHPUnit\Framework\MockObject\MockObject) {
  52257. $this->registerMockObject($object);
  52258. }
  52259. }
  52260. } else {
  52261. foreach ($testArguments as $testArgument) {
  52262. if ($testArgument instanceof \PHPUnit\Framework\MockObject\MockObject) {
  52263. if (\PHPUnit\Util\Type::isCloneable($testArgument)) {
  52264. $testArgument = clone $testArgument;
  52265. }
  52266. $this->registerMockObject($testArgument);
  52267. } elseif (\is_array($testArgument) && !\in_array($testArgument, $visited, \true)) {
  52268. $visited[] = $testArgument;
  52269. $this->registerMockObjectsFromTestArguments($testArgument, $visited);
  52270. }
  52271. }
  52272. }
  52273. }
  52274. private function setDoesNotPerformAssertionsFromAnnotation() : void
  52275. {
  52276. $annotations = $this->getAnnotations();
  52277. if (isset($annotations['method']['doesNotPerformAssertions'])) {
  52278. $this->doesNotPerformAssertions = \true;
  52279. }
  52280. }
  52281. private function unregisterCustomComparators() : void
  52282. {
  52283. $factory = \PHPUnit\SebastianBergmann\Comparator\Factory::getInstance();
  52284. foreach ($this->customComparators as $comparator) {
  52285. $factory->unregister($comparator);
  52286. }
  52287. $this->customComparators = [];
  52288. }
  52289. private function cleanupIniSettings() : void
  52290. {
  52291. foreach ($this->iniSettings as $varName => $oldValue) {
  52292. \ini_set($varName, $oldValue);
  52293. }
  52294. $this->iniSettings = [];
  52295. }
  52296. private function cleanupLocaleSettings() : void
  52297. {
  52298. foreach ($this->locale as $category => $locale) {
  52299. \setlocale($category, $locale);
  52300. }
  52301. $this->locale = [];
  52302. }
  52303. /**
  52304. * @throws Exception
  52305. */
  52306. private function checkExceptionExpectations(\Throwable $throwable) : bool
  52307. {
  52308. $result = \false;
  52309. if ($this->expectedException !== null || $this->expectedExceptionCode !== null || $this->expectedExceptionMessage !== null || $this->expectedExceptionMessageRegExp !== null) {
  52310. $result = \true;
  52311. }
  52312. if ($throwable instanceof \PHPUnit\Framework\Exception) {
  52313. $result = \false;
  52314. }
  52315. if (\is_string($this->expectedException)) {
  52316. try {
  52317. $reflector = new \ReflectionClass($this->expectedException);
  52318. // @codeCoverageIgnoreStart
  52319. } catch (\ReflectionException $e) {
  52320. throw new \PHPUnit\Framework\Exception($e->getMessage(), (int) $e->getCode(), $e);
  52321. }
  52322. // @codeCoverageIgnoreEnd
  52323. if ($this->expectedException === 'PHPUnit\\Framework\\Exception' || $this->expectedException === '\\PHPUnit\\Framework\\Exception' || $reflector->isSubclassOf(\PHPUnit\Framework\Exception::class)) {
  52324. $result = \true;
  52325. }
  52326. }
  52327. return $result;
  52328. }
  52329. private function runInSeparateProcess() : bool
  52330. {
  52331. return ($this->runTestInSeparateProcess || $this->runClassInSeparateProcess) && !$this->inIsolation && !$this instanceof \PHPUnit\Runner\PhptTestCase;
  52332. }
  52333. private function isCallableTestMethod(string $dependency) : bool
  52334. {
  52335. [$className, $methodName] = \explode('::', $dependency);
  52336. if (!\class_exists($className)) {
  52337. return \false;
  52338. }
  52339. try {
  52340. $class = new \ReflectionClass($className);
  52341. } catch (\ReflectionException $e) {
  52342. return \false;
  52343. }
  52344. if (!$class->isSubclassOf(__CLASS__)) {
  52345. return \false;
  52346. }
  52347. if (!$class->hasMethod($methodName)) {
  52348. return \false;
  52349. }
  52350. try {
  52351. $method = $class->getMethod($methodName);
  52352. } catch (\ReflectionException $e) {
  52353. return \false;
  52354. }
  52355. return \PHPUnit\Util\Test::isTestMethod($method);
  52356. }
  52357. }
  52358. <?php
  52359. declare (strict_types=1);
  52360. /*
  52361. * This file is part of PHPUnit.
  52362. *
  52363. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  52364. *
  52365. * For the full copyright and license information, please view the LICENSE
  52366. * file that was distributed with this source code.
  52367. */
  52368. namespace PHPUnit\Framework;
  52369. /**
  52370. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  52371. */
  52372. final class WarningTestCase extends \PHPUnit\Framework\TestCase
  52373. {
  52374. /**
  52375. * @var bool
  52376. */
  52377. protected $backupGlobals = \false;
  52378. /**
  52379. * @var bool
  52380. */
  52381. protected $backupStaticAttributes = \false;
  52382. /**
  52383. * @var bool
  52384. */
  52385. protected $runTestInSeparateProcess = \false;
  52386. /**
  52387. * @var bool
  52388. */
  52389. protected $useErrorHandler = \false;
  52390. /**
  52391. * @var string
  52392. */
  52393. private $message;
  52394. /**
  52395. * @param string $message
  52396. */
  52397. public function __construct($message = '')
  52398. {
  52399. $this->message = $message;
  52400. parent::__construct('Warning');
  52401. }
  52402. public function getMessage() : string
  52403. {
  52404. return $this->message;
  52405. }
  52406. /**
  52407. * Returns a string representation of the test case.
  52408. */
  52409. public function toString() : string
  52410. {
  52411. return 'Warning';
  52412. }
  52413. /**
  52414. * @throws Exception
  52415. *
  52416. * @psalm-return never-return
  52417. */
  52418. protected function runTest() : void
  52419. {
  52420. throw new \PHPUnit\Framework\Warning($this->message);
  52421. }
  52422. }
  52423. <?php
  52424. declare (strict_types=1);
  52425. /*
  52426. * This file is part of PHPUnit.
  52427. *
  52428. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  52429. *
  52430. * For the full copyright and license information, please view the LICENSE
  52431. * file that was distributed with this source code.
  52432. */
  52433. namespace PHPUnit\Framework;
  52434. /**
  52435. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  52436. */
  52437. final class InvalidParameterGroupException extends \PHPUnit\Framework\Exception
  52438. {
  52439. }
  52440. <?php
  52441. declare (strict_types=1);
  52442. /*
  52443. * This file is part of PHPUnit.
  52444. *
  52445. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  52446. *
  52447. * For the full copyright and license information, please view the LICENSE
  52448. * file that was distributed with this source code.
  52449. */
  52450. namespace PHPUnit\Framework\Constraint;
  52451. use PHPUnit\SebastianBergmann\Diff\Differ;
  52452. use PHPUnit\SebastianBergmann\Diff\Output\UnifiedDiffOutputBuilder;
  52453. final class StringMatchesFormatDescription extends \PHPUnit\Framework\Constraint\RegularExpression
  52454. {
  52455. /**
  52456. * @var string
  52457. */
  52458. private $string;
  52459. public function __construct(string $string)
  52460. {
  52461. parent::__construct($this->createPatternFromFormat($this->convertNewlines($string)));
  52462. $this->string = $string;
  52463. }
  52464. /**
  52465. * Evaluates the constraint for parameter $other. Returns true if the
  52466. * constraint is met, false otherwise.
  52467. *
  52468. * @param mixed $other value or object to evaluate
  52469. */
  52470. protected function matches($other) : bool
  52471. {
  52472. return parent::matches($this->convertNewlines($other));
  52473. }
  52474. protected function failureDescription($other) : string
  52475. {
  52476. return 'string matches format description';
  52477. }
  52478. protected function additionalFailureDescription($other) : string
  52479. {
  52480. $from = \explode("\n", $this->string);
  52481. $to = \explode("\n", $this->convertNewlines($other));
  52482. foreach ($from as $index => $line) {
  52483. if (isset($to[$index]) && $line !== $to[$index]) {
  52484. $line = $this->createPatternFromFormat($line);
  52485. if (\preg_match($line, $to[$index]) > 0) {
  52486. $from[$index] = $to[$index];
  52487. }
  52488. }
  52489. }
  52490. $this->string = \implode("\n", $from);
  52491. $other = \implode("\n", $to);
  52492. return (new \PHPUnit\SebastianBergmann\Diff\Differ(new \PHPUnit\SebastianBergmann\Diff\Output\UnifiedDiffOutputBuilder("--- Expected\n+++ Actual\n")))->diff($this->string, $other);
  52493. }
  52494. private function createPatternFromFormat(string $string) : string
  52495. {
  52496. $string = \strtr(\preg_quote($string, '/'), ['%%' => '%', '%e' => '\\' . \DIRECTORY_SEPARATOR, '%s' => '[^\\r\\n]+', '%S' => '[^\\r\\n]*', '%a' => '.+', '%A' => '.*', '%w' => '\\s*', '%i' => '[+-]?\\d+', '%d' => '\\d+', '%x' => '[0-9a-fA-F]+', '%f' => '[+-]?\\.?\\d+\\.?\\d*(?:[Ee][+-]?\\d+)?', '%c' => '.']);
  52497. return '/^' . $string . '$/s';
  52498. }
  52499. private function convertNewlines(string $text) : string
  52500. {
  52501. return \preg_replace('/\\r\\n/', "\n", $text);
  52502. }
  52503. }
  52504. <?php
  52505. declare (strict_types=1);
  52506. /*
  52507. * This file is part of PHPUnit.
  52508. *
  52509. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  52510. *
  52511. * For the full copyright and license information, please view the LICENSE
  52512. * file that was distributed with this source code.
  52513. */
  52514. namespace PHPUnit\Framework\Constraint;
  52515. /**
  52516. * Constraint that accepts null.
  52517. */
  52518. final class IsNull extends \PHPUnit\Framework\Constraint\Constraint
  52519. {
  52520. /**
  52521. * Returns a string representation of the constraint.
  52522. */
  52523. public function toString() : string
  52524. {
  52525. return 'is null';
  52526. }
  52527. /**
  52528. * Evaluates the constraint for parameter $other. Returns true if the
  52529. * constraint is met, false otherwise.
  52530. *
  52531. * @param mixed $other value or object to evaluate
  52532. */
  52533. protected function matches($other) : bool
  52534. {
  52535. return $other === null;
  52536. }
  52537. }
  52538. <?php
  52539. declare (strict_types=1);
  52540. /*
  52541. * This file is part of PHPUnit.
  52542. *
  52543. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  52544. *
  52545. * For the full copyright and license information, please view the LICENSE
  52546. * file that was distributed with this source code.
  52547. */
  52548. namespace PHPUnit\Framework\Constraint;
  52549. /**
  52550. * Constraint that asserts that a string is valid JSON.
  52551. */
  52552. final class IsJson extends \PHPUnit\Framework\Constraint\Constraint
  52553. {
  52554. /**
  52555. * Returns a string representation of the constraint.
  52556. */
  52557. public function toString() : string
  52558. {
  52559. return 'is valid JSON';
  52560. }
  52561. /**
  52562. * Evaluates the constraint for parameter $other. Returns true if the
  52563. * constraint is met, false otherwise.
  52564. *
  52565. * @param mixed $other value or object to evaluate
  52566. */
  52567. protected function matches($other) : bool
  52568. {
  52569. if ($other === '') {
  52570. return \false;
  52571. }
  52572. \json_decode($other);
  52573. if (\json_last_error()) {
  52574. return \false;
  52575. }
  52576. return \true;
  52577. }
  52578. /**
  52579. * Returns the description of the failure
  52580. *
  52581. * The beginning of failure messages is "Failed asserting that" in most
  52582. * cases. This method should return the second part of that sentence.
  52583. *
  52584. * @param mixed $other evaluated value or object
  52585. *
  52586. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  52587. */
  52588. protected function failureDescription($other) : string
  52589. {
  52590. if ($other === '') {
  52591. return 'an empty string is valid JSON';
  52592. }
  52593. \json_decode($other);
  52594. $error = (string) \PHPUnit\Framework\Constraint\JsonMatchesErrorMessageProvider::determineJsonError((string) \json_last_error());
  52595. return \sprintf('%s is valid JSON (%s)', $this->exporter()->shortenedExport($other), $error);
  52596. }
  52597. }
  52598. <?php
  52599. declare (strict_types=1);
  52600. /*
  52601. * This file is part of PHPUnit.
  52602. *
  52603. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  52604. *
  52605. * For the full copyright and license information, please view the LICENSE
  52606. * file that was distributed with this source code.
  52607. */
  52608. namespace PHPUnit\Framework\Constraint;
  52609. /**
  52610. * Constraint that asserts that the object it is evaluated for has a given
  52611. * attribute.
  52612. *
  52613. * The attribute name is passed in the constructor.
  52614. */
  52615. final class ObjectHasAttribute extends \PHPUnit\Framework\Constraint\ClassHasAttribute
  52616. {
  52617. /**
  52618. * Evaluates the constraint for parameter $other. Returns true if the
  52619. * constraint is met, false otherwise.
  52620. *
  52621. * @param mixed $other value or object to evaluate
  52622. */
  52623. protected function matches($other) : bool
  52624. {
  52625. return (new \ReflectionObject($other))->hasProperty($this->attributeName());
  52626. }
  52627. }
  52628. <?php
  52629. declare (strict_types=1);
  52630. /*
  52631. * This file is part of PHPUnit.
  52632. *
  52633. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  52634. *
  52635. * For the full copyright and license information, please view the LICENSE
  52636. * file that was distributed with this source code.
  52637. */
  52638. namespace PHPUnit\Framework\Constraint;
  52639. use ArrayAccess;
  52640. /**
  52641. * Constraint that asserts that the array it is evaluated for has a given key.
  52642. *
  52643. * Uses array_key_exists() to check if the key is found in the input array, if
  52644. * not found the evaluation fails.
  52645. *
  52646. * The array key is passed in the constructor.
  52647. */
  52648. final class ArrayHasKey extends \PHPUnit\Framework\Constraint\Constraint
  52649. {
  52650. /**
  52651. * @var int|string
  52652. */
  52653. private $key;
  52654. /**
  52655. * @param int|string $key
  52656. */
  52657. public function __construct($key)
  52658. {
  52659. $this->key = $key;
  52660. }
  52661. /**
  52662. * Returns a string representation of the constraint.
  52663. *
  52664. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  52665. */
  52666. public function toString() : string
  52667. {
  52668. return 'has the key ' . $this->exporter()->export($this->key);
  52669. }
  52670. /**
  52671. * Evaluates the constraint for parameter $other. Returns true if the
  52672. * constraint is met, false otherwise.
  52673. *
  52674. * @param mixed $other value or object to evaluate
  52675. */
  52676. protected function matches($other) : bool
  52677. {
  52678. if (\is_array($other)) {
  52679. return \array_key_exists($this->key, $other);
  52680. }
  52681. if ($other instanceof \ArrayAccess) {
  52682. return $other->offsetExists($this->key);
  52683. }
  52684. return \false;
  52685. }
  52686. /**
  52687. * Returns the description of the failure
  52688. *
  52689. * The beginning of failure messages is "Failed asserting that" in most
  52690. * cases. This method should return the second part of that sentence.
  52691. *
  52692. * @param mixed $other evaluated value or object
  52693. *
  52694. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  52695. */
  52696. protected function failureDescription($other) : string
  52697. {
  52698. return 'an array ' . $this->toString();
  52699. }
  52700. }
  52701. <?php
  52702. declare (strict_types=1);
  52703. /*
  52704. * This file is part of PHPUnit.
  52705. *
  52706. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  52707. *
  52708. * For the full copyright and license information, please view the LICENSE
  52709. * file that was distributed with this source code.
  52710. */
  52711. namespace PHPUnit\Framework\Constraint;
  52712. /**
  52713. * Constraint that asserts that the Traversable it is applied to contains
  52714. * a given value (using strict comparison).
  52715. */
  52716. final class TraversableContainsIdentical extends \PHPUnit\Framework\Constraint\TraversableContains
  52717. {
  52718. /**
  52719. * Evaluates the constraint for parameter $other. Returns true if the
  52720. * constraint is met, false otherwise.
  52721. *
  52722. * @param mixed $other value or object to evaluate
  52723. */
  52724. protected function matches($other) : bool
  52725. {
  52726. if ($other instanceof \SplObjectStorage) {
  52727. return $other->contains($this->value());
  52728. }
  52729. foreach ($other as $element) {
  52730. if ($this->value() === $element) {
  52731. return \true;
  52732. }
  52733. }
  52734. return \false;
  52735. }
  52736. }
  52737. <?php
  52738. declare (strict_types=1);
  52739. /*
  52740. * This file is part of PHPUnit.
  52741. *
  52742. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  52743. *
  52744. * For the full copyright and license information, please view the LICENSE
  52745. * file that was distributed with this source code.
  52746. */
  52747. namespace PHPUnit\Framework\Constraint;
  52748. /**
  52749. * Constraint that accepts nan.
  52750. */
  52751. final class IsNan extends \PHPUnit\Framework\Constraint\Constraint
  52752. {
  52753. /**
  52754. * Returns a string representation of the constraint.
  52755. */
  52756. public function toString() : string
  52757. {
  52758. return 'is nan';
  52759. }
  52760. /**
  52761. * Evaluates the constraint for parameter $other. Returns true if the
  52762. * constraint is met, false otherwise.
  52763. *
  52764. * @param mixed $other value or object to evaluate
  52765. */
  52766. protected function matches($other) : bool
  52767. {
  52768. return \is_nan($other);
  52769. }
  52770. }
  52771. <?php
  52772. declare (strict_types=1);
  52773. /*
  52774. * This file is part of PHPUnit.
  52775. *
  52776. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  52777. *
  52778. * For the full copyright and license information, please view the LICENSE
  52779. * file that was distributed with this source code.
  52780. */
  52781. namespace PHPUnit\Framework\Constraint;
  52782. final class ExceptionMessage extends \PHPUnit\Framework\Constraint\Constraint
  52783. {
  52784. /**
  52785. * @var string
  52786. */
  52787. private $expectedMessage;
  52788. public function __construct(string $expected)
  52789. {
  52790. $this->expectedMessage = $expected;
  52791. }
  52792. public function toString() : string
  52793. {
  52794. if ($this->expectedMessage === '') {
  52795. return 'exception message is empty';
  52796. }
  52797. return 'exception message contains ';
  52798. }
  52799. /**
  52800. * Evaluates the constraint for parameter $other. Returns true if the
  52801. * constraint is met, false otherwise.
  52802. *
  52803. * @param \Throwable $other
  52804. */
  52805. protected function matches($other) : bool
  52806. {
  52807. if ($this->expectedMessage === '') {
  52808. return $other->getMessage() === '';
  52809. }
  52810. return \strpos((string) $other->getMessage(), $this->expectedMessage) !== \false;
  52811. }
  52812. /**
  52813. * Returns the description of the failure
  52814. *
  52815. * The beginning of failure messages is "Failed asserting that" in most
  52816. * cases. This method should return the second part of that sentence.
  52817. *
  52818. * @param mixed $other evaluated value or object
  52819. */
  52820. protected function failureDescription($other) : string
  52821. {
  52822. if ($this->expectedMessage === '') {
  52823. return \sprintf("exception message is empty but is '%s'", $other->getMessage());
  52824. }
  52825. return \sprintf("exception message '%s' contains '%s'", $other->getMessage(), $this->expectedMessage);
  52826. }
  52827. }
  52828. <?php
  52829. declare (strict_types=1);
  52830. /*
  52831. * This file is part of PHPUnit.
  52832. *
  52833. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  52834. *
  52835. * For the full copyright and license information, please view the LICENSE
  52836. * file that was distributed with this source code.
  52837. */
  52838. namespace PHPUnit\Framework\Constraint;
  52839. /**
  52840. * Constraint that checks if the file(name) that it is evaluated for exists.
  52841. *
  52842. * The file path to check is passed as $other in evaluate().
  52843. */
  52844. final class FileExists extends \PHPUnit\Framework\Constraint\Constraint
  52845. {
  52846. /**
  52847. * Returns a string representation of the constraint.
  52848. */
  52849. public function toString() : string
  52850. {
  52851. return 'file exists';
  52852. }
  52853. /**
  52854. * Evaluates the constraint for parameter $other. Returns true if the
  52855. * constraint is met, false otherwise.
  52856. *
  52857. * @param mixed $other value or object to evaluate
  52858. */
  52859. protected function matches($other) : bool
  52860. {
  52861. return \file_exists($other);
  52862. }
  52863. /**
  52864. * Returns the description of the failure
  52865. *
  52866. * The beginning of failure messages is "Failed asserting that" in most
  52867. * cases. This method should return the second part of that sentence.
  52868. *
  52869. * @param mixed $other evaluated value or object
  52870. */
  52871. protected function failureDescription($other) : string
  52872. {
  52873. return \sprintf('file "%s" exists', $other);
  52874. }
  52875. }
  52876. <?php
  52877. declare (strict_types=1);
  52878. /*
  52879. * This file is part of PHPUnit.
  52880. *
  52881. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  52882. *
  52883. * For the full copyright and license information, please view the LICENSE
  52884. * file that was distributed with this source code.
  52885. */
  52886. namespace PHPUnit\Framework\Constraint;
  52887. /**
  52888. * Constraint that asserts that the value it is evaluated for is of a
  52889. * specified type.
  52890. *
  52891. * The expected value is passed in the constructor.
  52892. */
  52893. final class IsType extends \PHPUnit\Framework\Constraint\Constraint
  52894. {
  52895. /**
  52896. * @var string
  52897. */
  52898. public const TYPE_ARRAY = 'array';
  52899. /**
  52900. * @var string
  52901. */
  52902. public const TYPE_BOOL = 'bool';
  52903. /**
  52904. * @var string
  52905. */
  52906. public const TYPE_FLOAT = 'float';
  52907. /**
  52908. * @var string
  52909. */
  52910. public const TYPE_INT = 'int';
  52911. /**
  52912. * @var string
  52913. */
  52914. public const TYPE_NULL = 'null';
  52915. /**
  52916. * @var string
  52917. */
  52918. public const TYPE_NUMERIC = 'numeric';
  52919. /**
  52920. * @var string
  52921. */
  52922. public const TYPE_OBJECT = 'object';
  52923. /**
  52924. * @var string
  52925. */
  52926. public const TYPE_RESOURCE = 'resource';
  52927. /**
  52928. * @var string
  52929. */
  52930. public const TYPE_STRING = 'string';
  52931. /**
  52932. * @var string
  52933. */
  52934. public const TYPE_SCALAR = 'scalar';
  52935. /**
  52936. * @var string
  52937. */
  52938. public const TYPE_CALLABLE = 'callable';
  52939. /**
  52940. * @var string
  52941. */
  52942. public const TYPE_ITERABLE = 'iterable';
  52943. /**
  52944. * @var array<string,bool>
  52945. */
  52946. private const KNOWN_TYPES = ['array' => \true, 'boolean' => \true, 'bool' => \true, 'double' => \true, 'float' => \true, 'integer' => \true, 'int' => \true, 'null' => \true, 'numeric' => \true, 'object' => \true, 'real' => \true, 'resource' => \true, 'string' => \true, 'scalar' => \true, 'callable' => \true, 'iterable' => \true];
  52947. /**
  52948. * @var string
  52949. */
  52950. private $type;
  52951. /**
  52952. * @throws \PHPUnit\Framework\Exception
  52953. */
  52954. public function __construct(string $type)
  52955. {
  52956. if (!isset(self::KNOWN_TYPES[$type])) {
  52957. throw new \PHPUnit\Framework\Exception(\sprintf('Type specified for PHPUnit\\Framework\\Constraint\\IsType <%s> ' . 'is not a valid type.', $type));
  52958. }
  52959. $this->type = $type;
  52960. }
  52961. /**
  52962. * Returns a string representation of the constraint.
  52963. */
  52964. public function toString() : string
  52965. {
  52966. return \sprintf('is of type "%s"', $this->type);
  52967. }
  52968. /**
  52969. * Evaluates the constraint for parameter $other. Returns true if the
  52970. * constraint is met, false otherwise.
  52971. *
  52972. * @param mixed $other value or object to evaluate
  52973. */
  52974. protected function matches($other) : bool
  52975. {
  52976. switch ($this->type) {
  52977. case 'numeric':
  52978. return \is_numeric($other);
  52979. case 'integer':
  52980. case 'int':
  52981. return \is_int($other);
  52982. case 'double':
  52983. case 'float':
  52984. case 'real':
  52985. return \is_float($other);
  52986. case 'string':
  52987. return \is_string($other);
  52988. case 'boolean':
  52989. case 'bool':
  52990. return \is_bool($other);
  52991. case 'null':
  52992. return null === $other;
  52993. case 'array':
  52994. return \is_array($other);
  52995. case 'object':
  52996. return \is_object($other);
  52997. case 'resource':
  52998. if (\is_resource($other)) {
  52999. return \true;
  53000. }
  53001. try {
  53002. $resource = @\get_resource_type($other);
  53003. if (\is_string($resource)) {
  53004. return \true;
  53005. }
  53006. } catch (\TypeError $e) {
  53007. }
  53008. return \false;
  53009. case 'scalar':
  53010. return \is_scalar($other);
  53011. case 'callable':
  53012. return \is_callable($other);
  53013. case 'iterable':
  53014. return \is_iterable($other);
  53015. default:
  53016. return \false;
  53017. }
  53018. }
  53019. }
  53020. <?php
  53021. declare (strict_types=1);
  53022. /*
  53023. * This file is part of PHPUnit.
  53024. *
  53025. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  53026. *
  53027. * For the full copyright and license information, please view the LICENSE
  53028. * file that was distributed with this source code.
  53029. */
  53030. namespace PHPUnit\Framework\Constraint;
  53031. use PHPUnit\Framework\ExpectationFailedException;
  53032. use PHPUnit\SebastianBergmann\Comparator\ComparisonFailure;
  53033. use PHPUnit\SebastianBergmann\Comparator\Factory as ComparatorFactory;
  53034. final class IsEqualCanonicalizing extends \PHPUnit\Framework\Constraint\Constraint
  53035. {
  53036. /**
  53037. * @var mixed
  53038. */
  53039. private $value;
  53040. public function __construct($value)
  53041. {
  53042. $this->value = $value;
  53043. }
  53044. /**
  53045. * Evaluates the constraint for parameter $other
  53046. *
  53047. * If $returnResult is set to false (the default), an exception is thrown
  53048. * in case of a failure. null is returned otherwise.
  53049. *
  53050. * If $returnResult is true, the result of the evaluation is returned as
  53051. * a boolean value instead: true in case of success, false in case of a
  53052. * failure.
  53053. *
  53054. * @throws ExpectationFailedException
  53055. */
  53056. public function evaluate($other, string $description = '', bool $returnResult = \false) : ?bool
  53057. {
  53058. // If $this->value and $other are identical, they are also equal.
  53059. // This is the most common path and will allow us to skip
  53060. // initialization of all the comparators.
  53061. if ($this->value === $other) {
  53062. return \true;
  53063. }
  53064. $comparatorFactory = \PHPUnit\SebastianBergmann\Comparator\Factory::getInstance();
  53065. try {
  53066. $comparator = $comparatorFactory->getComparatorFor($this->value, $other);
  53067. $comparator->assertEquals($this->value, $other, 0.0, \true, \false);
  53068. } catch (\PHPUnit\SebastianBergmann\Comparator\ComparisonFailure $f) {
  53069. if ($returnResult) {
  53070. return \false;
  53071. }
  53072. throw new \PHPUnit\Framework\ExpectationFailedException(\trim($description . "\n" . $f->getMessage()), $f);
  53073. }
  53074. return \true;
  53075. }
  53076. /**
  53077. * Returns a string representation of the constraint.
  53078. *
  53079. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  53080. */
  53081. public function toString() : string
  53082. {
  53083. if (\is_string($this->value)) {
  53084. if (\strpos($this->value, "\n") !== \false) {
  53085. return 'is equal to <text>';
  53086. }
  53087. return \sprintf("is equal to '%s'", $this->value);
  53088. }
  53089. return \sprintf('is equal to %s', $this->exporter()->export($this->value));
  53090. }
  53091. }
  53092. <?php
  53093. declare (strict_types=1);
  53094. /*
  53095. * This file is part of PHPUnit.
  53096. *
  53097. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  53098. *
  53099. * For the full copyright and license information, please view the LICENSE
  53100. * file that was distributed with this source code.
  53101. */
  53102. namespace PHPUnit\Framework\Constraint;
  53103. /**
  53104. * Constraint that accepts true.
  53105. */
  53106. final class IsTrue extends \PHPUnit\Framework\Constraint\Constraint
  53107. {
  53108. /**
  53109. * Returns a string representation of the constraint.
  53110. */
  53111. public function toString() : string
  53112. {
  53113. return 'is true';
  53114. }
  53115. /**
  53116. * Evaluates the constraint for parameter $other. Returns true if the
  53117. * constraint is met, false otherwise.
  53118. *
  53119. * @param mixed $other value or object to evaluate
  53120. */
  53121. protected function matches($other) : bool
  53122. {
  53123. return $other === \true;
  53124. }
  53125. }
  53126. <?php
  53127. declare (strict_types=1);
  53128. /*
  53129. * This file is part of PHPUnit.
  53130. *
  53131. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  53132. *
  53133. * For the full copyright and license information, please view the LICENSE
  53134. * file that was distributed with this source code.
  53135. */
  53136. namespace PHPUnit\Framework\Constraint;
  53137. use PHPUnit\Framework\ExpectationFailedException;
  53138. /**
  53139. * Logical XOR.
  53140. */
  53141. final class LogicalXor extends \PHPUnit\Framework\Constraint\Constraint
  53142. {
  53143. /**
  53144. * @var Constraint[]
  53145. */
  53146. private $constraints = [];
  53147. public static function fromConstraints(\PHPUnit\Framework\Constraint\Constraint ...$constraints) : self
  53148. {
  53149. $constraint = new self();
  53150. $constraint->constraints = \array_values($constraints);
  53151. return $constraint;
  53152. }
  53153. /**
  53154. * @param mixed[] $constraints
  53155. */
  53156. public function setConstraints(array $constraints) : void
  53157. {
  53158. $this->constraints = [];
  53159. foreach ($constraints as $constraint) {
  53160. if (!$constraint instanceof \PHPUnit\Framework\Constraint\Constraint) {
  53161. $constraint = new \PHPUnit\Framework\Constraint\IsEqual($constraint);
  53162. }
  53163. $this->constraints[] = $constraint;
  53164. }
  53165. }
  53166. /**
  53167. * Evaluates the constraint for parameter $other
  53168. *
  53169. * If $returnResult is set to false (the default), an exception is thrown
  53170. * in case of a failure. null is returned otherwise.
  53171. *
  53172. * If $returnResult is true, the result of the evaluation is returned as
  53173. * a boolean value instead: true in case of success, false in case of a
  53174. * failure.
  53175. *
  53176. * @throws ExpectationFailedException
  53177. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  53178. */
  53179. public function evaluate($other, string $description = '', bool $returnResult = \false) : ?bool
  53180. {
  53181. $success = \true;
  53182. $lastResult = null;
  53183. foreach ($this->constraints as $constraint) {
  53184. $result = $constraint->evaluate($other, $description, \true);
  53185. if ($result === $lastResult) {
  53186. $success = \false;
  53187. break;
  53188. }
  53189. $lastResult = $result;
  53190. }
  53191. if ($returnResult) {
  53192. return $success;
  53193. }
  53194. if (!$success) {
  53195. $this->fail($other, $description);
  53196. }
  53197. return null;
  53198. }
  53199. /**
  53200. * Returns a string representation of the constraint.
  53201. */
  53202. public function toString() : string
  53203. {
  53204. $text = '';
  53205. foreach ($this->constraints as $key => $constraint) {
  53206. if ($key > 0) {
  53207. $text .= ' xor ';
  53208. }
  53209. $text .= $constraint->toString();
  53210. }
  53211. return $text;
  53212. }
  53213. /**
  53214. * Counts the number of constraint elements.
  53215. */
  53216. public function count() : int
  53217. {
  53218. $count = 0;
  53219. foreach ($this->constraints as $constraint) {
  53220. $count += \count($constraint);
  53221. }
  53222. return $count;
  53223. }
  53224. }
  53225. <?php
  53226. declare (strict_types=1);
  53227. /*
  53228. * This file is part of PHPUnit.
  53229. *
  53230. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  53231. *
  53232. * For the full copyright and license information, please view the LICENSE
  53233. * file that was distributed with this source code.
  53234. */
  53235. namespace PHPUnit\Framework\Constraint;
  53236. use PHPUnit\Framework\ExpectationFailedException;
  53237. /**
  53238. * Logical NOT.
  53239. */
  53240. final class LogicalNot extends \PHPUnit\Framework\Constraint\Constraint
  53241. {
  53242. /**
  53243. * @var Constraint
  53244. */
  53245. private $constraint;
  53246. public static function negate(string $string) : string
  53247. {
  53248. $positives = ['contains ', 'exists', 'has ', 'is ', 'are ', 'matches ', 'starts with ', 'ends with ', 'reference ', 'not not '];
  53249. $negatives = ['does not contain ', 'does not exist', 'does not have ', 'is not ', 'are not ', 'does not match ', 'starts not with ', 'ends not with ', 'don\'t reference ', 'not '];
  53250. \preg_match('/(\'[\\w\\W]*\')([\\w\\W]*)("[\\w\\W]*")/i', $string, $matches);
  53251. if (\count($matches) > 0) {
  53252. $nonInput = $matches[2];
  53253. $negatedString = \str_replace($nonInput, \str_replace($positives, $negatives, $nonInput), $string);
  53254. } else {
  53255. $negatedString = \str_replace($positives, $negatives, $string);
  53256. }
  53257. return $negatedString;
  53258. }
  53259. /**
  53260. * @param Constraint|mixed $constraint
  53261. */
  53262. public function __construct($constraint)
  53263. {
  53264. if (!$constraint instanceof \PHPUnit\Framework\Constraint\Constraint) {
  53265. $constraint = new \PHPUnit\Framework\Constraint\IsEqual($constraint);
  53266. }
  53267. $this->constraint = $constraint;
  53268. }
  53269. /**
  53270. * Evaluates the constraint for parameter $other
  53271. *
  53272. * If $returnResult is set to false (the default), an exception is thrown
  53273. * in case of a failure. null is returned otherwise.
  53274. *
  53275. * If $returnResult is true, the result of the evaluation is returned as
  53276. * a boolean value instead: true in case of success, false in case of a
  53277. * failure.
  53278. *
  53279. * @throws ExpectationFailedException
  53280. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  53281. */
  53282. public function evaluate($other, string $description = '', bool $returnResult = \false) : ?bool
  53283. {
  53284. $success = !$this->constraint->evaluate($other, $description, \true);
  53285. if ($returnResult) {
  53286. return $success;
  53287. }
  53288. if (!$success) {
  53289. $this->fail($other, $description);
  53290. }
  53291. return null;
  53292. }
  53293. /**
  53294. * Returns a string representation of the constraint.
  53295. */
  53296. public function toString() : string
  53297. {
  53298. switch (\get_class($this->constraint)) {
  53299. case \PHPUnit\Framework\Constraint\LogicalAnd::class:
  53300. case self::class:
  53301. case \PHPUnit\Framework\Constraint\LogicalOr::class:
  53302. return 'not( ' . $this->constraint->toString() . ' )';
  53303. default:
  53304. return self::negate($this->constraint->toString());
  53305. }
  53306. }
  53307. /**
  53308. * Counts the number of constraint elements.
  53309. */
  53310. public function count() : int
  53311. {
  53312. return \count($this->constraint);
  53313. }
  53314. /**
  53315. * Returns the description of the failure
  53316. *
  53317. * The beginning of failure messages is "Failed asserting that" in most
  53318. * cases. This method should return the second part of that sentence.
  53319. *
  53320. * @param mixed $other evaluated value or object
  53321. *
  53322. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  53323. */
  53324. protected function failureDescription($other) : string
  53325. {
  53326. switch (\get_class($this->constraint)) {
  53327. case \PHPUnit\Framework\Constraint\LogicalAnd::class:
  53328. case self::class:
  53329. case \PHPUnit\Framework\Constraint\LogicalOr::class:
  53330. return 'not( ' . $this->constraint->failureDescription($other) . ' )';
  53331. default:
  53332. return self::negate($this->constraint->failureDescription($other));
  53333. }
  53334. }
  53335. }
  53336. <?php
  53337. declare (strict_types=1);
  53338. /*
  53339. * This file is part of PHPUnit.
  53340. *
  53341. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  53342. *
  53343. * For the full copyright and license information, please view the LICENSE
  53344. * file that was distributed with this source code.
  53345. */
  53346. namespace PHPUnit\Framework\Constraint;
  53347. use PHPUnit\Framework\InvalidArgumentException;
  53348. /**
  53349. * Constraint that asserts that the string it is evaluated for begins with a
  53350. * given prefix.
  53351. */
  53352. final class StringStartsWith extends \PHPUnit\Framework\Constraint\Constraint
  53353. {
  53354. /**
  53355. * @var string
  53356. */
  53357. private $prefix;
  53358. public function __construct(string $prefix)
  53359. {
  53360. if (\strlen($prefix) === 0) {
  53361. throw \PHPUnit\Framework\InvalidArgumentException::create(1, 'non-empty string');
  53362. }
  53363. $this->prefix = $prefix;
  53364. }
  53365. /**
  53366. * Returns a string representation of the constraint.
  53367. */
  53368. public function toString() : string
  53369. {
  53370. return 'starts with "' . $this->prefix . '"';
  53371. }
  53372. /**
  53373. * Evaluates the constraint for parameter $other. Returns true if the
  53374. * constraint is met, false otherwise.
  53375. *
  53376. * @param mixed $other value or object to evaluate
  53377. */
  53378. protected function matches($other) : bool
  53379. {
  53380. return \strpos((string) $other, $this->prefix) === 0;
  53381. }
  53382. }
  53383. <?php
  53384. declare (strict_types=1);
  53385. /*
  53386. * This file is part of PHPUnit.
  53387. *
  53388. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  53389. *
  53390. * For the full copyright and license information, please view the LICENSE
  53391. * file that was distributed with this source code.
  53392. */
  53393. namespace PHPUnit\Framework\Constraint;
  53394. /**
  53395. * Constraint that asserts that the Traversable it is applied to contains
  53396. * a given value.
  53397. */
  53398. abstract class TraversableContains extends \PHPUnit\Framework\Constraint\Constraint
  53399. {
  53400. /**
  53401. * @var mixed
  53402. */
  53403. private $value;
  53404. public function __construct($value)
  53405. {
  53406. $this->value = $value;
  53407. }
  53408. /**
  53409. * Returns a string representation of the constraint.
  53410. *
  53411. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  53412. */
  53413. public function toString() : string
  53414. {
  53415. return 'contains ' . $this->exporter()->export($this->value);
  53416. }
  53417. /**
  53418. * Returns the description of the failure
  53419. *
  53420. * The beginning of failure messages is "Failed asserting that" in most
  53421. * cases. This method should return the second part of that sentence.
  53422. *
  53423. * @param mixed $other evaluated value or object
  53424. *
  53425. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  53426. */
  53427. protected function failureDescription($other) : string
  53428. {
  53429. return \sprintf('%s %s', \is_array($other) ? 'an array' : 'a traversable', $this->toString());
  53430. }
  53431. protected function value()
  53432. {
  53433. return $this->value;
  53434. }
  53435. }
  53436. <?php
  53437. declare (strict_types=1);
  53438. /*
  53439. * This file is part of PHPUnit.
  53440. *
  53441. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  53442. *
  53443. * For the full copyright and license information, please view the LICENSE
  53444. * file that was distributed with this source code.
  53445. */
  53446. namespace PHPUnit\Framework\Constraint;
  53447. /**
  53448. * Constraint that asserts that the Traversable it is applied to contains
  53449. * a given value (using non-strict comparison).
  53450. */
  53451. final class TraversableContainsEqual extends \PHPUnit\Framework\Constraint\TraversableContains
  53452. {
  53453. /**
  53454. * Evaluates the constraint for parameter $other. Returns true if the
  53455. * constraint is met, false otherwise.
  53456. *
  53457. * @param mixed $other value or object to evaluate
  53458. */
  53459. protected function matches($other) : bool
  53460. {
  53461. if ($other instanceof \SplObjectStorage) {
  53462. return $other->contains($this->value());
  53463. }
  53464. foreach ($other as $element) {
  53465. /* @noinspection TypeUnsafeComparisonInspection */
  53466. if ($this->value() == $element) {
  53467. return \true;
  53468. }
  53469. }
  53470. return \false;
  53471. }
  53472. }
  53473. <?php
  53474. declare (strict_types=1);
  53475. /*
  53476. * This file is part of PHPUnit.
  53477. *
  53478. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  53479. *
  53480. * For the full copyright and license information, please view the LICENSE
  53481. * file that was distributed with this source code.
  53482. */
  53483. namespace PHPUnit\Framework\Constraint;
  53484. final class ExceptionCode extends \PHPUnit\Framework\Constraint\Constraint
  53485. {
  53486. /**
  53487. * @var int|string
  53488. */
  53489. private $expectedCode;
  53490. /**
  53491. * @param int|string $expected
  53492. */
  53493. public function __construct($expected)
  53494. {
  53495. $this->expectedCode = $expected;
  53496. }
  53497. public function toString() : string
  53498. {
  53499. return 'exception code is ';
  53500. }
  53501. /**
  53502. * Evaluates the constraint for parameter $other. Returns true if the
  53503. * constraint is met, false otherwise.
  53504. *
  53505. * @param \Throwable $other
  53506. */
  53507. protected function matches($other) : bool
  53508. {
  53509. return (string) $other->getCode() === (string) $this->expectedCode;
  53510. }
  53511. /**
  53512. * Returns the description of the failure
  53513. *
  53514. * The beginning of failure messages is "Failed asserting that" in most
  53515. * cases. This method should return the second part of that sentence.
  53516. *
  53517. * @param mixed $other evaluated value or object
  53518. *
  53519. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  53520. */
  53521. protected function failureDescription($other) : string
  53522. {
  53523. return \sprintf('%s is equal to expected exception code %s', $this->exporter()->export($other->getCode()), $this->exporter()->export($this->expectedCode));
  53524. }
  53525. }
  53526. <?php
  53527. declare (strict_types=1);
  53528. /*
  53529. * This file is part of PHPUnit.
  53530. *
  53531. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  53532. *
  53533. * For the full copyright and license information, please view the LICENSE
  53534. * file that was distributed with this source code.
  53535. */
  53536. namespace PHPUnit\Framework\Constraint;
  53537. use PHPUnit\Framework\ExpectationFailedException;
  53538. use PHPUnit\SebastianBergmann\Comparator\ComparisonFailure;
  53539. use PHPUnit\SebastianBergmann\Comparator\Factory as ComparatorFactory;
  53540. final class IsEqualIgnoringCase extends \PHPUnit\Framework\Constraint\Constraint
  53541. {
  53542. /**
  53543. * @var mixed
  53544. */
  53545. private $value;
  53546. public function __construct($value)
  53547. {
  53548. $this->value = $value;
  53549. }
  53550. /**
  53551. * Evaluates the constraint for parameter $other
  53552. *
  53553. * If $returnResult is set to false (the default), an exception is thrown
  53554. * in case of a failure. null is returned otherwise.
  53555. *
  53556. * If $returnResult is true, the result of the evaluation is returned as
  53557. * a boolean value instead: true in case of success, false in case of a
  53558. * failure.
  53559. *
  53560. * @throws ExpectationFailedException
  53561. */
  53562. public function evaluate($other, string $description = '', bool $returnResult = \false) : ?bool
  53563. {
  53564. // If $this->value and $other are identical, they are also equal.
  53565. // This is the most common path and will allow us to skip
  53566. // initialization of all the comparators.
  53567. if ($this->value === $other) {
  53568. return \true;
  53569. }
  53570. $comparatorFactory = \PHPUnit\SebastianBergmann\Comparator\Factory::getInstance();
  53571. try {
  53572. $comparator = $comparatorFactory->getComparatorFor($this->value, $other);
  53573. $comparator->assertEquals($this->value, $other, 0.0, \false, \true);
  53574. } catch (\PHPUnit\SebastianBergmann\Comparator\ComparisonFailure $f) {
  53575. if ($returnResult) {
  53576. return \false;
  53577. }
  53578. throw new \PHPUnit\Framework\ExpectationFailedException(\trim($description . "\n" . $f->getMessage()), $f);
  53579. }
  53580. return \true;
  53581. }
  53582. /**
  53583. * Returns a string representation of the constraint.
  53584. *
  53585. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  53586. */
  53587. public function toString() : string
  53588. {
  53589. if (\is_string($this->value)) {
  53590. if (\strpos($this->value, "\n") !== \false) {
  53591. return 'is equal to <text>';
  53592. }
  53593. return \sprintf("is equal to '%s'", $this->value);
  53594. }
  53595. return \sprintf('is equal to %s', $this->exporter()->export($this->value));
  53596. }
  53597. }
  53598. <?php
  53599. declare (strict_types=1);
  53600. /*
  53601. * This file is part of PHPUnit.
  53602. *
  53603. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  53604. *
  53605. * For the full copyright and license information, please view the LICENSE
  53606. * file that was distributed with this source code.
  53607. */
  53608. namespace PHPUnit\Framework\Constraint;
  53609. /**
  53610. * Constraint that evaluates against a specified closure.
  53611. */
  53612. final class Callback extends \PHPUnit\Framework\Constraint\Constraint
  53613. {
  53614. /**
  53615. * @var callable
  53616. */
  53617. private $callback;
  53618. public function __construct(callable $callback)
  53619. {
  53620. $this->callback = $callback;
  53621. }
  53622. /**
  53623. * Returns a string representation of the constraint.
  53624. */
  53625. public function toString() : string
  53626. {
  53627. return 'is accepted by specified callback';
  53628. }
  53629. /**
  53630. * Evaluates the constraint for parameter $value. Returns true if the
  53631. * constraint is met, false otherwise.
  53632. *
  53633. * @param mixed $other value or object to evaluate
  53634. */
  53635. protected function matches($other) : bool
  53636. {
  53637. return \call_user_func($this->callback, $other);
  53638. }
  53639. }
  53640. <?php
  53641. declare (strict_types=1);
  53642. /*
  53643. * This file is part of PHPUnit.
  53644. *
  53645. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  53646. *
  53647. * For the full copyright and license information, please view the LICENSE
  53648. * file that was distributed with this source code.
  53649. */
  53650. namespace PHPUnit\Framework\Constraint;
  53651. /**
  53652. * Constraint that accepts finite.
  53653. */
  53654. final class IsFinite extends \PHPUnit\Framework\Constraint\Constraint
  53655. {
  53656. /**
  53657. * Returns a string representation of the constraint.
  53658. */
  53659. public function toString() : string
  53660. {
  53661. return 'is finite';
  53662. }
  53663. /**
  53664. * Evaluates the constraint for parameter $other. Returns true if the
  53665. * constraint is met, false otherwise.
  53666. *
  53667. * @param mixed $other value or object to evaluate
  53668. */
  53669. protected function matches($other) : bool
  53670. {
  53671. return \is_finite($other);
  53672. }
  53673. }
  53674. <?php
  53675. declare (strict_types=1);
  53676. /*
  53677. * This file is part of PHPUnit.
  53678. *
  53679. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  53680. *
  53681. * For the full copyright and license information, please view the LICENSE
  53682. * file that was distributed with this source code.
  53683. */
  53684. namespace PHPUnit\Framework\Constraint;
  53685. use PHPUnit\Framework\ExpectationFailedException;
  53686. /**
  53687. * Constraint that accepts any input value.
  53688. */
  53689. final class IsAnything extends \PHPUnit\Framework\Constraint\Constraint
  53690. {
  53691. /**
  53692. * Evaluates the constraint for parameter $other
  53693. *
  53694. * If $returnResult is set to false (the default), an exception is thrown
  53695. * in case of a failure. null is returned otherwise.
  53696. *
  53697. * If $returnResult is true, the result of the evaluation is returned as
  53698. * a boolean value instead: true in case of success, false in case of a
  53699. * failure.
  53700. *
  53701. * @throws ExpectationFailedException
  53702. */
  53703. public function evaluate($other, string $description = '', bool $returnResult = \false) : ?bool
  53704. {
  53705. return $returnResult ? \true : null;
  53706. }
  53707. /**
  53708. * Returns a string representation of the constraint.
  53709. */
  53710. public function toString() : string
  53711. {
  53712. return 'is anything';
  53713. }
  53714. /**
  53715. * Counts the number of constraint elements.
  53716. */
  53717. public function count() : int
  53718. {
  53719. return 0;
  53720. }
  53721. }
  53722. <?php
  53723. declare (strict_types=1);
  53724. /*
  53725. * This file is part of PHPUnit.
  53726. *
  53727. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  53728. *
  53729. * For the full copyright and license information, please view the LICENSE
  53730. * file that was distributed with this source code.
  53731. */
  53732. namespace PHPUnit\Framework\Constraint;
  53733. /**
  53734. * Constraint that asserts that the object it is evaluated for is an instance
  53735. * of a given class.
  53736. *
  53737. * The expected class name is passed in the constructor.
  53738. */
  53739. final class IsInstanceOf extends \PHPUnit\Framework\Constraint\Constraint
  53740. {
  53741. /**
  53742. * @var string
  53743. */
  53744. private $className;
  53745. public function __construct(string $className)
  53746. {
  53747. $this->className = $className;
  53748. }
  53749. /**
  53750. * Returns a string representation of the constraint.
  53751. */
  53752. public function toString() : string
  53753. {
  53754. return \sprintf('is instance of %s "%s"', $this->getType(), $this->className);
  53755. }
  53756. /**
  53757. * Evaluates the constraint for parameter $other. Returns true if the
  53758. * constraint is met, false otherwise.
  53759. *
  53760. * @param mixed $other value or object to evaluate
  53761. */
  53762. protected function matches($other) : bool
  53763. {
  53764. return $other instanceof $this->className;
  53765. }
  53766. /**
  53767. * Returns the description of the failure
  53768. *
  53769. * The beginning of failure messages is "Failed asserting that" in most
  53770. * cases. This method should return the second part of that sentence.
  53771. *
  53772. * @param mixed $other evaluated value or object
  53773. *
  53774. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  53775. */
  53776. protected function failureDescription($other) : string
  53777. {
  53778. return \sprintf('%s is an instance of %s "%s"', $this->exporter()->shortenedExport($other), $this->getType(), $this->className);
  53779. }
  53780. private function getType() : string
  53781. {
  53782. try {
  53783. $reflection = new \ReflectionClass($this->className);
  53784. if ($reflection->isInterface()) {
  53785. return 'interface';
  53786. }
  53787. } catch (\ReflectionException $e) {
  53788. }
  53789. return 'class';
  53790. }
  53791. }
  53792. <?php
  53793. declare (strict_types=1);
  53794. /*
  53795. * This file is part of PHPUnit.
  53796. *
  53797. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  53798. *
  53799. * For the full copyright and license information, please view the LICENSE
  53800. * file that was distributed with this source code.
  53801. */
  53802. namespace PHPUnit\Framework\Constraint;
  53803. use PHPUnit\Framework\Exception;
  53804. class Count extends \PHPUnit\Framework\Constraint\Constraint
  53805. {
  53806. /**
  53807. * @var int
  53808. */
  53809. private $expectedCount;
  53810. public function __construct(int $expected)
  53811. {
  53812. $this->expectedCount = $expected;
  53813. }
  53814. public function toString() : string
  53815. {
  53816. return \sprintf('count matches %d', $this->expectedCount);
  53817. }
  53818. /**
  53819. * Evaluates the constraint for parameter $other. Returns true if the
  53820. * constraint is met, false otherwise.
  53821. *
  53822. * @throws Exception
  53823. */
  53824. protected function matches($other) : bool
  53825. {
  53826. return $this->expectedCount === $this->getCountOf($other);
  53827. }
  53828. /**
  53829. * @throws Exception
  53830. */
  53831. protected function getCountOf($other) : ?int
  53832. {
  53833. if ($other instanceof \Countable || \is_array($other)) {
  53834. return \count($other);
  53835. }
  53836. if ($other instanceof \EmptyIterator) {
  53837. return 0;
  53838. }
  53839. if ($other instanceof \Traversable) {
  53840. while ($other instanceof \IteratorAggregate) {
  53841. try {
  53842. $other = $other->getIterator();
  53843. } catch (\Exception $e) {
  53844. throw new \PHPUnit\Framework\Exception($e->getMessage(), $e->getCode(), $e);
  53845. }
  53846. }
  53847. $iterator = $other;
  53848. if ($iterator instanceof \Generator) {
  53849. return $this->getCountOfGenerator($iterator);
  53850. }
  53851. if (!$iterator instanceof \Iterator) {
  53852. return \iterator_count($iterator);
  53853. }
  53854. $key = $iterator->key();
  53855. $count = \iterator_count($iterator);
  53856. // Manually rewind $iterator to previous key, since iterator_count
  53857. // moves pointer.
  53858. if ($key !== null) {
  53859. $iterator->rewind();
  53860. while ($iterator->valid() && $key !== $iterator->key()) {
  53861. $iterator->next();
  53862. }
  53863. }
  53864. return $count;
  53865. }
  53866. return null;
  53867. }
  53868. /**
  53869. * Returns the total number of iterations from a generator.
  53870. * This will fully exhaust the generator.
  53871. */
  53872. protected function getCountOfGenerator(\Generator $generator) : int
  53873. {
  53874. for ($count = 0; $generator->valid(); $generator->next()) {
  53875. ++$count;
  53876. }
  53877. return $count;
  53878. }
  53879. /**
  53880. * Returns the description of the failure.
  53881. *
  53882. * The beginning of failure messages is "Failed asserting that" in most
  53883. * cases. This method should return the second part of that sentence.
  53884. *
  53885. * @param mixed $other evaluated value or object
  53886. */
  53887. protected function failureDescription($other) : string
  53888. {
  53889. return \sprintf('actual size %d matches expected size %d', (int) $this->getCountOf($other), $this->expectedCount);
  53890. }
  53891. }
  53892. <?php
  53893. declare (strict_types=1);
  53894. /*
  53895. * This file is part of PHPUnit.
  53896. *
  53897. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  53898. *
  53899. * For the full copyright and license information, please view the LICENSE
  53900. * file that was distributed with this source code.
  53901. */
  53902. namespace PHPUnit\Framework\Constraint;
  53903. use PHPUnit\Util\RegularExpression as RegularExpressionUtil;
  53904. final class ExceptionMessageRegularExpression extends \PHPUnit\Framework\Constraint\Constraint
  53905. {
  53906. /**
  53907. * @var string
  53908. */
  53909. private $expectedMessageRegExp;
  53910. public function __construct(string $expected)
  53911. {
  53912. $this->expectedMessageRegExp = $expected;
  53913. }
  53914. public function toString() : string
  53915. {
  53916. return 'exception message matches ';
  53917. }
  53918. /**
  53919. * Evaluates the constraint for parameter $other. Returns true if the
  53920. * constraint is met, false otherwise.
  53921. *
  53922. * @param \PHPUnit\Framework\Exception $other
  53923. *
  53924. * @throws \Exception
  53925. * @throws \PHPUnit\Framework\Exception
  53926. */
  53927. protected function matches($other) : bool
  53928. {
  53929. $match = \PHPUnit\Util\RegularExpression::safeMatch($this->expectedMessageRegExp, $other->getMessage());
  53930. if ($match === \false) {
  53931. throw new \PHPUnit\Framework\Exception("Invalid expected exception message regex given: '{$this->expectedMessageRegExp}'");
  53932. }
  53933. return $match === 1;
  53934. }
  53935. /**
  53936. * Returns the description of the failure
  53937. *
  53938. * The beginning of failure messages is "Failed asserting that" in most
  53939. * cases. This method should return the second part of that sentence.
  53940. *
  53941. * @param mixed $other evaluated value or object
  53942. */
  53943. protected function failureDescription($other) : string
  53944. {
  53945. return \sprintf("exception message '%s' matches '%s'", $other->getMessage(), $this->expectedMessageRegExp);
  53946. }
  53947. }
  53948. <?php
  53949. declare (strict_types=1);
  53950. /*
  53951. * This file is part of PHPUnit.
  53952. *
  53953. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  53954. *
  53955. * For the full copyright and license information, please view the LICENSE
  53956. * file that was distributed with this source code.
  53957. */
  53958. namespace PHPUnit\Framework\Constraint;
  53959. /**
  53960. * Constraint that asserts that the value it is evaluated for is greater
  53961. * than a given value.
  53962. */
  53963. final class GreaterThan extends \PHPUnit\Framework\Constraint\Constraint
  53964. {
  53965. /**
  53966. * @var float|int
  53967. */
  53968. private $value;
  53969. /**
  53970. * @param float|int $value
  53971. */
  53972. public function __construct($value)
  53973. {
  53974. $this->value = $value;
  53975. }
  53976. /**
  53977. * Returns a string representation of the constraint.
  53978. *
  53979. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  53980. */
  53981. public function toString() : string
  53982. {
  53983. return 'is greater than ' . $this->exporter()->export($this->value);
  53984. }
  53985. /**
  53986. * Evaluates the constraint for parameter $other. Returns true if the
  53987. * constraint is met, false otherwise.
  53988. *
  53989. * @param mixed $other value or object to evaluate
  53990. */
  53991. protected function matches($other) : bool
  53992. {
  53993. return $this->value < $other;
  53994. }
  53995. }
  53996. <?php
  53997. declare (strict_types=1);
  53998. /*
  53999. * This file is part of PHPUnit.
  54000. *
  54001. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  54002. *
  54003. * For the full copyright and license information, please view the LICENSE
  54004. * file that was distributed with this source code.
  54005. */
  54006. namespace PHPUnit\Framework\Constraint;
  54007. use PHPUnit\Framework\ExpectationFailedException;
  54008. use PHPUnit\SebastianBergmann\Comparator\ComparisonFailure;
  54009. /**
  54010. * Constraint that asserts that one value is identical to another.
  54011. *
  54012. * Identical check is performed with PHP's === operator, the operator is
  54013. * explained in detail at
  54014. * {@url https://php.net/manual/en/types.comparisons.php}.
  54015. * Two values are identical if they have the same value and are of the same
  54016. * type.
  54017. *
  54018. * The expected value is passed in the constructor.
  54019. */
  54020. final class IsIdentical extends \PHPUnit\Framework\Constraint\Constraint
  54021. {
  54022. /**
  54023. * @var float
  54024. */
  54025. private const EPSILON = 1.0E-10;
  54026. /**
  54027. * @var mixed
  54028. */
  54029. private $value;
  54030. public function __construct($value)
  54031. {
  54032. $this->value = $value;
  54033. }
  54034. /**
  54035. * Evaluates the constraint for parameter $other
  54036. *
  54037. * If $returnResult is set to false (the default), an exception is thrown
  54038. * in case of a failure. null is returned otherwise.
  54039. *
  54040. * If $returnResult is true, the result of the evaluation is returned as
  54041. * a boolean value instead: true in case of success, false in case of a
  54042. * failure.
  54043. *
  54044. * @throws ExpectationFailedException
  54045. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  54046. */
  54047. public function evaluate($other, string $description = '', bool $returnResult = \false) : ?bool
  54048. {
  54049. if (\is_float($this->value) && \is_float($other) && !\is_infinite($this->value) && !\is_infinite($other) && !\is_nan($this->value) && !\is_nan($other)) {
  54050. $success = \abs($this->value - $other) < self::EPSILON;
  54051. } else {
  54052. $success = $this->value === $other;
  54053. }
  54054. if ($returnResult) {
  54055. return $success;
  54056. }
  54057. if (!$success) {
  54058. $f = null;
  54059. // if both values are strings, make sure a diff is generated
  54060. if (\is_string($this->value) && \is_string($other)) {
  54061. $f = new \PHPUnit\SebastianBergmann\Comparator\ComparisonFailure($this->value, $other, \sprintf("'%s'", $this->value), \sprintf("'%s'", $other));
  54062. }
  54063. // if both values are array, make sure a diff is generated
  54064. if (\is_array($this->value) && \is_array($other)) {
  54065. $f = new \PHPUnit\SebastianBergmann\Comparator\ComparisonFailure($this->value, $other, $this->exporter()->export($this->value), $this->exporter()->export($other));
  54066. }
  54067. $this->fail($other, $description, $f);
  54068. }
  54069. return null;
  54070. }
  54071. /**
  54072. * Returns a string representation of the constraint.
  54073. *
  54074. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  54075. */
  54076. public function toString() : string
  54077. {
  54078. if (\is_object($this->value)) {
  54079. return 'is identical to an object of class "' . \get_class($this->value) . '"';
  54080. }
  54081. return 'is identical to ' . $this->exporter()->export($this->value);
  54082. }
  54083. /**
  54084. * Returns the description of the failure
  54085. *
  54086. * The beginning of failure messages is "Failed asserting that" in most
  54087. * cases. This method should return the second part of that sentence.
  54088. *
  54089. * @param mixed $other evaluated value or object
  54090. *
  54091. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  54092. */
  54093. protected function failureDescription($other) : string
  54094. {
  54095. if (\is_object($this->value) && \is_object($other)) {
  54096. return 'two variables reference the same object';
  54097. }
  54098. if (\is_string($this->value) && \is_string($other)) {
  54099. return 'two strings are identical';
  54100. }
  54101. if (\is_array($this->value) && \is_array($other)) {
  54102. return 'two arrays are identical';
  54103. }
  54104. return parent::failureDescription($other);
  54105. }
  54106. }
  54107. <?php
  54108. declare (strict_types=1);
  54109. /*
  54110. * This file is part of PHPUnit.
  54111. *
  54112. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  54113. *
  54114. * For the full copyright and license information, please view the LICENSE
  54115. * file that was distributed with this source code.
  54116. */
  54117. namespace PHPUnit\Framework\Constraint;
  54118. /**
  54119. * Constraint that checks whether a variable is empty().
  54120. */
  54121. final class IsEmpty extends \PHPUnit\Framework\Constraint\Constraint
  54122. {
  54123. /**
  54124. * Returns a string representation of the constraint.
  54125. */
  54126. public function toString() : string
  54127. {
  54128. return 'is empty';
  54129. }
  54130. /**
  54131. * Evaluates the constraint for parameter $other. Returns true if the
  54132. * constraint is met, false otherwise.
  54133. *
  54134. * @param mixed $other value or object to evaluate
  54135. */
  54136. protected function matches($other) : bool
  54137. {
  54138. if ($other instanceof \EmptyIterator) {
  54139. return \true;
  54140. }
  54141. if ($other instanceof \Countable) {
  54142. return \count($other) === 0;
  54143. }
  54144. return empty($other);
  54145. }
  54146. /**
  54147. * Returns the description of the failure
  54148. *
  54149. * The beginning of failure messages is "Failed asserting that" in most
  54150. * cases. This method should return the second part of that sentence.
  54151. *
  54152. * @param mixed $other evaluated value or object
  54153. */
  54154. protected function failureDescription($other) : string
  54155. {
  54156. $type = \gettype($other);
  54157. return \sprintf('%s %s %s', \strpos($type, 'a') === 0 || \strpos($type, 'o') === 0 ? 'an' : 'a', $type, $this->toString());
  54158. }
  54159. }
  54160. <?php
  54161. declare (strict_types=1);
  54162. /*
  54163. * This file is part of PHPUnit.
  54164. *
  54165. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  54166. *
  54167. * For the full copyright and license information, please view the LICENSE
  54168. * file that was distributed with this source code.
  54169. */
  54170. namespace PHPUnit\Framework\Constraint;
  54171. use PHPUnit\Framework\ExpectationFailedException;
  54172. /**
  54173. * Logical OR.
  54174. */
  54175. final class LogicalOr extends \PHPUnit\Framework\Constraint\Constraint
  54176. {
  54177. /**
  54178. * @var Constraint[]
  54179. */
  54180. private $constraints = [];
  54181. public static function fromConstraints(\PHPUnit\Framework\Constraint\Constraint ...$constraints) : self
  54182. {
  54183. $constraint = new self();
  54184. $constraint->constraints = \array_values($constraints);
  54185. return $constraint;
  54186. }
  54187. /**
  54188. * @param mixed[] $constraints
  54189. */
  54190. public function setConstraints(array $constraints) : void
  54191. {
  54192. $this->constraints = [];
  54193. foreach ($constraints as $constraint) {
  54194. if (!$constraint instanceof \PHPUnit\Framework\Constraint\Constraint) {
  54195. $constraint = new \PHPUnit\Framework\Constraint\IsEqual($constraint);
  54196. }
  54197. $this->constraints[] = $constraint;
  54198. }
  54199. }
  54200. /**
  54201. * Evaluates the constraint for parameter $other
  54202. *
  54203. * If $returnResult is set to false (the default), an exception is thrown
  54204. * in case of a failure. null is returned otherwise.
  54205. *
  54206. * If $returnResult is true, the result of the evaluation is returned as
  54207. * a boolean value instead: true in case of success, false in case of a
  54208. * failure.
  54209. *
  54210. * @throws ExpectationFailedException
  54211. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  54212. */
  54213. public function evaluate($other, string $description = '', bool $returnResult = \false) : ?bool
  54214. {
  54215. $success = \false;
  54216. foreach ($this->constraints as $constraint) {
  54217. if ($constraint->evaluate($other, $description, \true)) {
  54218. $success = \true;
  54219. break;
  54220. }
  54221. }
  54222. if ($returnResult) {
  54223. return $success;
  54224. }
  54225. if (!$success) {
  54226. $this->fail($other, $description);
  54227. }
  54228. return null;
  54229. }
  54230. /**
  54231. * Returns a string representation of the constraint.
  54232. */
  54233. public function toString() : string
  54234. {
  54235. $text = '';
  54236. foreach ($this->constraints as $key => $constraint) {
  54237. if ($key > 0) {
  54238. $text .= ' or ';
  54239. }
  54240. $text .= $constraint->toString();
  54241. }
  54242. return $text;
  54243. }
  54244. /**
  54245. * Counts the number of constraint elements.
  54246. */
  54247. public function count() : int
  54248. {
  54249. $count = 0;
  54250. foreach ($this->constraints as $constraint) {
  54251. $count += \count($constraint);
  54252. }
  54253. return $count;
  54254. }
  54255. }
  54256. <?php
  54257. declare (strict_types=1);
  54258. /*
  54259. * This file is part of PHPUnit.
  54260. *
  54261. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  54262. *
  54263. * For the full copyright and license information, please view the LICENSE
  54264. * file that was distributed with this source code.
  54265. */
  54266. namespace PHPUnit\Framework\Constraint;
  54267. use PHPUnit\Framework\Exception;
  54268. /**
  54269. * Constraint that asserts that the class it is evaluated for has a given
  54270. * attribute.
  54271. *
  54272. * The attribute name is passed in the constructor.
  54273. */
  54274. class ClassHasAttribute extends \PHPUnit\Framework\Constraint\Constraint
  54275. {
  54276. /**
  54277. * @var string
  54278. */
  54279. private $attributeName;
  54280. public function __construct(string $attributeName)
  54281. {
  54282. $this->attributeName = $attributeName;
  54283. }
  54284. /**
  54285. * Returns a string representation of the constraint.
  54286. */
  54287. public function toString() : string
  54288. {
  54289. return \sprintf('has attribute "%s"', $this->attributeName);
  54290. }
  54291. /**
  54292. * Evaluates the constraint for parameter $other. Returns true if the
  54293. * constraint is met, false otherwise.
  54294. *
  54295. * @param mixed $other value or object to evaluate
  54296. */
  54297. protected function matches($other) : bool
  54298. {
  54299. try {
  54300. return (new \ReflectionClass($other))->hasProperty($this->attributeName);
  54301. // @codeCoverageIgnoreStart
  54302. } catch (\ReflectionException $e) {
  54303. throw new \PHPUnit\Framework\Exception($e->getMessage(), (int) $e->getCode(), $e);
  54304. }
  54305. // @codeCoverageIgnoreEnd
  54306. }
  54307. /**
  54308. * Returns the description of the failure
  54309. *
  54310. * The beginning of failure messages is "Failed asserting that" in most
  54311. * cases. This method should return the second part of that sentence.
  54312. *
  54313. * @param mixed $other evaluated value or object
  54314. */
  54315. protected function failureDescription($other) : string
  54316. {
  54317. return \sprintf('%sclass "%s" %s', \is_object($other) ? 'object of ' : '', \is_object($other) ? \get_class($other) : $other, $this->toString());
  54318. }
  54319. protected function attributeName() : string
  54320. {
  54321. return $this->attributeName;
  54322. }
  54323. }
  54324. <?php
  54325. declare (strict_types=1);
  54326. /*
  54327. * This file is part of PHPUnit.
  54328. *
  54329. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  54330. *
  54331. * For the full copyright and license information, please view the LICENSE
  54332. * file that was distributed with this source code.
  54333. */
  54334. namespace PHPUnit\Framework\Constraint;
  54335. /**
  54336. * Constraint that asserts that the value it is evaluated for is less than
  54337. * a given value.
  54338. */
  54339. final class LessThan extends \PHPUnit\Framework\Constraint\Constraint
  54340. {
  54341. /**
  54342. * @var float|int
  54343. */
  54344. private $value;
  54345. /**
  54346. * @param float|int $value
  54347. */
  54348. public function __construct($value)
  54349. {
  54350. $this->value = $value;
  54351. }
  54352. /**
  54353. * Returns a string representation of the constraint.
  54354. *
  54355. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  54356. */
  54357. public function toString() : string
  54358. {
  54359. return 'is less than ' . $this->exporter()->export($this->value);
  54360. }
  54361. /**
  54362. * Evaluates the constraint for parameter $other. Returns true if the
  54363. * constraint is met, false otherwise.
  54364. *
  54365. * @param mixed $other value or object to evaluate
  54366. */
  54367. protected function matches($other) : bool
  54368. {
  54369. return $this->value > $other;
  54370. }
  54371. }
  54372. <?php
  54373. declare (strict_types=1);
  54374. /*
  54375. * This file is part of PHPUnit.
  54376. *
  54377. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  54378. *
  54379. * For the full copyright and license information, please view the LICENSE
  54380. * file that was distributed with this source code.
  54381. */
  54382. namespace PHPUnit\Framework\Constraint;
  54383. /**
  54384. * Constraint that asserts that the string it is evaluated for contains
  54385. * a given string.
  54386. *
  54387. * Uses mb_strpos() to find the position of the string in the input, if not
  54388. * found the evaluation fails.
  54389. *
  54390. * The sub-string is passed in the constructor.
  54391. */
  54392. final class StringContains extends \PHPUnit\Framework\Constraint\Constraint
  54393. {
  54394. /**
  54395. * @var string
  54396. */
  54397. private $string;
  54398. /**
  54399. * @var bool
  54400. */
  54401. private $ignoreCase;
  54402. public function __construct(string $string, bool $ignoreCase = \false)
  54403. {
  54404. $this->string = $string;
  54405. $this->ignoreCase = $ignoreCase;
  54406. }
  54407. /**
  54408. * Returns a string representation of the constraint.
  54409. */
  54410. public function toString() : string
  54411. {
  54412. if ($this->ignoreCase) {
  54413. $string = \mb_strtolower($this->string, 'UTF-8');
  54414. } else {
  54415. $string = $this->string;
  54416. }
  54417. return \sprintf('contains "%s"', $string);
  54418. }
  54419. /**
  54420. * Evaluates the constraint for parameter $other. Returns true if the
  54421. * constraint is met, false otherwise.
  54422. *
  54423. * @param mixed $other value or object to evaluate
  54424. */
  54425. protected function matches($other) : bool
  54426. {
  54427. if ('' === $this->string) {
  54428. return \true;
  54429. }
  54430. if ($this->ignoreCase) {
  54431. /*
  54432. * We must use the multi byte safe version so we can accurately compare non latin upper characters with
  54433. * their lowercase equivalents.
  54434. */
  54435. return \mb_stripos($other, $this->string, 0, 'UTF-8') !== \false;
  54436. }
  54437. /*
  54438. * Use the non multi byte safe functions to see if the string is contained in $other.
  54439. *
  54440. * This function is very fast and we don't care about the character position in the string.
  54441. *
  54442. * Additionally, we want this method to be binary safe so we can check if some binary data is in other binary
  54443. * data.
  54444. */
  54445. return \strpos($other, $this->string) !== \false;
  54446. }
  54447. }
  54448. <?php
  54449. declare (strict_types=1);
  54450. /*
  54451. * This file is part of PHPUnit.
  54452. *
  54453. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  54454. *
  54455. * For the full copyright and license information, please view the LICENSE
  54456. * file that was distributed with this source code.
  54457. */
  54458. namespace PHPUnit\Framework\Constraint;
  54459. /**
  54460. * Constraint that accepts false.
  54461. */
  54462. final class IsFalse extends \PHPUnit\Framework\Constraint\Constraint
  54463. {
  54464. /**
  54465. * Returns a string representation of the constraint.
  54466. */
  54467. public function toString() : string
  54468. {
  54469. return 'is false';
  54470. }
  54471. /**
  54472. * Evaluates the constraint for parameter $other. Returns true if the
  54473. * constraint is met, false otherwise.
  54474. *
  54475. * @param mixed $other value or object to evaluate
  54476. */
  54477. protected function matches($other) : bool
  54478. {
  54479. return $other === \false;
  54480. }
  54481. }
  54482. <?php
  54483. declare (strict_types=1);
  54484. /*
  54485. * This file is part of PHPUnit.
  54486. *
  54487. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  54488. *
  54489. * For the full copyright and license information, please view the LICENSE
  54490. * file that was distributed with this source code.
  54491. */
  54492. namespace PHPUnit\Framework\Constraint;
  54493. use PHPUnit\Framework\ExpectationFailedException;
  54494. use PHPUnit\SebastianBergmann\Comparator\ComparisonFailure;
  54495. use PHPUnit\SebastianBergmann\Comparator\Factory as ComparatorFactory;
  54496. final class IsEqualWithDelta extends \PHPUnit\Framework\Constraint\Constraint
  54497. {
  54498. /**
  54499. * @var mixed
  54500. */
  54501. private $value;
  54502. /**
  54503. * @var float
  54504. */
  54505. private $delta;
  54506. public function __construct($value, float $delta)
  54507. {
  54508. $this->value = $value;
  54509. $this->delta = $delta;
  54510. }
  54511. /**
  54512. * Evaluates the constraint for parameter $other
  54513. *
  54514. * If $returnResult is set to false (the default), an exception is thrown
  54515. * in case of a failure. null is returned otherwise.
  54516. *
  54517. * If $returnResult is true, the result of the evaluation is returned as
  54518. * a boolean value instead: true in case of success, false in case of a
  54519. * failure.
  54520. *
  54521. * @throws ExpectationFailedException
  54522. */
  54523. public function evaluate($other, string $description = '', bool $returnResult = \false) : ?bool
  54524. {
  54525. // If $this->value and $other are identical, they are also equal.
  54526. // This is the most common path and will allow us to skip
  54527. // initialization of all the comparators.
  54528. if ($this->value === $other) {
  54529. return \true;
  54530. }
  54531. $comparatorFactory = \PHPUnit\SebastianBergmann\Comparator\Factory::getInstance();
  54532. try {
  54533. $comparator = $comparatorFactory->getComparatorFor($this->value, $other);
  54534. $comparator->assertEquals($this->value, $other, $this->delta);
  54535. } catch (\PHPUnit\SebastianBergmann\Comparator\ComparisonFailure $f) {
  54536. if ($returnResult) {
  54537. return \false;
  54538. }
  54539. throw new \PHPUnit\Framework\ExpectationFailedException(\trim($description . "\n" . $f->getMessage()), $f);
  54540. }
  54541. return \true;
  54542. }
  54543. /**
  54544. * Returns a string representation of the constraint.
  54545. *
  54546. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  54547. */
  54548. public function toString() : string
  54549. {
  54550. return \sprintf('is equal to %s with delta <%F>>', $this->exporter()->export($this->value), $this->delta);
  54551. }
  54552. }
  54553. <?php
  54554. declare (strict_types=1);
  54555. /*
  54556. * This file is part of PHPUnit.
  54557. *
  54558. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  54559. *
  54560. * For the full copyright and license information, please view the LICENSE
  54561. * file that was distributed with this source code.
  54562. */
  54563. namespace PHPUnit\Framework\Constraint;
  54564. use PHPUnit\Framework\ExpectationFailedException;
  54565. /**
  54566. * Logical AND.
  54567. */
  54568. final class LogicalAnd extends \PHPUnit\Framework\Constraint\Constraint
  54569. {
  54570. /**
  54571. * @var Constraint[]
  54572. */
  54573. private $constraints = [];
  54574. public static function fromConstraints(\PHPUnit\Framework\Constraint\Constraint ...$constraints) : self
  54575. {
  54576. $constraint = new self();
  54577. $constraint->constraints = \array_values($constraints);
  54578. return $constraint;
  54579. }
  54580. /**
  54581. * @param Constraint[] $constraints
  54582. *
  54583. * @throws \PHPUnit\Framework\Exception
  54584. */
  54585. public function setConstraints(array $constraints) : void
  54586. {
  54587. $this->constraints = [];
  54588. foreach ($constraints as $constraint) {
  54589. if (!$constraint instanceof \PHPUnit\Framework\Constraint\Constraint) {
  54590. throw new \PHPUnit\Framework\Exception('All parameters to ' . __CLASS__ . ' must be a constraint object.');
  54591. }
  54592. $this->constraints[] = $constraint;
  54593. }
  54594. }
  54595. /**
  54596. * Evaluates the constraint for parameter $other
  54597. *
  54598. * If $returnResult is set to false (the default), an exception is thrown
  54599. * in case of a failure. null is returned otherwise.
  54600. *
  54601. * If $returnResult is true, the result of the evaluation is returned as
  54602. * a boolean value instead: true in case of success, false in case of a
  54603. * failure.
  54604. *
  54605. * @throws ExpectationFailedException
  54606. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  54607. */
  54608. public function evaluate($other, string $description = '', bool $returnResult = \false) : ?bool
  54609. {
  54610. $success = \true;
  54611. foreach ($this->constraints as $constraint) {
  54612. if (!$constraint->evaluate($other, $description, \true)) {
  54613. $success = \false;
  54614. break;
  54615. }
  54616. }
  54617. if ($returnResult) {
  54618. return $success;
  54619. }
  54620. if (!$success) {
  54621. $this->fail($other, $description);
  54622. }
  54623. return null;
  54624. }
  54625. /**
  54626. * Returns a string representation of the constraint.
  54627. */
  54628. public function toString() : string
  54629. {
  54630. $text = '';
  54631. foreach ($this->constraints as $key => $constraint) {
  54632. if ($key > 0) {
  54633. $text .= ' and ';
  54634. }
  54635. $text .= $constraint->toString();
  54636. }
  54637. return $text;
  54638. }
  54639. /**
  54640. * Counts the number of constraint elements.
  54641. */
  54642. public function count() : int
  54643. {
  54644. $count = 0;
  54645. foreach ($this->constraints as $constraint) {
  54646. $count += \count($constraint);
  54647. }
  54648. return $count;
  54649. }
  54650. }
  54651. <?php
  54652. declare (strict_types=1);
  54653. /*
  54654. * This file is part of PHPUnit.
  54655. *
  54656. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  54657. *
  54658. * For the full copyright and license information, please view the LICENSE
  54659. * file that was distributed with this source code.
  54660. */
  54661. namespace PHPUnit\Framework\Constraint;
  54662. use PHPUnit\Framework\Exception;
  54663. /**
  54664. * Constraint that asserts that the class it is evaluated for has a given
  54665. * static attribute.
  54666. *
  54667. * The attribute name is passed in the constructor.
  54668. */
  54669. final class ClassHasStaticAttribute extends \PHPUnit\Framework\Constraint\ClassHasAttribute
  54670. {
  54671. /**
  54672. * Returns a string representation of the constraint.
  54673. */
  54674. public function toString() : string
  54675. {
  54676. return \sprintf('has static attribute "%s"', $this->attributeName());
  54677. }
  54678. /**
  54679. * Evaluates the constraint for parameter $other. Returns true if the
  54680. * constraint is met, false otherwise.
  54681. *
  54682. * @param mixed $other value or object to evaluate
  54683. */
  54684. protected function matches($other) : bool
  54685. {
  54686. try {
  54687. $class = new \ReflectionClass($other);
  54688. if ($class->hasProperty($this->attributeName())) {
  54689. return $class->getProperty($this->attributeName())->isStatic();
  54690. }
  54691. // @codeCoverageIgnoreStart
  54692. } catch (\ReflectionException $e) {
  54693. throw new \PHPUnit\Framework\Exception($e->getMessage(), (int) $e->getCode(), $e);
  54694. }
  54695. // @codeCoverageIgnoreEnd
  54696. return \false;
  54697. }
  54698. }
  54699. <?php
  54700. declare (strict_types=1);
  54701. /*
  54702. * This file is part of PHPUnit.
  54703. *
  54704. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  54705. *
  54706. * For the full copyright and license information, please view the LICENSE
  54707. * file that was distributed with this source code.
  54708. */
  54709. namespace PHPUnit\Framework\Constraint;
  54710. use PHPUnit\Framework\ExpectationFailedException;
  54711. /**
  54712. * Constraint that asserts that the Traversable it is applied to contains
  54713. * only values of a given type.
  54714. */
  54715. final class TraversableContainsOnly extends \PHPUnit\Framework\Constraint\Constraint
  54716. {
  54717. /**
  54718. * @var Constraint
  54719. */
  54720. private $constraint;
  54721. /**
  54722. * @var string
  54723. */
  54724. private $type;
  54725. /**
  54726. * @throws \PHPUnit\Framework\Exception
  54727. */
  54728. public function __construct(string $type, bool $isNativeType = \true)
  54729. {
  54730. if ($isNativeType) {
  54731. $this->constraint = new \PHPUnit\Framework\Constraint\IsType($type);
  54732. } else {
  54733. $this->constraint = new \PHPUnit\Framework\Constraint\IsInstanceOf($type);
  54734. }
  54735. $this->type = $type;
  54736. }
  54737. /**
  54738. * Evaluates the constraint for parameter $other
  54739. *
  54740. * If $returnResult is set to false (the default), an exception is thrown
  54741. * in case of a failure. null is returned otherwise.
  54742. *
  54743. * If $returnResult is true, the result of the evaluation is returned as
  54744. * a boolean value instead: true in case of success, false in case of a
  54745. * failure.
  54746. *
  54747. * @param mixed|\Traversable $other
  54748. *
  54749. * @throws ExpectationFailedException
  54750. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  54751. */
  54752. public function evaluate($other, string $description = '', bool $returnResult = \false) : ?bool
  54753. {
  54754. $success = \true;
  54755. foreach ($other as $item) {
  54756. if (!$this->constraint->evaluate($item, '', \true)) {
  54757. $success = \false;
  54758. break;
  54759. }
  54760. }
  54761. if ($returnResult) {
  54762. return $success;
  54763. }
  54764. if (!$success) {
  54765. $this->fail($other, $description);
  54766. }
  54767. return null;
  54768. }
  54769. /**
  54770. * Returns a string representation of the constraint.
  54771. */
  54772. public function toString() : string
  54773. {
  54774. return 'contains only values of type "' . $this->type . '"';
  54775. }
  54776. }
  54777. <?php
  54778. declare (strict_types=1);
  54779. /*
  54780. * This file is part of PHPUnit.
  54781. *
  54782. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  54783. *
  54784. * For the full copyright and license information, please view the LICENSE
  54785. * file that was distributed with this source code.
  54786. */
  54787. namespace PHPUnit\Framework\Constraint;
  54788. /**
  54789. * Constraint that checks if the file/dir(name) that it is evaluated for is writable.
  54790. *
  54791. * The file path to check is passed as $other in evaluate().
  54792. */
  54793. final class IsWritable extends \PHPUnit\Framework\Constraint\Constraint
  54794. {
  54795. /**
  54796. * Returns a string representation of the constraint.
  54797. */
  54798. public function toString() : string
  54799. {
  54800. return 'is writable';
  54801. }
  54802. /**
  54803. * Evaluates the constraint for parameter $other. Returns true if the
  54804. * constraint is met, false otherwise.
  54805. *
  54806. * @param mixed $other value or object to evaluate
  54807. */
  54808. protected function matches($other) : bool
  54809. {
  54810. return \is_writable($other);
  54811. }
  54812. /**
  54813. * Returns the description of the failure
  54814. *
  54815. * The beginning of failure messages is "Failed asserting that" in most
  54816. * cases. This method should return the second part of that sentence.
  54817. *
  54818. * @param mixed $other evaluated value or object
  54819. */
  54820. protected function failureDescription($other) : string
  54821. {
  54822. return \sprintf('"%s" is writable', $other);
  54823. }
  54824. }
  54825. <?php
  54826. declare (strict_types=1);
  54827. /*
  54828. * This file is part of PHPUnit.
  54829. *
  54830. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  54831. *
  54832. * For the full copyright and license information, please view the LICENSE
  54833. * file that was distributed with this source code.
  54834. */
  54835. namespace PHPUnit\Framework\Constraint;
  54836. /**
  54837. * Constraint that asserts that the string it is evaluated for matches
  54838. * a regular expression.
  54839. *
  54840. * Checks a given value using the Perl Compatible Regular Expression extension
  54841. * in PHP. The pattern is matched by executing preg_match().
  54842. *
  54843. * The pattern string passed in the constructor.
  54844. */
  54845. class RegularExpression extends \PHPUnit\Framework\Constraint\Constraint
  54846. {
  54847. /**
  54848. * @var string
  54849. */
  54850. private $pattern;
  54851. public function __construct(string $pattern)
  54852. {
  54853. $this->pattern = $pattern;
  54854. }
  54855. /**
  54856. * Returns a string representation of the constraint.
  54857. */
  54858. public function toString() : string
  54859. {
  54860. return \sprintf('matches PCRE pattern "%s"', $this->pattern);
  54861. }
  54862. /**
  54863. * Evaluates the constraint for parameter $other. Returns true if the
  54864. * constraint is met, false otherwise.
  54865. *
  54866. * @param mixed $other value or object to evaluate
  54867. */
  54868. protected function matches($other) : bool
  54869. {
  54870. return \preg_match($this->pattern, $other) > 0;
  54871. }
  54872. }
  54873. <?php
  54874. declare (strict_types=1);
  54875. /*
  54876. * This file is part of PHPUnit.
  54877. *
  54878. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  54879. *
  54880. * For the full copyright and license information, please view the LICENSE
  54881. * file that was distributed with this source code.
  54882. */
  54883. namespace PHPUnit\Framework\Constraint;
  54884. use PHPUnit\Util\Filter;
  54885. final class Exception extends \PHPUnit\Framework\Constraint\Constraint
  54886. {
  54887. /**
  54888. * @var string
  54889. */
  54890. private $className;
  54891. public function __construct(string $className)
  54892. {
  54893. $this->className = $className;
  54894. }
  54895. /**
  54896. * Returns a string representation of the constraint.
  54897. */
  54898. public function toString() : string
  54899. {
  54900. return \sprintf('exception of type "%s"', $this->className);
  54901. }
  54902. /**
  54903. * Evaluates the constraint for parameter $other. Returns true if the
  54904. * constraint is met, false otherwise.
  54905. *
  54906. * @param mixed $other value or object to evaluate
  54907. */
  54908. protected function matches($other) : bool
  54909. {
  54910. return $other instanceof $this->className;
  54911. }
  54912. /**
  54913. * Returns the description of the failure
  54914. *
  54915. * The beginning of failure messages is "Failed asserting that" in most
  54916. * cases. This method should return the second part of that sentence.
  54917. *
  54918. * @param mixed $other evaluated value or object
  54919. */
  54920. protected function failureDescription($other) : string
  54921. {
  54922. if ($other !== null) {
  54923. $message = '';
  54924. if ($other instanceof \Throwable) {
  54925. $message = '. Message was: "' . $other->getMessage() . '" at' . "\n" . \PHPUnit\Util\Filter::getFilteredStacktrace($other);
  54926. }
  54927. return \sprintf('exception of type "%s" matches expected exception "%s"%s', \get_class($other), $this->className, $message);
  54928. }
  54929. return \sprintf('exception of type "%s" is thrown', $this->className);
  54930. }
  54931. }
  54932. <?php
  54933. declare (strict_types=1);
  54934. /*
  54935. * This file is part of PHPUnit.
  54936. *
  54937. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  54938. *
  54939. * For the full copyright and license information, please view the LICENSE
  54940. * file that was distributed with this source code.
  54941. */
  54942. namespace PHPUnit\Framework\Constraint;
  54943. /**
  54944. * Constraint that accepts infinite.
  54945. */
  54946. final class IsInfinite extends \PHPUnit\Framework\Constraint\Constraint
  54947. {
  54948. /**
  54949. * Returns a string representation of the constraint.
  54950. */
  54951. public function toString() : string
  54952. {
  54953. return 'is infinite';
  54954. }
  54955. /**
  54956. * Evaluates the constraint for parameter $other. Returns true if the
  54957. * constraint is met, false otherwise.
  54958. *
  54959. * @param mixed $other value or object to evaluate
  54960. */
  54961. protected function matches($other) : bool
  54962. {
  54963. return \is_infinite($other);
  54964. }
  54965. }
  54966. <?php
  54967. declare (strict_types=1);
  54968. /*
  54969. * This file is part of PHPUnit.
  54970. *
  54971. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  54972. *
  54973. * For the full copyright and license information, please view the LICENSE
  54974. * file that was distributed with this source code.
  54975. */
  54976. namespace PHPUnit\Framework\Constraint;
  54977. /**
  54978. * Constraint that asserts that the string it is evaluated for ends with a given
  54979. * suffix.
  54980. */
  54981. final class StringEndsWith extends \PHPUnit\Framework\Constraint\Constraint
  54982. {
  54983. /**
  54984. * @var string
  54985. */
  54986. private $suffix;
  54987. public function __construct(string $suffix)
  54988. {
  54989. $this->suffix = $suffix;
  54990. }
  54991. /**
  54992. * Returns a string representation of the constraint.
  54993. */
  54994. public function toString() : string
  54995. {
  54996. return 'ends with "' . $this->suffix . '"';
  54997. }
  54998. /**
  54999. * Evaluates the constraint for parameter $other. Returns true if the
  55000. * constraint is met, false otherwise.
  55001. *
  55002. * @param mixed $other value or object to evaluate
  55003. */
  55004. protected function matches($other) : bool
  55005. {
  55006. return \substr($other, 0 - \strlen($this->suffix)) === $this->suffix;
  55007. }
  55008. }
  55009. <?php
  55010. declare (strict_types=1);
  55011. /*
  55012. * This file is part of PHPUnit.
  55013. *
  55014. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  55015. *
  55016. * For the full copyright and license information, please view the LICENSE
  55017. * file that was distributed with this source code.
  55018. */
  55019. namespace PHPUnit\Framework\Constraint;
  55020. final class SameSize extends \PHPUnit\Framework\Constraint\Count
  55021. {
  55022. public function __construct(iterable $expected)
  55023. {
  55024. parent::__construct((int) $this->getCountOf($expected));
  55025. }
  55026. }
  55027. <?php
  55028. declare (strict_types=1);
  55029. /*
  55030. * This file is part of PHPUnit.
  55031. *
  55032. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  55033. *
  55034. * For the full copyright and license information, please view the LICENSE
  55035. * file that was distributed with this source code.
  55036. */
  55037. namespace PHPUnit\Framework\Constraint;
  55038. use PHPUnit\Framework\ExpectationFailedException;
  55039. use PHPUnit\Framework\SelfDescribing;
  55040. use PHPUnit\SebastianBergmann\Comparator\ComparisonFailure;
  55041. use PHPUnit\SebastianBergmann\Exporter\Exporter;
  55042. /**
  55043. * Abstract base class for constraints which can be applied to any value.
  55044. */
  55045. abstract class Constraint implements \Countable, \PHPUnit\Framework\SelfDescribing
  55046. {
  55047. /**
  55048. * @var ?Exporter
  55049. */
  55050. private $exporter;
  55051. /**
  55052. * Evaluates the constraint for parameter $other
  55053. *
  55054. * If $returnResult is set to false (the default), an exception is thrown
  55055. * in case of a failure. null is returned otherwise.
  55056. *
  55057. * If $returnResult is true, the result of the evaluation is returned as
  55058. * a boolean value instead: true in case of success, false in case of a
  55059. * failure.
  55060. *
  55061. * @throws ExpectationFailedException
  55062. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  55063. */
  55064. public function evaluate($other, string $description = '', bool $returnResult = \false) : ?bool
  55065. {
  55066. $success = \false;
  55067. if ($this->matches($other)) {
  55068. $success = \true;
  55069. }
  55070. if ($returnResult) {
  55071. return $success;
  55072. }
  55073. if (!$success) {
  55074. $this->fail($other, $description);
  55075. }
  55076. return null;
  55077. }
  55078. /**
  55079. * Counts the number of constraint elements.
  55080. */
  55081. public function count() : int
  55082. {
  55083. return 1;
  55084. }
  55085. protected function exporter() : \PHPUnit\SebastianBergmann\Exporter\Exporter
  55086. {
  55087. if ($this->exporter === null) {
  55088. $this->exporter = new \PHPUnit\SebastianBergmann\Exporter\Exporter();
  55089. }
  55090. return $this->exporter;
  55091. }
  55092. /**
  55093. * Evaluates the constraint for parameter $other. Returns true if the
  55094. * constraint is met, false otherwise.
  55095. *
  55096. * This method can be overridden to implement the evaluation algorithm.
  55097. *
  55098. * @param mixed $other value or object to evaluate
  55099. * @codeCoverageIgnore
  55100. */
  55101. protected function matches($other) : bool
  55102. {
  55103. return \false;
  55104. }
  55105. /**
  55106. * Throws an exception for the given compared value and test description
  55107. *
  55108. * @param mixed $other evaluated value or object
  55109. * @param string $description Additional information about the test
  55110. * @param ComparisonFailure $comparisonFailure
  55111. *
  55112. * @throws ExpectationFailedException
  55113. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  55114. *
  55115. * @psalm-return never-return
  55116. */
  55117. protected function fail($other, $description, \PHPUnit\SebastianBergmann\Comparator\ComparisonFailure $comparisonFailure = null) : void
  55118. {
  55119. $failureDescription = \sprintf('Failed asserting that %s.', $this->failureDescription($other));
  55120. $additionalFailureDescription = $this->additionalFailureDescription($other);
  55121. if ($additionalFailureDescription) {
  55122. $failureDescription .= "\n" . $additionalFailureDescription;
  55123. }
  55124. if (!empty($description)) {
  55125. $failureDescription = $description . "\n" . $failureDescription;
  55126. }
  55127. throw new \PHPUnit\Framework\ExpectationFailedException($failureDescription, $comparisonFailure);
  55128. }
  55129. /**
  55130. * Return additional failure description where needed
  55131. *
  55132. * The function can be overridden to provide additional failure
  55133. * information like a diff
  55134. *
  55135. * @param mixed $other evaluated value or object
  55136. */
  55137. protected function additionalFailureDescription($other) : string
  55138. {
  55139. return '';
  55140. }
  55141. /**
  55142. * Returns the description of the failure
  55143. *
  55144. * The beginning of failure messages is "Failed asserting that" in most
  55145. * cases. This method should return the second part of that sentence.
  55146. *
  55147. * To provide additional failure information additionalFailureDescription
  55148. * can be used.
  55149. *
  55150. * @param mixed $other evaluated value or object
  55151. *
  55152. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  55153. */
  55154. protected function failureDescription($other) : string
  55155. {
  55156. return $this->exporter()->export($other) . ' ' . $this->toString();
  55157. }
  55158. }
  55159. <?php
  55160. declare (strict_types=1);
  55161. /*
  55162. * This file is part of PHPUnit.
  55163. *
  55164. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  55165. *
  55166. * For the full copyright and license information, please view the LICENSE
  55167. * file that was distributed with this source code.
  55168. */
  55169. namespace PHPUnit\Framework\Constraint;
  55170. use PHPUnit\Framework\ExpectationFailedException;
  55171. use PHPUnit\SebastianBergmann\Comparator\ComparisonFailure;
  55172. use PHPUnit\SebastianBergmann\Comparator\Factory as ComparatorFactory;
  55173. /**
  55174. * Constraint that checks if one value is equal to another.
  55175. *
  55176. * Equality is checked with PHP's == operator, the operator is explained in
  55177. * detail at {@url https://php.net/manual/en/types.comparisons.php}.
  55178. * Two values are equal if they have the same value disregarding type.
  55179. *
  55180. * The expected value is passed in the constructor.
  55181. */
  55182. final class IsEqual extends \PHPUnit\Framework\Constraint\Constraint
  55183. {
  55184. /**
  55185. * @var mixed
  55186. */
  55187. private $value;
  55188. /**
  55189. * @var float
  55190. */
  55191. private $delta;
  55192. /**
  55193. * @var bool
  55194. */
  55195. private $canonicalize;
  55196. /**
  55197. * @var bool
  55198. */
  55199. private $ignoreCase;
  55200. public function __construct($value, float $delta = 0.0, bool $canonicalize = \false, bool $ignoreCase = \false)
  55201. {
  55202. $this->value = $value;
  55203. $this->delta = $delta;
  55204. $this->canonicalize = $canonicalize;
  55205. $this->ignoreCase = $ignoreCase;
  55206. }
  55207. /**
  55208. * Evaluates the constraint for parameter $other
  55209. *
  55210. * If $returnResult is set to false (the default), an exception is thrown
  55211. * in case of a failure. null is returned otherwise.
  55212. *
  55213. * If $returnResult is true, the result of the evaluation is returned as
  55214. * a boolean value instead: true in case of success, false in case of a
  55215. * failure.
  55216. *
  55217. * @throws ExpectationFailedException
  55218. *
  55219. * @return bool
  55220. */
  55221. public function evaluate($other, string $description = '', bool $returnResult = \false) : ?bool
  55222. {
  55223. // If $this->value and $other are identical, they are also equal.
  55224. // This is the most common path and will allow us to skip
  55225. // initialization of all the comparators.
  55226. if ($this->value === $other) {
  55227. return \true;
  55228. }
  55229. $comparatorFactory = \PHPUnit\SebastianBergmann\Comparator\Factory::getInstance();
  55230. try {
  55231. $comparator = $comparatorFactory->getComparatorFor($this->value, $other);
  55232. $comparator->assertEquals($this->value, $other, $this->delta, $this->canonicalize, $this->ignoreCase);
  55233. } catch (\PHPUnit\SebastianBergmann\Comparator\ComparisonFailure $f) {
  55234. if ($returnResult) {
  55235. return \false;
  55236. }
  55237. throw new \PHPUnit\Framework\ExpectationFailedException(\trim($description . "\n" . $f->getMessage()), $f);
  55238. }
  55239. return \true;
  55240. }
  55241. /**
  55242. * Returns a string representation of the constraint.
  55243. *
  55244. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  55245. */
  55246. public function toString() : string
  55247. {
  55248. $delta = '';
  55249. if (\is_string($this->value)) {
  55250. if (\strpos($this->value, "\n") !== \false) {
  55251. return 'is equal to <text>';
  55252. }
  55253. return \sprintf("is equal to '%s'", $this->value);
  55254. }
  55255. if ($this->delta != 0) {
  55256. $delta = \sprintf(' with delta <%F>', $this->delta);
  55257. }
  55258. return \sprintf('is equal to %s%s', $this->exporter()->export($this->value), $delta);
  55259. }
  55260. }
  55261. <?php
  55262. declare (strict_types=1);
  55263. /*
  55264. * This file is part of PHPUnit.
  55265. *
  55266. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  55267. *
  55268. * For the full copyright and license information, please view the LICENSE
  55269. * file that was distributed with this source code.
  55270. */
  55271. namespace PHPUnit\Framework\Constraint;
  55272. /**
  55273. * Provides human readable messages for each JSON error.
  55274. */
  55275. final class JsonMatchesErrorMessageProvider
  55276. {
  55277. /**
  55278. * Translates JSON error to a human readable string.
  55279. */
  55280. public static function determineJsonError(string $error, string $prefix = '') : ?string
  55281. {
  55282. switch ($error) {
  55283. case \JSON_ERROR_NONE:
  55284. return null;
  55285. case \JSON_ERROR_DEPTH:
  55286. return $prefix . 'Maximum stack depth exceeded';
  55287. case \JSON_ERROR_STATE_MISMATCH:
  55288. return $prefix . 'Underflow or the modes mismatch';
  55289. case \JSON_ERROR_CTRL_CHAR:
  55290. return $prefix . 'Unexpected control character found';
  55291. case \JSON_ERROR_SYNTAX:
  55292. return $prefix . 'Syntax error, malformed JSON';
  55293. case \JSON_ERROR_UTF8:
  55294. return $prefix . 'Malformed UTF-8 characters, possibly incorrectly encoded';
  55295. default:
  55296. return $prefix . 'Unknown error';
  55297. }
  55298. }
  55299. /**
  55300. * Translates a given type to a human readable message prefix.
  55301. */
  55302. public static function translateTypeToPrefix(string $type) : string
  55303. {
  55304. switch (\strtolower($type)) {
  55305. case 'expected':
  55306. $prefix = 'Expected value JSON decode error - ';
  55307. break;
  55308. case 'actual':
  55309. $prefix = 'Actual value JSON decode error - ';
  55310. break;
  55311. default:
  55312. $prefix = '';
  55313. break;
  55314. }
  55315. return $prefix;
  55316. }
  55317. }
  55318. <?php
  55319. declare (strict_types=1);
  55320. /*
  55321. * This file is part of PHPUnit.
  55322. *
  55323. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  55324. *
  55325. * For the full copyright and license information, please view the LICENSE
  55326. * file that was distributed with this source code.
  55327. */
  55328. namespace PHPUnit\Framework\Constraint;
  55329. use PHPUnit\Framework\ExpectationFailedException;
  55330. use PHPUnit\Util\Json;
  55331. use PHPUnit\SebastianBergmann\Comparator\ComparisonFailure;
  55332. /**
  55333. * Asserts whether or not two JSON objects are equal.
  55334. */
  55335. final class JsonMatches extends \PHPUnit\Framework\Constraint\Constraint
  55336. {
  55337. /**
  55338. * @var string
  55339. */
  55340. private $value;
  55341. public function __construct(string $value)
  55342. {
  55343. $this->value = $value;
  55344. }
  55345. /**
  55346. * Returns a string representation of the object.
  55347. */
  55348. public function toString() : string
  55349. {
  55350. return \sprintf('matches JSON string "%s"', $this->value);
  55351. }
  55352. /**
  55353. * Evaluates the constraint for parameter $other. Returns true if the
  55354. * constraint is met, false otherwise.
  55355. *
  55356. * This method can be overridden to implement the evaluation algorithm.
  55357. *
  55358. * @param mixed $other value or object to evaluate
  55359. */
  55360. protected function matches($other) : bool
  55361. {
  55362. [$error, $recodedOther] = \PHPUnit\Util\Json::canonicalize($other);
  55363. if ($error) {
  55364. return \false;
  55365. }
  55366. [$error, $recodedValue] = \PHPUnit\Util\Json::canonicalize($this->value);
  55367. if ($error) {
  55368. return \false;
  55369. }
  55370. return $recodedOther == $recodedValue;
  55371. }
  55372. /**
  55373. * Throws an exception for the given compared value and test description
  55374. *
  55375. * @param mixed $other evaluated value or object
  55376. * @param string $description Additional information about the test
  55377. * @param ComparisonFailure $comparisonFailure
  55378. *
  55379. * @throws ExpectationFailedException
  55380. * @throws \PHPUnit\Framework\Exception
  55381. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  55382. *
  55383. * @psalm-return never-return
  55384. */
  55385. protected function fail($other, $description, \PHPUnit\SebastianBergmann\Comparator\ComparisonFailure $comparisonFailure = null) : void
  55386. {
  55387. if ($comparisonFailure === null) {
  55388. [$error, $recodedOther] = \PHPUnit\Util\Json::canonicalize($other);
  55389. if ($error) {
  55390. parent::fail($other, $description);
  55391. }
  55392. [$error, $recodedValue] = \PHPUnit\Util\Json::canonicalize($this->value);
  55393. if ($error) {
  55394. parent::fail($other, $description);
  55395. }
  55396. $comparisonFailure = new \PHPUnit\SebastianBergmann\Comparator\ComparisonFailure(\json_decode($this->value), \json_decode($other), \PHPUnit\Util\Json::prettify($recodedValue), \PHPUnit\Util\Json::prettify($recodedOther), \false, 'Failed asserting that two json values are equal.');
  55397. }
  55398. parent::fail($other, $description, $comparisonFailure);
  55399. }
  55400. }
  55401. <?php
  55402. declare (strict_types=1);
  55403. /*
  55404. * This file is part of PHPUnit.
  55405. *
  55406. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  55407. *
  55408. * For the full copyright and license information, please view the LICENSE
  55409. * file that was distributed with this source code.
  55410. */
  55411. namespace PHPUnit\Framework\Constraint;
  55412. /**
  55413. * Constraint that checks if the directory(name) that it is evaluated for exists.
  55414. *
  55415. * The file path to check is passed as $other in evaluate().
  55416. */
  55417. final class DirectoryExists extends \PHPUnit\Framework\Constraint\Constraint
  55418. {
  55419. /**
  55420. * Returns a string representation of the constraint.
  55421. */
  55422. public function toString() : string
  55423. {
  55424. return 'directory exists';
  55425. }
  55426. /**
  55427. * Evaluates the constraint for parameter $other. Returns true if the
  55428. * constraint is met, false otherwise.
  55429. *
  55430. * @param mixed $other value or object to evaluate
  55431. */
  55432. protected function matches($other) : bool
  55433. {
  55434. return \is_dir($other);
  55435. }
  55436. /**
  55437. * Returns the description of the failure
  55438. *
  55439. * The beginning of failure messages is "Failed asserting that" in most
  55440. * cases. This method should return the second part of that sentence.
  55441. *
  55442. * @param mixed $other evaluated value or object
  55443. */
  55444. protected function failureDescription($other) : string
  55445. {
  55446. return \sprintf('directory "%s" exists', $other);
  55447. }
  55448. }
  55449. <?php
  55450. declare (strict_types=1);
  55451. /*
  55452. * This file is part of PHPUnit.
  55453. *
  55454. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  55455. *
  55456. * For the full copyright and license information, please view the LICENSE
  55457. * file that was distributed with this source code.
  55458. */
  55459. namespace PHPUnit\Framework\Constraint;
  55460. /**
  55461. * Constraint that checks if the file/dir(name) that it is evaluated for is readable.
  55462. *
  55463. * The file path to check is passed as $other in evaluate().
  55464. */
  55465. final class IsReadable extends \PHPUnit\Framework\Constraint\Constraint
  55466. {
  55467. /**
  55468. * Returns a string representation of the constraint.
  55469. */
  55470. public function toString() : string
  55471. {
  55472. return 'is readable';
  55473. }
  55474. /**
  55475. * Evaluates the constraint for parameter $other. Returns true if the
  55476. * constraint is met, false otherwise.
  55477. *
  55478. * @param mixed $other value or object to evaluate
  55479. */
  55480. protected function matches($other) : bool
  55481. {
  55482. return \is_readable($other);
  55483. }
  55484. /**
  55485. * Returns the description of the failure
  55486. *
  55487. * The beginning of failure messages is "Failed asserting that" in most
  55488. * cases. This method should return the second part of that sentence.
  55489. *
  55490. * @param mixed $other evaluated value or object
  55491. */
  55492. protected function failureDescription($other) : string
  55493. {
  55494. return \sprintf('"%s" is readable', $other);
  55495. }
  55496. }
  55497. <?php
  55498. declare (strict_types=1);
  55499. /*
  55500. * This file is part of PHPUnit.
  55501. *
  55502. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  55503. *
  55504. * For the full copyright and license information, please view the LICENSE
  55505. * file that was distributed with this source code.
  55506. */
  55507. namespace PHPUnit\Framework;
  55508. /**
  55509. * @deprecated Use the `TestHook` interfaces instead
  55510. */
  55511. interface TestListener
  55512. {
  55513. /**
  55514. * An error occurred.
  55515. *
  55516. * @deprecated Use `AfterTestErrorHook::executeAfterTestError` instead
  55517. */
  55518. public function addError(\PHPUnit\Framework\Test $test, \Throwable $t, float $time) : void;
  55519. /**
  55520. * A warning occurred.
  55521. *
  55522. * @deprecated Use `AfterTestWarningHook::executeAfterTestWarning` instead
  55523. */
  55524. public function addWarning(\PHPUnit\Framework\Test $test, \PHPUnit\Framework\Warning $e, float $time) : void;
  55525. /**
  55526. * A failure occurred.
  55527. *
  55528. * @deprecated Use `AfterTestFailureHook::executeAfterTestFailure` instead
  55529. */
  55530. public function addFailure(\PHPUnit\Framework\Test $test, \PHPUnit\Framework\AssertionFailedError $e, float $time) : void;
  55531. /**
  55532. * Incomplete test.
  55533. *
  55534. * @deprecated Use `AfterIncompleteTestHook::executeAfterIncompleteTest` instead
  55535. */
  55536. public function addIncompleteTest(\PHPUnit\Framework\Test $test, \Throwable $t, float $time) : void;
  55537. /**
  55538. * Risky test.
  55539. *
  55540. * @deprecated Use `AfterRiskyTestHook::executeAfterRiskyTest` instead
  55541. */
  55542. public function addRiskyTest(\PHPUnit\Framework\Test $test, \Throwable $t, float $time) : void;
  55543. /**
  55544. * Skipped test.
  55545. *
  55546. * @deprecated Use `AfterSkippedTestHook::executeAfterSkippedTest` instead
  55547. */
  55548. public function addSkippedTest(\PHPUnit\Framework\Test $test, \Throwable $t, float $time) : void;
  55549. /**
  55550. * A test suite started.
  55551. */
  55552. public function startTestSuite(\PHPUnit\Framework\TestSuite $suite) : void;
  55553. /**
  55554. * A test suite ended.
  55555. */
  55556. public function endTestSuite(\PHPUnit\Framework\TestSuite $suite) : void;
  55557. /**
  55558. * A test started.
  55559. *
  55560. * @deprecated Use `BeforeTestHook::executeBeforeTest` instead
  55561. */
  55562. public function startTest(\PHPUnit\Framework\Test $test) : void;
  55563. /**
  55564. * A test ended.
  55565. *
  55566. * @deprecated Use `AfterTestHook::executeAfterTest` instead
  55567. */
  55568. public function endTest(\PHPUnit\Framework\Test $test, float $time) : void;
  55569. }
  55570. <?php
  55571. declare (strict_types=1);
  55572. /*
  55573. * This file is part of PHPUnit.
  55574. *
  55575. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  55576. *
  55577. * For the full copyright and license information, please view the LICENSE
  55578. * file that was distributed with this source code.
  55579. */
  55580. namespace PHPUnit\Framework;
  55581. use PHPUnit\Util\Filter;
  55582. use PHPUnit\Util\InvalidDataSetException;
  55583. use PHPUnit\Util\Test as TestUtil;
  55584. /**
  55585. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  55586. */
  55587. final class TestBuilder
  55588. {
  55589. public function build(\ReflectionClass $theClass, string $methodName) : \PHPUnit\Framework\Test
  55590. {
  55591. $className = $theClass->getName();
  55592. if (!$theClass->isInstantiable()) {
  55593. return new \PHPUnit\Framework\WarningTestCase(\sprintf('Cannot instantiate class "%s".', $className));
  55594. }
  55595. $backupSettings = \PHPUnit\Util\Test::getBackupSettings($className, $methodName);
  55596. $preserveGlobalState = \PHPUnit\Util\Test::getPreserveGlobalStateSettings($className, $methodName);
  55597. $runTestInSeparateProcess = \PHPUnit\Util\Test::getProcessIsolationSettings($className, $methodName);
  55598. $runClassInSeparateProcess = \PHPUnit\Util\Test::getClassProcessIsolationSettings($className, $methodName);
  55599. $constructor = $theClass->getConstructor();
  55600. if ($constructor === null) {
  55601. throw new \PHPUnit\Framework\Exception('No valid test provided.');
  55602. }
  55603. $parameters = $constructor->getParameters();
  55604. // TestCase() or TestCase($name)
  55605. if (\count($parameters) < 2) {
  55606. $test = $this->buildTestWithoutData($className);
  55607. } else {
  55608. try {
  55609. $data = \PHPUnit\Util\Test::getProvidedData($className, $methodName);
  55610. } catch (\PHPUnit\Framework\IncompleteTestError $e) {
  55611. $message = \sprintf("Test for %s::%s marked incomplete by data provider\n%s", $className, $methodName, $this->throwableToString($e));
  55612. $data = new \PHPUnit\Framework\IncompleteTestCase($className, $methodName, $message);
  55613. } catch (\PHPUnit\Framework\SkippedTestError $e) {
  55614. $message = \sprintf("Test for %s::%s skipped by data provider\n%s", $className, $methodName, $this->throwableToString($e));
  55615. $data = new \PHPUnit\Framework\SkippedTestCase($className, $methodName, $message);
  55616. } catch (\Throwable $t) {
  55617. $message = \sprintf("The data provider specified for %s::%s is invalid.\n%s", $className, $methodName, $this->throwableToString($t));
  55618. $data = new \PHPUnit\Framework\WarningTestCase($message);
  55619. }
  55620. // Test method with @dataProvider.
  55621. if (isset($data)) {
  55622. $test = $this->buildDataProviderTestSuite($methodName, $className, $data, $runTestInSeparateProcess, $preserveGlobalState, $runClassInSeparateProcess, $backupSettings);
  55623. } else {
  55624. $test = $this->buildTestWithoutData($className);
  55625. }
  55626. }
  55627. if ($test instanceof \PHPUnit\Framework\TestCase) {
  55628. $test->setName($methodName);
  55629. $this->configureTestCase($test, $runTestInSeparateProcess, $preserveGlobalState, $runClassInSeparateProcess, $backupSettings);
  55630. }
  55631. return $test;
  55632. }
  55633. /** @psalm-param class-string $className */
  55634. private function buildTestWithoutData(string $className)
  55635. {
  55636. return new $className();
  55637. }
  55638. /** @psalm-param class-string $className */
  55639. private function buildDataProviderTestSuite(string $methodName, string $className, $data, bool $runTestInSeparateProcess, ?bool $preserveGlobalState, bool $runClassInSeparateProcess, array $backupSettings) : \PHPUnit\Framework\DataProviderTestSuite
  55640. {
  55641. $dataProviderTestSuite = new \PHPUnit\Framework\DataProviderTestSuite($className . '::' . $methodName);
  55642. $groups = \PHPUnit\Util\Test::getGroups($className, $methodName);
  55643. if ($data instanceof \PHPUnit\Framework\WarningTestCase || $data instanceof \PHPUnit\Framework\SkippedTestCase || $data instanceof \PHPUnit\Framework\IncompleteTestCase) {
  55644. $dataProviderTestSuite->addTest($data, $groups);
  55645. } else {
  55646. foreach ($data as $_dataName => $_data) {
  55647. $_test = new $className($methodName, $_data, $_dataName);
  55648. \assert($_test instanceof \PHPUnit\Framework\TestCase);
  55649. $this->configureTestCase($_test, $runTestInSeparateProcess, $preserveGlobalState, $runClassInSeparateProcess, $backupSettings);
  55650. $dataProviderTestSuite->addTest($_test, $groups);
  55651. }
  55652. }
  55653. return $dataProviderTestSuite;
  55654. }
  55655. private function configureTestCase(\PHPUnit\Framework\TestCase $test, bool $runTestInSeparateProcess, ?bool $preserveGlobalState, bool $runClassInSeparateProcess, array $backupSettings) : void
  55656. {
  55657. if ($runTestInSeparateProcess) {
  55658. $test->setRunTestInSeparateProcess(\true);
  55659. if ($preserveGlobalState !== null) {
  55660. $test->setPreserveGlobalState($preserveGlobalState);
  55661. }
  55662. }
  55663. if ($runClassInSeparateProcess) {
  55664. $test->setRunClassInSeparateProcess(\true);
  55665. if ($preserveGlobalState !== null) {
  55666. $test->setPreserveGlobalState($preserveGlobalState);
  55667. }
  55668. }
  55669. if ($backupSettings['backupGlobals'] !== null) {
  55670. $test->setBackupGlobals($backupSettings['backupGlobals']);
  55671. }
  55672. if ($backupSettings['backupStaticAttributes'] !== null) {
  55673. $test->setBackupStaticAttributes($backupSettings['backupStaticAttributes']);
  55674. }
  55675. }
  55676. private function throwableToString(\Throwable $t) : string
  55677. {
  55678. $message = $t->getMessage();
  55679. if (empty(\trim($message))) {
  55680. $message = '<no message>';
  55681. }
  55682. if ($t instanceof \PHPUnit\Util\InvalidDataSetException) {
  55683. return \sprintf("%s\n%s", $message, \PHPUnit\Util\Filter::getFilteredStacktrace($t));
  55684. }
  55685. return \sprintf("%s: %s\n%s", \get_class($t), $message, \PHPUnit\Util\Filter::getFilteredStacktrace($t));
  55686. }
  55687. }
  55688. <?php
  55689. declare (strict_types=1);
  55690. /*
  55691. * This file is part of PHPUnit.
  55692. *
  55693. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  55694. *
  55695. * For the full copyright and license information, please view the LICENSE
  55696. * file that was distributed with this source code.
  55697. */
  55698. namespace PHPUnit\Framework;
  55699. use PHPUnit\Framework\MockObject\Exception as MockObjectException;
  55700. use PHPUnit\Util\Blacklist;
  55701. use PHPUnit\Util\ErrorHandler;
  55702. use PHPUnit\Util\Printer;
  55703. use PHPUnit\Util\Test as TestUtil;
  55704. use PHPUnit\SebastianBergmann\CodeCoverage\CodeCoverage;
  55705. use PHPUnit\SebastianBergmann\CodeCoverage\CoveredCodeNotExecutedException as OriginalCoveredCodeNotExecutedException;
  55706. use PHPUnit\SebastianBergmann\CodeCoverage\Exception as OriginalCodeCoverageException;
  55707. use PHPUnit\SebastianBergmann\CodeCoverage\UnintentionallyCoveredCodeException;
  55708. use PHPUnit\SebastianBergmann\Invoker\Invoker;
  55709. use PHPUnit\SebastianBergmann\Invoker\TimeoutException;
  55710. use PHPUnit\SebastianBergmann\ResourceOperations\ResourceOperations;
  55711. use PHPUnit\SebastianBergmann\Timer\Timer;
  55712. /**
  55713. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  55714. */
  55715. final class TestResult implements \Countable
  55716. {
  55717. /**
  55718. * @var array
  55719. */
  55720. private $passed = [];
  55721. /**
  55722. * @var TestFailure[]
  55723. */
  55724. private $errors = [];
  55725. /**
  55726. * @var TestFailure[]
  55727. */
  55728. private $failures = [];
  55729. /**
  55730. * @var TestFailure[]
  55731. */
  55732. private $warnings = [];
  55733. /**
  55734. * @var TestFailure[]
  55735. */
  55736. private $notImplemented = [];
  55737. /**
  55738. * @var TestFailure[]
  55739. */
  55740. private $risky = [];
  55741. /**
  55742. * @var TestFailure[]
  55743. */
  55744. private $skipped = [];
  55745. /**
  55746. * @deprecated Use the `TestHook` interfaces instead
  55747. *
  55748. * @var TestListener[]
  55749. */
  55750. private $listeners = [];
  55751. /**
  55752. * @var int
  55753. */
  55754. private $runTests = 0;
  55755. /**
  55756. * @var float
  55757. */
  55758. private $time = 0;
  55759. /**
  55760. * @var TestSuite
  55761. */
  55762. private $topTestSuite;
  55763. /**
  55764. * Code Coverage information.
  55765. *
  55766. * @var CodeCoverage
  55767. */
  55768. private $codeCoverage;
  55769. /**
  55770. * @var bool
  55771. */
  55772. private $convertDeprecationsToExceptions = \true;
  55773. /**
  55774. * @var bool
  55775. */
  55776. private $convertErrorsToExceptions = \true;
  55777. /**
  55778. * @var bool
  55779. */
  55780. private $convertNoticesToExceptions = \true;
  55781. /**
  55782. * @var bool
  55783. */
  55784. private $convertWarningsToExceptions = \true;
  55785. /**
  55786. * @var bool
  55787. */
  55788. private $stop = \false;
  55789. /**
  55790. * @var bool
  55791. */
  55792. private $stopOnError = \false;
  55793. /**
  55794. * @var bool
  55795. */
  55796. private $stopOnFailure = \false;
  55797. /**
  55798. * @var bool
  55799. */
  55800. private $stopOnWarning = \false;
  55801. /**
  55802. * @var bool
  55803. */
  55804. private $beStrictAboutTestsThatDoNotTestAnything = \true;
  55805. /**
  55806. * @var bool
  55807. */
  55808. private $beStrictAboutOutputDuringTests = \false;
  55809. /**
  55810. * @var bool
  55811. */
  55812. private $beStrictAboutTodoAnnotatedTests = \false;
  55813. /**
  55814. * @var bool
  55815. */
  55816. private $beStrictAboutResourceUsageDuringSmallTests = \false;
  55817. /**
  55818. * @var bool
  55819. */
  55820. private $enforceTimeLimit = \false;
  55821. /**
  55822. * @var bool
  55823. */
  55824. private $forceCoversAnnotation = \false;
  55825. /**
  55826. * @var int
  55827. */
  55828. private $timeoutForSmallTests = 1;
  55829. /**
  55830. * @var int
  55831. */
  55832. private $timeoutForMediumTests = 10;
  55833. /**
  55834. * @var int
  55835. */
  55836. private $timeoutForLargeTests = 60;
  55837. /**
  55838. * @var bool
  55839. */
  55840. private $stopOnRisky = \false;
  55841. /**
  55842. * @var bool
  55843. */
  55844. private $stopOnIncomplete = \false;
  55845. /**
  55846. * @var bool
  55847. */
  55848. private $stopOnSkipped = \false;
  55849. /**
  55850. * @var bool
  55851. */
  55852. private $lastTestFailed = \false;
  55853. /**
  55854. * @var int
  55855. */
  55856. private $defaultTimeLimit = 0;
  55857. /**
  55858. * @var bool
  55859. */
  55860. private $stopOnDefect = \false;
  55861. /**
  55862. * @var bool
  55863. */
  55864. private $registerMockObjectsFromTestArgumentsRecursively = \false;
  55865. /**
  55866. * @deprecated Use the `TestHook` interfaces instead
  55867. *
  55868. * @codeCoverageIgnore
  55869. *
  55870. * Registers a TestListener.
  55871. */
  55872. public function addListener(\PHPUnit\Framework\TestListener $listener) : void
  55873. {
  55874. $this->listeners[] = $listener;
  55875. }
  55876. /**
  55877. * @deprecated Use the `TestHook` interfaces instead
  55878. *
  55879. * @codeCoverageIgnore
  55880. *
  55881. * Unregisters a TestListener.
  55882. */
  55883. public function removeListener(\PHPUnit\Framework\TestListener $listener) : void
  55884. {
  55885. foreach ($this->listeners as $key => $_listener) {
  55886. if ($listener === $_listener) {
  55887. unset($this->listeners[$key]);
  55888. }
  55889. }
  55890. }
  55891. /**
  55892. * @deprecated Use the `TestHook` interfaces instead
  55893. *
  55894. * @codeCoverageIgnore
  55895. *
  55896. * Flushes all flushable TestListeners.
  55897. */
  55898. public function flushListeners() : void
  55899. {
  55900. foreach ($this->listeners as $listener) {
  55901. if ($listener instanceof \PHPUnit\Util\Printer) {
  55902. $listener->flush();
  55903. }
  55904. }
  55905. }
  55906. /**
  55907. * Adds an error to the list of errors.
  55908. */
  55909. public function addError(\PHPUnit\Framework\Test $test, \Throwable $t, float $time) : void
  55910. {
  55911. if ($t instanceof \PHPUnit\Framework\RiskyTestError) {
  55912. $this->risky[] = new \PHPUnit\Framework\TestFailure($test, $t);
  55913. $notifyMethod = 'addRiskyTest';
  55914. if ($test instanceof \PHPUnit\Framework\TestCase) {
  55915. $test->markAsRisky();
  55916. }
  55917. if ($this->stopOnRisky || $this->stopOnDefect) {
  55918. $this->stop();
  55919. }
  55920. } elseif ($t instanceof \PHPUnit\Framework\IncompleteTest) {
  55921. $this->notImplemented[] = new \PHPUnit\Framework\TestFailure($test, $t);
  55922. $notifyMethod = 'addIncompleteTest';
  55923. if ($this->stopOnIncomplete) {
  55924. $this->stop();
  55925. }
  55926. } elseif ($t instanceof \PHPUnit\Framework\SkippedTest) {
  55927. $this->skipped[] = new \PHPUnit\Framework\TestFailure($test, $t);
  55928. $notifyMethod = 'addSkippedTest';
  55929. if ($this->stopOnSkipped) {
  55930. $this->stop();
  55931. }
  55932. } else {
  55933. $this->errors[] = new \PHPUnit\Framework\TestFailure($test, $t);
  55934. $notifyMethod = 'addError';
  55935. if ($this->stopOnError || $this->stopOnFailure) {
  55936. $this->stop();
  55937. }
  55938. }
  55939. // @see https://github.com/sebastianbergmann/phpunit/issues/1953
  55940. if ($t instanceof \Error) {
  55941. $t = new \PHPUnit\Framework\ExceptionWrapper($t);
  55942. }
  55943. foreach ($this->listeners as $listener) {
  55944. $listener->{$notifyMethod}($test, $t, $time);
  55945. }
  55946. $this->lastTestFailed = \true;
  55947. $this->time += $time;
  55948. }
  55949. /**
  55950. * Adds a warning to the list of warnings.
  55951. * The passed in exception caused the warning.
  55952. */
  55953. public function addWarning(\PHPUnit\Framework\Test $test, \PHPUnit\Framework\Warning $e, float $time) : void
  55954. {
  55955. if ($this->stopOnWarning || $this->stopOnDefect) {
  55956. $this->stop();
  55957. }
  55958. $this->warnings[] = new \PHPUnit\Framework\TestFailure($test, $e);
  55959. foreach ($this->listeners as $listener) {
  55960. $listener->addWarning($test, $e, $time);
  55961. }
  55962. $this->time += $time;
  55963. }
  55964. /**
  55965. * Adds a failure to the list of failures.
  55966. * The passed in exception caused the failure.
  55967. */
  55968. public function addFailure(\PHPUnit\Framework\Test $test, \PHPUnit\Framework\AssertionFailedError $e, float $time) : void
  55969. {
  55970. if ($e instanceof \PHPUnit\Framework\RiskyTestError || $e instanceof \PHPUnit\Framework\OutputError) {
  55971. $this->risky[] = new \PHPUnit\Framework\TestFailure($test, $e);
  55972. $notifyMethod = 'addRiskyTest';
  55973. if ($test instanceof \PHPUnit\Framework\TestCase) {
  55974. $test->markAsRisky();
  55975. }
  55976. if ($this->stopOnRisky || $this->stopOnDefect) {
  55977. $this->stop();
  55978. }
  55979. } elseif ($e instanceof \PHPUnit\Framework\IncompleteTest) {
  55980. $this->notImplemented[] = new \PHPUnit\Framework\TestFailure($test, $e);
  55981. $notifyMethod = 'addIncompleteTest';
  55982. if ($this->stopOnIncomplete) {
  55983. $this->stop();
  55984. }
  55985. } elseif ($e instanceof \PHPUnit\Framework\SkippedTest) {
  55986. $this->skipped[] = new \PHPUnit\Framework\TestFailure($test, $e);
  55987. $notifyMethod = 'addSkippedTest';
  55988. if ($this->stopOnSkipped) {
  55989. $this->stop();
  55990. }
  55991. } else {
  55992. $this->failures[] = new \PHPUnit\Framework\TestFailure($test, $e);
  55993. $notifyMethod = 'addFailure';
  55994. if ($this->stopOnFailure || $this->stopOnDefect) {
  55995. $this->stop();
  55996. }
  55997. }
  55998. foreach ($this->listeners as $listener) {
  55999. $listener->{$notifyMethod}($test, $e, $time);
  56000. }
  56001. $this->lastTestFailed = \true;
  56002. $this->time += $time;
  56003. }
  56004. /**
  56005. * Informs the result that a test suite will be started.
  56006. */
  56007. public function startTestSuite(\PHPUnit\Framework\TestSuite $suite) : void
  56008. {
  56009. if ($this->topTestSuite === null) {
  56010. $this->topTestSuite = $suite;
  56011. }
  56012. foreach ($this->listeners as $listener) {
  56013. $listener->startTestSuite($suite);
  56014. }
  56015. }
  56016. /**
  56017. * Informs the result that a test suite was completed.
  56018. */
  56019. public function endTestSuite(\PHPUnit\Framework\TestSuite $suite) : void
  56020. {
  56021. foreach ($this->listeners as $listener) {
  56022. $listener->endTestSuite($suite);
  56023. }
  56024. }
  56025. /**
  56026. * Informs the result that a test will be started.
  56027. */
  56028. public function startTest(\PHPUnit\Framework\Test $test) : void
  56029. {
  56030. $this->lastTestFailed = \false;
  56031. $this->runTests += \count($test);
  56032. foreach ($this->listeners as $listener) {
  56033. $listener->startTest($test);
  56034. }
  56035. }
  56036. /**
  56037. * Informs the result that a test was completed.
  56038. *
  56039. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  56040. */
  56041. public function endTest(\PHPUnit\Framework\Test $test, float $time) : void
  56042. {
  56043. foreach ($this->listeners as $listener) {
  56044. $listener->endTest($test, $time);
  56045. }
  56046. if (!$this->lastTestFailed && $test instanceof \PHPUnit\Framework\TestCase) {
  56047. $class = \get_class($test);
  56048. $key = $class . '::' . $test->getName();
  56049. $this->passed[$key] = ['result' => $test->getResult(), 'size' => \PHPUnit\Util\Test::getSize($class, $test->getName(\false))];
  56050. $this->time += $time;
  56051. }
  56052. }
  56053. /**
  56054. * Returns true if no risky test occurred.
  56055. */
  56056. public function allHarmless() : bool
  56057. {
  56058. return $this->riskyCount() === 0;
  56059. }
  56060. /**
  56061. * Gets the number of risky tests.
  56062. */
  56063. public function riskyCount() : int
  56064. {
  56065. return \count($this->risky);
  56066. }
  56067. /**
  56068. * Returns true if no incomplete test occurred.
  56069. */
  56070. public function allCompletelyImplemented() : bool
  56071. {
  56072. return $this->notImplementedCount() === 0;
  56073. }
  56074. /**
  56075. * Gets the number of incomplete tests.
  56076. */
  56077. public function notImplementedCount() : int
  56078. {
  56079. return \count($this->notImplemented);
  56080. }
  56081. /**
  56082. * Returns an array of TestFailure objects for the risky tests
  56083. *
  56084. * @return TestFailure[]
  56085. */
  56086. public function risky() : array
  56087. {
  56088. return $this->risky;
  56089. }
  56090. /**
  56091. * Returns an array of TestFailure objects for the incomplete tests
  56092. *
  56093. * @return TestFailure[]
  56094. */
  56095. public function notImplemented() : array
  56096. {
  56097. return $this->notImplemented;
  56098. }
  56099. /**
  56100. * Returns true if no test has been skipped.
  56101. */
  56102. public function noneSkipped() : bool
  56103. {
  56104. return $this->skippedCount() === 0;
  56105. }
  56106. /**
  56107. * Gets the number of skipped tests.
  56108. */
  56109. public function skippedCount() : int
  56110. {
  56111. return \count($this->skipped);
  56112. }
  56113. /**
  56114. * Returns an array of TestFailure objects for the skipped tests
  56115. *
  56116. * @return TestFailure[]
  56117. */
  56118. public function skipped() : array
  56119. {
  56120. return $this->skipped;
  56121. }
  56122. /**
  56123. * Gets the number of detected errors.
  56124. */
  56125. public function errorCount() : int
  56126. {
  56127. return \count($this->errors);
  56128. }
  56129. /**
  56130. * Returns an array of TestFailure objects for the errors
  56131. *
  56132. * @return TestFailure[]
  56133. */
  56134. public function errors() : array
  56135. {
  56136. return $this->errors;
  56137. }
  56138. /**
  56139. * Gets the number of detected failures.
  56140. */
  56141. public function failureCount() : int
  56142. {
  56143. return \count($this->failures);
  56144. }
  56145. /**
  56146. * Returns an array of TestFailure objects for the failures
  56147. *
  56148. * @return TestFailure[]
  56149. */
  56150. public function failures() : array
  56151. {
  56152. return $this->failures;
  56153. }
  56154. /**
  56155. * Gets the number of detected warnings.
  56156. */
  56157. public function warningCount() : int
  56158. {
  56159. return \count($this->warnings);
  56160. }
  56161. /**
  56162. * Returns an array of TestFailure objects for the warnings
  56163. *
  56164. * @return TestFailure[]
  56165. */
  56166. public function warnings() : array
  56167. {
  56168. return $this->warnings;
  56169. }
  56170. /**
  56171. * Returns the names of the tests that have passed.
  56172. */
  56173. public function passed() : array
  56174. {
  56175. return $this->passed;
  56176. }
  56177. /**
  56178. * Returns the (top) test suite.
  56179. */
  56180. public function topTestSuite() : \PHPUnit\Framework\TestSuite
  56181. {
  56182. return $this->topTestSuite;
  56183. }
  56184. /**
  56185. * Returns whether code coverage information should be collected.
  56186. */
  56187. public function getCollectCodeCoverageInformation() : bool
  56188. {
  56189. return $this->codeCoverage !== null;
  56190. }
  56191. /**
  56192. * Runs a TestCase.
  56193. *
  56194. * @throws CodeCoverageException
  56195. * @throws OriginalCoveredCodeNotExecutedException
  56196. * @throws UnintentionallyCoveredCodeException
  56197. * @throws \SebastianBergmann\CodeCoverage\InvalidArgumentException
  56198. * @throws \SebastianBergmann\CodeCoverage\RuntimeException
  56199. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  56200. */
  56201. public function run(\PHPUnit\Framework\Test $test) : void
  56202. {
  56203. \PHPUnit\Framework\Assert::resetCount();
  56204. if ($test instanceof \PHPUnit\Framework\TestCase) {
  56205. $test->setRegisterMockObjectsFromTestArgumentsRecursively($this->registerMockObjectsFromTestArgumentsRecursively);
  56206. $isAnyCoverageRequired = \PHPUnit\Util\Test::requiresCodeCoverageDataCollection($test);
  56207. }
  56208. $error = \false;
  56209. $failure = \false;
  56210. $warning = \false;
  56211. $incomplete = \false;
  56212. $risky = \false;
  56213. $skipped = \false;
  56214. $this->startTest($test);
  56215. if ($this->convertDeprecationsToExceptions || $this->convertErrorsToExceptions || $this->convertNoticesToExceptions || $this->convertWarningsToExceptions) {
  56216. $errorHandler = new \PHPUnit\Util\ErrorHandler($this->convertDeprecationsToExceptions, $this->convertErrorsToExceptions, $this->convertNoticesToExceptions, $this->convertWarningsToExceptions);
  56217. $errorHandler->register();
  56218. }
  56219. $collectCodeCoverage = $this->codeCoverage !== null && !$test instanceof \PHPUnit\Framework\WarningTestCase && $isAnyCoverageRequired;
  56220. if ($collectCodeCoverage) {
  56221. $this->codeCoverage->start($test);
  56222. }
  56223. $monitorFunctions = $this->beStrictAboutResourceUsageDuringSmallTests && !$test instanceof \PHPUnit\Framework\WarningTestCase && $test->getSize() === \PHPUnit\Util\Test::SMALL && \function_exists('xdebug_start_function_monitor');
  56224. if ($monitorFunctions) {
  56225. /* @noinspection ForgottenDebugOutputInspection */
  56226. \xdebug_start_function_monitor(\PHPUnit\SebastianBergmann\ResourceOperations\ResourceOperations::getFunctions());
  56227. }
  56228. $timer = new \PHPUnit\SebastianBergmann\Timer\Timer();
  56229. $timer->start();
  56230. try {
  56231. $invoker = new \PHPUnit\SebastianBergmann\Invoker\Invoker();
  56232. if (!$test instanceof \PHPUnit\Framework\WarningTestCase && $this->enforceTimeLimit && ($this->defaultTimeLimit || $test->getSize() != \PHPUnit\Util\Test::UNKNOWN) && $invoker->canInvokeWithTimeout()) {
  56233. switch ($test->getSize()) {
  56234. case \PHPUnit\Util\Test::SMALL:
  56235. $_timeout = $this->timeoutForSmallTests;
  56236. break;
  56237. case \PHPUnit\Util\Test::MEDIUM:
  56238. $_timeout = $this->timeoutForMediumTests;
  56239. break;
  56240. case \PHPUnit\Util\Test::LARGE:
  56241. $_timeout = $this->timeoutForLargeTests;
  56242. break;
  56243. case \PHPUnit\Util\Test::UNKNOWN:
  56244. $_timeout = $this->defaultTimeLimit;
  56245. break;
  56246. }
  56247. $invoker->invoke([$test, 'runBare'], [], $_timeout);
  56248. } else {
  56249. $test->runBare();
  56250. }
  56251. } catch (\PHPUnit\SebastianBergmann\Invoker\TimeoutException $e) {
  56252. $this->addFailure($test, new \PHPUnit\Framework\RiskyTestError($e->getMessage()), $_timeout);
  56253. $risky = \true;
  56254. } catch (\PHPUnit\Framework\MockObject\Exception $e) {
  56255. $e = new \PHPUnit\Framework\Warning($e->getMessage());
  56256. $warning = \true;
  56257. } catch (\PHPUnit\Framework\AssertionFailedError $e) {
  56258. $failure = \true;
  56259. if ($e instanceof \PHPUnit\Framework\RiskyTestError) {
  56260. $risky = \true;
  56261. } elseif ($e instanceof \PHPUnit\Framework\IncompleteTestError) {
  56262. $incomplete = \true;
  56263. } elseif ($e instanceof \PHPUnit\Framework\SkippedTestError) {
  56264. $skipped = \true;
  56265. }
  56266. } catch (\AssertionError $e) {
  56267. $test->addToAssertionCount(1);
  56268. $failure = \true;
  56269. $frame = $e->getTrace()[0];
  56270. $e = new \PHPUnit\Framework\AssertionFailedError(\sprintf('%s in %s:%s', $e->getMessage(), $frame['file'], $frame['line']));
  56271. } catch (\PHPUnit\Framework\Warning $e) {
  56272. $warning = \true;
  56273. } catch (\PHPUnit\Framework\Exception $e) {
  56274. $error = \true;
  56275. } catch (\Throwable $e) {
  56276. $e = new \PHPUnit\Framework\ExceptionWrapper($e);
  56277. $error = \true;
  56278. }
  56279. $time = $timer->stop()->asSeconds();
  56280. $test->addToAssertionCount(\PHPUnit\Framework\Assert::getCount());
  56281. if ($monitorFunctions) {
  56282. $blacklist = new \PHPUnit\Util\Blacklist();
  56283. /** @noinspection ForgottenDebugOutputInspection */
  56284. $functions = \xdebug_get_monitored_functions();
  56285. /* @noinspection ForgottenDebugOutputInspection */
  56286. \xdebug_stop_function_monitor();
  56287. foreach ($functions as $function) {
  56288. if (!$blacklist->isBlacklisted($function['filename'])) {
  56289. $this->addFailure($test, new \PHPUnit\Framework\RiskyTestError(\sprintf('%s() used in %s:%s', $function['function'], $function['filename'], $function['lineno'])), $time);
  56290. }
  56291. }
  56292. }
  56293. if ($this->beStrictAboutTestsThatDoNotTestAnything && $test->getNumAssertions() === 0) {
  56294. $risky = \true;
  56295. }
  56296. if ($this->forceCoversAnnotation && !$incomplete && !$skipped) {
  56297. $annotations = $test->getAnnotations();
  56298. if (!isset($annotations['class']['covers']) && !isset($annotations['method']['covers']) && !isset($annotations['class']['coversNothing']) && !isset($annotations['method']['coversNothing'])) {
  56299. $this->addFailure($test, new \PHPUnit\Framework\MissingCoversAnnotationException('This test does not have a @covers annotation but is expected to have one'), $time);
  56300. $risky = \true;
  56301. }
  56302. }
  56303. if ($collectCodeCoverage) {
  56304. $append = !$risky && !$incomplete && !$skipped;
  56305. $linesToBeCovered = [];
  56306. $linesToBeUsed = [];
  56307. if ($append && $test instanceof \PHPUnit\Framework\TestCase) {
  56308. try {
  56309. $linesToBeCovered = \PHPUnit\Util\Test::getLinesToBeCovered(\get_class($test), $test->getName(\false));
  56310. $linesToBeUsed = \PHPUnit\Util\Test::getLinesToBeUsed(\get_class($test), $test->getName(\false));
  56311. } catch (\PHPUnit\Framework\InvalidCoversTargetException $cce) {
  56312. $this->addWarning($test, new \PHPUnit\Framework\Warning($cce->getMessage()), $time);
  56313. }
  56314. }
  56315. try {
  56316. $this->codeCoverage->stop($append, $linesToBeCovered, $linesToBeUsed);
  56317. } catch (\PHPUnit\SebastianBergmann\CodeCoverage\UnintentionallyCoveredCodeException $cce) {
  56318. $this->addFailure($test, new \PHPUnit\Framework\UnintentionallyCoveredCodeError('This test executed code that is not listed as code to be covered or used:' . \PHP_EOL . $cce->getMessage()), $time);
  56319. } catch (\PHPUnit\SebastianBergmann\CodeCoverage\CoveredCodeNotExecutedException $cce) {
  56320. $this->addFailure($test, new \PHPUnit\Framework\CoveredCodeNotExecutedException('This test did not execute all the code that is listed as code to be covered:' . \PHP_EOL . $cce->getMessage()), $time);
  56321. } catch (\PHPUnit\SebastianBergmann\CodeCoverage\Exception $cce) {
  56322. $error = \true;
  56323. $e = $e ?? $cce;
  56324. }
  56325. }
  56326. if (isset($errorHandler)) {
  56327. $errorHandler->unregister();
  56328. unset($errorHandler);
  56329. }
  56330. if ($error) {
  56331. $this->addError($test, $e, $time);
  56332. } elseif ($failure) {
  56333. $this->addFailure($test, $e, $time);
  56334. } elseif ($warning) {
  56335. $this->addWarning($test, $e, $time);
  56336. } elseif ($this->beStrictAboutTestsThatDoNotTestAnything && !$test->doesNotPerformAssertions() && $test->getNumAssertions() === 0) {
  56337. try {
  56338. $reflected = new \ReflectionClass($test);
  56339. // @codeCoverageIgnoreStart
  56340. } catch (\ReflectionException $e) {
  56341. throw new \PHPUnit\Framework\Exception($e->getMessage(), (int) $e->getCode(), $e);
  56342. }
  56343. // @codeCoverageIgnoreEnd
  56344. $name = $test->getName(\false);
  56345. if ($name && $reflected->hasMethod($name)) {
  56346. try {
  56347. $reflected = $reflected->getMethod($name);
  56348. // @codeCoverageIgnoreStart
  56349. } catch (\ReflectionException $e) {
  56350. throw new \PHPUnit\Framework\Exception($e->getMessage(), (int) $e->getCode(), $e);
  56351. }
  56352. // @codeCoverageIgnoreEnd
  56353. }
  56354. $this->addFailure($test, new \PHPUnit\Framework\RiskyTestError(\sprintf("This test did not perform any assertions\n\n%s:%d", $reflected->getFileName(), $reflected->getStartLine())), $time);
  56355. } elseif ($this->beStrictAboutTestsThatDoNotTestAnything && $test->doesNotPerformAssertions() && $test->getNumAssertions() > 0) {
  56356. $this->addFailure($test, new \PHPUnit\Framework\RiskyTestError(\sprintf('This test is annotated with "@doesNotPerformAssertions" but performed %d assertions', $test->getNumAssertions())), $time);
  56357. } elseif ($this->beStrictAboutOutputDuringTests && $test->hasOutput()) {
  56358. $this->addFailure($test, new \PHPUnit\Framework\OutputError(\sprintf('This test printed output: %s', $test->getActualOutput())), $time);
  56359. } elseif ($this->beStrictAboutTodoAnnotatedTests && $test instanceof \PHPUnit\Framework\TestCase) {
  56360. $annotations = $test->getAnnotations();
  56361. if (isset($annotations['method']['todo'])) {
  56362. $this->addFailure($test, new \PHPUnit\Framework\RiskyTestError('Test method is annotated with @todo'), $time);
  56363. }
  56364. }
  56365. $this->endTest($test, $time);
  56366. }
  56367. /**
  56368. * Gets the number of run tests.
  56369. */
  56370. public function count() : int
  56371. {
  56372. return $this->runTests;
  56373. }
  56374. /**
  56375. * Checks whether the test run should stop.
  56376. */
  56377. public function shouldStop() : bool
  56378. {
  56379. return $this->stop;
  56380. }
  56381. /**
  56382. * Marks that the test run should stop.
  56383. */
  56384. public function stop() : void
  56385. {
  56386. $this->stop = \true;
  56387. }
  56388. /**
  56389. * Returns the code coverage object.
  56390. */
  56391. public function getCodeCoverage() : ?\PHPUnit\SebastianBergmann\CodeCoverage\CodeCoverage
  56392. {
  56393. return $this->codeCoverage;
  56394. }
  56395. /**
  56396. * Sets the code coverage object.
  56397. */
  56398. public function setCodeCoverage(\PHPUnit\SebastianBergmann\CodeCoverage\CodeCoverage $codeCoverage) : void
  56399. {
  56400. $this->codeCoverage = $codeCoverage;
  56401. }
  56402. /**
  56403. * Enables or disables the deprecation-to-exception conversion.
  56404. */
  56405. public function convertDeprecationsToExceptions(bool $flag) : void
  56406. {
  56407. $this->convertDeprecationsToExceptions = $flag;
  56408. }
  56409. /**
  56410. * Returns the deprecation-to-exception conversion setting.
  56411. */
  56412. public function getConvertDeprecationsToExceptions() : bool
  56413. {
  56414. return $this->convertDeprecationsToExceptions;
  56415. }
  56416. /**
  56417. * Enables or disables the error-to-exception conversion.
  56418. */
  56419. public function convertErrorsToExceptions(bool $flag) : void
  56420. {
  56421. $this->convertErrorsToExceptions = $flag;
  56422. }
  56423. /**
  56424. * Returns the error-to-exception conversion setting.
  56425. */
  56426. public function getConvertErrorsToExceptions() : bool
  56427. {
  56428. return $this->convertErrorsToExceptions;
  56429. }
  56430. /**
  56431. * Enables or disables the notice-to-exception conversion.
  56432. */
  56433. public function convertNoticesToExceptions(bool $flag) : void
  56434. {
  56435. $this->convertNoticesToExceptions = $flag;
  56436. }
  56437. /**
  56438. * Returns the notice-to-exception conversion setting.
  56439. */
  56440. public function getConvertNoticesToExceptions() : bool
  56441. {
  56442. return $this->convertNoticesToExceptions;
  56443. }
  56444. /**
  56445. * Enables or disables the warning-to-exception conversion.
  56446. */
  56447. public function convertWarningsToExceptions(bool $flag) : void
  56448. {
  56449. $this->convertWarningsToExceptions = $flag;
  56450. }
  56451. /**
  56452. * Returns the warning-to-exception conversion setting.
  56453. */
  56454. public function getConvertWarningsToExceptions() : bool
  56455. {
  56456. return $this->convertWarningsToExceptions;
  56457. }
  56458. /**
  56459. * Enables or disables the stopping when an error occurs.
  56460. */
  56461. public function stopOnError(bool $flag) : void
  56462. {
  56463. $this->stopOnError = $flag;
  56464. }
  56465. /**
  56466. * Enables or disables the stopping when a failure occurs.
  56467. */
  56468. public function stopOnFailure(bool $flag) : void
  56469. {
  56470. $this->stopOnFailure = $flag;
  56471. }
  56472. /**
  56473. * Enables or disables the stopping when a warning occurs.
  56474. */
  56475. public function stopOnWarning(bool $flag) : void
  56476. {
  56477. $this->stopOnWarning = $flag;
  56478. }
  56479. public function beStrictAboutTestsThatDoNotTestAnything(bool $flag) : void
  56480. {
  56481. $this->beStrictAboutTestsThatDoNotTestAnything = $flag;
  56482. }
  56483. public function isStrictAboutTestsThatDoNotTestAnything() : bool
  56484. {
  56485. return $this->beStrictAboutTestsThatDoNotTestAnything;
  56486. }
  56487. public function beStrictAboutOutputDuringTests(bool $flag) : void
  56488. {
  56489. $this->beStrictAboutOutputDuringTests = $flag;
  56490. }
  56491. public function isStrictAboutOutputDuringTests() : bool
  56492. {
  56493. return $this->beStrictAboutOutputDuringTests;
  56494. }
  56495. public function beStrictAboutResourceUsageDuringSmallTests(bool $flag) : void
  56496. {
  56497. $this->beStrictAboutResourceUsageDuringSmallTests = $flag;
  56498. }
  56499. public function isStrictAboutResourceUsageDuringSmallTests() : bool
  56500. {
  56501. return $this->beStrictAboutResourceUsageDuringSmallTests;
  56502. }
  56503. public function enforceTimeLimit(bool $flag) : void
  56504. {
  56505. $this->enforceTimeLimit = $flag;
  56506. }
  56507. public function enforcesTimeLimit() : bool
  56508. {
  56509. return $this->enforceTimeLimit;
  56510. }
  56511. public function beStrictAboutTodoAnnotatedTests(bool $flag) : void
  56512. {
  56513. $this->beStrictAboutTodoAnnotatedTests = $flag;
  56514. }
  56515. public function isStrictAboutTodoAnnotatedTests() : bool
  56516. {
  56517. return $this->beStrictAboutTodoAnnotatedTests;
  56518. }
  56519. public function forceCoversAnnotation() : void
  56520. {
  56521. $this->forceCoversAnnotation = \true;
  56522. }
  56523. public function forcesCoversAnnotation() : bool
  56524. {
  56525. return $this->forceCoversAnnotation;
  56526. }
  56527. /**
  56528. * Enables or disables the stopping for risky tests.
  56529. */
  56530. public function stopOnRisky(bool $flag) : void
  56531. {
  56532. $this->stopOnRisky = $flag;
  56533. }
  56534. /**
  56535. * Enables or disables the stopping for incomplete tests.
  56536. */
  56537. public function stopOnIncomplete(bool $flag) : void
  56538. {
  56539. $this->stopOnIncomplete = $flag;
  56540. }
  56541. /**
  56542. * Enables or disables the stopping for skipped tests.
  56543. */
  56544. public function stopOnSkipped(bool $flag) : void
  56545. {
  56546. $this->stopOnSkipped = $flag;
  56547. }
  56548. /**
  56549. * Enables or disables the stopping for defects: error, failure, warning
  56550. */
  56551. public function stopOnDefect(bool $flag) : void
  56552. {
  56553. $this->stopOnDefect = $flag;
  56554. }
  56555. /**
  56556. * Returns the time spent running the tests.
  56557. */
  56558. public function time() : float
  56559. {
  56560. return $this->time;
  56561. }
  56562. /**
  56563. * Returns whether the entire test was successful or not.
  56564. */
  56565. public function wasSuccessful() : bool
  56566. {
  56567. return $this->wasSuccessfulIgnoringWarnings() && empty($this->warnings);
  56568. }
  56569. public function wasSuccessfulIgnoringWarnings() : bool
  56570. {
  56571. return empty($this->errors) && empty($this->failures);
  56572. }
  56573. public function wasSuccessfulAndNoTestIsRiskyOrSkippedOrIncomplete() : bool
  56574. {
  56575. return $this->wasSuccessful() && $this->allHarmless() && $this->allCompletelyImplemented() && $this->noneSkipped();
  56576. }
  56577. /**
  56578. * Sets the default timeout for tests
  56579. */
  56580. public function setDefaultTimeLimit(int $timeout) : void
  56581. {
  56582. $this->defaultTimeLimit = $timeout;
  56583. }
  56584. /**
  56585. * Sets the timeout for small tests.
  56586. */
  56587. public function setTimeoutForSmallTests(int $timeout) : void
  56588. {
  56589. $this->timeoutForSmallTests = $timeout;
  56590. }
  56591. /**
  56592. * Sets the timeout for medium tests.
  56593. */
  56594. public function setTimeoutForMediumTests(int $timeout) : void
  56595. {
  56596. $this->timeoutForMediumTests = $timeout;
  56597. }
  56598. /**
  56599. * Sets the timeout for large tests.
  56600. */
  56601. public function setTimeoutForLargeTests(int $timeout) : void
  56602. {
  56603. $this->timeoutForLargeTests = $timeout;
  56604. }
  56605. /**
  56606. * Returns the set timeout for large tests.
  56607. */
  56608. public function getTimeoutForLargeTests() : int
  56609. {
  56610. return $this->timeoutForLargeTests;
  56611. }
  56612. public function setRegisterMockObjectsFromTestArgumentsRecursively(bool $flag) : void
  56613. {
  56614. $this->registerMockObjectsFromTestArgumentsRecursively = $flag;
  56615. }
  56616. }
  56617. <?php
  56618. declare (strict_types=1);
  56619. /*
  56620. * This file is part of PHPUnit.
  56621. *
  56622. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  56623. *
  56624. * For the full copyright and license information, please view the LICENSE
  56625. * file that was distributed with this source code.
  56626. */
  56627. namespace PHPUnit\Framework;
  56628. /**
  56629. * @deprecated The `TestListener` interface is deprecated
  56630. */
  56631. trait TestListenerDefaultImplementation
  56632. {
  56633. public function addError(\PHPUnit\Framework\Test $test, \Throwable $t, float $time) : void
  56634. {
  56635. }
  56636. public function addWarning(\PHPUnit\Framework\Test $test, \PHPUnit\Framework\Warning $e, float $time) : void
  56637. {
  56638. }
  56639. public function addFailure(\PHPUnit\Framework\Test $test, \PHPUnit\Framework\AssertionFailedError $e, float $time) : void
  56640. {
  56641. }
  56642. public function addIncompleteTest(\PHPUnit\Framework\Test $test, \Throwable $t, float $time) : void
  56643. {
  56644. }
  56645. public function addRiskyTest(\PHPUnit\Framework\Test $test, \Throwable $t, float $time) : void
  56646. {
  56647. }
  56648. public function addSkippedTest(\PHPUnit\Framework\Test $test, \Throwable $t, float $time) : void
  56649. {
  56650. }
  56651. public function startTestSuite(\PHPUnit\Framework\TestSuite $suite) : void
  56652. {
  56653. }
  56654. public function endTestSuite(\PHPUnit\Framework\TestSuite $suite) : void
  56655. {
  56656. }
  56657. public function startTest(\PHPUnit\Framework\Test $test) : void
  56658. {
  56659. }
  56660. public function endTest(\PHPUnit\Framework\Test $test, float $time) : void
  56661. {
  56662. }
  56663. }
  56664. <?php
  56665. declare (strict_types=1);
  56666. /*
  56667. * This file is part of PHPUnit.
  56668. *
  56669. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  56670. *
  56671. * For the full copyright and license information, please view the LICENSE
  56672. * file that was distributed with this source code.
  56673. */
  56674. namespace PHPUnit\Framework\Error;
  56675. use PHPUnit\Framework\Exception;
  56676. /**
  56677. * @internal
  56678. */
  56679. class Error extends \PHPUnit\Framework\Exception
  56680. {
  56681. public function __construct(string $message, int $code, string $file, int $line, \Exception $previous = null)
  56682. {
  56683. parent::__construct($message, $code, $previous);
  56684. $this->file = $file;
  56685. $this->line = $line;
  56686. }
  56687. }
  56688. <?php
  56689. declare (strict_types=1);
  56690. /*
  56691. * This file is part of PHPUnit.
  56692. *
  56693. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  56694. *
  56695. * For the full copyright and license information, please view the LICENSE
  56696. * file that was distributed with this source code.
  56697. */
  56698. namespace PHPUnit\Framework\Error;
  56699. /**
  56700. * @internal
  56701. */
  56702. final class Warning extends \PHPUnit\Framework\Error\Error
  56703. {
  56704. }
  56705. <?php
  56706. declare (strict_types=1);
  56707. /*
  56708. * This file is part of PHPUnit.
  56709. *
  56710. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  56711. *
  56712. * For the full copyright and license information, please view the LICENSE
  56713. * file that was distributed with this source code.
  56714. */
  56715. namespace PHPUnit\Framework\Error;
  56716. /**
  56717. * @internal
  56718. */
  56719. final class Deprecated extends \PHPUnit\Framework\Error\Error
  56720. {
  56721. }
  56722. <?php
  56723. declare (strict_types=1);
  56724. /*
  56725. * This file is part of PHPUnit.
  56726. *
  56727. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  56728. *
  56729. * For the full copyright and license information, please view the LICENSE
  56730. * file that was distributed with this source code.
  56731. */
  56732. namespace PHPUnit\Framework\Error;
  56733. /**
  56734. * @internal
  56735. */
  56736. final class Notice extends \PHPUnit\Framework\Error\Error
  56737. {
  56738. }
  56739. <?php
  56740. declare (strict_types=1);
  56741. /*
  56742. * This file is part of PHPUnit.
  56743. *
  56744. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  56745. *
  56746. * For the full copyright and license information, please view the LICENSE
  56747. * file that was distributed with this source code.
  56748. */
  56749. namespace PHPUnit\Framework;
  56750. use PHPUnit\Util\Filter;
  56751. /**
  56752. * Wraps Exceptions thrown by code under test.
  56753. *
  56754. * Re-instantiates Exceptions thrown by user-space code to retain their original
  56755. * class names, properties, and stack traces (but without arguments).
  56756. *
  56757. * Unlike PHPUnit\Framework_\Exception, the complete stack of previous Exceptions
  56758. * is processed.
  56759. *
  56760. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  56761. */
  56762. final class ExceptionWrapper extends \PHPUnit\Framework\Exception
  56763. {
  56764. /**
  56765. * @var string
  56766. */
  56767. protected $className;
  56768. /**
  56769. * @var null|ExceptionWrapper
  56770. */
  56771. protected $previous;
  56772. public function __construct(\Throwable $t)
  56773. {
  56774. // PDOException::getCode() is a string.
  56775. // @see https://php.net/manual/en/class.pdoexception.php#95812
  56776. parent::__construct($t->getMessage(), (int) $t->getCode());
  56777. $this->setOriginalException($t);
  56778. }
  56779. public function __toString() : string
  56780. {
  56781. $string = \PHPUnit\Framework\TestFailure::exceptionToString($this);
  56782. if ($trace = \PHPUnit\Util\Filter::getFilteredStacktrace($this)) {
  56783. $string .= "\n" . $trace;
  56784. }
  56785. if ($this->previous) {
  56786. $string .= "\nCaused by\n" . $this->previous;
  56787. }
  56788. return $string;
  56789. }
  56790. public function getClassName() : string
  56791. {
  56792. return $this->className;
  56793. }
  56794. public function getPreviousWrapped() : ?self
  56795. {
  56796. return $this->previous;
  56797. }
  56798. public function setClassName(string $className) : void
  56799. {
  56800. $this->className = $className;
  56801. }
  56802. public function setOriginalException(\Throwable $t) : void
  56803. {
  56804. $this->originalException($t);
  56805. $this->className = \get_class($t);
  56806. $this->file = $t->getFile();
  56807. $this->line = $t->getLine();
  56808. $this->serializableTrace = $t->getTrace();
  56809. foreach (\array_keys($this->serializableTrace) as $key) {
  56810. unset($this->serializableTrace[$key]['args']);
  56811. }
  56812. if ($t->getPrevious()) {
  56813. $this->previous = new self($t->getPrevious());
  56814. }
  56815. }
  56816. public function getOriginalException() : ?\Throwable
  56817. {
  56818. return $this->originalException();
  56819. }
  56820. /**
  56821. * Method to contain static originalException to exclude it from stacktrace to prevent the stacktrace contents,
  56822. * which can be quite big, from being garbage-collected, thus blocking memory until shutdown.
  56823. * Approach works both for var_dump() and var_export() and print_r()
  56824. */
  56825. private function originalException(\Throwable $exceptionToStore = null) : ?\Throwable
  56826. {
  56827. static $originalExceptions;
  56828. $instanceId = \spl_object_hash($this);
  56829. if ($exceptionToStore) {
  56830. $originalExceptions[$instanceId] = $exceptionToStore;
  56831. }
  56832. return $originalExceptions[$instanceId] ?? null;
  56833. }
  56834. }
  56835. <?php
  56836. declare (strict_types=1);
  56837. /*
  56838. * This file is part of PHPUnit.
  56839. *
  56840. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  56841. *
  56842. * For the full copyright and license information, please view the LICENSE
  56843. * file that was distributed with this source code.
  56844. */
  56845. namespace PHPUnit\Framework;
  56846. /**
  56847. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  56848. */
  56849. final class IncompleteTestCase extends \PHPUnit\Framework\TestCase
  56850. {
  56851. /**
  56852. * @var bool
  56853. */
  56854. protected $backupGlobals = \false;
  56855. /**
  56856. * @var bool
  56857. */
  56858. protected $backupStaticAttributes = \false;
  56859. /**
  56860. * @var bool
  56861. */
  56862. protected $runTestInSeparateProcess = \false;
  56863. /**
  56864. * @var bool
  56865. */
  56866. protected $useErrorHandler = \false;
  56867. /**
  56868. * @var string
  56869. */
  56870. private $message;
  56871. public function __construct(string $className, string $methodName, string $message = '')
  56872. {
  56873. parent::__construct($className . '::' . $methodName);
  56874. $this->message = $message;
  56875. }
  56876. public function getMessage() : string
  56877. {
  56878. return $this->message;
  56879. }
  56880. /**
  56881. * Returns a string representation of the test case.
  56882. *
  56883. * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
  56884. */
  56885. public function toString() : string
  56886. {
  56887. return $this->getName();
  56888. }
  56889. /**
  56890. * @throws Exception
  56891. */
  56892. protected function runTest() : void
  56893. {
  56894. $this->markTestIncomplete($this->message);
  56895. }
  56896. }
  56897. <?php
  56898. declare (strict_types=1);
  56899. /*
  56900. * This file is part of PHPUnit.
  56901. *
  56902. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  56903. *
  56904. * For the full copyright and license information, please view the LICENSE
  56905. * file that was distributed with this source code.
  56906. */
  56907. namespace PHPUnit;
  56908. /**
  56909. * @internal This class is not covered by the backward compatibility promise for PHPUnit
  56910. */
  56911. interface Exception extends \Throwable
  56912. {
  56913. }
  56914. <?php
  56915. declare (strict_types=1);
  56916. /*
  56917. * This file is part of sebastian/exporter.
  56918. *
  56919. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  56920. *
  56921. * For the full copyright and license information, please view the LICENSE
  56922. * file that was distributed with this source code.
  56923. */
  56924. namespace PHPUnit\SebastianBergmann\Exporter;
  56925. use PHPUnit\SebastianBergmann\RecursionContext\Context;
  56926. /**
  56927. * A nifty utility for visualizing PHP variables.
  56928. *
  56929. * <code>
  56930. * <?php
  56931. * use SebastianBergmann\Exporter\Exporter;
  56932. *
  56933. * $exporter = new Exporter;
  56934. * print $exporter->export(new Exception);
  56935. * </code>
  56936. */
  56937. class Exporter
  56938. {
  56939. /**
  56940. * Exports a value as a string
  56941. *
  56942. * The output of this method is similar to the output of print_r(), but
  56943. * improved in various aspects:
  56944. *
  56945. * - NULL is rendered as "null" (instead of "")
  56946. * - TRUE is rendered as "true" (instead of "1")
  56947. * - FALSE is rendered as "false" (instead of "")
  56948. * - Strings are always quoted with single quotes
  56949. * - Carriage returns and newlines are normalized to \n
  56950. * - Recursion and repeated rendering is treated properly
  56951. *
  56952. * @param int $indentation The indentation level of the 2nd+ line
  56953. *
  56954. * @return string
  56955. */
  56956. public function export($value, $indentation = 0)
  56957. {
  56958. return $this->recursiveExport($value, $indentation);
  56959. }
  56960. /**
  56961. * @param array<mixed> $data
  56962. * @param Context $context
  56963. *
  56964. * @return string
  56965. */
  56966. public function shortenedRecursiveExport(&$data, \PHPUnit\SebastianBergmann\RecursionContext\Context $context = null)
  56967. {
  56968. $result = [];
  56969. $exporter = new self();
  56970. if (!$context) {
  56971. $context = new \PHPUnit\SebastianBergmann\RecursionContext\Context();
  56972. }
  56973. $array = $data;
  56974. $context->add($data);
  56975. foreach ($array as $key => $value) {
  56976. if (\is_array($value)) {
  56977. if ($context->contains($data[$key]) !== \false) {
  56978. $result[] = '*RECURSION*';
  56979. } else {
  56980. $result[] = \sprintf('array(%s)', $this->shortenedRecursiveExport($data[$key], $context));
  56981. }
  56982. } else {
  56983. $result[] = $exporter->shortenedExport($value);
  56984. }
  56985. }
  56986. return \implode(', ', $result);
  56987. }
  56988. /**
  56989. * Exports a value into a single-line string
  56990. *
  56991. * The output of this method is similar to the output of
  56992. * SebastianBergmann\Exporter\Exporter::export().
  56993. *
  56994. * Newlines are replaced by the visible string '\n'.
  56995. * Contents of arrays and objects (if any) are replaced by '...'.
  56996. *
  56997. * @return string
  56998. *
  56999. * @see SebastianBergmann\Exporter\Exporter::export
  57000. */
  57001. public function shortenedExport($value)
  57002. {
  57003. if (\is_string($value)) {
  57004. $string = \str_replace("\n", '', $this->export($value));
  57005. if (\function_exists('mb_strlen')) {
  57006. if (\mb_strlen($string) > 40) {
  57007. $string = \mb_substr($string, 0, 30) . '...' . \mb_substr($string, -7);
  57008. }
  57009. } else {
  57010. if (\strlen($string) > 40) {
  57011. $string = \substr($string, 0, 30) . '...' . \substr($string, -7);
  57012. }
  57013. }
  57014. return $string;
  57015. }
  57016. if (\is_object($value)) {
  57017. return \sprintf('%s Object (%s)', \get_class($value), \count($this->toArray($value)) > 0 ? '...' : '');
  57018. }
  57019. if (\is_array($value)) {
  57020. return \sprintf('Array (%s)', \count($value) > 0 ? '...' : '');
  57021. }
  57022. return $this->export($value);
  57023. }
  57024. /**
  57025. * Converts an object to an array containing all of its private, protected
  57026. * and public properties.
  57027. *
  57028. * @return array
  57029. */
  57030. public function toArray($value)
  57031. {
  57032. if (!\is_object($value)) {
  57033. return (array) $value;
  57034. }
  57035. $array = [];
  57036. foreach ((array) $value as $key => $val) {
  57037. // Exception traces commonly reference hundreds to thousands of
  57038. // objects currently loaded in memory. Including them in the result
  57039. // has a severe negative performance impact.
  57040. if ("\0Error\0trace" === $key || "\0Exception\0trace" === $key) {
  57041. continue;
  57042. }
  57043. // properties are transformed to keys in the following way:
  57044. // private $property => "\0Classname\0property"
  57045. // protected $property => "\0*\0property"
  57046. // public $property => "property"
  57047. if (\preg_match('/^\\0.+\\0(.+)$/', (string) $key, $matches)) {
  57048. $key = $matches[1];
  57049. }
  57050. // See https://github.com/php/php-src/commit/5721132
  57051. if ($key === "\0gcdata") {
  57052. continue;
  57053. }
  57054. $array[$key] = $val;
  57055. }
  57056. // Some internal classes like SplObjectStorage don't work with the
  57057. // above (fast) mechanism nor with reflection in Zend.
  57058. // Format the output similarly to print_r() in this case
  57059. if ($value instanceof \SplObjectStorage) {
  57060. foreach ($value as $key => $val) {
  57061. $array[\spl_object_hash($val)] = ['obj' => $val, 'inf' => $value->getInfo()];
  57062. }
  57063. }
  57064. return $array;
  57065. }
  57066. /**
  57067. * Recursive implementation of export
  57068. *
  57069. * @param mixed $value The value to export
  57070. * @param int $indentation The indentation level of the 2nd+ line
  57071. * @param \SebastianBergmann\RecursionContext\Context $processed Previously processed objects
  57072. *
  57073. * @return string
  57074. *
  57075. * @see SebastianBergmann\Exporter\Exporter::export
  57076. */
  57077. protected function recursiveExport(&$value, $indentation, $processed = null)
  57078. {
  57079. if ($value === null) {
  57080. return 'null';
  57081. }
  57082. if ($value === \true) {
  57083. return 'true';
  57084. }
  57085. if ($value === \false) {
  57086. return 'false';
  57087. }
  57088. if (\is_float($value) && (float) (int) $value === $value) {
  57089. return "{$value}.0";
  57090. }
  57091. if (\is_resource($value)) {
  57092. return \sprintf('resource(%d) of type (%s)', $value, \get_resource_type($value));
  57093. }
  57094. if (\is_string($value)) {
  57095. // Match for most non printable chars somewhat taking multibyte chars into account
  57096. if (\preg_match('/[^\\x09-\\x0d\\x1b\\x20-\\xff]/', $value)) {
  57097. return 'Binary String: 0x' . \bin2hex($value);
  57098. }
  57099. return "'" . \str_replace('<lf>', "\n", \str_replace(["\r\n", "\n\r", "\r", "\n"], ['\\r\\n<lf>', '\\n\\r<lf>', '\\r<lf>', '\\n<lf>'], $value)) . "'";
  57100. }
  57101. $whitespace = \str_repeat(' ', (int) (4 * $indentation));
  57102. if (!$processed) {
  57103. $processed = new \PHPUnit\SebastianBergmann\RecursionContext\Context();
  57104. }
  57105. if (\is_array($value)) {
  57106. if (($key = $processed->contains($value)) !== \false) {
  57107. return 'Array &' . $key;
  57108. }
  57109. $array = $value;
  57110. $key = $processed->add($value);
  57111. $values = '';
  57112. if (\count($array) > 0) {
  57113. foreach ($array as $k => $v) {
  57114. $values .= \sprintf('%s %s => %s' . "\n", $whitespace, $this->recursiveExport($k, $indentation), $this->recursiveExport($value[$k], $indentation + 1, $processed));
  57115. }
  57116. $values = "\n" . $values . $whitespace;
  57117. }
  57118. return \sprintf('Array &%s (%s)', $key, $values);
  57119. }
  57120. if (\is_object($value)) {
  57121. $class = \get_class($value);
  57122. if ($hash = $processed->contains($value)) {
  57123. return \sprintf('%s Object &%s', $class, $hash);
  57124. }
  57125. $hash = $processed->add($value);
  57126. $values = '';
  57127. $array = $this->toArray($value);
  57128. if (\count($array) > 0) {
  57129. foreach ($array as $k => $v) {
  57130. $values .= \sprintf('%s %s => %s' . "\n", $whitespace, $this->recursiveExport($k, $indentation), $this->recursiveExport($v, $indentation + 1, $processed));
  57131. }
  57132. $values = "\n" . $values . $whitespace;
  57133. }
  57134. return \sprintf('%s Object &%s (%s)', $class, $hash, $values);
  57135. }
  57136. return \var_export($value, \true);
  57137. }
  57138. }
  57139. Exporter
  57140. Copyright (c) 2002-2020, Sebastian Bergmann <sebastian@phpunit.de>.
  57141. All rights reserved.
  57142. Redistribution and use in source and binary forms, with or without
  57143. modification, are permitted provided that the following conditions
  57144. are met:
  57145. * Redistributions of source code must retain the above copyright
  57146. notice, this list of conditions and the following disclaimer.
  57147. * Redistributions in binary form must reproduce the above copyright
  57148. notice, this list of conditions and the following disclaimer in
  57149. the documentation and/or other materials provided with the
  57150. distribution.
  57151. * Neither the name of Sebastian Bergmann nor the names of his
  57152. contributors may be used to endorse or promote products derived
  57153. from this software without specific prior written permission.
  57154. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  57155. "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  57156. LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  57157. FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  57158. COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  57159. INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  57160. BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  57161. LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  57162. CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  57163. LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
  57164. ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  57165. POSSIBILITY OF SUCH DAMAGE.
  57166. <?php
  57167. declare (strict_types=1);
  57168. /*
  57169. * This file is part of phpunit/php-file-iterator.
  57170. *
  57171. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  57172. *
  57173. * For the full copyright and license information, please view the LICENSE
  57174. * file that was distributed with this source code.
  57175. */
  57176. namespace PHPUnit\SebastianBergmann\FileIterator;
  57177. class Facade
  57178. {
  57179. /**
  57180. * @param array|string $paths
  57181. * @param array|string $suffixes
  57182. * @param array|string $prefixes
  57183. */
  57184. public function getFilesAsArray($paths, $suffixes = '', $prefixes = '', array $exclude = [], bool $commonPath = \false) : array
  57185. {
  57186. if (\is_string($paths)) {
  57187. $paths = [$paths];
  57188. }
  57189. $iterator = (new \PHPUnit\SebastianBergmann\FileIterator\Factory())->getFileIterator($paths, $suffixes, $prefixes, $exclude);
  57190. $files = [];
  57191. foreach ($iterator as $file) {
  57192. $file = $file->getRealPath();
  57193. if ($file) {
  57194. $files[] = $file;
  57195. }
  57196. }
  57197. foreach ($paths as $path) {
  57198. if (\is_file($path)) {
  57199. $files[] = \realpath($path);
  57200. }
  57201. }
  57202. $files = \array_unique($files);
  57203. \sort($files);
  57204. if ($commonPath) {
  57205. return ['commonPath' => $this->getCommonPath($files), 'files' => $files];
  57206. }
  57207. return $files;
  57208. }
  57209. protected function getCommonPath(array $files) : string
  57210. {
  57211. $count = \count($files);
  57212. if ($count === 0) {
  57213. return '';
  57214. }
  57215. if ($count === 1) {
  57216. return \dirname($files[0]) . \DIRECTORY_SEPARATOR;
  57217. }
  57218. $_files = [];
  57219. foreach ($files as $file) {
  57220. $_files[] = $_fileParts = \explode(\DIRECTORY_SEPARATOR, $file);
  57221. if (empty($_fileParts[0])) {
  57222. $_fileParts[0] = \DIRECTORY_SEPARATOR;
  57223. }
  57224. }
  57225. $common = '';
  57226. $done = \false;
  57227. $j = 0;
  57228. $count--;
  57229. while (!$done) {
  57230. for ($i = 0; $i < $count; $i++) {
  57231. if ($_files[$i][$j] != $_files[$i + 1][$j]) {
  57232. $done = \true;
  57233. break;
  57234. }
  57235. }
  57236. if (!$done) {
  57237. $common .= $_files[0][$j];
  57238. if ($j > 0) {
  57239. $common .= \DIRECTORY_SEPARATOR;
  57240. }
  57241. }
  57242. $j++;
  57243. }
  57244. return \DIRECTORY_SEPARATOR . $common;
  57245. }
  57246. }
  57247. <?php
  57248. declare (strict_types=1);
  57249. /*
  57250. * This file is part of phpunit/php-file-iterator.
  57251. *
  57252. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  57253. *
  57254. * For the full copyright and license information, please view the LICENSE
  57255. * file that was distributed with this source code.
  57256. */
  57257. namespace PHPUnit\SebastianBergmann\FileIterator;
  57258. class Factory
  57259. {
  57260. /**
  57261. * @param array|string $paths
  57262. * @param array|string $suffixes
  57263. * @param array|string $prefixes
  57264. */
  57265. public function getFileIterator($paths, $suffixes = '', $prefixes = '', array $exclude = []) : \AppendIterator
  57266. {
  57267. if (\is_string($paths)) {
  57268. $paths = [$paths];
  57269. }
  57270. $paths = $this->getPathsAfterResolvingWildcards($paths);
  57271. $exclude = $this->getPathsAfterResolvingWildcards($exclude);
  57272. if (\is_string($prefixes)) {
  57273. if ($prefixes !== '') {
  57274. $prefixes = [$prefixes];
  57275. } else {
  57276. $prefixes = [];
  57277. }
  57278. }
  57279. if (\is_string($suffixes)) {
  57280. if ($suffixes !== '') {
  57281. $suffixes = [$suffixes];
  57282. } else {
  57283. $suffixes = [];
  57284. }
  57285. }
  57286. $iterator = new \AppendIterator();
  57287. foreach ($paths as $path) {
  57288. if (\is_dir($path)) {
  57289. $iterator->append(new \PHPUnit\SebastianBergmann\FileIterator\Iterator($path, new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($path, \RecursiveDirectoryIterator::FOLLOW_SYMLINKS | \RecursiveDirectoryIterator::SKIP_DOTS)), $suffixes, $prefixes, $exclude));
  57290. }
  57291. }
  57292. return $iterator;
  57293. }
  57294. protected function getPathsAfterResolvingWildcards(array $paths) : array
  57295. {
  57296. $_paths = [];
  57297. foreach ($paths as $path) {
  57298. if ($locals = \glob($path, \GLOB_ONLYDIR)) {
  57299. $_paths = \array_merge($_paths, \array_map('\\realpath', $locals));
  57300. } else {
  57301. $_paths[] = \realpath($path);
  57302. }
  57303. }
  57304. return \array_filter($_paths);
  57305. }
  57306. }
  57307. <?php
  57308. declare (strict_types=1);
  57309. /*
  57310. * This file is part of phpunit/php-file-iterator.
  57311. *
  57312. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  57313. *
  57314. * For the full copyright and license information, please view the LICENSE
  57315. * file that was distributed with this source code.
  57316. */
  57317. namespace PHPUnit\SebastianBergmann\FileIterator;
  57318. class Iterator extends \FilterIterator
  57319. {
  57320. public const PREFIX = 0;
  57321. public const SUFFIX = 1;
  57322. /**
  57323. * @var string
  57324. */
  57325. private $basePath;
  57326. /**
  57327. * @var array
  57328. */
  57329. private $suffixes = [];
  57330. /**
  57331. * @var array
  57332. */
  57333. private $prefixes = [];
  57334. /**
  57335. * @var array
  57336. */
  57337. private $exclude = [];
  57338. public function __construct(string $basePath, \Iterator $iterator, array $suffixes = [], array $prefixes = [], array $exclude = [])
  57339. {
  57340. $this->basePath = \realpath($basePath);
  57341. $this->prefixes = $prefixes;
  57342. $this->suffixes = $suffixes;
  57343. $this->exclude = \array_filter(\array_map('realpath', $exclude));
  57344. parent::__construct($iterator);
  57345. }
  57346. public function accept() : bool
  57347. {
  57348. $current = $this->getInnerIterator()->current();
  57349. $filename = $current->getFilename();
  57350. $realPath = $current->getRealPath();
  57351. return $this->acceptPath($realPath) && $this->acceptPrefix($filename) && $this->acceptSuffix($filename);
  57352. }
  57353. private function acceptPath(string $path) : bool
  57354. {
  57355. // Filter files in hidden directories by checking path that is relative to the base path.
  57356. if (\preg_match('=/\\.[^/]*/=', \str_replace($this->basePath, '', $path))) {
  57357. return \false;
  57358. }
  57359. foreach ($this->exclude as $exclude) {
  57360. if (\strpos($path, $exclude) === 0) {
  57361. return \false;
  57362. }
  57363. }
  57364. return \true;
  57365. }
  57366. private function acceptPrefix(string $filename) : bool
  57367. {
  57368. return $this->acceptSubString($filename, $this->prefixes, self::PREFIX);
  57369. }
  57370. private function acceptSuffix(string $filename) : bool
  57371. {
  57372. return $this->acceptSubString($filename, $this->suffixes, self::SUFFIX);
  57373. }
  57374. private function acceptSubString(string $filename, array $subStrings, int $type) : bool
  57375. {
  57376. if (empty($subStrings)) {
  57377. return \true;
  57378. }
  57379. $matched = \false;
  57380. foreach ($subStrings as $string) {
  57381. if ($type === self::PREFIX && \strpos($filename, $string) === 0 || $type === self::SUFFIX && \substr($filename, -1 * \strlen($string)) === $string) {
  57382. $matched = \true;
  57383. break;
  57384. }
  57385. }
  57386. return $matched;
  57387. }
  57388. }
  57389. php-file-iterator
  57390. Copyright (c) 2009-2020, Sebastian Bergmann <sebastian@phpunit.de>.
  57391. All rights reserved.
  57392. Redistribution and use in source and binary forms, with or without
  57393. modification, are permitted provided that the following conditions
  57394. are met:
  57395. * Redistributions of source code must retain the above copyright
  57396. notice, this list of conditions and the following disclaimer.
  57397. * Redistributions in binary form must reproduce the above copyright
  57398. notice, this list of conditions and the following disclaimer in
  57399. the documentation and/or other materials provided with the
  57400. distribution.
  57401. * Neither the name of Sebastian Bergmann nor the names of his
  57402. contributors may be used to endorse or promote products derived
  57403. from this software without specific prior written permission.
  57404. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  57405. "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  57406. LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  57407. FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  57408. COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  57409. INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  57410. BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  57411. LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  57412. CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  57413. LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
  57414. ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  57415. POSSIBILITY OF SUCH DAMAGE.
  57416. <?php
  57417. /*
  57418. * This file is part of the Prophecy.
  57419. * (c) Konstantin Kudryashov <ever.zet@gmail.com>
  57420. * Marcello Duarte <marcello.duarte@gmail.com>
  57421. *
  57422. * For the full copyright and license information, please view the LICENSE
  57423. * file that was distributed with this source code.
  57424. */
  57425. namespace Prophecy\Prophecy;
  57426. /**
  57427. * Basic prophecies revealer.
  57428. *
  57429. * @author Konstantin Kudryashov <ever.zet@gmail.com>
  57430. */
  57431. class Revealer implements \Prophecy\Prophecy\RevealerInterface
  57432. {
  57433. /**
  57434. * Unwraps value(s).
  57435. *
  57436. * @param mixed $value
  57437. *
  57438. * @return mixed
  57439. */
  57440. public function reveal($value)
  57441. {
  57442. if (\is_array($value)) {
  57443. return \array_map(array($this, __FUNCTION__), $value);
  57444. }
  57445. if (!\is_object($value)) {
  57446. return $value;
  57447. }
  57448. if ($value instanceof \Prophecy\Prophecy\ProphecyInterface) {
  57449. $value = $value->reveal();
  57450. }
  57451. return $value;
  57452. }
  57453. }
  57454. <?php
  57455. /*
  57456. * This file is part of the Prophecy.
  57457. * (c) Konstantin Kudryashov <ever.zet@gmail.com>
  57458. * Marcello Duarte <marcello.duarte@gmail.com>
  57459. *
  57460. * For the full copyright and license information, please view the LICENSE
  57461. * file that was distributed with this source code.
  57462. */
  57463. namespace Prophecy\Prophecy;
  57464. use Prophecy\Argument;
  57465. use Prophecy\Prophet;
  57466. use Prophecy\Promise;
  57467. use Prophecy\Prediction;
  57468. use Prophecy\Exception\Doubler\MethodNotFoundException;
  57469. use Prophecy\Exception\InvalidArgumentException;
  57470. use Prophecy\Exception\Prophecy\MethodProphecyException;
  57471. /**
  57472. * Method prophecy.
  57473. *
  57474. * @author Konstantin Kudryashov <ever.zet@gmail.com>
  57475. */
  57476. class MethodProphecy
  57477. {
  57478. private $objectProphecy;
  57479. private $methodName;
  57480. private $argumentsWildcard;
  57481. private $promise;
  57482. private $prediction;
  57483. private $checkedPredictions = array();
  57484. private $bound = \false;
  57485. private $voidReturnType = \false;
  57486. /**
  57487. * Initializes method prophecy.
  57488. *
  57489. * @param ObjectProphecy $objectProphecy
  57490. * @param string $methodName
  57491. * @param null|Argument\ArgumentsWildcard|array $arguments
  57492. *
  57493. * @throws \Prophecy\Exception\Doubler\MethodNotFoundException If method not found
  57494. */
  57495. public function __construct(\Prophecy\Prophecy\ObjectProphecy $objectProphecy, $methodName, $arguments = null)
  57496. {
  57497. $double = $objectProphecy->reveal();
  57498. if (!\method_exists($double, $methodName)) {
  57499. throw new \Prophecy\Exception\Doubler\MethodNotFoundException(\sprintf('Method `%s::%s()` is not defined.', \get_class($double), $methodName), \get_class($double), $methodName, $arguments);
  57500. }
  57501. $this->objectProphecy = $objectProphecy;
  57502. $this->methodName = $methodName;
  57503. $reflectedMethod = new \ReflectionMethod($double, $methodName);
  57504. if ($reflectedMethod->isFinal()) {
  57505. throw new \Prophecy\Exception\Prophecy\MethodProphecyException(\sprintf("Can not add prophecy for a method `%s::%s()`\n" . "as it is a final method.", \get_class($double), $methodName), $this);
  57506. }
  57507. if (null !== $arguments) {
  57508. $this->withArguments($arguments);
  57509. }
  57510. if (\version_compare(\PHP_VERSION, '7.0', '>=') && \true === $reflectedMethod->hasReturnType()) {
  57511. $type = \PHP_VERSION_ID >= 70100 ? $reflectedMethod->getReturnType()->getName() : (string) $reflectedMethod->getReturnType();
  57512. if ('void' === $type) {
  57513. $this->voidReturnType = \true;
  57514. }
  57515. $this->will(function () use($type) {
  57516. switch ($type) {
  57517. case 'void':
  57518. return;
  57519. case 'string':
  57520. return '';
  57521. case 'float':
  57522. return 0.0;
  57523. case 'int':
  57524. return 0;
  57525. case 'bool':
  57526. return \false;
  57527. case 'array':
  57528. return array();
  57529. case 'callable':
  57530. case 'Closure':
  57531. return function () {
  57532. };
  57533. case 'Traversable':
  57534. case 'Generator':
  57535. // Remove eval() when minimum version >=5.5
  57536. /** @var callable $generator */
  57537. $generator = eval('return function () { yield; };');
  57538. return $generator();
  57539. default:
  57540. $prophet = new \Prophecy\Prophet();
  57541. return $prophet->prophesize($type)->reveal();
  57542. }
  57543. });
  57544. }
  57545. }
  57546. /**
  57547. * Sets argument wildcard.
  57548. *
  57549. * @param array|Argument\ArgumentsWildcard $arguments
  57550. *
  57551. * @return $this
  57552. *
  57553. * @throws \Prophecy\Exception\InvalidArgumentException
  57554. */
  57555. public function withArguments($arguments)
  57556. {
  57557. if (\is_array($arguments)) {
  57558. $arguments = new \Prophecy\Argument\ArgumentsWildcard($arguments);
  57559. }
  57560. if (!$arguments instanceof \Prophecy\Argument\ArgumentsWildcard) {
  57561. throw new \Prophecy\Exception\InvalidArgumentException(\sprintf("Either an array or an instance of ArgumentsWildcard expected as\n" . 'a `MethodProphecy::withArguments()` argument, but got %s.', \gettype($arguments)));
  57562. }
  57563. $this->argumentsWildcard = $arguments;
  57564. return $this;
  57565. }
  57566. /**
  57567. * Sets custom promise to the prophecy.
  57568. *
  57569. * @param callable|Promise\PromiseInterface $promise
  57570. *
  57571. * @return $this
  57572. *
  57573. * @throws \Prophecy\Exception\InvalidArgumentException
  57574. */
  57575. public function will($promise)
  57576. {
  57577. if (\is_callable($promise)) {
  57578. $promise = new \Prophecy\Promise\CallbackPromise($promise);
  57579. }
  57580. if (!$promise instanceof \Prophecy\Promise\PromiseInterface) {
  57581. throw new \Prophecy\Exception\InvalidArgumentException(\sprintf('Expected callable or instance of PromiseInterface, but got %s.', \gettype($promise)));
  57582. }
  57583. $this->bindToObjectProphecy();
  57584. $this->promise = $promise;
  57585. return $this;
  57586. }
  57587. /**
  57588. * Sets return promise to the prophecy.
  57589. *
  57590. * @see \Prophecy\Promise\ReturnPromise
  57591. *
  57592. * @return $this
  57593. */
  57594. public function willReturn()
  57595. {
  57596. if ($this->voidReturnType) {
  57597. throw new \Prophecy\Exception\Prophecy\MethodProphecyException("The method \"{$this->methodName}\" has a void return type, and so cannot return anything", $this);
  57598. }
  57599. return $this->will(new \Prophecy\Promise\ReturnPromise(\func_get_args()));
  57600. }
  57601. /**
  57602. * @param array $items
  57603. *
  57604. * @return $this
  57605. *
  57606. * @throws \Prophecy\Exception\InvalidArgumentException
  57607. */
  57608. public function willYield($items)
  57609. {
  57610. if ($this->voidReturnType) {
  57611. throw new \Prophecy\Exception\Prophecy\MethodProphecyException("The method \"{$this->methodName}\" has a void return type, and so cannot yield anything", $this);
  57612. }
  57613. if (!\is_array($items)) {
  57614. throw new \Prophecy\Exception\InvalidArgumentException(\sprintf('Expected array, but got %s.', \gettype($items)));
  57615. }
  57616. // Remove eval() when minimum version >=5.5
  57617. /** @var callable $generator */
  57618. $generator = eval('return function() use ($items) {
  57619. foreach ($items as $key => $value) {
  57620. yield $key => $value;
  57621. }
  57622. };');
  57623. return $this->will($generator);
  57624. }
  57625. /**
  57626. * Sets return argument promise to the prophecy.
  57627. *
  57628. * @param int $index The zero-indexed number of the argument to return
  57629. *
  57630. * @see \Prophecy\Promise\ReturnArgumentPromise
  57631. *
  57632. * @return $this
  57633. */
  57634. public function willReturnArgument($index = 0)
  57635. {
  57636. if ($this->voidReturnType) {
  57637. throw new \Prophecy\Exception\Prophecy\MethodProphecyException("The method \"{$this->methodName}\" has a void return type", $this);
  57638. }
  57639. return $this->will(new \Prophecy\Promise\ReturnArgumentPromise($index));
  57640. }
  57641. /**
  57642. * Sets throw promise to the prophecy.
  57643. *
  57644. * @see \Prophecy\Promise\ThrowPromise
  57645. *
  57646. * @param string|\Exception $exception Exception class or instance
  57647. *
  57648. * @return $this
  57649. */
  57650. public function willThrow($exception)
  57651. {
  57652. return $this->will(new \Prophecy\Promise\ThrowPromise($exception));
  57653. }
  57654. /**
  57655. * Sets custom prediction to the prophecy.
  57656. *
  57657. * @param callable|Prediction\PredictionInterface $prediction
  57658. *
  57659. * @return $this
  57660. *
  57661. * @throws \Prophecy\Exception\InvalidArgumentException
  57662. */
  57663. public function should($prediction)
  57664. {
  57665. if (\is_callable($prediction)) {
  57666. $prediction = new \Prophecy\Prediction\CallbackPrediction($prediction);
  57667. }
  57668. if (!$prediction instanceof \Prophecy\Prediction\PredictionInterface) {
  57669. throw new \Prophecy\Exception\InvalidArgumentException(\sprintf('Expected callable or instance of PredictionInterface, but got %s.', \gettype($prediction)));
  57670. }
  57671. $this->bindToObjectProphecy();
  57672. $this->prediction = $prediction;
  57673. return $this;
  57674. }
  57675. /**
  57676. * Sets call prediction to the prophecy.
  57677. *
  57678. * @see \Prophecy\Prediction\CallPrediction
  57679. *
  57680. * @return $this
  57681. */
  57682. public function shouldBeCalled()
  57683. {
  57684. return $this->should(new \Prophecy\Prediction\CallPrediction());
  57685. }
  57686. /**
  57687. * Sets no calls prediction to the prophecy.
  57688. *
  57689. * @see \Prophecy\Prediction\NoCallsPrediction
  57690. *
  57691. * @return $this
  57692. */
  57693. public function shouldNotBeCalled()
  57694. {
  57695. return $this->should(new \Prophecy\Prediction\NoCallsPrediction());
  57696. }
  57697. /**
  57698. * Sets call times prediction to the prophecy.
  57699. *
  57700. * @see \Prophecy\Prediction\CallTimesPrediction
  57701. *
  57702. * @param $count
  57703. *
  57704. * @return $this
  57705. */
  57706. public function shouldBeCalledTimes($count)
  57707. {
  57708. return $this->should(new \Prophecy\Prediction\CallTimesPrediction($count));
  57709. }
  57710. /**
  57711. * Sets call times prediction to the prophecy.
  57712. *
  57713. * @see \Prophecy\Prediction\CallTimesPrediction
  57714. *
  57715. * @return $this
  57716. */
  57717. public function shouldBeCalledOnce()
  57718. {
  57719. return $this->shouldBeCalledTimes(1);
  57720. }
  57721. /**
  57722. * Checks provided prediction immediately.
  57723. *
  57724. * @param callable|Prediction\PredictionInterface $prediction
  57725. *
  57726. * @return $this
  57727. *
  57728. * @throws \Prophecy\Exception\InvalidArgumentException
  57729. */
  57730. public function shouldHave($prediction)
  57731. {
  57732. if (\is_callable($prediction)) {
  57733. $prediction = new \Prophecy\Prediction\CallbackPrediction($prediction);
  57734. }
  57735. if (!$prediction instanceof \Prophecy\Prediction\PredictionInterface) {
  57736. throw new \Prophecy\Exception\InvalidArgumentException(\sprintf('Expected callable or instance of PredictionInterface, but got %s.', \gettype($prediction)));
  57737. }
  57738. if (null === $this->promise && !$this->voidReturnType) {
  57739. $this->willReturn();
  57740. }
  57741. $calls = $this->getObjectProphecy()->findProphecyMethodCalls($this->getMethodName(), $this->getArgumentsWildcard());
  57742. try {
  57743. $prediction->check($calls, $this->getObjectProphecy(), $this);
  57744. $this->checkedPredictions[] = $prediction;
  57745. } catch (\Exception $e) {
  57746. $this->checkedPredictions[] = $prediction;
  57747. throw $e;
  57748. }
  57749. return $this;
  57750. }
  57751. /**
  57752. * Checks call prediction.
  57753. *
  57754. * @see \Prophecy\Prediction\CallPrediction
  57755. *
  57756. * @return $this
  57757. */
  57758. public function shouldHaveBeenCalled()
  57759. {
  57760. return $this->shouldHave(new \Prophecy\Prediction\CallPrediction());
  57761. }
  57762. /**
  57763. * Checks no calls prediction.
  57764. *
  57765. * @see \Prophecy\Prediction\NoCallsPrediction
  57766. *
  57767. * @return $this
  57768. */
  57769. public function shouldNotHaveBeenCalled()
  57770. {
  57771. return $this->shouldHave(new \Prophecy\Prediction\NoCallsPrediction());
  57772. }
  57773. /**
  57774. * Checks no calls prediction.
  57775. *
  57776. * @see \Prophecy\Prediction\NoCallsPrediction
  57777. * @deprecated
  57778. *
  57779. * @return $this
  57780. */
  57781. public function shouldNotBeenCalled()
  57782. {
  57783. return $this->shouldNotHaveBeenCalled();
  57784. }
  57785. /**
  57786. * Checks call times prediction.
  57787. *
  57788. * @see \Prophecy\Prediction\CallTimesPrediction
  57789. *
  57790. * @param int $count
  57791. *
  57792. * @return $this
  57793. */
  57794. public function shouldHaveBeenCalledTimes($count)
  57795. {
  57796. return $this->shouldHave(new \Prophecy\Prediction\CallTimesPrediction($count));
  57797. }
  57798. /**
  57799. * Checks call times prediction.
  57800. *
  57801. * @see \Prophecy\Prediction\CallTimesPrediction
  57802. *
  57803. * @return $this
  57804. */
  57805. public function shouldHaveBeenCalledOnce()
  57806. {
  57807. return $this->shouldHaveBeenCalledTimes(1);
  57808. }
  57809. /**
  57810. * Checks currently registered [with should(...)] prediction.
  57811. */
  57812. public function checkPrediction()
  57813. {
  57814. if (null === $this->prediction) {
  57815. return;
  57816. }
  57817. $this->shouldHave($this->prediction);
  57818. }
  57819. /**
  57820. * Returns currently registered promise.
  57821. *
  57822. * @return null|Promise\PromiseInterface
  57823. */
  57824. public function getPromise()
  57825. {
  57826. return $this->promise;
  57827. }
  57828. /**
  57829. * Returns currently registered prediction.
  57830. *
  57831. * @return null|Prediction\PredictionInterface
  57832. */
  57833. public function getPrediction()
  57834. {
  57835. return $this->prediction;
  57836. }
  57837. /**
  57838. * Returns predictions that were checked on this object.
  57839. *
  57840. * @return Prediction\PredictionInterface[]
  57841. */
  57842. public function getCheckedPredictions()
  57843. {
  57844. return $this->checkedPredictions;
  57845. }
  57846. /**
  57847. * Returns object prophecy this method prophecy is tied to.
  57848. *
  57849. * @return ObjectProphecy
  57850. */
  57851. public function getObjectProphecy()
  57852. {
  57853. return $this->objectProphecy;
  57854. }
  57855. /**
  57856. * Returns method name.
  57857. *
  57858. * @return string
  57859. */
  57860. public function getMethodName()
  57861. {
  57862. return $this->methodName;
  57863. }
  57864. /**
  57865. * Returns arguments wildcard.
  57866. *
  57867. * @return Argument\ArgumentsWildcard
  57868. */
  57869. public function getArgumentsWildcard()
  57870. {
  57871. return $this->argumentsWildcard;
  57872. }
  57873. /**
  57874. * @return bool
  57875. */
  57876. public function hasReturnVoid()
  57877. {
  57878. return $this->voidReturnType;
  57879. }
  57880. private function bindToObjectProphecy()
  57881. {
  57882. if ($this->bound) {
  57883. return;
  57884. }
  57885. $this->getObjectProphecy()->addMethodProphecy($this);
  57886. $this->bound = \true;
  57887. }
  57888. }
  57889. <?php
  57890. /*
  57891. * This file is part of the Prophecy.
  57892. * (c) Konstantin Kudryashov <ever.zet@gmail.com>
  57893. * Marcello Duarte <marcello.duarte@gmail.com>
  57894. *
  57895. * For the full copyright and license information, please view the LICENSE
  57896. * file that was distributed with this source code.
  57897. */
  57898. namespace Prophecy\Prophecy;
  57899. /**
  57900. * Prophecies revealer interface.
  57901. *
  57902. * @author Konstantin Kudryashov <ever.zet@gmail.com>
  57903. */
  57904. interface RevealerInterface
  57905. {
  57906. /**
  57907. * Unwraps value(s).
  57908. *
  57909. * @param mixed $value
  57910. *
  57911. * @return mixed
  57912. */
  57913. public function reveal($value);
  57914. }
  57915. <?php
  57916. /*
  57917. * This file is part of the Prophecy.
  57918. * (c) Konstantin Kudryashov <ever.zet@gmail.com>
  57919. * Marcello Duarte <marcello.duarte@gmail.com>
  57920. *
  57921. * For the full copyright and license information, please view the LICENSE
  57922. * file that was distributed with this source code.
  57923. */
  57924. namespace Prophecy\Prophecy;
  57925. /**
  57926. * Controllable doubles interface.
  57927. *
  57928. * @author Konstantin Kudryashov <ever.zet@gmail.com>
  57929. */
  57930. interface ProphecySubjectInterface
  57931. {
  57932. /**
  57933. * Sets subject prophecy.
  57934. *
  57935. * @param ProphecyInterface $prophecy
  57936. */
  57937. public function setProphecy(\Prophecy\Prophecy\ProphecyInterface $prophecy);
  57938. /**
  57939. * Returns subject prophecy.
  57940. *
  57941. * @return ProphecyInterface
  57942. */
  57943. public function getProphecy();
  57944. }
  57945. <?php
  57946. /*
  57947. * This file is part of the Prophecy.
  57948. * (c) Konstantin Kudryashov <ever.zet@gmail.com>
  57949. * Marcello Duarte <marcello.duarte@gmail.com>
  57950. *
  57951. * For the full copyright and license information, please view the LICENSE
  57952. * file that was distributed with this source code.
  57953. */
  57954. namespace Prophecy\Prophecy;
  57955. /**
  57956. * Core Prophecy interface.
  57957. *
  57958. * @author Konstantin Kudryashov <ever.zet@gmail.com>
  57959. */
  57960. interface ProphecyInterface
  57961. {
  57962. /**
  57963. * Reveals prophecy object (double) .
  57964. *
  57965. * @return object
  57966. */
  57967. public function reveal();
  57968. }
  57969. <?php
  57970. /*
  57971. * This file is part of the Prophecy.
  57972. * (c) Konstantin Kudryashov <ever.zet@gmail.com>
  57973. * Marcello Duarte <marcello.duarte@gmail.com>
  57974. *
  57975. * For the full copyright and license information, please view the LICENSE
  57976. * file that was distributed with this source code.
  57977. */
  57978. namespace Prophecy\Prophecy;
  57979. use PHPUnit\SebastianBergmann\Comparator\ComparisonFailure;
  57980. use Prophecy\Comparator\Factory as ComparatorFactory;
  57981. use Prophecy\Call\Call;
  57982. use Prophecy\Doubler\LazyDouble;
  57983. use Prophecy\Argument\ArgumentsWildcard;
  57984. use Prophecy\Call\CallCenter;
  57985. use Prophecy\Exception\Prophecy\ObjectProphecyException;
  57986. use Prophecy\Exception\Prophecy\MethodProphecyException;
  57987. use Prophecy\Exception\Prediction\AggregateException;
  57988. use Prophecy\Exception\Prediction\PredictionException;
  57989. /**
  57990. * Object prophecy.
  57991. *
  57992. * @author Konstantin Kudryashov <ever.zet@gmail.com>
  57993. */
  57994. class ObjectProphecy implements \Prophecy\Prophecy\ProphecyInterface
  57995. {
  57996. private $lazyDouble;
  57997. private $callCenter;
  57998. private $revealer;
  57999. private $comparatorFactory;
  58000. /**
  58001. * @var MethodProphecy[][]
  58002. */
  58003. private $methodProphecies = array();
  58004. /**
  58005. * Initializes object prophecy.
  58006. *
  58007. * @param LazyDouble $lazyDouble
  58008. * @param CallCenter $callCenter
  58009. * @param RevealerInterface $revealer
  58010. * @param ComparatorFactory $comparatorFactory
  58011. */
  58012. public function __construct(\Prophecy\Doubler\LazyDouble $lazyDouble, \Prophecy\Call\CallCenter $callCenter = null, \Prophecy\Prophecy\RevealerInterface $revealer = null, \Prophecy\Comparator\Factory $comparatorFactory = null)
  58013. {
  58014. $this->lazyDouble = $lazyDouble;
  58015. $this->callCenter = $callCenter ?: new \Prophecy\Call\CallCenter();
  58016. $this->revealer = $revealer ?: new \Prophecy\Prophecy\Revealer();
  58017. $this->comparatorFactory = $comparatorFactory ?: \Prophecy\Comparator\Factory::getInstance();
  58018. }
  58019. /**
  58020. * Forces double to extend specific class.
  58021. *
  58022. * @param string $class
  58023. *
  58024. * @return $this
  58025. */
  58026. public function willExtend($class)
  58027. {
  58028. $this->lazyDouble->setParentClass($class);
  58029. return $this;
  58030. }
  58031. /**
  58032. * Forces double to implement specific interface.
  58033. *
  58034. * @param string $interface
  58035. *
  58036. * @return $this
  58037. */
  58038. public function willImplement($interface)
  58039. {
  58040. $this->lazyDouble->addInterface($interface);
  58041. return $this;
  58042. }
  58043. /**
  58044. * Sets constructor arguments.
  58045. *
  58046. * @param array $arguments
  58047. *
  58048. * @return $this
  58049. */
  58050. public function willBeConstructedWith(array $arguments = null)
  58051. {
  58052. $this->lazyDouble->setArguments($arguments);
  58053. return $this;
  58054. }
  58055. /**
  58056. * Reveals double.
  58057. *
  58058. * @return object
  58059. *
  58060. * @throws \Prophecy\Exception\Prophecy\ObjectProphecyException If double doesn't implement needed interface
  58061. */
  58062. public function reveal()
  58063. {
  58064. $double = $this->lazyDouble->getInstance();
  58065. if (null === $double || !$double instanceof \Prophecy\Prophecy\ProphecySubjectInterface) {
  58066. throw new \Prophecy\Exception\Prophecy\ObjectProphecyException("Generated double must implement ProphecySubjectInterface, but it does not.\n" . 'It seems you have wrongly configured doubler without required ClassPatch.', $this);
  58067. }
  58068. $double->setProphecy($this);
  58069. return $double;
  58070. }
  58071. /**
  58072. * Adds method prophecy to object prophecy.
  58073. *
  58074. * @param MethodProphecy $methodProphecy
  58075. *
  58076. * @throws \Prophecy\Exception\Prophecy\MethodProphecyException If method prophecy doesn't
  58077. * have arguments wildcard
  58078. */
  58079. public function addMethodProphecy(\Prophecy\Prophecy\MethodProphecy $methodProphecy)
  58080. {
  58081. $argumentsWildcard = $methodProphecy->getArgumentsWildcard();
  58082. if (null === $argumentsWildcard) {
  58083. throw new \Prophecy\Exception\Prophecy\MethodProphecyException(\sprintf("Can not add prophecy for a method `%s::%s()`\n" . "as you did not specify arguments wildcard for it.", \get_class($this->reveal()), $methodProphecy->getMethodName()), $methodProphecy);
  58084. }
  58085. $methodName = \strtolower($methodProphecy->getMethodName());
  58086. if (!isset($this->methodProphecies[$methodName])) {
  58087. $this->methodProphecies[$methodName] = array();
  58088. }
  58089. $this->methodProphecies[$methodName][] = $methodProphecy;
  58090. }
  58091. /**
  58092. * Returns either all or related to single method prophecies.
  58093. *
  58094. * @param null|string $methodName
  58095. *
  58096. * @return MethodProphecy[]
  58097. */
  58098. public function getMethodProphecies($methodName = null)
  58099. {
  58100. if (null === $methodName) {
  58101. return $this->methodProphecies;
  58102. }
  58103. $methodName = \strtolower($methodName);
  58104. if (!isset($this->methodProphecies[$methodName])) {
  58105. return array();
  58106. }
  58107. return $this->methodProphecies[$methodName];
  58108. }
  58109. /**
  58110. * Makes specific method call.
  58111. *
  58112. * @param string $methodName
  58113. * @param array $arguments
  58114. *
  58115. * @return mixed
  58116. */
  58117. public function makeProphecyMethodCall($methodName, array $arguments)
  58118. {
  58119. $arguments = $this->revealer->reveal($arguments);
  58120. $return = $this->callCenter->makeCall($this, $methodName, $arguments);
  58121. return $this->revealer->reveal($return);
  58122. }
  58123. /**
  58124. * Finds calls by method name & arguments wildcard.
  58125. *
  58126. * @param string $methodName
  58127. * @param ArgumentsWildcard $wildcard
  58128. *
  58129. * @return Call[]
  58130. */
  58131. public function findProphecyMethodCalls($methodName, \Prophecy\Argument\ArgumentsWildcard $wildcard)
  58132. {
  58133. return $this->callCenter->findCalls($methodName, $wildcard);
  58134. }
  58135. /**
  58136. * Checks that registered method predictions do not fail.
  58137. *
  58138. * @throws \Prophecy\Exception\Prediction\AggregateException If any of registered predictions fail
  58139. * @throws \Prophecy\Exception\Call\UnexpectedCallException
  58140. */
  58141. public function checkProphecyMethodsPredictions()
  58142. {
  58143. $exception = new \Prophecy\Exception\Prediction\AggregateException(\sprintf("%s:\n", \get_class($this->reveal())));
  58144. $exception->setObjectProphecy($this);
  58145. $this->callCenter->checkUnexpectedCalls();
  58146. foreach ($this->methodProphecies as $prophecies) {
  58147. foreach ($prophecies as $prophecy) {
  58148. try {
  58149. $prophecy->checkPrediction();
  58150. } catch (\Prophecy\Exception\Prediction\PredictionException $e) {
  58151. $exception->append($e);
  58152. }
  58153. }
  58154. }
  58155. if (\count($exception->getExceptions())) {
  58156. throw $exception;
  58157. }
  58158. }
  58159. /**
  58160. * Creates new method prophecy using specified method name and arguments.
  58161. *
  58162. * @param string $methodName
  58163. * @param array $arguments
  58164. *
  58165. * @return MethodProphecy
  58166. */
  58167. public function __call($methodName, array $arguments)
  58168. {
  58169. $arguments = new \Prophecy\Argument\ArgumentsWildcard($this->revealer->reveal($arguments));
  58170. foreach ($this->getMethodProphecies($methodName) as $prophecy) {
  58171. $argumentsWildcard = $prophecy->getArgumentsWildcard();
  58172. $comparator = $this->comparatorFactory->getComparatorFor($argumentsWildcard, $arguments);
  58173. try {
  58174. $comparator->assertEquals($argumentsWildcard, $arguments);
  58175. return $prophecy;
  58176. } catch (\PHPUnit\SebastianBergmann\Comparator\ComparisonFailure $failure) {
  58177. }
  58178. }
  58179. return new \Prophecy\Prophecy\MethodProphecy($this, $methodName, $arguments);
  58180. }
  58181. /**
  58182. * Tries to get property value from double.
  58183. *
  58184. * @param string $name
  58185. *
  58186. * @return mixed
  58187. */
  58188. public function __get($name)
  58189. {
  58190. return $this->reveal()->{$name};
  58191. }
  58192. /**
  58193. * Tries to set property value to double.
  58194. *
  58195. * @param string $name
  58196. * @param mixed $value
  58197. */
  58198. public function __set($name, $value)
  58199. {
  58200. $this->reveal()->{$name} = $this->revealer->reveal($value);
  58201. }
  58202. }
  58203. <?php
  58204. /*
  58205. * This file is part of the Prophecy.
  58206. * (c) Konstantin Kudryashov <ever.zet@gmail.com>
  58207. * Marcello Duarte <marcello.duarte@gmail.com>
  58208. *
  58209. * For the full copyright and license information, please view the LICENSE
  58210. * file that was distributed with this source code.
  58211. */
  58212. namespace Prophecy;
  58213. use Prophecy\Argument\Token;
  58214. /**
  58215. * Argument tokens shortcuts.
  58216. *
  58217. * @author Konstantin Kudryashov <ever.zet@gmail.com>
  58218. */
  58219. class Argument
  58220. {
  58221. /**
  58222. * Checks that argument is exact value or object.
  58223. *
  58224. * @param mixed $value
  58225. *
  58226. * @return Token\ExactValueToken
  58227. */
  58228. public static function exact($value)
  58229. {
  58230. return new \Prophecy\Argument\Token\ExactValueToken($value);
  58231. }
  58232. /**
  58233. * Checks that argument is of specific type or instance of specific class.
  58234. *
  58235. * @param string $type Type name (`integer`, `string`) or full class name
  58236. *
  58237. * @return Token\TypeToken
  58238. */
  58239. public static function type($type)
  58240. {
  58241. return new \Prophecy\Argument\Token\TypeToken($type);
  58242. }
  58243. /**
  58244. * Checks that argument object has specific state.
  58245. *
  58246. * @param string $methodName
  58247. * @param mixed $value
  58248. *
  58249. * @return Token\ObjectStateToken
  58250. */
  58251. public static function which($methodName, $value)
  58252. {
  58253. return new \Prophecy\Argument\Token\ObjectStateToken($methodName, $value);
  58254. }
  58255. /**
  58256. * Checks that argument matches provided callback.
  58257. *
  58258. * @param callable $callback
  58259. *
  58260. * @return Token\CallbackToken
  58261. */
  58262. public static function that($callback)
  58263. {
  58264. return new \Prophecy\Argument\Token\CallbackToken($callback);
  58265. }
  58266. /**
  58267. * Matches any single value.
  58268. *
  58269. * @return Token\AnyValueToken
  58270. */
  58271. public static function any()
  58272. {
  58273. return new \Prophecy\Argument\Token\AnyValueToken();
  58274. }
  58275. /**
  58276. * Matches all values to the rest of the signature.
  58277. *
  58278. * @return Token\AnyValuesToken
  58279. */
  58280. public static function cetera()
  58281. {
  58282. return new \Prophecy\Argument\Token\AnyValuesToken();
  58283. }
  58284. /**
  58285. * Checks that argument matches all tokens
  58286. *
  58287. * @param mixed ... a list of tokens
  58288. *
  58289. * @return Token\LogicalAndToken
  58290. */
  58291. public static function allOf()
  58292. {
  58293. return new \Prophecy\Argument\Token\LogicalAndToken(\func_get_args());
  58294. }
  58295. /**
  58296. * Checks that argument array or countable object has exact number of elements.
  58297. *
  58298. * @param integer $value array elements count
  58299. *
  58300. * @return Token\ArrayCountToken
  58301. */
  58302. public static function size($value)
  58303. {
  58304. return new \Prophecy\Argument\Token\ArrayCountToken($value);
  58305. }
  58306. /**
  58307. * Checks that argument array contains (key, value) pair
  58308. *
  58309. * @param mixed $key exact value or token
  58310. * @param mixed $value exact value or token
  58311. *
  58312. * @return Token\ArrayEntryToken
  58313. */
  58314. public static function withEntry($key, $value)
  58315. {
  58316. return new \Prophecy\Argument\Token\ArrayEntryToken($key, $value);
  58317. }
  58318. /**
  58319. * Checks that arguments array entries all match value
  58320. *
  58321. * @param mixed $value
  58322. *
  58323. * @return Token\ArrayEveryEntryToken
  58324. */
  58325. public static function withEveryEntry($value)
  58326. {
  58327. return new \Prophecy\Argument\Token\ArrayEveryEntryToken($value);
  58328. }
  58329. /**
  58330. * Checks that argument array contains value
  58331. *
  58332. * @param mixed $value
  58333. *
  58334. * @return Token\ArrayEntryToken
  58335. */
  58336. public static function containing($value)
  58337. {
  58338. return new \Prophecy\Argument\Token\ArrayEntryToken(self::any(), $value);
  58339. }
  58340. /**
  58341. * Checks that argument array has key
  58342. *
  58343. * @param mixed $key exact value or token
  58344. *
  58345. * @return Token\ArrayEntryToken
  58346. */
  58347. public static function withKey($key)
  58348. {
  58349. return new \Prophecy\Argument\Token\ArrayEntryToken($key, self::any());
  58350. }
  58351. /**
  58352. * Checks that argument does not match the value|token.
  58353. *
  58354. * @param mixed $value either exact value or argument token
  58355. *
  58356. * @return Token\LogicalNotToken
  58357. */
  58358. public static function not($value)
  58359. {
  58360. return new \Prophecy\Argument\Token\LogicalNotToken($value);
  58361. }
  58362. /**
  58363. * @param string $value
  58364. *
  58365. * @return Token\StringContainsToken
  58366. */
  58367. public static function containingString($value)
  58368. {
  58369. return new \Prophecy\Argument\Token\StringContainsToken($value);
  58370. }
  58371. /**
  58372. * Checks that argument is identical value.
  58373. *
  58374. * @param mixed $value
  58375. *
  58376. * @return Token\IdenticalValueToken
  58377. */
  58378. public static function is($value)
  58379. {
  58380. return new \Prophecy\Argument\Token\IdenticalValueToken($value);
  58381. }
  58382. /**
  58383. * Check that argument is same value when rounding to the
  58384. * given precision.
  58385. *
  58386. * @param float $value
  58387. * @param float $precision
  58388. *
  58389. * @return Token\ApproximateValueToken
  58390. */
  58391. public static function approximate($value, $precision = 0)
  58392. {
  58393. return new \Prophecy\Argument\Token\ApproximateValueToken($value, $precision);
  58394. }
  58395. }
  58396. <?php
  58397. /*
  58398. * This file is part of the Prophecy.
  58399. * (c) Konstantin Kudryashov <ever.zet@gmail.com>
  58400. * Marcello Duarte <marcello.duarte@gmail.com>
  58401. *
  58402. * For the full copyright and license information, please view the LICENSE
  58403. * file that was distributed with this source code.
  58404. */
  58405. namespace Prophecy\Util;
  58406. use Prophecy\Call\Call;
  58407. /**
  58408. * String utility.
  58409. *
  58410. * @author Konstantin Kudryashov <ever.zet@gmail.com>
  58411. */
  58412. class StringUtil
  58413. {
  58414. private $verbose;
  58415. /**
  58416. * @param bool $verbose
  58417. */
  58418. public function __construct($verbose = \true)
  58419. {
  58420. $this->verbose = $verbose;
  58421. }
  58422. /**
  58423. * Stringifies any provided value.
  58424. *
  58425. * @param mixed $value
  58426. * @param boolean $exportObject
  58427. *
  58428. * @return string
  58429. */
  58430. public function stringify($value, $exportObject = \true)
  58431. {
  58432. if (\is_array($value)) {
  58433. if (\range(0, \count($value) - 1) === \array_keys($value)) {
  58434. return '[' . \implode(', ', \array_map(array($this, __FUNCTION__), $value)) . ']';
  58435. }
  58436. $stringify = array($this, __FUNCTION__);
  58437. return '[' . \implode(', ', \array_map(function ($item, $key) use($stringify) {
  58438. return (\is_integer($key) ? $key : '"' . $key . '"') . ' => ' . \call_user_func($stringify, $item);
  58439. }, $value, \array_keys($value))) . ']';
  58440. }
  58441. if (\is_resource($value)) {
  58442. return \get_resource_type($value) . ':' . $value;
  58443. }
  58444. if (\is_object($value)) {
  58445. return $exportObject ? \Prophecy\Util\ExportUtil::export($value) : \sprintf('%s:%s', \get_class($value), \spl_object_hash($value));
  58446. }
  58447. if (\true === $value || \false === $value) {
  58448. return $value ? 'true' : 'false';
  58449. }
  58450. if (\is_string($value)) {
  58451. $str = \sprintf('"%s"', \str_replace("\n", '\\n', $value));
  58452. if (!$this->verbose && 50 <= \strlen($str)) {
  58453. return \substr($str, 0, 50) . '"...';
  58454. }
  58455. return $str;
  58456. }
  58457. if (null === $value) {
  58458. return 'null';
  58459. }
  58460. return (string) $value;
  58461. }
  58462. /**
  58463. * Stringifies provided array of calls.
  58464. *
  58465. * @param Call[] $calls Array of Call instances
  58466. *
  58467. * @return string
  58468. */
  58469. public function stringifyCalls(array $calls)
  58470. {
  58471. $self = $this;
  58472. return \implode(\PHP_EOL, \array_map(function (\Prophecy\Call\Call $call) use($self) {
  58473. return \sprintf(' - %s(%s) @ %s', $call->getMethodName(), \implode(', ', \array_map(array($self, 'stringify'), $call->getArguments())), \str_replace(\GETCWD() . \DIRECTORY_SEPARATOR, '', $call->getCallPlace()));
  58474. }, $calls));
  58475. }
  58476. }
  58477. <?php
  58478. namespace Prophecy\Util;
  58479. use Prophecy\Prophecy\ProphecyInterface;
  58480. use PHPUnit\SebastianBergmann\RecursionContext\Context;
  58481. /*
  58482. * This file is part of the Prophecy.
  58483. * (c) Konstantin Kudryashov <ever.zet@gmail.com>
  58484. * Marcello Duarte <marcello.duarte@gmail.com>
  58485. *
  58486. * For the full copyright and license information, please view the LICENSE
  58487. * file that was distributed with this source code.
  58488. */
  58489. /**
  58490. * This class is a modification from sebastianbergmann/exporter
  58491. * @see https://github.com/sebastianbergmann/exporter
  58492. */
  58493. class ExportUtil
  58494. {
  58495. /**
  58496. * Exports a value as a string
  58497. *
  58498. * The output of this method is similar to the output of print_r(), but
  58499. * improved in various aspects:
  58500. *
  58501. * - NULL is rendered as "null" (instead of "")
  58502. * - TRUE is rendered as "true" (instead of "1")
  58503. * - FALSE is rendered as "false" (instead of "")
  58504. * - Strings are always quoted with single quotes
  58505. * - Carriage returns and newlines are normalized to \n
  58506. * - Recursion and repeated rendering is treated properly
  58507. *
  58508. * @param mixed $value
  58509. * @param int $indentation The indentation level of the 2nd+ line
  58510. * @return string
  58511. */
  58512. public static function export($value, $indentation = 0)
  58513. {
  58514. return self::recursiveExport($value, $indentation);
  58515. }
  58516. /**
  58517. * Converts an object to an array containing all of its private, protected
  58518. * and public properties.
  58519. *
  58520. * @param mixed $value
  58521. * @return array
  58522. */
  58523. public static function toArray($value)
  58524. {
  58525. if (!\is_object($value)) {
  58526. return (array) $value;
  58527. }
  58528. $array = array();
  58529. foreach ((array) $value as $key => $val) {
  58530. // properties are transformed to keys in the following way:
  58531. // private $property => "\0Classname\0property"
  58532. // protected $property => "\0*\0property"
  58533. // public $property => "property"
  58534. if (\preg_match('/^\\0.+\\0(.+)$/', $key, $matches)) {
  58535. $key = $matches[1];
  58536. }
  58537. // See https://github.com/php/php-src/commit/5721132
  58538. if ($key === "\0gcdata") {
  58539. continue;
  58540. }
  58541. $array[$key] = $val;
  58542. }
  58543. // Some internal classes like SplObjectStorage don't work with the
  58544. // above (fast) mechanism nor with reflection in Zend.
  58545. // Format the output similarly to print_r() in this case
  58546. if ($value instanceof \SplObjectStorage) {
  58547. // However, the fast method does work in HHVM, and exposes the
  58548. // internal implementation. Hide it again.
  58549. if (\property_exists('\\SplObjectStorage', '__storage')) {
  58550. unset($array['__storage']);
  58551. } elseif (\property_exists('\\SplObjectStorage', 'storage')) {
  58552. unset($array['storage']);
  58553. }
  58554. if (\property_exists('\\SplObjectStorage', '__key')) {
  58555. unset($array['__key']);
  58556. }
  58557. foreach ($value as $key => $val) {
  58558. $array[\spl_object_hash($val)] = array('obj' => $val, 'inf' => $value->getInfo());
  58559. }
  58560. }
  58561. return $array;
  58562. }
  58563. /**
  58564. * Recursive implementation of export
  58565. *
  58566. * @param mixed $value The value to export
  58567. * @param int $indentation The indentation level of the 2nd+ line
  58568. * @param \SebastianBergmann\RecursionContext\Context $processed Previously processed objects
  58569. * @return string
  58570. * @see SebastianBergmann\Exporter\Exporter::export
  58571. */
  58572. protected static function recursiveExport(&$value, $indentation, $processed = null)
  58573. {
  58574. if ($value === null) {
  58575. return 'null';
  58576. }
  58577. if ($value === \true) {
  58578. return 'true';
  58579. }
  58580. if ($value === \false) {
  58581. return 'false';
  58582. }
  58583. if (\is_float($value) && \floatval(\intval($value)) === $value) {
  58584. return "{$value}.0";
  58585. }
  58586. if (\is_resource($value)) {
  58587. return \sprintf('resource(%d) of type (%s)', $value, \get_resource_type($value));
  58588. }
  58589. if (\is_string($value)) {
  58590. // Match for most non printable chars somewhat taking multibyte chars into account
  58591. if (\preg_match('/[^\\x09-\\x0d\\x20-\\xff]/', $value)) {
  58592. return 'Binary String: 0x' . \bin2hex($value);
  58593. }
  58594. return "'" . \str_replace(array("\r\n", "\n\r", "\r"), array("\n", "\n", "\n"), $value) . "'";
  58595. }
  58596. $whitespace = \str_repeat(' ', 4 * $indentation);
  58597. if (!$processed) {
  58598. $processed = new \PHPUnit\SebastianBergmann\RecursionContext\Context();
  58599. }
  58600. if (\is_array($value)) {
  58601. if (($key = $processed->contains($value)) !== \false) {
  58602. return 'Array &' . $key;
  58603. }
  58604. $array = $value;
  58605. $key = $processed->add($value);
  58606. $values = '';
  58607. if (\count($array) > 0) {
  58608. foreach ($array as $k => $v) {
  58609. $values .= \sprintf('%s %s => %s' . "\n", $whitespace, self::recursiveExport($k, $indentation), self::recursiveExport($value[$k], $indentation + 1, $processed));
  58610. }
  58611. $values = "\n" . $values . $whitespace;
  58612. }
  58613. return \sprintf('Array &%s (%s)', $key, $values);
  58614. }
  58615. if (\is_object($value)) {
  58616. $class = \get_class($value);
  58617. if ($hash = $processed->contains($value)) {
  58618. return \sprintf('%s:%s Object', $class, $hash);
  58619. }
  58620. $hash = $processed->add($value);
  58621. $values = '';
  58622. $array = self::toArray($value);
  58623. if (\count($array) > 0) {
  58624. foreach ($array as $k => $v) {
  58625. $values .= \sprintf('%s %s => %s' . "\n", $whitespace, self::recursiveExport($k, $indentation), self::recursiveExport($v, $indentation + 1, $processed));
  58626. }
  58627. $values = "\n" . $values . $whitespace;
  58628. }
  58629. return \sprintf('%s:%s Object (%s)', $class, $hash, $values);
  58630. }
  58631. return \var_export($value, \true);
  58632. }
  58633. }
  58634. <?php
  58635. /*
  58636. * This file is part of the Prophecy.
  58637. * (c) Konstantin Kudryashov <ever.zet@gmail.com>
  58638. * Marcello Duarte <marcello.duarte@gmail.com>
  58639. *
  58640. * For the full copyright and license information, please view the LICENSE
  58641. * file that was distributed with this source code.
  58642. */
  58643. namespace Prophecy\Exception\Prophecy;
  58644. use Prophecy\Exception\Exception;
  58645. interface ProphecyException extends \Prophecy\Exception\Exception
  58646. {
  58647. }
  58648. <?php
  58649. /*
  58650. * This file is part of the Prophecy.
  58651. * (c) Konstantin Kudryashov <ever.zet@gmail.com>
  58652. * Marcello Duarte <marcello.duarte@gmail.com>
  58653. *
  58654. * For the full copyright and license information, please view the LICENSE
  58655. * file that was distributed with this source code.
  58656. */
  58657. namespace Prophecy\Exception\Prophecy;
  58658. use Prophecy\Prophecy\MethodProphecy;
  58659. class MethodProphecyException extends \Prophecy\Exception\Prophecy\ObjectProphecyException
  58660. {
  58661. private $methodProphecy;
  58662. public function __construct($message, \Prophecy\Prophecy\MethodProphecy $methodProphecy)
  58663. {
  58664. parent::__construct($message, $methodProphecy->getObjectProphecy());
  58665. $this->methodProphecy = $methodProphecy;
  58666. }
  58667. /**
  58668. * @return MethodProphecy
  58669. */
  58670. public function getMethodProphecy()
  58671. {
  58672. return $this->methodProphecy;
  58673. }
  58674. }
  58675. <?php
  58676. /*
  58677. * This file is part of the Prophecy.
  58678. * (c) Konstantin Kudryashov <ever.zet@gmail.com>
  58679. * Marcello Duarte <marcello.duarte@gmail.com>
  58680. *
  58681. * For the full copyright and license information, please view the LICENSE
  58682. * file that was distributed with this source code.
  58683. */
  58684. namespace Prophecy\Exception\Prophecy;
  58685. use Prophecy\Prophecy\ObjectProphecy;
  58686. class ObjectProphecyException extends \RuntimeException implements \Prophecy\Exception\Prophecy\ProphecyException
  58687. {
  58688. private $objectProphecy;
  58689. public function __construct($message, \Prophecy\Prophecy\ObjectProphecy $objectProphecy)
  58690. {
  58691. parent::__construct($message);
  58692. $this->objectProphecy = $objectProphecy;
  58693. }
  58694. /**
  58695. * @return ObjectProphecy
  58696. */
  58697. public function getObjectProphecy()
  58698. {
  58699. return $this->objectProphecy;
  58700. }
  58701. }
  58702. <?php
  58703. /*
  58704. * This file is part of the Prophecy.
  58705. * (c) Konstantin Kudryashov <ever.zet@gmail.com>
  58706. * Marcello Duarte <marcello.duarte@gmail.com>
  58707. *
  58708. * For the full copyright and license information, please view the LICENSE
  58709. * file that was distributed with this source code.
  58710. */
  58711. namespace Prophecy\Exception\Prediction;
  58712. use Prophecy\Prophecy\MethodProphecy;
  58713. class UnexpectedCallsCountException extends \Prophecy\Exception\Prediction\UnexpectedCallsException
  58714. {
  58715. private $expectedCount;
  58716. public function __construct($message, \Prophecy\Prophecy\MethodProphecy $methodProphecy, $count, array $calls)
  58717. {
  58718. parent::__construct($message, $methodProphecy, $calls);
  58719. $this->expectedCount = \intval($count);
  58720. }
  58721. public function getExpectedCount()
  58722. {
  58723. return $this->expectedCount;
  58724. }
  58725. }
  58726. <?php
  58727. /*
  58728. * This file is part of the Prophecy.
  58729. * (c) Konstantin Kudryashov <ever.zet@gmail.com>
  58730. * Marcello Duarte <marcello.duarte@gmail.com>
  58731. *
  58732. * For the full copyright and license information, please view the LICENSE
  58733. * file that was distributed with this source code.
  58734. */
  58735. namespace Prophecy\Exception\Prediction;
  58736. use Prophecy\Prophecy\MethodProphecy;
  58737. use Prophecy\Exception\Prophecy\MethodProphecyException;
  58738. class UnexpectedCallsException extends \Prophecy\Exception\Prophecy\MethodProphecyException implements \Prophecy\Exception\Prediction\PredictionException
  58739. {
  58740. private $calls = array();
  58741. public function __construct($message, \Prophecy\Prophecy\MethodProphecy $methodProphecy, array $calls)
  58742. {
  58743. parent::__construct($message, $methodProphecy);
  58744. $this->calls = $calls;
  58745. }
  58746. public function getCalls()
  58747. {
  58748. return $this->calls;
  58749. }
  58750. }
  58751. <?php
  58752. /*
  58753. * This file is part of the Prophecy.
  58754. * (c) Konstantin Kudryashov <ever.zet@gmail.com>
  58755. * Marcello Duarte <marcello.duarte@gmail.com>
  58756. *
  58757. * For the full copyright and license information, please view the LICENSE
  58758. * file that was distributed with this source code.
  58759. */
  58760. namespace Prophecy\Exception\Prediction;
  58761. use RuntimeException;
  58762. /**
  58763. * Basic failed prediction exception.
  58764. * Use it for custom prediction failures.
  58765. *
  58766. * @author Konstantin Kudryashov <ever.zet@gmail.com>
  58767. */
  58768. class FailedPredictionException extends \RuntimeException implements \Prophecy\Exception\Prediction\PredictionException
  58769. {
  58770. }
  58771. <?php
  58772. /*
  58773. * This file is part of the Prophecy.
  58774. * (c) Konstantin Kudryashov <ever.zet@gmail.com>
  58775. * Marcello Duarte <marcello.duarte@gmail.com>
  58776. *
  58777. * For the full copyright and license information, please view the LICENSE
  58778. * file that was distributed with this source code.
  58779. */
  58780. namespace Prophecy\Exception\Prediction;
  58781. use Prophecy\Prophecy\ObjectProphecy;
  58782. class AggregateException extends \RuntimeException implements \Prophecy\Exception\Prediction\PredictionException
  58783. {
  58784. private $exceptions = array();
  58785. private $objectProphecy;
  58786. public function append(\Prophecy\Exception\Prediction\PredictionException $exception)
  58787. {
  58788. $message = $exception->getMessage();
  58789. $message = \strtr($message, array("\n" => "\n ")) . "\n";
  58790. $message = empty($this->exceptions) ? $message : "\n" . $message;
  58791. $this->message = \rtrim($this->message . $message);
  58792. $this->exceptions[] = $exception;
  58793. }
  58794. /**
  58795. * @return PredictionException[]
  58796. */
  58797. public function getExceptions()
  58798. {
  58799. return $this->exceptions;
  58800. }
  58801. public function setObjectProphecy(\Prophecy\Prophecy\ObjectProphecy $objectProphecy)
  58802. {
  58803. $this->objectProphecy = $objectProphecy;
  58804. }
  58805. /**
  58806. * @return ObjectProphecy
  58807. */
  58808. public function getObjectProphecy()
  58809. {
  58810. return $this->objectProphecy;
  58811. }
  58812. }
  58813. <?php
  58814. /*
  58815. * This file is part of the Prophecy.
  58816. * (c) Konstantin Kudryashov <ever.zet@gmail.com>
  58817. * Marcello Duarte <marcello.duarte@gmail.com>
  58818. *
  58819. * For the full copyright and license information, please view the LICENSE
  58820. * file that was distributed with this source code.
  58821. */
  58822. namespace Prophecy\Exception\Prediction;
  58823. use Prophecy\Exception\Prophecy\MethodProphecyException;
  58824. class NoCallsException extends \Prophecy\Exception\Prophecy\MethodProphecyException implements \Prophecy\Exception\Prediction\PredictionException
  58825. {
  58826. }
  58827. <?php
  58828. /*
  58829. * This file is part of the Prophecy.
  58830. * (c) Konstantin Kudryashov <ever.zet@gmail.com>
  58831. * Marcello Duarte <marcello.duarte@gmail.com>
  58832. *
  58833. * For the full copyright and license information, please view the LICENSE
  58834. * file that was distributed with this source code.
  58835. */
  58836. namespace Prophecy\Exception\Prediction;
  58837. use Prophecy\Exception\Exception;
  58838. interface PredictionException extends \Prophecy\Exception\Exception
  58839. {
  58840. }
  58841. <?php
  58842. /*
  58843. * This file is part of the Prophecy.
  58844. * (c) Konstantin Kudryashov <ever.zet@gmail.com>
  58845. * Marcello Duarte <marcello.duarte@gmail.com>
  58846. *
  58847. * For the full copyright and license information, please view the LICENSE
  58848. * file that was distributed with this source code.
  58849. */
  58850. namespace Prophecy\Exception\Call;
  58851. use Prophecy\Exception\Prophecy\ObjectProphecyException;
  58852. use Prophecy\Prophecy\ObjectProphecy;
  58853. class UnexpectedCallException extends \Prophecy\Exception\Prophecy\ObjectProphecyException
  58854. {
  58855. private $methodName;
  58856. private $arguments;
  58857. public function __construct($message, \Prophecy\Prophecy\ObjectProphecy $objectProphecy, $methodName, array $arguments)
  58858. {
  58859. parent::__construct($message, $objectProphecy);
  58860. $this->methodName = $methodName;
  58861. $this->arguments = $arguments;
  58862. }
  58863. public function getMethodName()
  58864. {
  58865. return $this->methodName;
  58866. }
  58867. public function getArguments()
  58868. {
  58869. return $this->arguments;
  58870. }
  58871. }
  58872. <?php
  58873. /*
  58874. * This file is part of the Prophecy.
  58875. * (c) Konstantin Kudryashov <ever.zet@gmail.com>
  58876. * Marcello Duarte <marcello.duarte@gmail.com>
  58877. *
  58878. * For the full copyright and license information, please view the LICENSE
  58879. * file that was distributed with this source code.
  58880. */
  58881. namespace Prophecy\Exception;
  58882. /**
  58883. * Core Prophecy exception interface.
  58884. * All Prophecy exceptions implement it.
  58885. *
  58886. * @author Konstantin Kudryashov <ever.zet@gmail.com>
  58887. */
  58888. interface Exception
  58889. {
  58890. /**
  58891. * @return string
  58892. */
  58893. public function getMessage();
  58894. }
  58895. <?php
  58896. /*
  58897. * This file is part of the Prophecy.
  58898. * (c) Konstantin Kudryashov <ever.zet@gmail.com>
  58899. * Marcello Duarte <marcello.duarte@gmail.com>
  58900. *
  58901. * For the full copyright and license information, please view the LICENSE
  58902. * file that was distributed with this source code.
  58903. */
  58904. namespace Prophecy\Exception\Doubler;
  58905. class MethodNotFoundException extends \Prophecy\Exception\Doubler\DoubleException
  58906. {
  58907. /**
  58908. * @var string|object
  58909. */
  58910. private $classname;
  58911. /**
  58912. * @var string
  58913. */
  58914. private $methodName;
  58915. /**
  58916. * @var array
  58917. */
  58918. private $arguments;
  58919. /**
  58920. * @param string $message
  58921. * @param string|object $classname
  58922. * @param string $methodName
  58923. * @param null|Argument\ArgumentsWildcard|array $arguments
  58924. */
  58925. public function __construct($message, $classname, $methodName, $arguments = null)
  58926. {
  58927. parent::__construct($message);
  58928. $this->classname = $classname;
  58929. $this->methodName = $methodName;
  58930. $this->arguments = $arguments;
  58931. }
  58932. public function getClassname()
  58933. {
  58934. return $this->classname;
  58935. }
  58936. public function getMethodName()
  58937. {
  58938. return $this->methodName;
  58939. }
  58940. public function getArguments()
  58941. {
  58942. return $this->arguments;
  58943. }
  58944. }
  58945. <?php
  58946. /*
  58947. * This file is part of the Prophecy.
  58948. * (c) Konstantin Kudryashov <ever.zet@gmail.com>
  58949. * Marcello Duarte <marcello.duarte@gmail.com>
  58950. *
  58951. * For the full copyright and license information, please view the LICENSE
  58952. * file that was distributed with this source code.
  58953. */
  58954. namespace Prophecy\Exception\Doubler;
  58955. class ClassNotFoundException extends \Prophecy\Exception\Doubler\DoubleException
  58956. {
  58957. private $classname;
  58958. /**
  58959. * @param string $message
  58960. * @param string $classname
  58961. */
  58962. public function __construct($message, $classname)
  58963. {
  58964. parent::__construct($message);
  58965. $this->classname = $classname;
  58966. }
  58967. public function getClassname()
  58968. {
  58969. return $this->classname;
  58970. }
  58971. }
  58972. <?php
  58973. /*
  58974. * This file is part of the Prophecy.
  58975. * (c) Konstantin Kudryashov <ever.zet@gmail.com>
  58976. * Marcello Duarte <marcello.duarte@gmail.com>
  58977. *
  58978. * For the full copyright and license information, please view the LICENSE
  58979. * file that was distributed with this source code.
  58980. */
  58981. namespace Prophecy\Exception\Doubler;
  58982. use ReflectionClass;
  58983. class ClassMirrorException extends \RuntimeException implements \Prophecy\Exception\Doubler\DoublerException
  58984. {
  58985. private $class;
  58986. public function __construct($message, \ReflectionClass $class)
  58987. {
  58988. parent::__construct($message);
  58989. $this->class = $class;
  58990. }
  58991. public function getReflectedClass()
  58992. {
  58993. return $this->class;
  58994. }
  58995. }
  58996. <?php
  58997. /*
  58998. * This file is part of the Prophecy.
  58999. * (c) Konstantin Kudryashov <ever.zet@gmail.com>
  59000. * Marcello Duarte <marcello.duarte@gmail.com>
  59001. *
  59002. * For the full copyright and license information, please view the LICENSE
  59003. * file that was distributed with this source code.
  59004. */
  59005. namespace Prophecy\Exception\Doubler;
  59006. use Prophecy\Exception\Exception;
  59007. interface DoublerException extends \Prophecy\Exception\Exception
  59008. {
  59009. }
  59010. <?php
  59011. /*
  59012. * This file is part of the Prophecy.
  59013. * (c) Konstantin Kudryashov <ever.zet@gmail.com>
  59014. * Marcello Duarte <marcello.duarte@gmail.com>
  59015. *
  59016. * For the full copyright and license information, please view the LICENSE
  59017. * file that was distributed with this source code.
  59018. */
  59019. namespace Prophecy\Exception\Doubler;
  59020. class InterfaceNotFoundException extends \Prophecy\Exception\Doubler\ClassNotFoundException
  59021. {
  59022. public function getInterfaceName()
  59023. {
  59024. return $this->getClassname();
  59025. }
  59026. }
  59027. <?php
  59028. /*
  59029. * This file is part of the Prophecy.
  59030. * (c) Konstantin Kudryashov <ever.zet@gmail.com>
  59031. * Marcello Duarte <marcello.duarte@gmail.com>
  59032. *
  59033. * For the full copyright and license information, please view the LICENSE
  59034. * file that was distributed with this source code.
  59035. */
  59036. namespace Prophecy\Exception\Doubler;
  59037. class ReturnByReferenceException extends \Prophecy\Exception\Doubler\DoubleException
  59038. {
  59039. private $classname;
  59040. private $methodName;
  59041. /**
  59042. * @param string $message
  59043. * @param string $classname
  59044. * @param string $methodName
  59045. */
  59046. public function __construct($message, $classname, $methodName)
  59047. {
  59048. parent::__construct($message);
  59049. $this->classname = $classname;
  59050. $this->methodName = $methodName;
  59051. }
  59052. public function getClassname()
  59053. {
  59054. return $this->classname;
  59055. }
  59056. public function getMethodName()
  59057. {
  59058. return $this->methodName;
  59059. }
  59060. }
  59061. <?php
  59062. namespace Prophecy\Exception\Doubler;
  59063. class MethodNotExtendableException extends \Prophecy\Exception\Doubler\DoubleException
  59064. {
  59065. private $methodName;
  59066. private $className;
  59067. /**
  59068. * @param string $message
  59069. * @param string $className
  59070. * @param string $methodName
  59071. */
  59072. public function __construct($message, $className, $methodName)
  59073. {
  59074. parent::__construct($message);
  59075. $this->methodName = $methodName;
  59076. $this->className = $className;
  59077. }
  59078. /**
  59079. * @return string
  59080. */
  59081. public function getMethodName()
  59082. {
  59083. return $this->methodName;
  59084. }
  59085. /**
  59086. * @return string
  59087. */
  59088. public function getClassName()
  59089. {
  59090. return $this->className;
  59091. }
  59092. }
  59093. <?php
  59094. /*
  59095. * This file is part of the Prophecy.
  59096. * (c) Konstantin Kudryashov <ever.zet@gmail.com>
  59097. * Marcello Duarte <marcello.duarte@gmail.com>
  59098. *
  59099. * For the full copyright and license information, please view the LICENSE
  59100. * file that was distributed with this source code.
  59101. */
  59102. namespace Prophecy\Exception\Doubler;
  59103. use RuntimeException;
  59104. class DoubleException extends \RuntimeException implements \Prophecy\Exception\Doubler\DoublerException
  59105. {
  59106. }
  59107. <?php
  59108. /*
  59109. * This file is part of the Prophecy.
  59110. * (c) Konstantin Kudryashov <ever.zet@gmail.com>
  59111. * Marcello Duarte <marcello.duarte@gmail.com>
  59112. *
  59113. * For the full copyright and license information, please view the LICENSE
  59114. * file that was distributed with this source code.
  59115. */
  59116. namespace Prophecy\Exception\Doubler;
  59117. use Prophecy\Doubler\Generator\Node\ClassNode;
  59118. class ClassCreatorException extends \RuntimeException implements \Prophecy\Exception\Doubler\DoublerException
  59119. {
  59120. private $node;
  59121. public function __construct($message, \Prophecy\Doubler\Generator\Node\ClassNode $node)
  59122. {
  59123. parent::__construct($message);
  59124. $this->node = $node;
  59125. }
  59126. public function getClassNode()
  59127. {
  59128. return $this->node;
  59129. }
  59130. }
  59131. <?php
  59132. /*
  59133. * This file is part of the Prophecy.
  59134. * (c) Konstantin Kudryashov <ever.zet@gmail.com>
  59135. * Marcello Duarte <marcello.duarte@gmail.com>
  59136. *
  59137. * For the full copyright and license information, please view the LICENSE
  59138. * file that was distributed with this source code.
  59139. */
  59140. namespace Prophecy\Exception;
  59141. class InvalidArgumentException extends \InvalidArgumentException implements \Prophecy\Exception\Exception
  59142. {
  59143. }
  59144. <?php
  59145. /*
  59146. * This file is part of the Prophecy.
  59147. * (c) Konstantin Kudryashov <ever.zet@gmail.com>
  59148. * Marcello Duarte <marcello.duarte@gmail.com>
  59149. *
  59150. * For the full copyright and license information, please view the LICENSE
  59151. * file that was distributed with this source code.
  59152. */
  59153. namespace Prophecy\Promise;
  59154. use Prophecy\Prophecy\ObjectProphecy;
  59155. use Prophecy\Prophecy\MethodProphecy;
  59156. /**
  59157. * Promise interface.
  59158. * Promises are logical blocks, tied to `will...` keyword.
  59159. *
  59160. * @author Konstantin Kudryashov <ever.zet@gmail.com>
  59161. */
  59162. interface PromiseInterface
  59163. {
  59164. /**
  59165. * Evaluates promise.
  59166. *
  59167. * @param array $args
  59168. * @param ObjectProphecy $object
  59169. * @param MethodProphecy $method
  59170. *
  59171. * @return mixed
  59172. */
  59173. public function execute(array $args, \Prophecy\Prophecy\ObjectProphecy $object, \Prophecy\Prophecy\MethodProphecy $method);
  59174. }
  59175. <?php
  59176. /*
  59177. * This file is part of the Prophecy.
  59178. * (c) Konstantin Kudryashov <ever.zet@gmail.com>
  59179. * Marcello Duarte <marcello.duarte@gmail.com>
  59180. *
  59181. * For the full copyright and license information, please view the LICENSE
  59182. * file that was distributed with this source code.
  59183. */
  59184. namespace Prophecy\Promise;
  59185. use PHPUnit\Doctrine\Instantiator\Instantiator;
  59186. use Prophecy\Prophecy\ObjectProphecy;
  59187. use Prophecy\Prophecy\MethodProphecy;
  59188. use Prophecy\Exception\InvalidArgumentException;
  59189. use ReflectionClass;
  59190. /**
  59191. * Throw promise.
  59192. *
  59193. * @author Konstantin Kudryashov <ever.zet@gmail.com>
  59194. */
  59195. class ThrowPromise implements \Prophecy\Promise\PromiseInterface
  59196. {
  59197. private $exception;
  59198. /**
  59199. * @var \Doctrine\Instantiator\Instantiator
  59200. */
  59201. private $instantiator;
  59202. /**
  59203. * Initializes promise.
  59204. *
  59205. * @param string|\Exception|\Throwable $exception Exception class name or instance
  59206. *
  59207. * @throws \Prophecy\Exception\InvalidArgumentException
  59208. */
  59209. public function __construct($exception)
  59210. {
  59211. if (\is_string($exception)) {
  59212. if (!\class_exists($exception) && !\interface_exists($exception) || !$this->isAValidThrowable($exception)) {
  59213. throw new \Prophecy\Exception\InvalidArgumentException(\sprintf('Exception / Throwable class or instance expected as argument to ThrowPromise, but got %s.', $exception));
  59214. }
  59215. } elseif (!$exception instanceof \Exception && !$exception instanceof \Throwable) {
  59216. throw new \Prophecy\Exception\InvalidArgumentException(\sprintf('Exception / Throwable class or instance expected as argument to ThrowPromise, but got %s.', \is_object($exception) ? \get_class($exception) : \gettype($exception)));
  59217. }
  59218. $this->exception = $exception;
  59219. }
  59220. /**
  59221. * Throws predefined exception.
  59222. *
  59223. * @param array $args
  59224. * @param ObjectProphecy $object
  59225. * @param MethodProphecy $method
  59226. *
  59227. * @throws object
  59228. */
  59229. public function execute(array $args, \Prophecy\Prophecy\ObjectProphecy $object, \Prophecy\Prophecy\MethodProphecy $method)
  59230. {
  59231. if (\is_string($this->exception)) {
  59232. $classname = $this->exception;
  59233. $reflection = new \ReflectionClass($classname);
  59234. $constructor = $reflection->getConstructor();
  59235. if ($constructor->isPublic() && 0 == $constructor->getNumberOfRequiredParameters()) {
  59236. throw $reflection->newInstance();
  59237. }
  59238. if (!$this->instantiator) {
  59239. $this->instantiator = new \PHPUnit\Doctrine\Instantiator\Instantiator();
  59240. }
  59241. throw $this->instantiator->instantiate($classname);
  59242. }
  59243. throw $this->exception;
  59244. }
  59245. /**
  59246. * @param string $exception
  59247. *
  59248. * @return bool
  59249. */
  59250. private function isAValidThrowable($exception)
  59251. {
  59252. return \is_a($exception, 'Exception', \true) || \is_a($exception, 'Throwable', \true);
  59253. }
  59254. }
  59255. <?php
  59256. /*
  59257. * This file is part of the Prophecy.
  59258. * (c) Konstantin Kudryashov <ever.zet@gmail.com>
  59259. * Marcello Duarte <marcello.duarte@gmail.com>
  59260. *
  59261. * For the full copyright and license information, please view the LICENSE
  59262. * file that was distributed with this source code.
  59263. */
  59264. namespace Prophecy\Promise;
  59265. use Prophecy\Prophecy\ObjectProphecy;
  59266. use Prophecy\Prophecy\MethodProphecy;
  59267. /**
  59268. * Return promise.
  59269. *
  59270. * @author Konstantin Kudryashov <ever.zet@gmail.com>
  59271. */
  59272. class ReturnPromise implements \Prophecy\Promise\PromiseInterface
  59273. {
  59274. private $returnValues = array();
  59275. /**
  59276. * Initializes promise.
  59277. *
  59278. * @param array $returnValues Array of values
  59279. */
  59280. public function __construct(array $returnValues)
  59281. {
  59282. $this->returnValues = $returnValues;
  59283. }
  59284. /**
  59285. * Returns saved values one by one until last one, then continuously returns last value.
  59286. *
  59287. * @param array $args
  59288. * @param ObjectProphecy $object
  59289. * @param MethodProphecy $method
  59290. *
  59291. * @return mixed
  59292. */
  59293. public function execute(array $args, \Prophecy\Prophecy\ObjectProphecy $object, \Prophecy\Prophecy\MethodProphecy $method)
  59294. {
  59295. $value = \array_shift($this->returnValues);
  59296. if (!\count($this->returnValues)) {
  59297. $this->returnValues[] = $value;
  59298. }
  59299. return $value;
  59300. }
  59301. }
  59302. <?php
  59303. /*
  59304. * This file is part of the Prophecy.
  59305. * (c) Konstantin Kudryashov <ever.zet@gmail.com>
  59306. * Marcello Duarte <marcello.duarte@gmail.com>
  59307. *
  59308. * For the full copyright and license information, please view the LICENSE
  59309. * file that was distributed with this source code.
  59310. */
  59311. namespace Prophecy\Promise;
  59312. use Prophecy\Exception\InvalidArgumentException;
  59313. use Prophecy\Prophecy\ObjectProphecy;
  59314. use Prophecy\Prophecy\MethodProphecy;
  59315. /**
  59316. * Return argument promise.
  59317. *
  59318. * @author Konstantin Kudryashov <ever.zet@gmail.com>
  59319. */
  59320. class ReturnArgumentPromise implements \Prophecy\Promise\PromiseInterface
  59321. {
  59322. /**
  59323. * @var int
  59324. */
  59325. private $index;
  59326. /**
  59327. * Initializes callback promise.
  59328. *
  59329. * @param int $index The zero-indexed number of the argument to return
  59330. *
  59331. * @throws \Prophecy\Exception\InvalidArgumentException
  59332. */
  59333. public function __construct($index = 0)
  59334. {
  59335. if (!\is_int($index) || $index < 0) {
  59336. throw new \Prophecy\Exception\InvalidArgumentException(\sprintf('Zero-based index expected as argument to ReturnArgumentPromise, but got %s.', $index));
  59337. }
  59338. $this->index = $index;
  59339. }
  59340. /**
  59341. * Returns nth argument if has one, null otherwise.
  59342. *
  59343. * @param array $args
  59344. * @param ObjectProphecy $object
  59345. * @param MethodProphecy $method
  59346. *
  59347. * @return null|mixed
  59348. */
  59349. public function execute(array $args, \Prophecy\Prophecy\ObjectProphecy $object, \Prophecy\Prophecy\MethodProphecy $method)
  59350. {
  59351. return \count($args) > $this->index ? $args[$this->index] : null;
  59352. }
  59353. }
  59354. <?php
  59355. /*
  59356. * This file is part of the Prophecy.
  59357. * (c) Konstantin Kudryashov <ever.zet@gmail.com>
  59358. * Marcello Duarte <marcello.duarte@gmail.com>
  59359. *
  59360. * For the full copyright and license information, please view the LICENSE
  59361. * file that was distributed with this source code.
  59362. */
  59363. namespace Prophecy\Promise;
  59364. use Prophecy\Prophecy\ObjectProphecy;
  59365. use Prophecy\Prophecy\MethodProphecy;
  59366. use Prophecy\Exception\InvalidArgumentException;
  59367. use Closure;
  59368. /**
  59369. * Callback promise.
  59370. *
  59371. * @author Konstantin Kudryashov <ever.zet@gmail.com>
  59372. */
  59373. class CallbackPromise implements \Prophecy\Promise\PromiseInterface
  59374. {
  59375. private $callback;
  59376. /**
  59377. * Initializes callback promise.
  59378. *
  59379. * @param callable $callback Custom callback
  59380. *
  59381. * @throws \Prophecy\Exception\InvalidArgumentException
  59382. */
  59383. public function __construct($callback)
  59384. {
  59385. if (!\is_callable($callback)) {
  59386. throw new \Prophecy\Exception\InvalidArgumentException(\sprintf('Callable expected as an argument to CallbackPromise, but got %s.', \gettype($callback)));
  59387. }
  59388. $this->callback = $callback;
  59389. }
  59390. /**
  59391. * Evaluates promise callback.
  59392. *
  59393. * @param array $args
  59394. * @param ObjectProphecy $object
  59395. * @param MethodProphecy $method
  59396. *
  59397. * @return mixed
  59398. */
  59399. public function execute(array $args, \Prophecy\Prophecy\ObjectProphecy $object, \Prophecy\Prophecy\MethodProphecy $method)
  59400. {
  59401. $callback = $this->callback;
  59402. if ($callback instanceof \Closure && \method_exists('Closure', 'bind')) {
  59403. $callback = \Closure::bind($callback, $object);
  59404. }
  59405. return \call_user_func($callback, $args, $object, $method);
  59406. }
  59407. }
  59408. <?php
  59409. /*
  59410. * This file is part of the Prophecy.
  59411. * (c) Konstantin Kudryashov <ever.zet@gmail.com>
  59412. * Marcello Duarte <marcello.duarte@gmail.com>
  59413. *
  59414. * For the full copyright and license information, please view the LICENSE
  59415. * file that was distributed with this source code.
  59416. */
  59417. namespace Prophecy\Prediction;
  59418. use Prophecy\Call\Call;
  59419. use Prophecy\Prophecy\ObjectProphecy;
  59420. use Prophecy\Prophecy\MethodProphecy;
  59421. use Prophecy\Exception\InvalidArgumentException;
  59422. use Closure;
  59423. /**
  59424. * Callback prediction.
  59425. *
  59426. * @author Konstantin Kudryashov <ever.zet@gmail.com>
  59427. */
  59428. class CallbackPrediction implements \Prophecy\Prediction\PredictionInterface
  59429. {
  59430. private $callback;
  59431. /**
  59432. * Initializes callback prediction.
  59433. *
  59434. * @param callable $callback Custom callback
  59435. *
  59436. * @throws \Prophecy\Exception\InvalidArgumentException
  59437. */
  59438. public function __construct($callback)
  59439. {
  59440. if (!\is_callable($callback)) {
  59441. throw new \Prophecy\Exception\InvalidArgumentException(\sprintf('Callable expected as an argument to CallbackPrediction, but got %s.', \gettype($callback)));
  59442. }
  59443. $this->callback = $callback;
  59444. }
  59445. /**
  59446. * Executes preset callback.
  59447. *
  59448. * @param Call[] $calls
  59449. * @param ObjectProphecy $object
  59450. * @param MethodProphecy $method
  59451. */
  59452. public function check(array $calls, \Prophecy\Prophecy\ObjectProphecy $object, \Prophecy\Prophecy\MethodProphecy $method)
  59453. {
  59454. $callback = $this->callback;
  59455. if ($callback instanceof \Closure && \method_exists('Closure', 'bind')) {
  59456. $callback = \Closure::bind($callback, $object);
  59457. }
  59458. \call_user_func($callback, $calls, $object, $method);
  59459. }
  59460. }
  59461. <?php
  59462. /*
  59463. * This file is part of the Prophecy.
  59464. * (c) Konstantin Kudryashov <ever.zet@gmail.com>
  59465. * Marcello Duarte <marcello.duarte@gmail.com>
  59466. *
  59467. * For the full copyright and license information, please view the LICENSE
  59468. * file that was distributed with this source code.
  59469. */
  59470. namespace Prophecy\Prediction;
  59471. use Prophecy\Call\Call;
  59472. use Prophecy\Prophecy\ObjectProphecy;
  59473. use Prophecy\Prophecy\MethodProphecy;
  59474. use Prophecy\Argument\ArgumentsWildcard;
  59475. use Prophecy\Argument\Token\AnyValuesToken;
  59476. use Prophecy\Util\StringUtil;
  59477. use Prophecy\Exception\Prediction\NoCallsException;
  59478. /**
  59479. * Call prediction.
  59480. *
  59481. * @author Konstantin Kudryashov <ever.zet@gmail.com>
  59482. */
  59483. class CallPrediction implements \Prophecy\Prediction\PredictionInterface
  59484. {
  59485. private $util;
  59486. /**
  59487. * Initializes prediction.
  59488. *
  59489. * @param StringUtil $util
  59490. */
  59491. public function __construct(\Prophecy\Util\StringUtil $util = null)
  59492. {
  59493. $this->util = $util ?: new \Prophecy\Util\StringUtil();
  59494. }
  59495. /**
  59496. * Tests that there was at least one call.
  59497. *
  59498. * @param Call[] $calls
  59499. * @param ObjectProphecy $object
  59500. * @param MethodProphecy $method
  59501. *
  59502. * @throws \Prophecy\Exception\Prediction\NoCallsException
  59503. */
  59504. public function check(array $calls, \Prophecy\Prophecy\ObjectProphecy $object, \Prophecy\Prophecy\MethodProphecy $method)
  59505. {
  59506. if (\count($calls)) {
  59507. return;
  59508. }
  59509. $methodCalls = $object->findProphecyMethodCalls($method->getMethodName(), new \Prophecy\Argument\ArgumentsWildcard(array(new \Prophecy\Argument\Token\AnyValuesToken())));
  59510. if (\count($methodCalls)) {
  59511. throw new \Prophecy\Exception\Prediction\NoCallsException(\sprintf("No calls have been made that match:\n" . " %s->%s(%s)\n" . "but expected at least one.\n" . "Recorded `%s(...)` calls:\n%s", \get_class($object->reveal()), $method->getMethodName(), $method->getArgumentsWildcard(), $method->getMethodName(), $this->util->stringifyCalls($methodCalls)), $method);
  59512. }
  59513. throw new \Prophecy\Exception\Prediction\NoCallsException(\sprintf("No calls have been made that match:\n" . " %s->%s(%s)\n" . "but expected at least one.", \get_class($object->reveal()), $method->getMethodName(), $method->getArgumentsWildcard()), $method);
  59514. }
  59515. }
  59516. <?php
  59517. /*
  59518. * This file is part of the Prophecy.
  59519. * (c) Konstantin Kudryashov <ever.zet@gmail.com>
  59520. * Marcello Duarte <marcello.duarte@gmail.com>
  59521. *
  59522. * For the full copyright and license information, please view the LICENSE
  59523. * file that was distributed with this source code.
  59524. */
  59525. namespace Prophecy\Prediction;
  59526. use Prophecy\Call\Call;
  59527. use Prophecy\Prophecy\ObjectProphecy;
  59528. use Prophecy\Prophecy\MethodProphecy;
  59529. use Prophecy\Argument\ArgumentsWildcard;
  59530. use Prophecy\Argument\Token\AnyValuesToken;
  59531. use Prophecy\Util\StringUtil;
  59532. use Prophecy\Exception\Prediction\UnexpectedCallsCountException;
  59533. /**
  59534. * Prediction interface.
  59535. * Predictions are logical test blocks, tied to `should...` keyword.
  59536. *
  59537. * @author Konstantin Kudryashov <ever.zet@gmail.com>
  59538. */
  59539. class CallTimesPrediction implements \Prophecy\Prediction\PredictionInterface
  59540. {
  59541. private $times;
  59542. private $util;
  59543. /**
  59544. * Initializes prediction.
  59545. *
  59546. * @param int $times
  59547. * @param StringUtil $util
  59548. */
  59549. public function __construct($times, \Prophecy\Util\StringUtil $util = null)
  59550. {
  59551. $this->times = \intval($times);
  59552. $this->util = $util ?: new \Prophecy\Util\StringUtil();
  59553. }
  59554. /**
  59555. * Tests that there was exact amount of calls made.
  59556. *
  59557. * @param Call[] $calls
  59558. * @param ObjectProphecy $object
  59559. * @param MethodProphecy $method
  59560. *
  59561. * @throws \Prophecy\Exception\Prediction\UnexpectedCallsCountException
  59562. */
  59563. public function check(array $calls, \Prophecy\Prophecy\ObjectProphecy $object, \Prophecy\Prophecy\MethodProphecy $method)
  59564. {
  59565. if ($this->times == \count($calls)) {
  59566. return;
  59567. }
  59568. $methodCalls = $object->findProphecyMethodCalls($method->getMethodName(), new \Prophecy\Argument\ArgumentsWildcard(array(new \Prophecy\Argument\Token\AnyValuesToken())));
  59569. if (\count($calls)) {
  59570. $message = \sprintf("Expected exactly %d calls that match:\n" . " %s->%s(%s)\n" . "but %d were made:\n%s", $this->times, \get_class($object->reveal()), $method->getMethodName(), $method->getArgumentsWildcard(), \count($calls), $this->util->stringifyCalls($calls));
  59571. } elseif (\count($methodCalls)) {
  59572. $message = \sprintf("Expected exactly %d calls that match:\n" . " %s->%s(%s)\n" . "but none were made.\n" . "Recorded `%s(...)` calls:\n%s", $this->times, \get_class($object->reveal()), $method->getMethodName(), $method->getArgumentsWildcard(), $method->getMethodName(), $this->util->stringifyCalls($methodCalls));
  59573. } else {
  59574. $message = \sprintf("Expected exactly %d calls that match:\n" . " %s->%s(%s)\n" . "but none were made.", $this->times, \get_class($object->reveal()), $method->getMethodName(), $method->getArgumentsWildcard());
  59575. }
  59576. throw new \Prophecy\Exception\Prediction\UnexpectedCallsCountException($message, $method, $this->times, $calls);
  59577. }
  59578. }
  59579. <?php
  59580. /*
  59581. * This file is part of the Prophecy.
  59582. * (c) Konstantin Kudryashov <ever.zet@gmail.com>
  59583. * Marcello Duarte <marcello.duarte@gmail.com>
  59584. *
  59585. * For the full copyright and license information, please view the LICENSE
  59586. * file that was distributed with this source code.
  59587. */
  59588. namespace Prophecy\Prediction;
  59589. use Prophecy\Call\Call;
  59590. use Prophecy\Prophecy\ObjectProphecy;
  59591. use Prophecy\Prophecy\MethodProphecy;
  59592. /**
  59593. * Prediction interface.
  59594. * Predictions are logical test blocks, tied to `should...` keyword.
  59595. *
  59596. * @author Konstantin Kudryashov <ever.zet@gmail.com>
  59597. */
  59598. interface PredictionInterface
  59599. {
  59600. /**
  59601. * Tests that double fulfilled prediction.
  59602. *
  59603. * @param Call[] $calls
  59604. * @param ObjectProphecy $object
  59605. * @param MethodProphecy $method
  59606. *
  59607. * @throws object
  59608. * @return void
  59609. */
  59610. public function check(array $calls, \Prophecy\Prophecy\ObjectProphecy $object, \Prophecy\Prophecy\MethodProphecy $method);
  59611. }
  59612. <?php
  59613. /*
  59614. * This file is part of the Prophecy.
  59615. * (c) Konstantin Kudryashov <ever.zet@gmail.com>
  59616. * Marcello Duarte <marcello.duarte@gmail.com>
  59617. *
  59618. * For the full copyright and license information, please view the LICENSE
  59619. * file that was distributed with this source code.
  59620. */
  59621. namespace Prophecy\Prediction;
  59622. use Prophecy\Call\Call;
  59623. use Prophecy\Prophecy\ObjectProphecy;
  59624. use Prophecy\Prophecy\MethodProphecy;
  59625. use Prophecy\Util\StringUtil;
  59626. use Prophecy\Exception\Prediction\UnexpectedCallsException;
  59627. /**
  59628. * No calls prediction.
  59629. *
  59630. * @author Konstantin Kudryashov <ever.zet@gmail.com>
  59631. */
  59632. class NoCallsPrediction implements \Prophecy\Prediction\PredictionInterface
  59633. {
  59634. private $util;
  59635. /**
  59636. * Initializes prediction.
  59637. *
  59638. * @param null|StringUtil $util
  59639. */
  59640. public function __construct(\Prophecy\Util\StringUtil $util = null)
  59641. {
  59642. $this->util = $util ?: new \Prophecy\Util\StringUtil();
  59643. }
  59644. /**
  59645. * Tests that there were no calls made.
  59646. *
  59647. * @param Call[] $calls
  59648. * @param ObjectProphecy $object
  59649. * @param MethodProphecy $method
  59650. *
  59651. * @throws \Prophecy\Exception\Prediction\UnexpectedCallsException
  59652. */
  59653. public function check(array $calls, \Prophecy\Prophecy\ObjectProphecy $object, \Prophecy\Prophecy\MethodProphecy $method)
  59654. {
  59655. if (!\count($calls)) {
  59656. return;
  59657. }
  59658. $verb = \count($calls) === 1 ? 'was' : 'were';
  59659. throw new \Prophecy\Exception\Prediction\UnexpectedCallsException(\sprintf("No calls expected that match:\n" . " %s->%s(%s)\n" . "but %d %s made:\n%s", \get_class($object->reveal()), $method->getMethodName(), $method->getArgumentsWildcard(), \count($calls), $verb, $this->util->stringifyCalls($calls)), $method, $calls);
  59660. }
  59661. }
  59662. <?php
  59663. /*
  59664. * This file is part of the Prophecy.
  59665. * (c) Konstantin Kudryashov <ever.zet@gmail.com>
  59666. * Marcello Duarte <marcello.duarte@gmail.com>
  59667. *
  59668. * For the full copyright and license information, please view the LICENSE
  59669. * file that was distributed with this source code.
  59670. */
  59671. namespace Prophecy\PhpDocumentor;
  59672. use PHPUnit\phpDocumentor\Reflection\DocBlock;
  59673. use PHPUnit\phpDocumentor\Reflection\DocBlock\Tag\MethodTag as LegacyMethodTag;
  59674. /**
  59675. * @author Théo FIDRY <theo.fidry@gmail.com>
  59676. *
  59677. * @internal
  59678. */
  59679. final class LegacyClassTagRetriever implements \Prophecy\PhpDocumentor\MethodTagRetrieverInterface
  59680. {
  59681. /**
  59682. * @param \ReflectionClass $reflectionClass
  59683. *
  59684. * @return LegacyMethodTag[]
  59685. */
  59686. public function getTagList(\ReflectionClass $reflectionClass)
  59687. {
  59688. $phpdoc = new \PHPUnit\phpDocumentor\Reflection\DocBlock($reflectionClass->getDocComment());
  59689. return $phpdoc->getTagsByName('method');
  59690. }
  59691. }
  59692. <?php
  59693. /*
  59694. * This file is part of the Prophecy.
  59695. * (c) Konstantin Kudryashov <ever.zet@gmail.com>
  59696. * Marcello Duarte <marcello.duarte@gmail.com>
  59697. *
  59698. * For the full copyright and license information, please view the LICENSE
  59699. * file that was distributed with this source code.
  59700. */
  59701. namespace Prophecy\PhpDocumentor;
  59702. use PHPUnit\phpDocumentor\Reflection\DocBlock\Tag\MethodTag as LegacyMethodTag;
  59703. use PHPUnit\phpDocumentor\Reflection\DocBlock\Tags\Method;
  59704. /**
  59705. * @author Théo FIDRY <theo.fidry@gmail.com>
  59706. *
  59707. * @internal
  59708. */
  59709. interface MethodTagRetrieverInterface
  59710. {
  59711. /**
  59712. * @param \ReflectionClass $reflectionClass
  59713. *
  59714. * @return LegacyMethodTag[]|Method[]
  59715. */
  59716. public function getTagList(\ReflectionClass $reflectionClass);
  59717. }
  59718. <?php
  59719. /*
  59720. * This file is part of the Prophecy.
  59721. * (c) Konstantin Kudryashov <ever.zet@gmail.com>
  59722. * Marcello Duarte <marcello.duarte@gmail.com>
  59723. *
  59724. * For the full copyright and license information, please view the LICENSE
  59725. * file that was distributed with this source code.
  59726. */
  59727. namespace Prophecy\PhpDocumentor;
  59728. use PHPUnit\phpDocumentor\Reflection\DocBlock\Tags\Method;
  59729. use PHPUnit\phpDocumentor\Reflection\DocBlockFactory;
  59730. use PHPUnit\phpDocumentor\Reflection\Types\ContextFactory;
  59731. /**
  59732. * @author Théo FIDRY <theo.fidry@gmail.com>
  59733. *
  59734. * @internal
  59735. */
  59736. final class ClassTagRetriever implements \Prophecy\PhpDocumentor\MethodTagRetrieverInterface
  59737. {
  59738. private $docBlockFactory;
  59739. private $contextFactory;
  59740. public function __construct()
  59741. {
  59742. $this->docBlockFactory = \PHPUnit\phpDocumentor\Reflection\DocBlockFactory::createInstance();
  59743. $this->contextFactory = new \PHPUnit\phpDocumentor\Reflection\Types\ContextFactory();
  59744. }
  59745. /**
  59746. * @param \ReflectionClass $reflectionClass
  59747. *
  59748. * @return Method[]
  59749. */
  59750. public function getTagList(\ReflectionClass $reflectionClass)
  59751. {
  59752. try {
  59753. $phpdoc = $this->docBlockFactory->create($reflectionClass, $this->contextFactory->createFromReflector($reflectionClass));
  59754. $methods = array();
  59755. foreach ($phpdoc->getTagsByName('method') as $tag) {
  59756. if ($tag instanceof \PHPUnit\phpDocumentor\Reflection\DocBlock\Tags\Method) {
  59757. $methods[] = $tag;
  59758. }
  59759. }
  59760. return $methods;
  59761. } catch (\InvalidArgumentException $e) {
  59762. return array();
  59763. }
  59764. }
  59765. }
  59766. <?php
  59767. /*
  59768. * This file is part of the Prophecy.
  59769. * (c) Konstantin Kudryashov <ever.zet@gmail.com>
  59770. * Marcello Duarte <marcello.duarte@gmail.com>
  59771. *
  59772. * For the full copyright and license information, please view the LICENSE
  59773. * file that was distributed with this source code.
  59774. */
  59775. namespace Prophecy\PhpDocumentor;
  59776. use PHPUnit\phpDocumentor\Reflection\DocBlock\Tag\MethodTag as LegacyMethodTag;
  59777. use PHPUnit\phpDocumentor\Reflection\DocBlock\Tags\Method;
  59778. /**
  59779. * @author Théo FIDRY <theo.fidry@gmail.com>
  59780. *
  59781. * @internal
  59782. */
  59783. final class ClassAndInterfaceTagRetriever implements \Prophecy\PhpDocumentor\MethodTagRetrieverInterface
  59784. {
  59785. private $classRetriever;
  59786. public function __construct(\Prophecy\PhpDocumentor\MethodTagRetrieverInterface $classRetriever = null)
  59787. {
  59788. if (null !== $classRetriever) {
  59789. $this->classRetriever = $classRetriever;
  59790. return;
  59791. }
  59792. $this->classRetriever = \class_exists('PHPUnit\\phpDocumentor\\Reflection\\DocBlockFactory') && \class_exists('PHPUnit\\phpDocumentor\\Reflection\\Types\\ContextFactory') ? new \Prophecy\PhpDocumentor\ClassTagRetriever() : new \Prophecy\PhpDocumentor\LegacyClassTagRetriever();
  59793. }
  59794. /**
  59795. * @param \ReflectionClass $reflectionClass
  59796. *
  59797. * @return LegacyMethodTag[]|Method[]
  59798. */
  59799. public function getTagList(\ReflectionClass $reflectionClass)
  59800. {
  59801. return \array_merge($this->classRetriever->getTagList($reflectionClass), $this->getInterfacesTagList($reflectionClass));
  59802. }
  59803. /**
  59804. * @param \ReflectionClass $reflectionClass
  59805. *
  59806. * @return LegacyMethodTag[]|Method[]
  59807. */
  59808. private function getInterfacesTagList(\ReflectionClass $reflectionClass)
  59809. {
  59810. $interfaces = $reflectionClass->getInterfaces();
  59811. $tagList = array();
  59812. foreach ($interfaces as $interface) {
  59813. $tagList = \array_merge($tagList, $this->classRetriever->getTagList($interface));
  59814. }
  59815. return $tagList;
  59816. }
  59817. }
  59818. <?php
  59819. /*
  59820. * This file is part of the Prophecy.
  59821. * (c) Konstantin Kudryashov <ever.zet@gmail.com>
  59822. * Marcello Duarte <marcello.duarte@gmail.com>
  59823. *
  59824. * For the full copyright and license information, please view the LICENSE
  59825. * file that was distributed with this source code.
  59826. */
  59827. namespace Prophecy\Call;
  59828. use Prophecy\Exception\Prophecy\MethodProphecyException;
  59829. use Prophecy\Prophecy\ObjectProphecy;
  59830. use Prophecy\Argument\ArgumentsWildcard;
  59831. use Prophecy\Util\StringUtil;
  59832. use Prophecy\Exception\Call\UnexpectedCallException;
  59833. use SplObjectStorage;
  59834. /**
  59835. * Calls receiver & manager.
  59836. *
  59837. * @author Konstantin Kudryashov <ever.zet@gmail.com>
  59838. */
  59839. class CallCenter
  59840. {
  59841. private $util;
  59842. /**
  59843. * @var Call[]
  59844. */
  59845. private $recordedCalls = array();
  59846. /**
  59847. * @var SplObjectStorage
  59848. */
  59849. private $unexpectedCalls;
  59850. /**
  59851. * Initializes call center.
  59852. *
  59853. * @param StringUtil $util
  59854. */
  59855. public function __construct(\Prophecy\Util\StringUtil $util = null)
  59856. {
  59857. $this->util = $util ?: new \Prophecy\Util\StringUtil();
  59858. $this->unexpectedCalls = new \SplObjectStorage();
  59859. }
  59860. /**
  59861. * Makes and records specific method call for object prophecy.
  59862. *
  59863. * @param ObjectProphecy $prophecy
  59864. * @param string $methodName
  59865. * @param array $arguments
  59866. *
  59867. * @return mixed Returns null if no promise for prophecy found or promise return value.
  59868. *
  59869. * @throws \Prophecy\Exception\Call\UnexpectedCallException If no appropriate method prophecy found
  59870. */
  59871. public function makeCall(\Prophecy\Prophecy\ObjectProphecy $prophecy, $methodName, array $arguments)
  59872. {
  59873. // For efficiency exclude 'args' from the generated backtrace
  59874. if (\PHP_VERSION_ID >= 50400) {
  59875. // Limit backtrace to last 3 calls as we don't use the rest
  59876. // Limit argument was introduced in PHP 5.4.0
  59877. $backtrace = \debug_backtrace(\DEBUG_BACKTRACE_IGNORE_ARGS, 3);
  59878. } elseif (\defined('DEBUG_BACKTRACE_IGNORE_ARGS')) {
  59879. // DEBUG_BACKTRACE_IGNORE_ARGS was introduced in PHP 5.3.6
  59880. $backtrace = \debug_backtrace(\DEBUG_BACKTRACE_IGNORE_ARGS);
  59881. } else {
  59882. $backtrace = \debug_backtrace();
  59883. }
  59884. $file = $line = null;
  59885. if (isset($backtrace[2]) && isset($backtrace[2]['file'])) {
  59886. $file = $backtrace[2]['file'];
  59887. $line = $backtrace[2]['line'];
  59888. }
  59889. // If no method prophecies defined, then it's a dummy, so we'll just return null
  59890. if ('__destruct' === \strtolower($methodName) || 0 == \count($prophecy->getMethodProphecies())) {
  59891. $this->recordedCalls[] = new \Prophecy\Call\Call($methodName, $arguments, null, null, $file, $line);
  59892. return null;
  59893. }
  59894. // There are method prophecies, so it's a fake/stub. Searching prophecy for this call
  59895. $matches = $this->findMethodProphecies($prophecy, $methodName, $arguments);
  59896. // If fake/stub doesn't have method prophecy for this call - throw exception
  59897. if (!\count($matches)) {
  59898. $this->unexpectedCalls->attach(new \Prophecy\Call\Call($methodName, $arguments, null, null, $file, $line), $prophecy);
  59899. $this->recordedCalls[] = new \Prophecy\Call\Call($methodName, $arguments, null, null, $file, $line);
  59900. return null;
  59901. }
  59902. // Sort matches by their score value
  59903. @\usort($matches, function ($match1, $match2) {
  59904. return $match2[0] - $match1[0];
  59905. });
  59906. $score = $matches[0][0];
  59907. // If Highest rated method prophecy has a promise - execute it or return null instead
  59908. $methodProphecy = $matches[0][1];
  59909. $returnValue = null;
  59910. $exception = null;
  59911. if ($promise = $methodProphecy->getPromise()) {
  59912. try {
  59913. $returnValue = $promise->execute($arguments, $prophecy, $methodProphecy);
  59914. } catch (\Exception $e) {
  59915. $exception = $e;
  59916. }
  59917. }
  59918. if ($methodProphecy->hasReturnVoid() && $returnValue !== null) {
  59919. throw new \Prophecy\Exception\Prophecy\MethodProphecyException("The method \"{$methodName}\" has a void return type, but the promise returned a value", $methodProphecy);
  59920. }
  59921. $this->recordedCalls[] = $call = new \Prophecy\Call\Call($methodName, $arguments, $returnValue, $exception, $file, $line);
  59922. $call->addScore($methodProphecy->getArgumentsWildcard(), $score);
  59923. if (null !== $exception) {
  59924. throw $exception;
  59925. }
  59926. return $returnValue;
  59927. }
  59928. /**
  59929. * Searches for calls by method name & arguments wildcard.
  59930. *
  59931. * @param string $methodName
  59932. * @param ArgumentsWildcard $wildcard
  59933. *
  59934. * @return Call[]
  59935. */
  59936. public function findCalls($methodName, \Prophecy\Argument\ArgumentsWildcard $wildcard)
  59937. {
  59938. $methodName = \strtolower($methodName);
  59939. return \array_values(\array_filter($this->recordedCalls, function (\Prophecy\Call\Call $call) use($methodName, $wildcard) {
  59940. return $methodName === \strtolower($call->getMethodName()) && 0 < $call->getScore($wildcard);
  59941. }));
  59942. }
  59943. /**
  59944. * @throws UnexpectedCallException
  59945. */
  59946. public function checkUnexpectedCalls()
  59947. {
  59948. /** @var Call $call */
  59949. foreach ($this->unexpectedCalls as $call) {
  59950. $prophecy = $this->unexpectedCalls[$call];
  59951. // If fake/stub doesn't have method prophecy for this call - throw exception
  59952. if (!\count($this->findMethodProphecies($prophecy, $call->getMethodName(), $call->getArguments()))) {
  59953. throw $this->createUnexpectedCallException($prophecy, $call->getMethodName(), $call->getArguments());
  59954. }
  59955. }
  59956. }
  59957. private function createUnexpectedCallException(\Prophecy\Prophecy\ObjectProphecy $prophecy, $methodName, array $arguments)
  59958. {
  59959. $classname = \get_class($prophecy->reveal());
  59960. $indentationLength = 8;
  59961. // looks good
  59962. $argstring = \implode(",\n", $this->indentArguments(\array_map(array($this->util, 'stringify'), $arguments), $indentationLength));
  59963. $expected = array();
  59964. foreach (\call_user_func_array('array_merge', $prophecy->getMethodProphecies()) as $methodProphecy) {
  59965. $expected[] = \sprintf(" - %s(\n" . "%s\n" . " )", $methodProphecy->getMethodName(), \implode(",\n", $this->indentArguments(\array_map('strval', $methodProphecy->getArgumentsWildcard()->getTokens()), $indentationLength)));
  59966. }
  59967. return new \Prophecy\Exception\Call\UnexpectedCallException(\sprintf("Unexpected method call on %s:\n" . " - %s(\n" . "%s\n" . " )\n" . "expected calls were:\n" . "%s", $classname, $methodName, $argstring, \implode("\n", $expected)), $prophecy, $methodName, $arguments);
  59968. }
  59969. private function indentArguments(array $arguments, $indentationLength)
  59970. {
  59971. return \preg_replace_callback('/^/m', function () use($indentationLength) {
  59972. return \str_repeat(' ', $indentationLength);
  59973. }, $arguments);
  59974. }
  59975. /**
  59976. * @param ObjectProphecy $prophecy
  59977. * @param string $methodName
  59978. * @param array $arguments
  59979. *
  59980. * @return array
  59981. */
  59982. private function findMethodProphecies(\Prophecy\Prophecy\ObjectProphecy $prophecy, $methodName, array $arguments)
  59983. {
  59984. $matches = array();
  59985. foreach ($prophecy->getMethodProphecies($methodName) as $methodProphecy) {
  59986. if (0 < ($score = $methodProphecy->getArgumentsWildcard()->scoreArguments($arguments))) {
  59987. $matches[] = array($score, $methodProphecy);
  59988. }
  59989. }
  59990. return $matches;
  59991. }
  59992. }
  59993. <?php
  59994. /*
  59995. * This file is part of the Prophecy.
  59996. * (c) Konstantin Kudryashov <ever.zet@gmail.com>
  59997. * Marcello Duarte <marcello.duarte@gmail.com>
  59998. *
  59999. * For the full copyright and license information, please view the LICENSE
  60000. * file that was distributed with this source code.
  60001. */
  60002. namespace Prophecy\Call;
  60003. use Exception;
  60004. use Prophecy\Argument\ArgumentsWildcard;
  60005. /**
  60006. * Call object.
  60007. *
  60008. * @author Konstantin Kudryashov <ever.zet@gmail.com>
  60009. */
  60010. class Call
  60011. {
  60012. private $methodName;
  60013. private $arguments;
  60014. private $returnValue;
  60015. private $exception;
  60016. private $file;
  60017. private $line;
  60018. private $scores;
  60019. /**
  60020. * Initializes call.
  60021. *
  60022. * @param string $methodName
  60023. * @param array $arguments
  60024. * @param mixed $returnValue
  60025. * @param Exception $exception
  60026. * @param null|string $file
  60027. * @param null|int $line
  60028. */
  60029. public function __construct($methodName, array $arguments, $returnValue, \Exception $exception = null, $file, $line)
  60030. {
  60031. $this->methodName = $methodName;
  60032. $this->arguments = $arguments;
  60033. $this->returnValue = $returnValue;
  60034. $this->exception = $exception;
  60035. $this->scores = new \SplObjectStorage();
  60036. if ($file) {
  60037. $this->file = $file;
  60038. $this->line = \intval($line);
  60039. }
  60040. }
  60041. /**
  60042. * Returns called method name.
  60043. *
  60044. * @return string
  60045. */
  60046. public function getMethodName()
  60047. {
  60048. return $this->methodName;
  60049. }
  60050. /**
  60051. * Returns called method arguments.
  60052. *
  60053. * @return array
  60054. */
  60055. public function getArguments()
  60056. {
  60057. return $this->arguments;
  60058. }
  60059. /**
  60060. * Returns called method return value.
  60061. *
  60062. * @return null|mixed
  60063. */
  60064. public function getReturnValue()
  60065. {
  60066. return $this->returnValue;
  60067. }
  60068. /**
  60069. * Returns exception that call thrown.
  60070. *
  60071. * @return null|Exception
  60072. */
  60073. public function getException()
  60074. {
  60075. return $this->exception;
  60076. }
  60077. /**
  60078. * Returns callee filename.
  60079. *
  60080. * @return string
  60081. */
  60082. public function getFile()
  60083. {
  60084. return $this->file;
  60085. }
  60086. /**
  60087. * Returns callee line number.
  60088. *
  60089. * @return int
  60090. */
  60091. public function getLine()
  60092. {
  60093. return $this->line;
  60094. }
  60095. /**
  60096. * Returns short notation for callee place.
  60097. *
  60098. * @return string
  60099. */
  60100. public function getCallPlace()
  60101. {
  60102. if (null === $this->file) {
  60103. return 'unknown';
  60104. }
  60105. return \sprintf('%s:%d', $this->file, $this->line);
  60106. }
  60107. /**
  60108. * Adds the wildcard match score for the provided wildcard.
  60109. *
  60110. * @param ArgumentsWildcard $wildcard
  60111. * @param false|int $score
  60112. *
  60113. * @return $this
  60114. */
  60115. public function addScore(\Prophecy\Argument\ArgumentsWildcard $wildcard, $score)
  60116. {
  60117. $this->scores[$wildcard] = $score;
  60118. return $this;
  60119. }
  60120. /**
  60121. * Returns wildcard match score for the provided wildcard. The score is
  60122. * calculated if not already done.
  60123. *
  60124. * @param ArgumentsWildcard $wildcard
  60125. *
  60126. * @return false|int False OR integer score (higher - better)
  60127. */
  60128. public function getScore(\Prophecy\Argument\ArgumentsWildcard $wildcard)
  60129. {
  60130. if (isset($this->scores[$wildcard])) {
  60131. return $this->scores[$wildcard];
  60132. }
  60133. return $this->scores[$wildcard] = $wildcard->scoreArguments($this->getArguments());
  60134. }
  60135. }
  60136. <?php
  60137. /*
  60138. * This file is part of the Prophecy.
  60139. * (c) Konstantin Kudryashov <ever.zet@gmail.com>
  60140. * Marcello Duarte <marcello.duarte@gmail.com>
  60141. *
  60142. * For the full copyright and license information, please view the LICENSE
  60143. * file that was distributed with this source code.
  60144. */
  60145. namespace Prophecy\Comparator;
  60146. use Prophecy\Prophecy\ProphecyInterface;
  60147. use PHPUnit\SebastianBergmann\Comparator\ObjectComparator;
  60148. class ProphecyComparator extends \PHPUnit\SebastianBergmann\Comparator\ObjectComparator
  60149. {
  60150. public function accepts($expected, $actual)
  60151. {
  60152. return \is_object($expected) && \is_object($actual) && $actual instanceof \Prophecy\Prophecy\ProphecyInterface;
  60153. }
  60154. public function assertEquals($expected, $actual, $delta = 0.0, $canonicalize = \false, $ignoreCase = \false, array &$processed = array())
  60155. {
  60156. parent::assertEquals($expected, $actual->reveal(), $delta, $canonicalize, $ignoreCase, $processed);
  60157. }
  60158. }
  60159. <?php
  60160. /*
  60161. * This file is part of the Prophecy.
  60162. * (c) Konstantin Kudryashov <ever.zet@gmail.com>
  60163. * Marcello Duarte <marcello.duarte@gmail.com>
  60164. *
  60165. * For the full copyright and license information, please view the LICENSE
  60166. * file that was distributed with this source code.
  60167. */
  60168. namespace Prophecy\Comparator;
  60169. use PHPUnit\SebastianBergmann\Comparator\Factory as BaseFactory;
  60170. /**
  60171. * Prophecy comparator factory.
  60172. *
  60173. * @author Konstantin Kudryashov <ever.zet@gmail.com>
  60174. */
  60175. final class Factory extends \PHPUnit\SebastianBergmann\Comparator\Factory
  60176. {
  60177. /**
  60178. * @var Factory
  60179. */
  60180. private static $instance;
  60181. public function __construct()
  60182. {
  60183. parent::__construct();
  60184. $this->register(new \Prophecy\Comparator\ClosureComparator());
  60185. $this->register(new \Prophecy\Comparator\ProphecyComparator());
  60186. }
  60187. /**
  60188. * @return Factory
  60189. */
  60190. public static function getInstance()
  60191. {
  60192. if (self::$instance === null) {
  60193. self::$instance = new \Prophecy\Comparator\Factory();
  60194. }
  60195. return self::$instance;
  60196. }
  60197. }
  60198. <?php
  60199. /*
  60200. * This file is part of the Prophecy.
  60201. * (c) Konstantin Kudryashov <ever.zet@gmail.com>
  60202. * Marcello Duarte <marcello.duarte@gmail.com>
  60203. *
  60204. * For the full copyright and license information, please view the LICENSE
  60205. * file that was distributed with this source code.
  60206. */
  60207. namespace Prophecy\Comparator;
  60208. use PHPUnit\SebastianBergmann\Comparator\Comparator;
  60209. use PHPUnit\SebastianBergmann\Comparator\ComparisonFailure;
  60210. /**
  60211. * Closure comparator.
  60212. *
  60213. * @author Konstantin Kudryashov <ever.zet@gmail.com>
  60214. */
  60215. final class ClosureComparator extends \PHPUnit\SebastianBergmann\Comparator\Comparator
  60216. {
  60217. public function accepts($expected, $actual)
  60218. {
  60219. return \is_object($expected) && $expected instanceof \Closure && \is_object($actual) && $actual instanceof \Closure;
  60220. }
  60221. public function assertEquals($expected, $actual, $delta = 0.0, $canonicalize = \false, $ignoreCase = \false, array &$processed = array())
  60222. {
  60223. if ($expected !== $actual) {
  60224. throw new \PHPUnit\SebastianBergmann\Comparator\ComparisonFailure(
  60225. $expected,
  60226. $actual,
  60227. // we don't need a diff
  60228. '',
  60229. '',
  60230. \false,
  60231. 'all closures are different if not identical'
  60232. );
  60233. }
  60234. }
  60235. }
  60236. <?php
  60237. /*
  60238. * This file is part of the Prophecy.
  60239. * (c) Konstantin Kudryashov <ever.zet@gmail.com>
  60240. * Marcello Duarte <marcello.duarte@gmail.com>
  60241. *
  60242. * For the full copyright and license information, please view the LICENSE
  60243. * file that was distributed with this source code.
  60244. */
  60245. namespace Prophecy;
  60246. use Prophecy\Doubler\CachedDoubler;
  60247. use Prophecy\Doubler\Doubler;
  60248. use Prophecy\Doubler\LazyDouble;
  60249. use Prophecy\Doubler\ClassPatch;
  60250. use Prophecy\Prophecy\ObjectProphecy;
  60251. use Prophecy\Prophecy\RevealerInterface;
  60252. use Prophecy\Prophecy\Revealer;
  60253. use Prophecy\Call\CallCenter;
  60254. use Prophecy\Util\StringUtil;
  60255. use Prophecy\Exception\Prediction\PredictionException;
  60256. use Prophecy\Exception\Prediction\AggregateException;
  60257. /**
  60258. * Prophet creates prophecies.
  60259. *
  60260. * @author Konstantin Kudryashov <ever.zet@gmail.com>
  60261. */
  60262. class Prophet
  60263. {
  60264. private $doubler;
  60265. private $revealer;
  60266. private $util;
  60267. /**
  60268. * @var ObjectProphecy[]
  60269. */
  60270. private $prophecies = array();
  60271. /**
  60272. * Initializes Prophet.
  60273. *
  60274. * @param null|Doubler $doubler
  60275. * @param null|RevealerInterface $revealer
  60276. * @param null|StringUtil $util
  60277. */
  60278. public function __construct(\Prophecy\Doubler\Doubler $doubler = null, \Prophecy\Prophecy\RevealerInterface $revealer = null, \Prophecy\Util\StringUtil $util = null)
  60279. {
  60280. if (null === $doubler) {
  60281. $doubler = new \Prophecy\Doubler\CachedDoubler();
  60282. $doubler->registerClassPatch(new \Prophecy\Doubler\ClassPatch\SplFileInfoPatch());
  60283. $doubler->registerClassPatch(new \Prophecy\Doubler\ClassPatch\TraversablePatch());
  60284. $doubler->registerClassPatch(new \Prophecy\Doubler\ClassPatch\ThrowablePatch());
  60285. $doubler->registerClassPatch(new \Prophecy\Doubler\ClassPatch\DisableConstructorPatch());
  60286. $doubler->registerClassPatch(new \Prophecy\Doubler\ClassPatch\ProphecySubjectPatch());
  60287. $doubler->registerClassPatch(new \Prophecy\Doubler\ClassPatch\ReflectionClassNewInstancePatch());
  60288. $doubler->registerClassPatch(new \Prophecy\Doubler\ClassPatch\HhvmExceptionPatch());
  60289. $doubler->registerClassPatch(new \Prophecy\Doubler\ClassPatch\MagicCallPatch());
  60290. $doubler->registerClassPatch(new \Prophecy\Doubler\ClassPatch\KeywordPatch());
  60291. }
  60292. $this->doubler = $doubler;
  60293. $this->revealer = $revealer ?: new \Prophecy\Prophecy\Revealer();
  60294. $this->util = $util ?: new \Prophecy\Util\StringUtil();
  60295. }
  60296. /**
  60297. * Creates new object prophecy.
  60298. *
  60299. * @param null|string $classOrInterface Class or interface name
  60300. *
  60301. * @return ObjectProphecy
  60302. */
  60303. public function prophesize($classOrInterface = null)
  60304. {
  60305. $this->prophecies[] = $prophecy = new \Prophecy\Prophecy\ObjectProphecy(new \Prophecy\Doubler\LazyDouble($this->doubler), new \Prophecy\Call\CallCenter($this->util), $this->revealer);
  60306. if ($classOrInterface && \class_exists($classOrInterface)) {
  60307. return $prophecy->willExtend($classOrInterface);
  60308. }
  60309. if ($classOrInterface && \interface_exists($classOrInterface)) {
  60310. return $prophecy->willImplement($classOrInterface);
  60311. }
  60312. return $prophecy;
  60313. }
  60314. /**
  60315. * Returns all created object prophecies.
  60316. *
  60317. * @return ObjectProphecy[]
  60318. */
  60319. public function getProphecies()
  60320. {
  60321. return $this->prophecies;
  60322. }
  60323. /**
  60324. * Returns Doubler instance assigned to this Prophet.
  60325. *
  60326. * @return Doubler
  60327. */
  60328. public function getDoubler()
  60329. {
  60330. return $this->doubler;
  60331. }
  60332. /**
  60333. * Checks all predictions defined by prophecies of this Prophet.
  60334. *
  60335. * @throws Exception\Prediction\AggregateException If any prediction fails
  60336. */
  60337. public function checkPredictions()
  60338. {
  60339. $exception = new \Prophecy\Exception\Prediction\AggregateException("Some predictions failed:\n");
  60340. foreach ($this->prophecies as $prophecy) {
  60341. try {
  60342. $prophecy->checkProphecyMethodsPredictions();
  60343. } catch (\Prophecy\Exception\Prediction\PredictionException $e) {
  60344. $exception->append($e);
  60345. }
  60346. }
  60347. if (\count($exception->getExceptions())) {
  60348. throw $exception;
  60349. }
  60350. }
  60351. }
  60352. <?php
  60353. /*
  60354. * This file is part of the Prophecy.
  60355. * (c) Konstantin Kudryashov <ever.zet@gmail.com>
  60356. * Marcello Duarte <marcello.duarte@gmail.com>
  60357. *
  60358. * For the full copyright and license information, please view the LICENSE
  60359. * file that was distributed with this source code.
  60360. */
  60361. namespace Prophecy\Doubler;
  60362. use ReflectionClass;
  60363. /**
  60364. * Name generator.
  60365. * Generates classname for double.
  60366. *
  60367. * @author Konstantin Kudryashov <ever.zet@gmail.com>
  60368. */
  60369. class NameGenerator
  60370. {
  60371. private static $counter = 1;
  60372. /**
  60373. * Generates name.
  60374. *
  60375. * @param ReflectionClass $class
  60376. * @param ReflectionClass[] $interfaces
  60377. *
  60378. * @return string
  60379. */
  60380. public function name(\ReflectionClass $class = null, array $interfaces)
  60381. {
  60382. $parts = array();
  60383. if (null !== $class) {
  60384. $parts[] = $class->getName();
  60385. } else {
  60386. foreach ($interfaces as $interface) {
  60387. $parts[] = $interface->getShortName();
  60388. }
  60389. }
  60390. if (!\count($parts)) {
  60391. $parts[] = 'stdClass';
  60392. }
  60393. return \sprintf('Double\\%s\\P%d', \implode('\\', $parts), self::$counter++);
  60394. }
  60395. }
  60396. <?php
  60397. /*
  60398. * This file is part of the Prophecy.
  60399. * (c) Konstantin Kudryashov <ever.zet@gmail.com>
  60400. * Marcello Duarte <marcello.duarte@gmail.com>
  60401. *
  60402. * For the full copyright and license information, please view the LICENSE
  60403. * file that was distributed with this source code.
  60404. */
  60405. namespace Prophecy\Doubler;
  60406. use Prophecy\Exception\Doubler\DoubleException;
  60407. use Prophecy\Exception\Doubler\ClassNotFoundException;
  60408. use Prophecy\Exception\Doubler\InterfaceNotFoundException;
  60409. use ReflectionClass;
  60410. /**
  60411. * Lazy double.
  60412. * Gives simple interface to describe double before creating it.
  60413. *
  60414. * @author Konstantin Kudryashov <ever.zet@gmail.com>
  60415. */
  60416. class LazyDouble
  60417. {
  60418. private $doubler;
  60419. private $class;
  60420. private $interfaces = array();
  60421. private $arguments = null;
  60422. private $double;
  60423. /**
  60424. * Initializes lazy double.
  60425. *
  60426. * @param Doubler $doubler
  60427. */
  60428. public function __construct(\Prophecy\Doubler\Doubler $doubler)
  60429. {
  60430. $this->doubler = $doubler;
  60431. }
  60432. /**
  60433. * Tells doubler to use specific class as parent one for double.
  60434. *
  60435. * @param string|ReflectionClass $class
  60436. *
  60437. * @throws \Prophecy\Exception\Doubler\ClassNotFoundException
  60438. * @throws \Prophecy\Exception\Doubler\DoubleException
  60439. */
  60440. public function setParentClass($class)
  60441. {
  60442. if (null !== $this->double) {
  60443. throw new \Prophecy\Exception\Doubler\DoubleException('Can not extend class with already instantiated double.');
  60444. }
  60445. if (!$class instanceof \ReflectionClass) {
  60446. if (!\class_exists($class)) {
  60447. throw new \Prophecy\Exception\Doubler\ClassNotFoundException(\sprintf('Class %s not found.', $class), $class);
  60448. }
  60449. $class = new \ReflectionClass($class);
  60450. }
  60451. $this->class = $class;
  60452. }
  60453. /**
  60454. * Tells doubler to implement specific interface with double.
  60455. *
  60456. * @param string|ReflectionClass $interface
  60457. *
  60458. * @throws \Prophecy\Exception\Doubler\InterfaceNotFoundException
  60459. * @throws \Prophecy\Exception\Doubler\DoubleException
  60460. */
  60461. public function addInterface($interface)
  60462. {
  60463. if (null !== $this->double) {
  60464. throw new \Prophecy\Exception\Doubler\DoubleException('Can not implement interface with already instantiated double.');
  60465. }
  60466. if (!$interface instanceof \ReflectionClass) {
  60467. if (!\interface_exists($interface)) {
  60468. throw new \Prophecy\Exception\Doubler\InterfaceNotFoundException(\sprintf('Interface %s not found.', $interface), $interface);
  60469. }
  60470. $interface = new \ReflectionClass($interface);
  60471. }
  60472. $this->interfaces[] = $interface;
  60473. }
  60474. /**
  60475. * Sets constructor arguments.
  60476. *
  60477. * @param array $arguments
  60478. */
  60479. public function setArguments(array $arguments = null)
  60480. {
  60481. $this->arguments = $arguments;
  60482. }
  60483. /**
  60484. * Creates double instance or returns already created one.
  60485. *
  60486. * @return DoubleInterface
  60487. */
  60488. public function getInstance()
  60489. {
  60490. if (null === $this->double) {
  60491. if (null !== $this->arguments) {
  60492. return $this->double = $this->doubler->double($this->class, $this->interfaces, $this->arguments);
  60493. }
  60494. $this->double = $this->doubler->double($this->class, $this->interfaces);
  60495. }
  60496. return $this->double;
  60497. }
  60498. }
  60499. <?php
  60500. /*
  60501. * This file is part of the Prophecy.
  60502. * (c) Konstantin Kudryashov <ever.zet@gmail.com>
  60503. * Marcello Duarte <marcello.duarte@gmail.com>
  60504. *
  60505. * For the full copyright and license information, please view the LICENSE
  60506. * file that was distributed with this source code.
  60507. */
  60508. namespace Prophecy\Doubler;
  60509. use ReflectionClass;
  60510. /**
  60511. * Cached class doubler.
  60512. * Prevents mirroring/creation of the same structure twice.
  60513. *
  60514. * @author Konstantin Kudryashov <ever.zet@gmail.com>
  60515. */
  60516. class CachedDoubler extends \Prophecy\Doubler\Doubler
  60517. {
  60518. private static $classes = array();
  60519. /**
  60520. * {@inheritdoc}
  60521. */
  60522. protected function createDoubleClass(\ReflectionClass $class = null, array $interfaces)
  60523. {
  60524. $classId = $this->generateClassId($class, $interfaces);
  60525. if (isset(self::$classes[$classId])) {
  60526. return self::$classes[$classId];
  60527. }
  60528. return self::$classes[$classId] = parent::createDoubleClass($class, $interfaces);
  60529. }
  60530. /**
  60531. * @param ReflectionClass $class
  60532. * @param ReflectionClass[] $interfaces
  60533. *
  60534. * @return string
  60535. */
  60536. private function generateClassId(\ReflectionClass $class = null, array $interfaces)
  60537. {
  60538. $parts = array();
  60539. if (null !== $class) {
  60540. $parts[] = $class->getName();
  60541. }
  60542. foreach ($interfaces as $interface) {
  60543. $parts[] = $interface->getName();
  60544. }
  60545. foreach ($this->getClassPatches() as $patch) {
  60546. $parts[] = \get_class($patch);
  60547. }
  60548. \sort($parts);
  60549. return \md5(\implode('', $parts));
  60550. }
  60551. public function resetCache()
  60552. {
  60553. self::$classes = array();
  60554. }
  60555. }
  60556. <?php
  60557. /*
  60558. * This file is part of the Prophecy.
  60559. * (c) Konstantin Kudryashov <ever.zet@gmail.com>
  60560. * Marcello Duarte <marcello.duarte@gmail.com>
  60561. *
  60562. * For the full copyright and license information, please view the LICENSE
  60563. * file that was distributed with this source code.
  60564. */
  60565. namespace Prophecy\Doubler;
  60566. /**
  60567. * Core double interface.
  60568. * All doubled classes will implement this one.
  60569. *
  60570. * @author Konstantin Kudryashov <ever.zet@gmail.com>
  60571. */
  60572. interface DoubleInterface
  60573. {
  60574. }
  60575. <?php
  60576. namespace Prophecy\Doubler\Generator;
  60577. /**
  60578. * Tells whether a keyword refers to a class or to a built-in type for the
  60579. * current version of php
  60580. */
  60581. final class TypeHintReference
  60582. {
  60583. public function isBuiltInParamTypeHint($type)
  60584. {
  60585. switch ($type) {
  60586. case 'self':
  60587. case 'array':
  60588. return \true;
  60589. case 'callable':
  60590. return \PHP_VERSION_ID >= 50400;
  60591. case 'bool':
  60592. case 'float':
  60593. case 'int':
  60594. case 'string':
  60595. return \PHP_VERSION_ID >= 70000;
  60596. case 'iterable':
  60597. return \PHP_VERSION_ID >= 70100;
  60598. case 'object':
  60599. return \PHP_VERSION_ID >= 70200;
  60600. default:
  60601. return \false;
  60602. }
  60603. }
  60604. public function isBuiltInReturnTypeHint($type)
  60605. {
  60606. if ($type === 'void') {
  60607. return \PHP_VERSION_ID >= 70100;
  60608. }
  60609. return $this->isBuiltInParamTypeHint($type);
  60610. }
  60611. }
  60612. <?php
  60613. /*
  60614. * This file is part of the Prophecy.
  60615. * (c) Konstantin Kudryashov <ever.zet@gmail.com>
  60616. * Marcello Duarte <marcello.duarte@gmail.com>
  60617. *
  60618. * For the full copyright and license information, please view the LICENSE
  60619. * file that was distributed with this source code.
  60620. */
  60621. namespace Prophecy\Doubler\Generator;
  60622. /**
  60623. * Class code creator.
  60624. * Generates PHP code for specific class node tree.
  60625. *
  60626. * @author Konstantin Kudryashov <ever.zet@gmail.com>
  60627. */
  60628. class ClassCodeGenerator
  60629. {
  60630. /**
  60631. * @var TypeHintReference
  60632. */
  60633. private $typeHintReference;
  60634. public function __construct(\Prophecy\Doubler\Generator\TypeHintReference $typeHintReference = null)
  60635. {
  60636. $this->typeHintReference = $typeHintReference ?: new \Prophecy\Doubler\Generator\TypeHintReference();
  60637. }
  60638. /**
  60639. * Generates PHP code for class node.
  60640. *
  60641. * @param string $classname
  60642. * @param Node\ClassNode $class
  60643. *
  60644. * @return string
  60645. */
  60646. public function generate($classname, \Prophecy\Doubler\Generator\Node\ClassNode $class)
  60647. {
  60648. $parts = \explode('\\', $classname);
  60649. $classname = \array_pop($parts);
  60650. $namespace = \implode('\\', $parts);
  60651. $code = \sprintf("class %s extends \\%s implements %s {\n", $classname, $class->getParentClass(), \implode(', ', \array_map(function ($interface) {
  60652. return '\\' . $interface;
  60653. }, $class->getInterfaces())));
  60654. foreach ($class->getProperties() as $name => $visibility) {
  60655. $code .= \sprintf("%s \$%s;\n", $visibility, $name);
  60656. }
  60657. $code .= "\n";
  60658. foreach ($class->getMethods() as $method) {
  60659. $code .= $this->generateMethod($method) . "\n";
  60660. }
  60661. $code .= "\n}";
  60662. return \sprintf("namespace %s {\n%s\n}", $namespace, $code);
  60663. }
  60664. private function generateMethod(\Prophecy\Doubler\Generator\Node\MethodNode $method)
  60665. {
  60666. $php = \sprintf("%s %s function %s%s(%s)%s {\n", $method->getVisibility(), $method->isStatic() ? 'static' : '', $method->returnsReference() ? '&' : '', $method->getName(), \implode(', ', $this->generateArguments($method->getArguments())), $this->getReturnType($method));
  60667. $php .= $method->getCode() . "\n";
  60668. return $php . '}';
  60669. }
  60670. /**
  60671. * @return string
  60672. */
  60673. private function getReturnType(\Prophecy\Doubler\Generator\Node\MethodNode $method)
  60674. {
  60675. if (\version_compare(\PHP_VERSION, '7.1', '>=')) {
  60676. if ($method->hasReturnType()) {
  60677. return $method->hasNullableReturnType() ? \sprintf(': ?%s', $method->getReturnType()) : \sprintf(': %s', $method->getReturnType());
  60678. }
  60679. }
  60680. if (\version_compare(\PHP_VERSION, '7.0', '>=')) {
  60681. return $method->hasReturnType() && $method->getReturnType() !== 'void' ? \sprintf(': %s', $method->getReturnType()) : '';
  60682. }
  60683. return '';
  60684. }
  60685. private function generateArguments(array $arguments)
  60686. {
  60687. $typeHintReference = $this->typeHintReference;
  60688. return \array_map(function (\Prophecy\Doubler\Generator\Node\ArgumentNode $argument) use($typeHintReference) {
  60689. $php = '';
  60690. if (\version_compare(\PHP_VERSION, '7.1', '>=')) {
  60691. $php .= $argument->isNullable() ? '?' : '';
  60692. }
  60693. if ($hint = $argument->getTypeHint()) {
  60694. $php .= $typeHintReference->isBuiltInParamTypeHint($hint) ? $hint : '\\' . $hint;
  60695. }
  60696. $php .= ' ' . ($argument->isPassedByReference() ? '&' : '');
  60697. $php .= $argument->isVariadic() ? '...' : '';
  60698. $php .= '$' . $argument->getName();
  60699. if ($argument->isOptional() && !$argument->isVariadic()) {
  60700. $php .= ' = ' . \var_export($argument->getDefault(), \true);
  60701. }
  60702. return $php;
  60703. }, $arguments);
  60704. }
  60705. }
  60706. <?php
  60707. /*
  60708. * This file is part of the Prophecy.
  60709. * (c) Konstantin Kudryashov <ever.zet@gmail.com>
  60710. * Marcello Duarte <marcello.duarte@gmail.com>
  60711. *
  60712. * For the full copyright and license information, please view the LICENSE
  60713. * file that was distributed with this source code.
  60714. */
  60715. namespace Prophecy\Doubler\Generator;
  60716. use Prophecy\Exception\Doubler\ClassCreatorException;
  60717. /**
  60718. * Class creator.
  60719. * Creates specific class in current environment.
  60720. *
  60721. * @author Konstantin Kudryashov <ever.zet@gmail.com>
  60722. */
  60723. class ClassCreator
  60724. {
  60725. private $generator;
  60726. /**
  60727. * Initializes creator.
  60728. *
  60729. * @param ClassCodeGenerator $generator
  60730. */
  60731. public function __construct(\Prophecy\Doubler\Generator\ClassCodeGenerator $generator = null)
  60732. {
  60733. $this->generator = $generator ?: new \Prophecy\Doubler\Generator\ClassCodeGenerator();
  60734. }
  60735. /**
  60736. * Creates class.
  60737. *
  60738. * @param string $classname
  60739. * @param Node\ClassNode $class
  60740. *
  60741. * @return mixed
  60742. *
  60743. * @throws \Prophecy\Exception\Doubler\ClassCreatorException
  60744. */
  60745. public function create($classname, \Prophecy\Doubler\Generator\Node\ClassNode $class)
  60746. {
  60747. $code = $this->generator->generate($classname, $class);
  60748. $return = eval($code);
  60749. if (!\class_exists($classname, \false)) {
  60750. if (\count($class->getInterfaces())) {
  60751. throw new \Prophecy\Exception\Doubler\ClassCreatorException(\sprintf('Could not double `%s` and implement interfaces: [%s].', $class->getParentClass(), \implode(', ', $class->getInterfaces())), $class);
  60752. }
  60753. throw new \Prophecy\Exception\Doubler\ClassCreatorException(\sprintf('Could not double `%s`.', $class->getParentClass()), $class);
  60754. }
  60755. return $return;
  60756. }
  60757. }
  60758. <?php
  60759. /*
  60760. * This file is part of the Prophecy.
  60761. * (c) Konstantin Kudryashov <ever.zet@gmail.com>
  60762. * Marcello Duarte <marcello.duarte@gmail.com>
  60763. *
  60764. * For the full copyright and license information, please view the LICENSE
  60765. * file that was distributed with this source code.
  60766. */
  60767. namespace Prophecy\Doubler\Generator\Node;
  60768. use Prophecy\Exception\Doubler\MethodNotExtendableException;
  60769. use Prophecy\Exception\InvalidArgumentException;
  60770. /**
  60771. * Class node.
  60772. *
  60773. * @author Konstantin Kudryashov <ever.zet@gmail.com>
  60774. */
  60775. class ClassNode
  60776. {
  60777. private $parentClass = 'stdClass';
  60778. private $interfaces = array();
  60779. private $properties = array();
  60780. private $unextendableMethods = array();
  60781. /**
  60782. * @var MethodNode[]
  60783. */
  60784. private $methods = array();
  60785. public function getParentClass()
  60786. {
  60787. return $this->parentClass;
  60788. }
  60789. /**
  60790. * @param string $class
  60791. */
  60792. public function setParentClass($class)
  60793. {
  60794. $this->parentClass = $class ?: 'stdClass';
  60795. }
  60796. /**
  60797. * @return string[]
  60798. */
  60799. public function getInterfaces()
  60800. {
  60801. return $this->interfaces;
  60802. }
  60803. /**
  60804. * @param string $interface
  60805. */
  60806. public function addInterface($interface)
  60807. {
  60808. if ($this->hasInterface($interface)) {
  60809. return;
  60810. }
  60811. \array_unshift($this->interfaces, $interface);
  60812. }
  60813. /**
  60814. * @param string $interface
  60815. *
  60816. * @return bool
  60817. */
  60818. public function hasInterface($interface)
  60819. {
  60820. return \in_array($interface, $this->interfaces);
  60821. }
  60822. public function getProperties()
  60823. {
  60824. return $this->properties;
  60825. }
  60826. public function addProperty($name, $visibility = 'public')
  60827. {
  60828. $visibility = \strtolower($visibility);
  60829. if (!\in_array($visibility, array('public', 'private', 'protected'))) {
  60830. throw new \Prophecy\Exception\InvalidArgumentException(\sprintf('`%s` property visibility is not supported.', $visibility));
  60831. }
  60832. $this->properties[$name] = $visibility;
  60833. }
  60834. /**
  60835. * @return MethodNode[]
  60836. */
  60837. public function getMethods()
  60838. {
  60839. return $this->methods;
  60840. }
  60841. public function addMethod(\Prophecy\Doubler\Generator\Node\MethodNode $method, $force = \false)
  60842. {
  60843. if (!$this->isExtendable($method->getName())) {
  60844. $message = \sprintf('Method `%s` is not extendable, so can not be added.', $method->getName());
  60845. throw new \Prophecy\Exception\Doubler\MethodNotExtendableException($message, $this->getParentClass(), $method->getName());
  60846. }
  60847. if ($force || !isset($this->methods[$method->getName()])) {
  60848. $this->methods[$method->getName()] = $method;
  60849. }
  60850. }
  60851. public function removeMethod($name)
  60852. {
  60853. unset($this->methods[$name]);
  60854. }
  60855. /**
  60856. * @param string $name
  60857. *
  60858. * @return MethodNode|null
  60859. */
  60860. public function getMethod($name)
  60861. {
  60862. return $this->hasMethod($name) ? $this->methods[$name] : null;
  60863. }
  60864. /**
  60865. * @param string $name
  60866. *
  60867. * @return bool
  60868. */
  60869. public function hasMethod($name)
  60870. {
  60871. return isset($this->methods[$name]);
  60872. }
  60873. /**
  60874. * @return string[]
  60875. */
  60876. public function getUnextendableMethods()
  60877. {
  60878. return $this->unextendableMethods;
  60879. }
  60880. /**
  60881. * @param string $unextendableMethod
  60882. */
  60883. public function addUnextendableMethod($unextendableMethod)
  60884. {
  60885. if (!$this->isExtendable($unextendableMethod)) {
  60886. return;
  60887. }
  60888. $this->unextendableMethods[] = $unextendableMethod;
  60889. }
  60890. /**
  60891. * @param string $method
  60892. * @return bool
  60893. */
  60894. public function isExtendable($method)
  60895. {
  60896. return !\in_array($method, $this->unextendableMethods);
  60897. }
  60898. }
  60899. <?php
  60900. /*
  60901. * This file is part of the Prophecy.
  60902. * (c) Konstantin Kudryashov <ever.zet@gmail.com>
  60903. * Marcello Duarte <marcello.duarte@gmail.com>
  60904. *
  60905. * For the full copyright and license information, please view the LICENSE
  60906. * file that was distributed with this source code.
  60907. */
  60908. namespace Prophecy\Doubler\Generator\Node;
  60909. use Prophecy\Doubler\Generator\TypeHintReference;
  60910. use Prophecy\Exception\InvalidArgumentException;
  60911. /**
  60912. * Method node.
  60913. *
  60914. * @author Konstantin Kudryashov <ever.zet@gmail.com>
  60915. */
  60916. class MethodNode
  60917. {
  60918. private $name;
  60919. private $code;
  60920. private $visibility = 'public';
  60921. private $static = \false;
  60922. private $returnsReference = \false;
  60923. private $returnType;
  60924. private $nullableReturnType = \false;
  60925. /**
  60926. * @var ArgumentNode[]
  60927. */
  60928. private $arguments = array();
  60929. /**
  60930. * @var TypeHintReference
  60931. */
  60932. private $typeHintReference;
  60933. /**
  60934. * @param string $name
  60935. * @param string $code
  60936. */
  60937. public function __construct($name, $code = null, \Prophecy\Doubler\Generator\TypeHintReference $typeHintReference = null)
  60938. {
  60939. $this->name = $name;
  60940. $this->code = $code;
  60941. $this->typeHintReference = $typeHintReference ?: new \Prophecy\Doubler\Generator\TypeHintReference();
  60942. }
  60943. public function getVisibility()
  60944. {
  60945. return $this->visibility;
  60946. }
  60947. /**
  60948. * @param string $visibility
  60949. */
  60950. public function setVisibility($visibility)
  60951. {
  60952. $visibility = \strtolower($visibility);
  60953. if (!\in_array($visibility, array('public', 'private', 'protected'))) {
  60954. throw new \Prophecy\Exception\InvalidArgumentException(\sprintf('`%s` method visibility is not supported.', $visibility));
  60955. }
  60956. $this->visibility = $visibility;
  60957. }
  60958. public function isStatic()
  60959. {
  60960. return $this->static;
  60961. }
  60962. public function setStatic($static = \true)
  60963. {
  60964. $this->static = (bool) $static;
  60965. }
  60966. public function returnsReference()
  60967. {
  60968. return $this->returnsReference;
  60969. }
  60970. public function setReturnsReference()
  60971. {
  60972. $this->returnsReference = \true;
  60973. }
  60974. public function getName()
  60975. {
  60976. return $this->name;
  60977. }
  60978. public function addArgument(\Prophecy\Doubler\Generator\Node\ArgumentNode $argument)
  60979. {
  60980. $this->arguments[] = $argument;
  60981. }
  60982. /**
  60983. * @return ArgumentNode[]
  60984. */
  60985. public function getArguments()
  60986. {
  60987. return $this->arguments;
  60988. }
  60989. public function hasReturnType()
  60990. {
  60991. return null !== $this->returnType;
  60992. }
  60993. /**
  60994. * @param string $type
  60995. */
  60996. public function setReturnType($type = null)
  60997. {
  60998. if ($type === '' || $type === null) {
  60999. $this->returnType = null;
  61000. return;
  61001. }
  61002. $typeMap = array('double' => 'float', 'real' => 'float', 'boolean' => 'bool', 'integer' => 'int');
  61003. if (isset($typeMap[$type])) {
  61004. $type = $typeMap[$type];
  61005. }
  61006. $this->returnType = $this->typeHintReference->isBuiltInReturnTypeHint($type) ? $type : '\\' . \ltrim($type, '\\');
  61007. }
  61008. public function getReturnType()
  61009. {
  61010. return $this->returnType;
  61011. }
  61012. /**
  61013. * @param bool $bool
  61014. */
  61015. public function setNullableReturnType($bool = \true)
  61016. {
  61017. $this->nullableReturnType = (bool) $bool;
  61018. }
  61019. /**
  61020. * @return bool
  61021. */
  61022. public function hasNullableReturnType()
  61023. {
  61024. return $this->nullableReturnType;
  61025. }
  61026. /**
  61027. * @param string $code
  61028. */
  61029. public function setCode($code)
  61030. {
  61031. $this->code = $code;
  61032. }
  61033. public function getCode()
  61034. {
  61035. if ($this->returnsReference) {
  61036. return "throw new \\Prophecy\\Exception\\Doubler\\ReturnByReferenceException('Returning by reference not supported', get_class(\$this), '{$this->name}');";
  61037. }
  61038. return (string) $this->code;
  61039. }
  61040. public function useParentCode()
  61041. {
  61042. $this->code = \sprintf('return parent::%s(%s);', $this->getName(), \implode(', ', \array_map(array($this, 'generateArgument'), $this->arguments)));
  61043. }
  61044. private function generateArgument(\Prophecy\Doubler\Generator\Node\ArgumentNode $arg)
  61045. {
  61046. $argument = '$' . $arg->getName();
  61047. if ($arg->isVariadic()) {
  61048. $argument = '...' . $argument;
  61049. }
  61050. return $argument;
  61051. }
  61052. }
  61053. <?php
  61054. /*
  61055. * This file is part of the Prophecy.
  61056. * (c) Konstantin Kudryashov <ever.zet@gmail.com>
  61057. * Marcello Duarte <marcello.duarte@gmail.com>
  61058. *
  61059. * For the full copyright and license information, please view the LICENSE
  61060. * file that was distributed with this source code.
  61061. */
  61062. namespace Prophecy\Doubler\Generator\Node;
  61063. /**
  61064. * Argument node.
  61065. *
  61066. * @author Konstantin Kudryashov <ever.zet@gmail.com>
  61067. */
  61068. class ArgumentNode
  61069. {
  61070. private $name;
  61071. private $typeHint;
  61072. private $default;
  61073. private $optional = \false;
  61074. private $byReference = \false;
  61075. private $isVariadic = \false;
  61076. private $isNullable = \false;
  61077. /**
  61078. * @param string $name
  61079. */
  61080. public function __construct($name)
  61081. {
  61082. $this->name = $name;
  61083. }
  61084. public function getName()
  61085. {
  61086. return $this->name;
  61087. }
  61088. public function getTypeHint()
  61089. {
  61090. return $this->typeHint;
  61091. }
  61092. public function setTypeHint($typeHint = null)
  61093. {
  61094. $this->typeHint = $typeHint;
  61095. }
  61096. public function hasDefault()
  61097. {
  61098. return $this->isOptional() && !$this->isVariadic();
  61099. }
  61100. public function getDefault()
  61101. {
  61102. return $this->default;
  61103. }
  61104. public function setDefault($default = null)
  61105. {
  61106. $this->optional = \true;
  61107. $this->default = $default;
  61108. }
  61109. public function isOptional()
  61110. {
  61111. return $this->optional;
  61112. }
  61113. public function setAsPassedByReference($byReference = \true)
  61114. {
  61115. $this->byReference = $byReference;
  61116. }
  61117. public function isPassedByReference()
  61118. {
  61119. return $this->byReference;
  61120. }
  61121. public function setAsVariadic($isVariadic = \true)
  61122. {
  61123. $this->isVariadic = $isVariadic;
  61124. }
  61125. public function isVariadic()
  61126. {
  61127. return $this->isVariadic;
  61128. }
  61129. public function isNullable()
  61130. {
  61131. return $this->isNullable;
  61132. }
  61133. public function setAsNullable($isNullable = \true)
  61134. {
  61135. $this->isNullable = $isNullable;
  61136. }
  61137. }
  61138. <?php
  61139. /*
  61140. * This file is part of the Prophecy.
  61141. * (c) Konstantin Kudryashov <ever.zet@gmail.com>
  61142. * Marcello Duarte <marcello.duarte@gmail.com>
  61143. *
  61144. * For the full copyright and license information, please view the LICENSE
  61145. * file that was distributed with this source code.
  61146. */
  61147. namespace Prophecy\Doubler\Generator;
  61148. use Prophecy\Exception\InvalidArgumentException;
  61149. use Prophecy\Exception\Doubler\ClassMirrorException;
  61150. use ReflectionClass;
  61151. use ReflectionMethod;
  61152. use ReflectionParameter;
  61153. /**
  61154. * Class mirror.
  61155. * Core doubler class. Mirrors specific class and/or interfaces into class node tree.
  61156. *
  61157. * @author Konstantin Kudryashov <ever.zet@gmail.com>
  61158. */
  61159. class ClassMirror
  61160. {
  61161. private static $reflectableMethods = array('__construct', '__destruct', '__sleep', '__wakeup', '__toString', '__call', '__invoke');
  61162. /**
  61163. * Reflects provided arguments into class node.
  61164. *
  61165. * @param ReflectionClass $class
  61166. * @param ReflectionClass[] $interfaces
  61167. *
  61168. * @return Node\ClassNode
  61169. *
  61170. * @throws \Prophecy\Exception\InvalidArgumentException
  61171. */
  61172. public function reflect(\ReflectionClass $class = null, array $interfaces)
  61173. {
  61174. $node = new \Prophecy\Doubler\Generator\Node\ClassNode();
  61175. if (null !== $class) {
  61176. if (\true === $class->isInterface()) {
  61177. throw new \Prophecy\Exception\InvalidArgumentException(\sprintf("Could not reflect %s as a class, because it\n" . "is interface - use the second argument instead.", $class->getName()));
  61178. }
  61179. $this->reflectClassToNode($class, $node);
  61180. }
  61181. foreach ($interfaces as $interface) {
  61182. if (!$interface instanceof \ReflectionClass) {
  61183. throw new \Prophecy\Exception\InvalidArgumentException(\sprintf("[ReflectionClass \$interface1 [, ReflectionClass \$interface2]] array expected as\n" . "a second argument to `ClassMirror::reflect(...)`, but got %s.", \is_object($interface) ? \get_class($interface) . ' class' : \gettype($interface)));
  61184. }
  61185. if (\false === $interface->isInterface()) {
  61186. throw new \Prophecy\Exception\InvalidArgumentException(\sprintf("Could not reflect %s as an interface, because it\n" . "is class - use the first argument instead.", $interface->getName()));
  61187. }
  61188. $this->reflectInterfaceToNode($interface, $node);
  61189. }
  61190. $node->addInterface('Prophecy\\Doubler\\Generator\\ReflectionInterface');
  61191. return $node;
  61192. }
  61193. private function reflectClassToNode(\ReflectionClass $class, \Prophecy\Doubler\Generator\Node\ClassNode $node)
  61194. {
  61195. if (\true === $class->isFinal()) {
  61196. throw new \Prophecy\Exception\Doubler\ClassMirrorException(\sprintf('Could not reflect class %s as it is marked final.', $class->getName()), $class);
  61197. }
  61198. $node->setParentClass($class->getName());
  61199. foreach ($class->getMethods(\ReflectionMethod::IS_ABSTRACT) as $method) {
  61200. if (\false === $method->isProtected()) {
  61201. continue;
  61202. }
  61203. $this->reflectMethodToNode($method, $node);
  61204. }
  61205. foreach ($class->getMethods(\ReflectionMethod::IS_PUBLIC) as $method) {
  61206. if (0 === \strpos($method->getName(), '_') && !\in_array($method->getName(), self::$reflectableMethods)) {
  61207. continue;
  61208. }
  61209. if (\true === $method->isFinal()) {
  61210. $node->addUnextendableMethod($method->getName());
  61211. continue;
  61212. }
  61213. $this->reflectMethodToNode($method, $node);
  61214. }
  61215. }
  61216. private function reflectInterfaceToNode(\ReflectionClass $interface, \Prophecy\Doubler\Generator\Node\ClassNode $node)
  61217. {
  61218. $node->addInterface($interface->getName());
  61219. foreach ($interface->getMethods() as $method) {
  61220. $this->reflectMethodToNode($method, $node);
  61221. }
  61222. }
  61223. private function reflectMethodToNode(\ReflectionMethod $method, \Prophecy\Doubler\Generator\Node\ClassNode $classNode)
  61224. {
  61225. $node = new \Prophecy\Doubler\Generator\Node\MethodNode($method->getName());
  61226. if (\true === $method->isProtected()) {
  61227. $node->setVisibility('protected');
  61228. }
  61229. if (\true === $method->isStatic()) {
  61230. $node->setStatic();
  61231. }
  61232. if (\true === $method->returnsReference()) {
  61233. $node->setReturnsReference();
  61234. }
  61235. if (\version_compare(\PHP_VERSION, '7.0', '>=') && $method->hasReturnType()) {
  61236. $returnType = \PHP_VERSION_ID >= 70100 ? $method->getReturnType()->getName() : (string) $method->getReturnType();
  61237. $returnTypeLower = \strtolower($returnType);
  61238. if ('self' === $returnTypeLower) {
  61239. $returnType = $method->getDeclaringClass()->getName();
  61240. }
  61241. if ('parent' === $returnTypeLower) {
  61242. $returnType = $method->getDeclaringClass()->getParentClass()->getName();
  61243. }
  61244. $node->setReturnType($returnType);
  61245. if (\version_compare(\PHP_VERSION, '7.1', '>=') && $method->getReturnType()->allowsNull()) {
  61246. $node->setNullableReturnType(\true);
  61247. }
  61248. }
  61249. if (\is_array($params = $method->getParameters()) && \count($params)) {
  61250. foreach ($params as $param) {
  61251. $this->reflectArgumentToNode($param, $node);
  61252. }
  61253. }
  61254. $classNode->addMethod($node);
  61255. }
  61256. private function reflectArgumentToNode(\ReflectionParameter $parameter, \Prophecy\Doubler\Generator\Node\MethodNode $methodNode)
  61257. {
  61258. $name = $parameter->getName() == '...' ? '__dot_dot_dot__' : $parameter->getName();
  61259. $node = new \Prophecy\Doubler\Generator\Node\ArgumentNode($name);
  61260. $node->setTypeHint($this->getTypeHint($parameter));
  61261. if ($this->isVariadic($parameter)) {
  61262. $node->setAsVariadic();
  61263. }
  61264. if ($this->hasDefaultValue($parameter)) {
  61265. $node->setDefault($this->getDefaultValue($parameter));
  61266. }
  61267. if ($parameter->isPassedByReference()) {
  61268. $node->setAsPassedByReference();
  61269. }
  61270. $node->setAsNullable($this->isNullable($parameter));
  61271. $methodNode->addArgument($node);
  61272. }
  61273. private function hasDefaultValue(\ReflectionParameter $parameter)
  61274. {
  61275. if ($this->isVariadic($parameter)) {
  61276. return \false;
  61277. }
  61278. if ($parameter->isDefaultValueAvailable()) {
  61279. return \true;
  61280. }
  61281. return $parameter->isOptional() || $this->isNullable($parameter);
  61282. }
  61283. private function getDefaultValue(\ReflectionParameter $parameter)
  61284. {
  61285. if (!$parameter->isDefaultValueAvailable()) {
  61286. return null;
  61287. }
  61288. return $parameter->getDefaultValue();
  61289. }
  61290. private function getTypeHint(\ReflectionParameter $parameter)
  61291. {
  61292. if (null !== ($className = $this->getParameterClassName($parameter))) {
  61293. return $className;
  61294. }
  61295. if (\true === $parameter->isArray()) {
  61296. return 'array';
  61297. }
  61298. if (\version_compare(\PHP_VERSION, '5.4', '>=') && \true === $parameter->isCallable()) {
  61299. return 'callable';
  61300. }
  61301. if (\version_compare(\PHP_VERSION, '7.0', '>=') && \true === $parameter->hasType()) {
  61302. return \PHP_VERSION_ID >= 70100 ? $parameter->getType()->getName() : (string) $parameter->getType();
  61303. }
  61304. return null;
  61305. }
  61306. private function isVariadic(\ReflectionParameter $parameter)
  61307. {
  61308. return \PHP_VERSION_ID >= 50600 && $parameter->isVariadic();
  61309. }
  61310. private function isNullable(\ReflectionParameter $parameter)
  61311. {
  61312. return $parameter->allowsNull() && null !== $this->getTypeHint($parameter);
  61313. }
  61314. private function getParameterClassName(\ReflectionParameter $parameter)
  61315. {
  61316. try {
  61317. return $parameter->getClass() ? $parameter->getClass()->getName() : null;
  61318. } catch (\ReflectionException $e) {
  61319. \preg_match('/\\[\\s\\<\\w+?>\\s([\\w,\\\\]+)/s', $parameter, $matches);
  61320. return isset($matches[1]) ? $matches[1] : null;
  61321. }
  61322. }
  61323. }
  61324. <?php
  61325. /*
  61326. * This file is part of the Prophecy.
  61327. * (c) Konstantin Kudryashov <ever.zet@gmail.com>
  61328. * Marcello Duarte <marcello.duarte@gmail.com>
  61329. *
  61330. * For the full copyright and license information, please view the LICENSE
  61331. * file that was distributed with this source code.
  61332. */
  61333. namespace Prophecy\Doubler\Generator;
  61334. /**
  61335. * Reflection interface.
  61336. * All reflected classes implement this interface.
  61337. *
  61338. * @author Konstantin Kudryashov <ever.zet@gmail.com>
  61339. */
  61340. interface ReflectionInterface
  61341. {
  61342. }
  61343. <?php
  61344. /*
  61345. * This file is part of the Prophecy.
  61346. * (c) Konstantin Kudryashov <ever.zet@gmail.com>
  61347. * Marcello Duarte <marcello.duarte@gmail.com>
  61348. *
  61349. * For the full copyright and license information, please view the LICENSE
  61350. * file that was distributed with this source code.
  61351. */
  61352. namespace Prophecy\Doubler;
  61353. use PHPUnit\Doctrine\Instantiator\Instantiator;
  61354. use Prophecy\Doubler\ClassPatch\ClassPatchInterface;
  61355. use Prophecy\Doubler\Generator\ClassMirror;
  61356. use Prophecy\Doubler\Generator\ClassCreator;
  61357. use Prophecy\Exception\InvalidArgumentException;
  61358. use ReflectionClass;
  61359. /**
  61360. * Cached class doubler.
  61361. * Prevents mirroring/creation of the same structure twice.
  61362. *
  61363. * @author Konstantin Kudryashov <ever.zet@gmail.com>
  61364. */
  61365. class Doubler
  61366. {
  61367. private $mirror;
  61368. private $creator;
  61369. private $namer;
  61370. /**
  61371. * @var ClassPatchInterface[]
  61372. */
  61373. private $patches = array();
  61374. /**
  61375. * @var \Doctrine\Instantiator\Instantiator
  61376. */
  61377. private $instantiator;
  61378. /**
  61379. * Initializes doubler.
  61380. *
  61381. * @param ClassMirror $mirror
  61382. * @param ClassCreator $creator
  61383. * @param NameGenerator $namer
  61384. */
  61385. public function __construct(\Prophecy\Doubler\Generator\ClassMirror $mirror = null, \Prophecy\Doubler\Generator\ClassCreator $creator = null, \Prophecy\Doubler\NameGenerator $namer = null)
  61386. {
  61387. $this->mirror = $mirror ?: new \Prophecy\Doubler\Generator\ClassMirror();
  61388. $this->creator = $creator ?: new \Prophecy\Doubler\Generator\ClassCreator();
  61389. $this->namer = $namer ?: new \Prophecy\Doubler\NameGenerator();
  61390. }
  61391. /**
  61392. * Returns list of registered class patches.
  61393. *
  61394. * @return ClassPatchInterface[]
  61395. */
  61396. public function getClassPatches()
  61397. {
  61398. return $this->patches;
  61399. }
  61400. /**
  61401. * Registers new class patch.
  61402. *
  61403. * @param ClassPatchInterface $patch
  61404. */
  61405. public function registerClassPatch(\Prophecy\Doubler\ClassPatch\ClassPatchInterface $patch)
  61406. {
  61407. $this->patches[] = $patch;
  61408. @\usort($this->patches, function (\Prophecy\Doubler\ClassPatch\ClassPatchInterface $patch1, \Prophecy\Doubler\ClassPatch\ClassPatchInterface $patch2) {
  61409. return $patch2->getPriority() - $patch1->getPriority();
  61410. });
  61411. }
  61412. /**
  61413. * Creates double from specific class or/and list of interfaces.
  61414. *
  61415. * @param ReflectionClass $class
  61416. * @param ReflectionClass[] $interfaces Array of ReflectionClass instances
  61417. * @param array $args Constructor arguments
  61418. *
  61419. * @return DoubleInterface
  61420. *
  61421. * @throws \Prophecy\Exception\InvalidArgumentException
  61422. */
  61423. public function double(\ReflectionClass $class = null, array $interfaces, array $args = null)
  61424. {
  61425. foreach ($interfaces as $interface) {
  61426. if (!$interface instanceof \ReflectionClass) {
  61427. throw new \Prophecy\Exception\InvalidArgumentException(\sprintf("[ReflectionClass \$interface1 [, ReflectionClass \$interface2]] array expected as\n" . "a second argument to `Doubler::double(...)`, but got %s.", \is_object($interface) ? \get_class($interface) . ' class' : \gettype($interface)));
  61428. }
  61429. }
  61430. $classname = $this->createDoubleClass($class, $interfaces);
  61431. $reflection = new \ReflectionClass($classname);
  61432. if (null !== $args) {
  61433. return $reflection->newInstanceArgs($args);
  61434. }
  61435. if (null === ($constructor = $reflection->getConstructor()) || $constructor->isPublic() && !$constructor->isFinal()) {
  61436. return $reflection->newInstance();
  61437. }
  61438. if (!$this->instantiator) {
  61439. $this->instantiator = new \PHPUnit\Doctrine\Instantiator\Instantiator();
  61440. }
  61441. return $this->instantiator->instantiate($classname);
  61442. }
  61443. /**
  61444. * Creates double class and returns its FQN.
  61445. *
  61446. * @param ReflectionClass $class
  61447. * @param ReflectionClass[] $interfaces
  61448. *
  61449. * @return string
  61450. */
  61451. protected function createDoubleClass(\ReflectionClass $class = null, array $interfaces)
  61452. {
  61453. $name = $this->namer->name($class, $interfaces);
  61454. $node = $this->mirror->reflect($class, $interfaces);
  61455. foreach ($this->patches as $patch) {
  61456. if ($patch->supports($node)) {
  61457. $patch->apply($node);
  61458. }
  61459. }
  61460. $this->creator->create($name, $node);
  61461. return $name;
  61462. }
  61463. }
  61464. <?php
  61465. namespace Prophecy\Doubler\ClassPatch;
  61466. use Prophecy\Doubler\Generator\Node\ClassNode;
  61467. use Prophecy\Exception\Doubler\ClassCreatorException;
  61468. class ThrowablePatch implements \Prophecy\Doubler\ClassPatch\ClassPatchInterface
  61469. {
  61470. /**
  61471. * Checks if patch supports specific class node.
  61472. *
  61473. * @param ClassNode $node
  61474. * @return bool
  61475. */
  61476. public function supports(\Prophecy\Doubler\Generator\Node\ClassNode $node)
  61477. {
  61478. return $this->implementsAThrowableInterface($node) && $this->doesNotExtendAThrowableClass($node);
  61479. }
  61480. /**
  61481. * @param ClassNode $node
  61482. * @return bool
  61483. */
  61484. private function implementsAThrowableInterface(\Prophecy\Doubler\Generator\Node\ClassNode $node)
  61485. {
  61486. foreach ($node->getInterfaces() as $type) {
  61487. if (\is_a($type, 'Throwable', \true)) {
  61488. return \true;
  61489. }
  61490. }
  61491. return \false;
  61492. }
  61493. /**
  61494. * @param ClassNode $node
  61495. * @return bool
  61496. */
  61497. private function doesNotExtendAThrowableClass(\Prophecy\Doubler\Generator\Node\ClassNode $node)
  61498. {
  61499. return !\is_a($node->getParentClass(), 'Throwable', \true);
  61500. }
  61501. /**
  61502. * Applies patch to the specific class node.
  61503. *
  61504. * @param ClassNode $node
  61505. *
  61506. * @return void
  61507. */
  61508. public function apply(\Prophecy\Doubler\Generator\Node\ClassNode $node)
  61509. {
  61510. $this->checkItCanBeDoubled($node);
  61511. $this->setParentClassToException($node);
  61512. }
  61513. private function checkItCanBeDoubled(\Prophecy\Doubler\Generator\Node\ClassNode $node)
  61514. {
  61515. $className = $node->getParentClass();
  61516. if ($className !== 'stdClass') {
  61517. throw new \Prophecy\Exception\Doubler\ClassCreatorException(\sprintf('Cannot double concrete class %s as well as implement Traversable', $className), $node);
  61518. }
  61519. }
  61520. private function setParentClassToException(\Prophecy\Doubler\Generator\Node\ClassNode $node)
  61521. {
  61522. $node->setParentClass('Exception');
  61523. $node->removeMethod('getMessage');
  61524. $node->removeMethod('getCode');
  61525. $node->removeMethod('getFile');
  61526. $node->removeMethod('getLine');
  61527. $node->removeMethod('getTrace');
  61528. $node->removeMethod('getPrevious');
  61529. $node->removeMethod('getNext');
  61530. $node->removeMethod('getTraceAsString');
  61531. }
  61532. /**
  61533. * Returns patch priority, which determines when patch will be applied.
  61534. *
  61535. * @return int Priority number (higher - earlier)
  61536. */
  61537. public function getPriority()
  61538. {
  61539. return 100;
  61540. }
  61541. }
  61542. <?php
  61543. /*
  61544. * This file is part of the Prophecy.
  61545. * (c) Konstantin Kudryashov <ever.zet@gmail.com>
  61546. * Marcello Duarte <marcello.duarte@gmail.com>
  61547. *
  61548. * For the full copyright and license information, please view the LICENSE
  61549. * file that was distributed with this source code.
  61550. */
  61551. namespace Prophecy\Doubler\ClassPatch;
  61552. use Prophecy\Doubler\Generator\Node\ClassNode;
  61553. use Prophecy\Doubler\Generator\Node\MethodNode;
  61554. /**
  61555. * Disable constructor.
  61556. * Makes all constructor arguments optional.
  61557. *
  61558. * @author Konstantin Kudryashov <ever.zet@gmail.com>
  61559. */
  61560. class DisableConstructorPatch implements \Prophecy\Doubler\ClassPatch\ClassPatchInterface
  61561. {
  61562. /**
  61563. * Checks if class has `__construct` method.
  61564. *
  61565. * @param ClassNode $node
  61566. *
  61567. * @return bool
  61568. */
  61569. public function supports(\Prophecy\Doubler\Generator\Node\ClassNode $node)
  61570. {
  61571. return \true;
  61572. }
  61573. /**
  61574. * Makes all class constructor arguments optional.
  61575. *
  61576. * @param ClassNode $node
  61577. */
  61578. public function apply(\Prophecy\Doubler\Generator\Node\ClassNode $node)
  61579. {
  61580. if (!$node->isExtendable('__construct')) {
  61581. return;
  61582. }
  61583. if (!$node->hasMethod('__construct')) {
  61584. $node->addMethod(new \Prophecy\Doubler\Generator\Node\MethodNode('__construct', ''));
  61585. return;
  61586. }
  61587. $constructor = $node->getMethod('__construct');
  61588. foreach ($constructor->getArguments() as $argument) {
  61589. $argument->setDefault(null);
  61590. }
  61591. $constructor->setCode(<<<PHP
  61592. if (0 < func_num_args()) {
  61593. call_user_func_array(array('parent', '__construct'), func_get_args());
  61594. }
  61595. PHP
  61596. );
  61597. }
  61598. /**
  61599. * Returns patch priority, which determines when patch will be applied.
  61600. *
  61601. * @return int Priority number (higher - earlier)
  61602. */
  61603. public function getPriority()
  61604. {
  61605. return 100;
  61606. }
  61607. }
  61608. <?php
  61609. /*
  61610. * This file is part of the Prophecy.
  61611. * (c) Konstantin Kudryashov <ever.zet@gmail.com>
  61612. * Marcello Duarte <marcello.duarte@gmail.com>
  61613. *
  61614. * For the full copyright and license information, please view the LICENSE
  61615. * file that was distributed with this source code.
  61616. */
  61617. namespace Prophecy\Doubler\ClassPatch;
  61618. use Prophecy\Doubler\Generator\Node\ClassNode;
  61619. use Prophecy\Doubler\Generator\Node\MethodNode;
  61620. use Prophecy\PhpDocumentor\ClassAndInterfaceTagRetriever;
  61621. use Prophecy\PhpDocumentor\MethodTagRetrieverInterface;
  61622. /**
  61623. * Discover Magical API using "@method" PHPDoc format.
  61624. *
  61625. * @author Thomas Tourlourat <thomas@tourlourat.com>
  61626. * @author Kévin Dunglas <dunglas@gmail.com>
  61627. * @author Théo FIDRY <theo.fidry@gmail.com>
  61628. */
  61629. class MagicCallPatch implements \Prophecy\Doubler\ClassPatch\ClassPatchInterface
  61630. {
  61631. private $tagRetriever;
  61632. public function __construct(\Prophecy\PhpDocumentor\MethodTagRetrieverInterface $tagRetriever = null)
  61633. {
  61634. $this->tagRetriever = null === $tagRetriever ? new \Prophecy\PhpDocumentor\ClassAndInterfaceTagRetriever() : $tagRetriever;
  61635. }
  61636. /**
  61637. * Support any class
  61638. *
  61639. * @param ClassNode $node
  61640. *
  61641. * @return boolean
  61642. */
  61643. public function supports(\Prophecy\Doubler\Generator\Node\ClassNode $node)
  61644. {
  61645. return \true;
  61646. }
  61647. /**
  61648. * Discover Magical API
  61649. *
  61650. * @param ClassNode $node
  61651. */
  61652. public function apply(\Prophecy\Doubler\Generator\Node\ClassNode $node)
  61653. {
  61654. $types = \array_filter($node->getInterfaces(), function ($interface) {
  61655. return 0 !== \strpos($interface, 'Prophecy\\');
  61656. });
  61657. $types[] = $node->getParentClass();
  61658. foreach ($types as $type) {
  61659. $reflectionClass = new \ReflectionClass($type);
  61660. while ($reflectionClass) {
  61661. $tagList = $this->tagRetriever->getTagList($reflectionClass);
  61662. foreach ($tagList as $tag) {
  61663. $methodName = $tag->getMethodName();
  61664. if (empty($methodName)) {
  61665. continue;
  61666. }
  61667. if (!$reflectionClass->hasMethod($methodName)) {
  61668. $methodNode = new \Prophecy\Doubler\Generator\Node\MethodNode($methodName);
  61669. $methodNode->setStatic($tag->isStatic());
  61670. $node->addMethod($methodNode);
  61671. }
  61672. }
  61673. $reflectionClass = $reflectionClass->getParentClass();
  61674. }
  61675. }
  61676. }
  61677. /**
  61678. * Returns patch priority, which determines when patch will be applied.
  61679. *
  61680. * @return integer Priority number (higher - earlier)
  61681. */
  61682. public function getPriority()
  61683. {
  61684. return 50;
  61685. }
  61686. }
  61687. <?php
  61688. /*
  61689. * This file is part of the Prophecy.
  61690. * (c) Konstantin Kudryashov <ever.zet@gmail.com>
  61691. * Marcello Duarte <marcello.duarte@gmail.com>
  61692. *
  61693. * For the full copyright and license information, please view the LICENSE
  61694. * file that was distributed with this source code.
  61695. */
  61696. namespace Prophecy\Doubler\ClassPatch;
  61697. use Prophecy\Doubler\Generator\Node\ClassNode;
  61698. /**
  61699. * Class patch interface.
  61700. * Class patches extend doubles functionality or help
  61701. * Prophecy to avoid some internal PHP bugs.
  61702. *
  61703. * @author Konstantin Kudryashov <ever.zet@gmail.com>
  61704. */
  61705. interface ClassPatchInterface
  61706. {
  61707. /**
  61708. * Checks if patch supports specific class node.
  61709. *
  61710. * @param ClassNode $node
  61711. *
  61712. * @return bool
  61713. */
  61714. public function supports(\Prophecy\Doubler\Generator\Node\ClassNode $node);
  61715. /**
  61716. * Applies patch to the specific class node.
  61717. *
  61718. * @param ClassNode $node
  61719. * @return void
  61720. */
  61721. public function apply(\Prophecy\Doubler\Generator\Node\ClassNode $node);
  61722. /**
  61723. * Returns patch priority, which determines when patch will be applied.
  61724. *
  61725. * @return int Priority number (higher - earlier)
  61726. */
  61727. public function getPriority();
  61728. }
  61729. <?php
  61730. /*
  61731. * This file is part of the Prophecy.
  61732. * (c) Konstantin Kudryashov <ever.zet@gmail.com>
  61733. * Marcello Duarte <marcello.duarte@gmail.com>
  61734. *
  61735. * For the full copyright and license information, please view the LICENSE
  61736. * file that was distributed with this source code.
  61737. */
  61738. namespace Prophecy\Doubler\ClassPatch;
  61739. use Prophecy\Doubler\Generator\Node\ClassNode;
  61740. use Prophecy\Doubler\Generator\Node\MethodNode;
  61741. use Prophecy\Doubler\Generator\Node\ArgumentNode;
  61742. /**
  61743. * Add Prophecy functionality to the double.
  61744. * This is a core class patch for Prophecy.
  61745. *
  61746. * @author Konstantin Kudryashov <ever.zet@gmail.com>
  61747. */
  61748. class ProphecySubjectPatch implements \Prophecy\Doubler\ClassPatch\ClassPatchInterface
  61749. {
  61750. /**
  61751. * Always returns true.
  61752. *
  61753. * @param ClassNode $node
  61754. *
  61755. * @return bool
  61756. */
  61757. public function supports(\Prophecy\Doubler\Generator\Node\ClassNode $node)
  61758. {
  61759. return \true;
  61760. }
  61761. /**
  61762. * Apply Prophecy functionality to class node.
  61763. *
  61764. * @param ClassNode $node
  61765. */
  61766. public function apply(\Prophecy\Doubler\Generator\Node\ClassNode $node)
  61767. {
  61768. $node->addInterface('Prophecy\\Prophecy\\ProphecySubjectInterface');
  61769. $node->addProperty('objectProphecyClosure', 'private');
  61770. foreach ($node->getMethods() as $name => $method) {
  61771. if ('__construct' === \strtolower($name)) {
  61772. continue;
  61773. }
  61774. if ($method->getReturnType() === 'void') {
  61775. $method->setCode('$this->getProphecy()->makeProphecyMethodCall(__FUNCTION__, func_get_args());');
  61776. } else {
  61777. $method->setCode('return $this->getProphecy()->makeProphecyMethodCall(__FUNCTION__, func_get_args());');
  61778. }
  61779. }
  61780. $prophecySetter = new \Prophecy\Doubler\Generator\Node\MethodNode('setProphecy');
  61781. $prophecyArgument = new \Prophecy\Doubler\Generator\Node\ArgumentNode('prophecy');
  61782. $prophecyArgument->setTypeHint('Prophecy\\Prophecy\\ProphecyInterface');
  61783. $prophecySetter->addArgument($prophecyArgument);
  61784. $prophecySetter->setCode('$this->objectProphecyClosure = function () use ($prophecy) { return $prophecy; };');
  61785. $prophecyGetter = new \Prophecy\Doubler\Generator\Node\MethodNode('getProphecy');
  61786. $prophecyGetter->setCode('return call_user_func($this->objectProphecyClosure);');
  61787. if ($node->hasMethod('__call')) {
  61788. $__call = $node->getMethod('__call');
  61789. } else {
  61790. $__call = new \Prophecy\Doubler\Generator\Node\MethodNode('__call');
  61791. $__call->addArgument(new \Prophecy\Doubler\Generator\Node\ArgumentNode('name'));
  61792. $__call->addArgument(new \Prophecy\Doubler\Generator\Node\ArgumentNode('arguments'));
  61793. $node->addMethod($__call, \true);
  61794. }
  61795. $__call->setCode(<<<PHP
  61796. throw new \\Prophecy\\Exception\\Doubler\\MethodNotFoundException(
  61797. sprintf('Method `%s::%s()` not found.', get_class(\$this), func_get_arg(0)),
  61798. \$this->getProphecy(), func_get_arg(0)
  61799. );
  61800. PHP
  61801. );
  61802. $node->addMethod($prophecySetter, \true);
  61803. $node->addMethod($prophecyGetter, \true);
  61804. }
  61805. /**
  61806. * Returns patch priority, which determines when patch will be applied.
  61807. *
  61808. * @return int Priority number (higher - earlier)
  61809. */
  61810. public function getPriority()
  61811. {
  61812. return 0;
  61813. }
  61814. }
  61815. <?php
  61816. /*
  61817. * This file is part of the Prophecy.
  61818. * (c) Konstantin Kudryashov <ever.zet@gmail.com>
  61819. * Marcello Duarte <marcello.duarte@gmail.com>
  61820. *
  61821. * For the full copyright and license information, please view the LICENSE
  61822. * file that was distributed with this source code.
  61823. */
  61824. namespace Prophecy\Doubler\ClassPatch;
  61825. use Prophecy\Doubler\Generator\Node\ClassNode;
  61826. use Prophecy\Doubler\Generator\Node\MethodNode;
  61827. /**
  61828. * SplFileInfo patch.
  61829. * Makes SplFileInfo and derivative classes usable with Prophecy.
  61830. *
  61831. * @author Konstantin Kudryashov <ever.zet@gmail.com>
  61832. */
  61833. class SplFileInfoPatch implements \Prophecy\Doubler\ClassPatch\ClassPatchInterface
  61834. {
  61835. /**
  61836. * Supports everything that extends SplFileInfo.
  61837. *
  61838. * @param ClassNode $node
  61839. *
  61840. * @return bool
  61841. */
  61842. public function supports(\Prophecy\Doubler\Generator\Node\ClassNode $node)
  61843. {
  61844. if (null === $node->getParentClass()) {
  61845. return \false;
  61846. }
  61847. return 'SplFileInfo' === $node->getParentClass() || \is_subclass_of($node->getParentClass(), 'SplFileInfo');
  61848. }
  61849. /**
  61850. * Updated constructor code to call parent one with dummy file argument.
  61851. *
  61852. * @param ClassNode $node
  61853. */
  61854. public function apply(\Prophecy\Doubler\Generator\Node\ClassNode $node)
  61855. {
  61856. if ($node->hasMethod('__construct')) {
  61857. $constructor = $node->getMethod('__construct');
  61858. } else {
  61859. $constructor = new \Prophecy\Doubler\Generator\Node\MethodNode('__construct');
  61860. $node->addMethod($constructor);
  61861. }
  61862. if ($this->nodeIsDirectoryIterator($node)) {
  61863. $constructor->setCode('return parent::__construct("' . __DIR__ . '");');
  61864. return;
  61865. }
  61866. if ($this->nodeIsSplFileObject($node)) {
  61867. $filePath = \str_replace('\\', '\\\\', __FILE__);
  61868. $constructor->setCode('return parent::__construct("' . $filePath . '");');
  61869. return;
  61870. }
  61871. if ($this->nodeIsSymfonySplFileInfo($node)) {
  61872. $filePath = \str_replace('\\', '\\\\', __FILE__);
  61873. $constructor->setCode('return parent::__construct("' . $filePath . '", "", "");');
  61874. return;
  61875. }
  61876. $constructor->useParentCode();
  61877. }
  61878. /**
  61879. * Returns patch priority, which determines when patch will be applied.
  61880. *
  61881. * @return int Priority number (higher - earlier)
  61882. */
  61883. public function getPriority()
  61884. {
  61885. return 50;
  61886. }
  61887. /**
  61888. * @param ClassNode $node
  61889. * @return boolean
  61890. */
  61891. private function nodeIsDirectoryIterator(\Prophecy\Doubler\Generator\Node\ClassNode $node)
  61892. {
  61893. $parent = $node->getParentClass();
  61894. return 'DirectoryIterator' === $parent || \is_subclass_of($parent, 'DirectoryIterator');
  61895. }
  61896. /**
  61897. * @param ClassNode $node
  61898. * @return boolean
  61899. */
  61900. private function nodeIsSplFileObject(\Prophecy\Doubler\Generator\Node\ClassNode $node)
  61901. {
  61902. $parent = $node->getParentClass();
  61903. return 'SplFileObject' === $parent || \is_subclass_of($parent, 'SplFileObject');
  61904. }
  61905. /**
  61906. * @param ClassNode $node
  61907. * @return boolean
  61908. */
  61909. private function nodeIsSymfonySplFileInfo(\Prophecy\Doubler\Generator\Node\ClassNode $node)
  61910. {
  61911. $parent = $node->getParentClass();
  61912. return 'Symfony\\Component\\Finder\\SplFileInfo' === $parent;
  61913. }
  61914. }
  61915. <?php
  61916. /*
  61917. * This file is part of the Prophecy.
  61918. * (c) Konstantin Kudryashov <ever.zet@gmail.com>
  61919. * Marcello Duarte <marcello.duarte@gmail.com>
  61920. *
  61921. * For the full copyright and license information, please view the LICENSE
  61922. * file that was distributed with this source code.
  61923. */
  61924. namespace Prophecy\Doubler\ClassPatch;
  61925. use Prophecy\Doubler\Generator\Node\ClassNode;
  61926. /**
  61927. * Remove method functionality from the double which will clash with php keywords.
  61928. *
  61929. * @author Milan Magudia <milan@magudia.com>
  61930. */
  61931. class KeywordPatch implements \Prophecy\Doubler\ClassPatch\ClassPatchInterface
  61932. {
  61933. /**
  61934. * Support any class
  61935. *
  61936. * @param ClassNode $node
  61937. *
  61938. * @return boolean
  61939. */
  61940. public function supports(\Prophecy\Doubler\Generator\Node\ClassNode $node)
  61941. {
  61942. return \true;
  61943. }
  61944. /**
  61945. * Remove methods that clash with php keywords
  61946. *
  61947. * @param ClassNode $node
  61948. */
  61949. public function apply(\Prophecy\Doubler\Generator\Node\ClassNode $node)
  61950. {
  61951. $methodNames = \array_keys($node->getMethods());
  61952. $methodsToRemove = \array_intersect($methodNames, $this->getKeywords());
  61953. foreach ($methodsToRemove as $methodName) {
  61954. $node->removeMethod($methodName);
  61955. }
  61956. }
  61957. /**
  61958. * Returns patch priority, which determines when patch will be applied.
  61959. *
  61960. * @return int Priority number (higher - earlier)
  61961. */
  61962. public function getPriority()
  61963. {
  61964. return 49;
  61965. }
  61966. /**
  61967. * Returns array of php keywords.
  61968. *
  61969. * @return array
  61970. */
  61971. private function getKeywords()
  61972. {
  61973. if (\PHP_VERSION_ID >= 70000) {
  61974. return array('__halt_compiler');
  61975. }
  61976. return array('__halt_compiler', 'abstract', 'and', 'array', 'as', 'break', 'callable', 'case', 'catch', 'class', 'clone', 'const', 'continue', 'declare', 'default', 'die', 'do', 'echo', 'else', 'elseif', 'empty', 'enddeclare', 'endfor', 'endforeach', 'endif', 'endswitch', 'endwhile', 'eval', 'exit', 'extends', 'final', 'finally', 'for', 'foreach', 'function', 'global', 'goto', 'if', 'implements', 'include', 'include_once', 'instanceof', 'insteadof', 'interface', 'isset', 'list', 'namespace', 'new', 'or', 'print', 'private', 'protected', 'public', 'require', 'require_once', 'return', 'static', 'switch', 'throw', 'trait', 'try', 'unset', 'use', 'var', 'while', 'xor', 'yield');
  61977. }
  61978. }
  61979. <?php
  61980. /*
  61981. * This file is part of the Prophecy.
  61982. * (c) Konstantin Kudryashov <ever.zet@gmail.com>
  61983. * Marcello Duarte <marcello.duarte@gmail.com>
  61984. *
  61985. * For the full copyright and license information, please view the LICENSE
  61986. * file that was distributed with this source code.
  61987. */
  61988. namespace Prophecy\Doubler\ClassPatch;
  61989. use Prophecy\Doubler\Generator\Node\ClassNode;
  61990. /**
  61991. * Exception patch for HHVM to remove the stubs from special methods
  61992. *
  61993. * @author Christophe Coevoet <stof@notk.org>
  61994. */
  61995. class HhvmExceptionPatch implements \Prophecy\Doubler\ClassPatch\ClassPatchInterface
  61996. {
  61997. /**
  61998. * Supports exceptions on HHVM.
  61999. *
  62000. * @param ClassNode $node
  62001. *
  62002. * @return bool
  62003. */
  62004. public function supports(\Prophecy\Doubler\Generator\Node\ClassNode $node)
  62005. {
  62006. if (!\defined('HHVM_VERSION')) {
  62007. return \false;
  62008. }
  62009. return 'Exception' === $node->getParentClass() || \is_subclass_of($node->getParentClass(), 'Exception');
  62010. }
  62011. /**
  62012. * Removes special exception static methods from the doubled methods.
  62013. *
  62014. * @param ClassNode $node
  62015. *
  62016. * @return void
  62017. */
  62018. public function apply(\Prophecy\Doubler\Generator\Node\ClassNode $node)
  62019. {
  62020. if ($node->hasMethod('setTraceOptions')) {
  62021. $node->getMethod('setTraceOptions')->useParentCode();
  62022. }
  62023. if ($node->hasMethod('getTraceOptions')) {
  62024. $node->getMethod('getTraceOptions')->useParentCode();
  62025. }
  62026. }
  62027. /**
  62028. * {@inheritdoc}
  62029. */
  62030. public function getPriority()
  62031. {
  62032. return -50;
  62033. }
  62034. }
  62035. <?php
  62036. /*
  62037. * This file is part of the Prophecy.
  62038. * (c) Konstantin Kudryashov <ever.zet@gmail.com>
  62039. * Marcello Duarte <marcello.duarte@gmail.com>
  62040. *
  62041. * For the full copyright and license information, please view the LICENSE
  62042. * file that was distributed with this source code.
  62043. */
  62044. namespace Prophecy\Doubler\ClassPatch;
  62045. use Prophecy\Doubler\Generator\Node\ClassNode;
  62046. use Prophecy\Doubler\Generator\Node\MethodNode;
  62047. /**
  62048. * Traversable interface patch.
  62049. * Forces classes that implement interfaces, that extend Traversable to also implement Iterator.
  62050. *
  62051. * @author Konstantin Kudryashov <ever.zet@gmail.com>
  62052. */
  62053. class TraversablePatch implements \Prophecy\Doubler\ClassPatch\ClassPatchInterface
  62054. {
  62055. /**
  62056. * Supports nodetree, that implement Traversable, but not Iterator or IteratorAggregate.
  62057. *
  62058. * @param ClassNode $node
  62059. *
  62060. * @return bool
  62061. */
  62062. public function supports(\Prophecy\Doubler\Generator\Node\ClassNode $node)
  62063. {
  62064. if (\in_array('Iterator', $node->getInterfaces())) {
  62065. return \false;
  62066. }
  62067. if (\in_array('IteratorAggregate', $node->getInterfaces())) {
  62068. return \false;
  62069. }
  62070. foreach ($node->getInterfaces() as $interface) {
  62071. if ('Traversable' !== $interface && !\is_subclass_of($interface, 'Traversable')) {
  62072. continue;
  62073. }
  62074. if ('Iterator' === $interface || \is_subclass_of($interface, 'Iterator')) {
  62075. continue;
  62076. }
  62077. if ('IteratorAggregate' === $interface || \is_subclass_of($interface, 'IteratorAggregate')) {
  62078. continue;
  62079. }
  62080. return \true;
  62081. }
  62082. return \false;
  62083. }
  62084. /**
  62085. * Forces class to implement Iterator interface.
  62086. *
  62087. * @param ClassNode $node
  62088. */
  62089. public function apply(\Prophecy\Doubler\Generator\Node\ClassNode $node)
  62090. {
  62091. $node->addInterface('Iterator');
  62092. $node->addMethod(new \Prophecy\Doubler\Generator\Node\MethodNode('current'));
  62093. $node->addMethod(new \Prophecy\Doubler\Generator\Node\MethodNode('key'));
  62094. $node->addMethod(new \Prophecy\Doubler\Generator\Node\MethodNode('next'));
  62095. $node->addMethod(new \Prophecy\Doubler\Generator\Node\MethodNode('rewind'));
  62096. $node->addMethod(new \Prophecy\Doubler\Generator\Node\MethodNode('valid'));
  62097. }
  62098. /**
  62099. * Returns patch priority, which determines when patch will be applied.
  62100. *
  62101. * @return int Priority number (higher - earlier)
  62102. */
  62103. public function getPriority()
  62104. {
  62105. return 100;
  62106. }
  62107. }
  62108. <?php
  62109. /*
  62110. * This file is part of the Prophecy.
  62111. * (c) Konstantin Kudryashov <ever.zet@gmail.com>
  62112. * Marcello Duarte <marcello.duarte@gmail.com>
  62113. *
  62114. * For the full copyright and license information, please view the LICENSE
  62115. * file that was distributed with this source code.
  62116. */
  62117. namespace Prophecy\Doubler\ClassPatch;
  62118. use Prophecy\Doubler\Generator\Node\ClassNode;
  62119. /**
  62120. * ReflectionClass::newInstance patch.
  62121. * Makes first argument of newInstance optional, since it works but signature is misleading
  62122. *
  62123. * @author Florian Klein <florian.klein@free.fr>
  62124. */
  62125. class ReflectionClassNewInstancePatch implements \Prophecy\Doubler\ClassPatch\ClassPatchInterface
  62126. {
  62127. /**
  62128. * Supports ReflectionClass
  62129. *
  62130. * @param ClassNode $node
  62131. *
  62132. * @return bool
  62133. */
  62134. public function supports(\Prophecy\Doubler\Generator\Node\ClassNode $node)
  62135. {
  62136. return 'ReflectionClass' === $node->getParentClass();
  62137. }
  62138. /**
  62139. * Updates newInstance's first argument to make it optional
  62140. *
  62141. * @param ClassNode $node
  62142. */
  62143. public function apply(\Prophecy\Doubler\Generator\Node\ClassNode $node)
  62144. {
  62145. foreach ($node->getMethod('newInstance')->getArguments() as $argument) {
  62146. $argument->setDefault(null);
  62147. }
  62148. }
  62149. /**
  62150. * Returns patch priority, which determines when patch will be applied.
  62151. *
  62152. * @return int Priority number (higher = earlier)
  62153. */
  62154. public function getPriority()
  62155. {
  62156. return 50;
  62157. }
  62158. }
  62159. <?php
  62160. /*
  62161. * This file is part of the Prophecy.
  62162. * (c) Konstantin Kudryashov <ever.zet@gmail.com>
  62163. * Marcello Duarte <marcello.duarte@gmail.com>
  62164. *
  62165. * For the full copyright and license information, please view the LICENSE
  62166. * file that was distributed with this source code.
  62167. */
  62168. namespace Prophecy\Argument\Token;
  62169. /**
  62170. * Logical NOT token.
  62171. *
  62172. * @author Boris Mikhaylov <kaguxmail@gmail.com>
  62173. */
  62174. class LogicalNotToken implements \Prophecy\Argument\Token\TokenInterface
  62175. {
  62176. /** @var \Prophecy\Argument\Token\TokenInterface */
  62177. private $token;
  62178. /**
  62179. * @param mixed $value exact value or token
  62180. */
  62181. public function __construct($value)
  62182. {
  62183. $this->token = $value instanceof \Prophecy\Argument\Token\TokenInterface ? $value : new \Prophecy\Argument\Token\ExactValueToken($value);
  62184. }
  62185. /**
  62186. * Scores 4 when preset token does not match the argument.
  62187. *
  62188. * @param $argument
  62189. *
  62190. * @return bool|int
  62191. */
  62192. public function scoreArgument($argument)
  62193. {
  62194. return \false === $this->token->scoreArgument($argument) ? 4 : \false;
  62195. }
  62196. /**
  62197. * Returns true if preset token is last.
  62198. *
  62199. * @return bool|int
  62200. */
  62201. public function isLast()
  62202. {
  62203. return $this->token->isLast();
  62204. }
  62205. /**
  62206. * Returns originating token.
  62207. *
  62208. * @return TokenInterface
  62209. */
  62210. public function getOriginatingToken()
  62211. {
  62212. return $this->token;
  62213. }
  62214. /**
  62215. * Returns string representation for token.
  62216. *
  62217. * @return string
  62218. */
  62219. public function __toString()
  62220. {
  62221. return \sprintf('not(%s)', $this->token);
  62222. }
  62223. }
  62224. <?php
  62225. /*
  62226. * This file is part of the Prophecy.
  62227. * (c) Konstantin Kudryashov <ever.zet@gmail.com>
  62228. * Marcello Duarte <marcello.duarte@gmail.com>
  62229. *
  62230. * For the full copyright and license information, please view the LICENSE
  62231. * file that was distributed with this source code.
  62232. */
  62233. namespace Prophecy\Argument\Token;
  62234. /**
  62235. * Array every entry token.
  62236. *
  62237. * @author Adrien Brault <adrien.brault@gmail.com>
  62238. */
  62239. class ArrayEveryEntryToken implements \Prophecy\Argument\Token\TokenInterface
  62240. {
  62241. /**
  62242. * @var TokenInterface
  62243. */
  62244. private $value;
  62245. /**
  62246. * @param mixed $value exact value or token
  62247. */
  62248. public function __construct($value)
  62249. {
  62250. if (!$value instanceof \Prophecy\Argument\Token\TokenInterface) {
  62251. $value = new \Prophecy\Argument\Token\ExactValueToken($value);
  62252. }
  62253. $this->value = $value;
  62254. }
  62255. /**
  62256. * {@inheritdoc}
  62257. */
  62258. public function scoreArgument($argument)
  62259. {
  62260. if (!$argument instanceof \Traversable && !\is_array($argument)) {
  62261. return \false;
  62262. }
  62263. $scores = array();
  62264. foreach ($argument as $key => $argumentEntry) {
  62265. $scores[] = $this->value->scoreArgument($argumentEntry);
  62266. }
  62267. if (empty($scores) || \in_array(\false, $scores, \true)) {
  62268. return \false;
  62269. }
  62270. return \array_sum($scores) / \count($scores);
  62271. }
  62272. /**
  62273. * {@inheritdoc}
  62274. */
  62275. public function isLast()
  62276. {
  62277. return \false;
  62278. }
  62279. /**
  62280. * {@inheritdoc}
  62281. */
  62282. public function __toString()
  62283. {
  62284. return \sprintf('[%s, ..., %s]', $this->value, $this->value);
  62285. }
  62286. /**
  62287. * @return TokenInterface
  62288. */
  62289. public function getValue()
  62290. {
  62291. return $this->value;
  62292. }
  62293. }
  62294. <?php
  62295. /*
  62296. * This file is part of the Prophecy.
  62297. * (c) Konstantin Kudryashov <ever.zet@gmail.com>
  62298. * Marcello Duarte <marcello.duarte@gmail.com>
  62299. *
  62300. * For the full copyright and license information, please view the LICENSE
  62301. * file that was distributed with this source code.
  62302. */
  62303. namespace Prophecy\Argument\Token;
  62304. /**
  62305. * Logical AND token.
  62306. *
  62307. * @author Boris Mikhaylov <kaguxmail@gmail.com>
  62308. */
  62309. class LogicalAndToken implements \Prophecy\Argument\Token\TokenInterface
  62310. {
  62311. private $tokens = array();
  62312. /**
  62313. * @param array $arguments exact values or tokens
  62314. */
  62315. public function __construct(array $arguments)
  62316. {
  62317. foreach ($arguments as $argument) {
  62318. if (!$argument instanceof \Prophecy\Argument\Token\TokenInterface) {
  62319. $argument = new \Prophecy\Argument\Token\ExactValueToken($argument);
  62320. }
  62321. $this->tokens[] = $argument;
  62322. }
  62323. }
  62324. /**
  62325. * Scores maximum score from scores returned by tokens for this argument if all of them score.
  62326. *
  62327. * @param $argument
  62328. *
  62329. * @return bool|int
  62330. */
  62331. public function scoreArgument($argument)
  62332. {
  62333. if (0 === \count($this->tokens)) {
  62334. return \false;
  62335. }
  62336. $maxScore = 0;
  62337. foreach ($this->tokens as $token) {
  62338. $score = $token->scoreArgument($argument);
  62339. if (\false === $score) {
  62340. return \false;
  62341. }
  62342. $maxScore = \max($score, $maxScore);
  62343. }
  62344. return $maxScore;
  62345. }
  62346. /**
  62347. * Returns false.
  62348. *
  62349. * @return boolean
  62350. */
  62351. public function isLast()
  62352. {
  62353. return \false;
  62354. }
  62355. /**
  62356. * Returns string representation for token.
  62357. *
  62358. * @return string
  62359. */
  62360. public function __toString()
  62361. {
  62362. return \sprintf('bool(%s)', \implode(' AND ', $this->tokens));
  62363. }
  62364. }
  62365. <?php
  62366. /*
  62367. * This file is part of the Prophecy.
  62368. * (c) Konstantin Kudryashov <ever.zet@gmail.com>
  62369. * Marcello Duarte <marcello.duarte@gmail.com>
  62370. *
  62371. * For the full copyright and license information, please view the LICENSE
  62372. * file that was distributed with this source code.
  62373. */
  62374. namespace Prophecy\Argument\Token;
  62375. use Prophecy\Exception\InvalidArgumentException;
  62376. /**
  62377. * Array entry token.
  62378. *
  62379. * @author Boris Mikhaylov <kaguxmail@gmail.com>
  62380. */
  62381. class ArrayEntryToken implements \Prophecy\Argument\Token\TokenInterface
  62382. {
  62383. /** @var \Prophecy\Argument\Token\TokenInterface */
  62384. private $key;
  62385. /** @var \Prophecy\Argument\Token\TokenInterface */
  62386. private $value;
  62387. /**
  62388. * @param mixed $key exact value or token
  62389. * @param mixed $value exact value or token
  62390. */
  62391. public function __construct($key, $value)
  62392. {
  62393. $this->key = $this->wrapIntoExactValueToken($key);
  62394. $this->value = $this->wrapIntoExactValueToken($value);
  62395. }
  62396. /**
  62397. * Scores half of combined scores from key and value tokens for same entry. Capped at 8.
  62398. * If argument implements \ArrayAccess without \Traversable, then key token is restricted to ExactValueToken.
  62399. *
  62400. * @param array|\ArrayAccess|\Traversable $argument
  62401. *
  62402. * @throws \Prophecy\Exception\InvalidArgumentException
  62403. * @return bool|int
  62404. */
  62405. public function scoreArgument($argument)
  62406. {
  62407. if ($argument instanceof \Traversable) {
  62408. $argument = \iterator_to_array($argument);
  62409. }
  62410. if ($argument instanceof \ArrayAccess) {
  62411. $argument = $this->convertArrayAccessToEntry($argument);
  62412. }
  62413. if (!\is_array($argument) || empty($argument)) {
  62414. return \false;
  62415. }
  62416. $keyScores = \array_map(array($this->key, 'scoreArgument'), \array_keys($argument));
  62417. $valueScores = \array_map(array($this->value, 'scoreArgument'), $argument);
  62418. $scoreEntry = function ($value, $key) {
  62419. return $value && $key ? \min(8, ($key + $value) / 2) : \false;
  62420. };
  62421. return \max(\array_map($scoreEntry, $valueScores, $keyScores));
  62422. }
  62423. /**
  62424. * Returns false.
  62425. *
  62426. * @return boolean
  62427. */
  62428. public function isLast()
  62429. {
  62430. return \false;
  62431. }
  62432. /**
  62433. * Returns string representation for token.
  62434. *
  62435. * @return string
  62436. */
  62437. public function __toString()
  62438. {
  62439. return \sprintf('[..., %s => %s, ...]', $this->key, $this->value);
  62440. }
  62441. /**
  62442. * Returns key
  62443. *
  62444. * @return TokenInterface
  62445. */
  62446. public function getKey()
  62447. {
  62448. return $this->key;
  62449. }
  62450. /**
  62451. * Returns value
  62452. *
  62453. * @return TokenInterface
  62454. */
  62455. public function getValue()
  62456. {
  62457. return $this->value;
  62458. }
  62459. /**
  62460. * Wraps non token $value into ExactValueToken
  62461. *
  62462. * @param $value
  62463. * @return TokenInterface
  62464. */
  62465. private function wrapIntoExactValueToken($value)
  62466. {
  62467. return $value instanceof \Prophecy\Argument\Token\TokenInterface ? $value : new \Prophecy\Argument\Token\ExactValueToken($value);
  62468. }
  62469. /**
  62470. * Converts instance of \ArrayAccess to key => value array entry
  62471. *
  62472. * @param \ArrayAccess $object
  62473. *
  62474. * @return array|null
  62475. * @throws \Prophecy\Exception\InvalidArgumentException
  62476. */
  62477. private function convertArrayAccessToEntry(\ArrayAccess $object)
  62478. {
  62479. if (!$this->key instanceof \Prophecy\Argument\Token\ExactValueToken) {
  62480. throw new \Prophecy\Exception\InvalidArgumentException(\sprintf('You can only use exact value tokens to match key of ArrayAccess object' . \PHP_EOL . 'But you used `%s`.', $this->key));
  62481. }
  62482. $key = $this->key->getValue();
  62483. return $object->offsetExists($key) ? array($key => $object[$key]) : array();
  62484. }
  62485. }
  62486. <?php
  62487. /*
  62488. * This file is part of the Prophecy.
  62489. * (c) Konstantin Kudryashov <ever.zet@gmail.com>
  62490. * Marcello Duarte <marcello.duarte@gmail.com>
  62491. *
  62492. * For the full copyright and license information, please view the LICENSE
  62493. * file that was distributed with this source code.
  62494. */
  62495. namespace Prophecy\Argument\Token;
  62496. use Prophecy\Util\StringUtil;
  62497. /**
  62498. * Identical value token.
  62499. *
  62500. * @author Florian Voutzinos <florian@voutzinos.com>
  62501. */
  62502. class IdenticalValueToken implements \Prophecy\Argument\Token\TokenInterface
  62503. {
  62504. private $value;
  62505. private $string;
  62506. private $util;
  62507. /**
  62508. * Initializes token.
  62509. *
  62510. * @param mixed $value
  62511. * @param StringUtil $util
  62512. */
  62513. public function __construct($value, \Prophecy\Util\StringUtil $util = null)
  62514. {
  62515. $this->value = $value;
  62516. $this->util = $util ?: new \Prophecy\Util\StringUtil();
  62517. }
  62518. /**
  62519. * Scores 11 if argument matches preset value.
  62520. *
  62521. * @param $argument
  62522. *
  62523. * @return bool|int
  62524. */
  62525. public function scoreArgument($argument)
  62526. {
  62527. return $argument === $this->value ? 11 : \false;
  62528. }
  62529. /**
  62530. * Returns false.
  62531. *
  62532. * @return bool
  62533. */
  62534. public function isLast()
  62535. {
  62536. return \false;
  62537. }
  62538. /**
  62539. * Returns string representation for token.
  62540. *
  62541. * @return string
  62542. */
  62543. public function __toString()
  62544. {
  62545. if (null === $this->string) {
  62546. $this->string = \sprintf('identical(%s)', $this->util->stringify($this->value));
  62547. }
  62548. return $this->string;
  62549. }
  62550. }
  62551. <?php
  62552. /*
  62553. * This file is part of the Prophecy.
  62554. * (c) Konstantin Kudryashov <ever.zet@gmail.com>
  62555. * Marcello Duarte <marcello.duarte@gmail.com>
  62556. *
  62557. * For the full copyright and license information, please view the LICENSE
  62558. * file that was distributed with this source code.
  62559. */
  62560. namespace Prophecy\Argument\Token;
  62561. use Prophecy\Exception\InvalidArgumentException;
  62562. /**
  62563. * Value type token.
  62564. *
  62565. * @author Konstantin Kudryashov <ever.zet@gmail.com>
  62566. */
  62567. class TypeToken implements \Prophecy\Argument\Token\TokenInterface
  62568. {
  62569. private $type;
  62570. /**
  62571. * @param string $type
  62572. */
  62573. public function __construct($type)
  62574. {
  62575. $checker = "is_{$type}";
  62576. if (!\function_exists($checker) && !\interface_exists($type) && !\class_exists($type)) {
  62577. throw new \Prophecy\Exception\InvalidArgumentException(\sprintf('Type or class name expected as an argument to TypeToken, but got %s.', $type));
  62578. }
  62579. $this->type = $type;
  62580. }
  62581. /**
  62582. * Scores 5 if argument has the same type this token was constructed with.
  62583. *
  62584. * @param $argument
  62585. *
  62586. * @return bool|int
  62587. */
  62588. public function scoreArgument($argument)
  62589. {
  62590. $checker = "is_{$this->type}";
  62591. if (\function_exists($checker)) {
  62592. return \call_user_func($checker, $argument) ? 5 : \false;
  62593. }
  62594. return $argument instanceof $this->type ? 5 : \false;
  62595. }
  62596. /**
  62597. * Returns false.
  62598. *
  62599. * @return bool
  62600. */
  62601. public function isLast()
  62602. {
  62603. return \false;
  62604. }
  62605. /**
  62606. * Returns string representation for token.
  62607. *
  62608. * @return string
  62609. */
  62610. public function __toString()
  62611. {
  62612. return \sprintf('type(%s)', $this->type);
  62613. }
  62614. }
  62615. <?php
  62616. /*
  62617. * This file is part of the Prophecy.
  62618. * (c) Konstantin Kudryashov <ever.zet@gmail.com>
  62619. * Marcello Duarte <marcello.duarte@gmail.com>
  62620. *
  62621. * For the full copyright and license information, please view the LICENSE
  62622. * file that was distributed with this source code.
  62623. */
  62624. namespace Prophecy\Argument\Token;
  62625. use PHPUnit\SebastianBergmann\Comparator\ComparisonFailure;
  62626. use Prophecy\Comparator\Factory as ComparatorFactory;
  62627. use Prophecy\Util\StringUtil;
  62628. /**
  62629. * Object state-checker token.
  62630. *
  62631. * @author Konstantin Kudryashov <ever.zet@gmail.com>
  62632. */
  62633. class ObjectStateToken implements \Prophecy\Argument\Token\TokenInterface
  62634. {
  62635. private $name;
  62636. private $value;
  62637. private $util;
  62638. private $comparatorFactory;
  62639. /**
  62640. * Initializes token.
  62641. *
  62642. * @param string $methodName
  62643. * @param mixed $value Expected return value
  62644. * @param null|StringUtil $util
  62645. * @param ComparatorFactory $comparatorFactory
  62646. */
  62647. public function __construct($methodName, $value, \Prophecy\Util\StringUtil $util = null, \Prophecy\Comparator\Factory $comparatorFactory = null)
  62648. {
  62649. $this->name = $methodName;
  62650. $this->value = $value;
  62651. $this->util = $util ?: new \Prophecy\Util\StringUtil();
  62652. $this->comparatorFactory = $comparatorFactory ?: \Prophecy\Comparator\Factory::getInstance();
  62653. }
  62654. /**
  62655. * Scores 8 if argument is an object, which method returns expected value.
  62656. *
  62657. * @param mixed $argument
  62658. *
  62659. * @return bool|int
  62660. */
  62661. public function scoreArgument($argument)
  62662. {
  62663. if (\is_object($argument) && \method_exists($argument, $this->name)) {
  62664. $actual = \call_user_func(array($argument, $this->name));
  62665. $comparator = $this->comparatorFactory->getComparatorFor($this->value, $actual);
  62666. try {
  62667. $comparator->assertEquals($this->value, $actual);
  62668. return 8;
  62669. } catch (\PHPUnit\SebastianBergmann\Comparator\ComparisonFailure $failure) {
  62670. return \false;
  62671. }
  62672. }
  62673. if (\is_object($argument) && \property_exists($argument, $this->name)) {
  62674. return $argument->{$this->name} === $this->value ? 8 : \false;
  62675. }
  62676. return \false;
  62677. }
  62678. /**
  62679. * Returns false.
  62680. *
  62681. * @return bool
  62682. */
  62683. public function isLast()
  62684. {
  62685. return \false;
  62686. }
  62687. /**
  62688. * Returns string representation for token.
  62689. *
  62690. * @return string
  62691. */
  62692. public function __toString()
  62693. {
  62694. return \sprintf('state(%s(), %s)', $this->name, $this->util->stringify($this->value));
  62695. }
  62696. }
  62697. <?php
  62698. /*
  62699. * This file is part of the Prophecy.
  62700. * (c) Konstantin Kudryashov <ever.zet@gmail.com>
  62701. * Marcello Duarte <marcello.duarte@gmail.com>
  62702. *
  62703. * For the full copyright and license information, please view the LICENSE
  62704. * file that was distributed with this source code.
  62705. */
  62706. namespace Prophecy\Argument\Token;
  62707. /**
  62708. * Any single value token.
  62709. *
  62710. * @author Konstantin Kudryashov <ever.zet@gmail.com>
  62711. */
  62712. class AnyValueToken implements \Prophecy\Argument\Token\TokenInterface
  62713. {
  62714. /**
  62715. * Always scores 3 for any argument.
  62716. *
  62717. * @param $argument
  62718. *
  62719. * @return int
  62720. */
  62721. public function scoreArgument($argument)
  62722. {
  62723. return 3;
  62724. }
  62725. /**
  62726. * Returns false.
  62727. *
  62728. * @return bool
  62729. */
  62730. public function isLast()
  62731. {
  62732. return \false;
  62733. }
  62734. /**
  62735. * Returns string representation for token.
  62736. *
  62737. * @return string
  62738. */
  62739. public function __toString()
  62740. {
  62741. return '*';
  62742. }
  62743. }
  62744. <?php
  62745. /*
  62746. * This file is part of the Prophecy.
  62747. * (c) Konstantin Kudryashov <ever.zet@gmail.com>
  62748. * Marcello Duarte <marcello.duarte@gmail.com>
  62749. *
  62750. * For the full copyright and license information, please view the LICENSE
  62751. * file that was distributed with this source code.
  62752. */
  62753. namespace Prophecy\Argument\Token;
  62754. /**
  62755. * Approximate value token
  62756. *
  62757. * @author Daniel Leech <daniel@dantleech.com>
  62758. */
  62759. class ApproximateValueToken implements \Prophecy\Argument\Token\TokenInterface
  62760. {
  62761. private $value;
  62762. private $precision;
  62763. public function __construct($value, $precision = 0)
  62764. {
  62765. $this->value = $value;
  62766. $this->precision = $precision;
  62767. }
  62768. /**
  62769. * {@inheritdoc}
  62770. */
  62771. public function scoreArgument($argument)
  62772. {
  62773. return \round($argument, $this->precision) === \round($this->value, $this->precision) ? 10 : \false;
  62774. }
  62775. /**
  62776. * {@inheritdoc}
  62777. */
  62778. public function isLast()
  62779. {
  62780. return \false;
  62781. }
  62782. /**
  62783. * Returns string representation for token.
  62784. *
  62785. * @return string
  62786. */
  62787. public function __toString()
  62788. {
  62789. return \sprintf('≅%s', \round($this->value, $this->precision));
  62790. }
  62791. }
  62792. <?php
  62793. /*
  62794. * This file is part of the Prophecy.
  62795. * (c) Konstantin Kudryashov <ever.zet@gmail.com>
  62796. * Marcello Duarte <marcello.duarte@gmail.com>
  62797. *
  62798. * For the full copyright and license information, please view the LICENSE
  62799. * file that was distributed with this source code.
  62800. */
  62801. namespace Prophecy\Argument\Token;
  62802. /**
  62803. * Any values token.
  62804. *
  62805. * @author Konstantin Kudryashov <ever.zet@gmail.com>
  62806. */
  62807. class AnyValuesToken implements \Prophecy\Argument\Token\TokenInterface
  62808. {
  62809. /**
  62810. * Always scores 2 for any argument.
  62811. *
  62812. * @param $argument
  62813. *
  62814. * @return int
  62815. */
  62816. public function scoreArgument($argument)
  62817. {
  62818. return 2;
  62819. }
  62820. /**
  62821. * Returns true to stop wildcard from processing other tokens.
  62822. *
  62823. * @return bool
  62824. */
  62825. public function isLast()
  62826. {
  62827. return \true;
  62828. }
  62829. /**
  62830. * Returns string representation for token.
  62831. *
  62832. * @return string
  62833. */
  62834. public function __toString()
  62835. {
  62836. return '* [, ...]';
  62837. }
  62838. }
  62839. <?php
  62840. /*
  62841. * This file is part of the Prophecy.
  62842. * (c) Konstantin Kudryashov <ever.zet@gmail.com>
  62843. * Marcello Duarte <marcello.duarte@gmail.com>
  62844. *
  62845. * For the full copyright and license information, please view the LICENSE
  62846. * file that was distributed with this source code.
  62847. */
  62848. namespace Prophecy\Argument\Token;
  62849. use PHPUnit\SebastianBergmann\Comparator\ComparisonFailure;
  62850. use Prophecy\Comparator\Factory as ComparatorFactory;
  62851. use Prophecy\Util\StringUtil;
  62852. /**
  62853. * Exact value token.
  62854. *
  62855. * @author Konstantin Kudryashov <ever.zet@gmail.com>
  62856. */
  62857. class ExactValueToken implements \Prophecy\Argument\Token\TokenInterface
  62858. {
  62859. private $value;
  62860. private $string;
  62861. private $util;
  62862. private $comparatorFactory;
  62863. /**
  62864. * Initializes token.
  62865. *
  62866. * @param mixed $value
  62867. * @param StringUtil $util
  62868. * @param ComparatorFactory $comparatorFactory
  62869. */
  62870. public function __construct($value, \Prophecy\Util\StringUtil $util = null, \Prophecy\Comparator\Factory $comparatorFactory = null)
  62871. {
  62872. $this->value = $value;
  62873. $this->util = $util ?: new \Prophecy\Util\StringUtil();
  62874. $this->comparatorFactory = $comparatorFactory ?: \Prophecy\Comparator\Factory::getInstance();
  62875. }
  62876. /**
  62877. * Scores 10 if argument matches preset value.
  62878. *
  62879. * @param $argument
  62880. *
  62881. * @return bool|int
  62882. */
  62883. public function scoreArgument($argument)
  62884. {
  62885. if (\is_object($argument) && \is_object($this->value)) {
  62886. $comparator = $this->comparatorFactory->getComparatorFor($argument, $this->value);
  62887. try {
  62888. $comparator->assertEquals($argument, $this->value);
  62889. return 10;
  62890. } catch (\PHPUnit\SebastianBergmann\Comparator\ComparisonFailure $failure) {
  62891. return \false;
  62892. }
  62893. }
  62894. // If either one is an object it should be castable to a string
  62895. if (\is_object($argument) xor \is_object($this->value)) {
  62896. if (\is_object($argument) && !\method_exists($argument, '__toString')) {
  62897. return \false;
  62898. }
  62899. if (\is_object($this->value) && !\method_exists($this->value, '__toString')) {
  62900. return \false;
  62901. }
  62902. } elseif (\is_numeric($argument) && \is_numeric($this->value)) {
  62903. // noop
  62904. } elseif (\gettype($argument) !== \gettype($this->value)) {
  62905. return \false;
  62906. }
  62907. return $argument == $this->value ? 10 : \false;
  62908. }
  62909. /**
  62910. * Returns preset value against which token checks arguments.
  62911. *
  62912. * @return mixed
  62913. */
  62914. public function getValue()
  62915. {
  62916. return $this->value;
  62917. }
  62918. /**
  62919. * Returns false.
  62920. *
  62921. * @return bool
  62922. */
  62923. public function isLast()
  62924. {
  62925. return \false;
  62926. }
  62927. /**
  62928. * Returns string representation for token.
  62929. *
  62930. * @return string
  62931. */
  62932. public function __toString()
  62933. {
  62934. if (null === $this->string) {
  62935. $this->string = \sprintf('exact(%s)', $this->util->stringify($this->value));
  62936. }
  62937. return $this->string;
  62938. }
  62939. }
  62940. <?php
  62941. /*
  62942. * This file is part of the Prophecy.
  62943. * (c) Konstantin Kudryashov <ever.zet@gmail.com>
  62944. * Marcello Duarte <marcello.duarte@gmail.com>
  62945. *
  62946. * For the full copyright and license information, please view the LICENSE
  62947. * file that was distributed with this source code.
  62948. */
  62949. namespace Prophecy\Argument\Token;
  62950. /**
  62951. * Array elements count token.
  62952. *
  62953. * @author Boris Mikhaylov <kaguxmail@gmail.com>
  62954. */
  62955. class ArrayCountToken implements \Prophecy\Argument\Token\TokenInterface
  62956. {
  62957. private $count;
  62958. /**
  62959. * @param integer $value
  62960. */
  62961. public function __construct($value)
  62962. {
  62963. $this->count = $value;
  62964. }
  62965. /**
  62966. * Scores 6 when argument has preset number of elements.
  62967. *
  62968. * @param $argument
  62969. *
  62970. * @return bool|int
  62971. */
  62972. public function scoreArgument($argument)
  62973. {
  62974. return $this->isCountable($argument) && $this->hasProperCount($argument) ? 6 : \false;
  62975. }
  62976. /**
  62977. * Returns false.
  62978. *
  62979. * @return boolean
  62980. */
  62981. public function isLast()
  62982. {
  62983. return \false;
  62984. }
  62985. /**
  62986. * Returns string representation for token.
  62987. *
  62988. * @return string
  62989. */
  62990. public function __toString()
  62991. {
  62992. return \sprintf('count(%s)', $this->count);
  62993. }
  62994. /**
  62995. * Returns true if object is either array or instance of \Countable
  62996. *
  62997. * @param $argument
  62998. * @return bool
  62999. */
  63000. private function isCountable($argument)
  63001. {
  63002. return \is_array($argument) || $argument instanceof \Countable;
  63003. }
  63004. /**
  63005. * Returns true if $argument has expected number of elements
  63006. *
  63007. * @param array|\Countable $argument
  63008. *
  63009. * @return bool
  63010. */
  63011. private function hasProperCount($argument)
  63012. {
  63013. return $this->count === \count($argument);
  63014. }
  63015. }
  63016. <?php
  63017. /*
  63018. * This file is part of the Prophecy.
  63019. * (c) Konstantin Kudryashov <ever.zet@gmail.com>
  63020. * Marcello Duarte <marcello.duarte@gmail.com>
  63021. *
  63022. * For the full copyright and license information, please view the LICENSE
  63023. * file that was distributed with this source code.
  63024. */
  63025. namespace Prophecy\Argument\Token;
  63026. /**
  63027. * String contains token.
  63028. *
  63029. * @author Peter Mitchell <pete@peterjmit.com>
  63030. */
  63031. class StringContainsToken implements \Prophecy\Argument\Token\TokenInterface
  63032. {
  63033. private $value;
  63034. /**
  63035. * Initializes token.
  63036. *
  63037. * @param string $value
  63038. */
  63039. public function __construct($value)
  63040. {
  63041. $this->value = $value;
  63042. }
  63043. public function scoreArgument($argument)
  63044. {
  63045. return \is_string($argument) && \strpos($argument, $this->value) !== \false ? 6 : \false;
  63046. }
  63047. /**
  63048. * Returns preset value against which token checks arguments.
  63049. *
  63050. * @return mixed
  63051. */
  63052. public function getValue()
  63053. {
  63054. return $this->value;
  63055. }
  63056. /**
  63057. * Returns false.
  63058. *
  63059. * @return bool
  63060. */
  63061. public function isLast()
  63062. {
  63063. return \false;
  63064. }
  63065. /**
  63066. * Returns string representation for token.
  63067. *
  63068. * @return string
  63069. */
  63070. public function __toString()
  63071. {
  63072. return \sprintf('contains("%s")', $this->value);
  63073. }
  63074. }
  63075. <?php
  63076. /*
  63077. * This file is part of the Prophecy.
  63078. * (c) Konstantin Kudryashov <ever.zet@gmail.com>
  63079. * Marcello Duarte <marcello.duarte@gmail.com>
  63080. *
  63081. * For the full copyright and license information, please view the LICENSE
  63082. * file that was distributed with this source code.
  63083. */
  63084. namespace Prophecy\Argument\Token;
  63085. /**
  63086. * Argument token interface.
  63087. *
  63088. * @author Konstantin Kudryashov <ever.zet@gmail.com>
  63089. */
  63090. interface TokenInterface
  63091. {
  63092. /**
  63093. * Calculates token match score for provided argument.
  63094. *
  63095. * @param $argument
  63096. *
  63097. * @return bool|int
  63098. */
  63099. public function scoreArgument($argument);
  63100. /**
  63101. * Returns true if this token prevents check of other tokens (is last one).
  63102. *
  63103. * @return bool|int
  63104. */
  63105. public function isLast();
  63106. /**
  63107. * Returns string representation for token.
  63108. *
  63109. * @return string
  63110. */
  63111. public function __toString();
  63112. }
  63113. <?php
  63114. /*
  63115. * This file is part of the Prophecy.
  63116. * (c) Konstantin Kudryashov <ever.zet@gmail.com>
  63117. * Marcello Duarte <marcello.duarte@gmail.com>
  63118. *
  63119. * For the full copyright and license information, please view the LICENSE
  63120. * file that was distributed with this source code.
  63121. */
  63122. namespace Prophecy\Argument\Token;
  63123. use Prophecy\Exception\InvalidArgumentException;
  63124. /**
  63125. * Callback-verified token.
  63126. *
  63127. * @author Konstantin Kudryashov <ever.zet@gmail.com>
  63128. */
  63129. class CallbackToken implements \Prophecy\Argument\Token\TokenInterface
  63130. {
  63131. private $callback;
  63132. /**
  63133. * Initializes token.
  63134. *
  63135. * @param callable $callback
  63136. *
  63137. * @throws \Prophecy\Exception\InvalidArgumentException
  63138. */
  63139. public function __construct($callback)
  63140. {
  63141. if (!\is_callable($callback)) {
  63142. throw new \Prophecy\Exception\InvalidArgumentException(\sprintf('Callable expected as an argument to CallbackToken, but got %s.', \gettype($callback)));
  63143. }
  63144. $this->callback = $callback;
  63145. }
  63146. /**
  63147. * Scores 7 if callback returns true, false otherwise.
  63148. *
  63149. * @param $argument
  63150. *
  63151. * @return bool|int
  63152. */
  63153. public function scoreArgument($argument)
  63154. {
  63155. return \call_user_func($this->callback, $argument) ? 7 : \false;
  63156. }
  63157. /**
  63158. * Returns false.
  63159. *
  63160. * @return bool
  63161. */
  63162. public function isLast()
  63163. {
  63164. return \false;
  63165. }
  63166. /**
  63167. * Returns string representation for token.
  63168. *
  63169. * @return string
  63170. */
  63171. public function __toString()
  63172. {
  63173. return 'callback()';
  63174. }
  63175. }
  63176. <?php
  63177. /*
  63178. * This file is part of the Prophecy.
  63179. * (c) Konstantin Kudryashov <ever.zet@gmail.com>
  63180. * Marcello Duarte <marcello.duarte@gmail.com>
  63181. *
  63182. * For the full copyright and license information, please view the LICENSE
  63183. * file that was distributed with this source code.
  63184. */
  63185. namespace Prophecy\Argument;
  63186. /**
  63187. * Arguments wildcarding.
  63188. *
  63189. * @author Konstantin Kudryashov <ever.zet@gmail.com>
  63190. */
  63191. class ArgumentsWildcard
  63192. {
  63193. /**
  63194. * @var Token\TokenInterface[]
  63195. */
  63196. private $tokens = array();
  63197. private $string;
  63198. /**
  63199. * Initializes wildcard.
  63200. *
  63201. * @param array $arguments Array of argument tokens or values
  63202. */
  63203. public function __construct(array $arguments)
  63204. {
  63205. foreach ($arguments as $argument) {
  63206. if (!$argument instanceof \Prophecy\Argument\Token\TokenInterface) {
  63207. $argument = new \Prophecy\Argument\Token\ExactValueToken($argument);
  63208. }
  63209. $this->tokens[] = $argument;
  63210. }
  63211. }
  63212. /**
  63213. * Calculates wildcard match score for provided arguments.
  63214. *
  63215. * @param array $arguments
  63216. *
  63217. * @return false|int False OR integer score (higher - better)
  63218. */
  63219. public function scoreArguments(array $arguments)
  63220. {
  63221. if (0 == \count($arguments) && 0 == \count($this->tokens)) {
  63222. return 1;
  63223. }
  63224. $arguments = \array_values($arguments);
  63225. $totalScore = 0;
  63226. foreach ($this->tokens as $i => $token) {
  63227. $argument = isset($arguments[$i]) ? $arguments[$i] : null;
  63228. if (1 >= ($score = $token->scoreArgument($argument))) {
  63229. return \false;
  63230. }
  63231. $totalScore += $score;
  63232. if (\true === $token->isLast()) {
  63233. return $totalScore;
  63234. }
  63235. }
  63236. if (\count($arguments) > \count($this->tokens)) {
  63237. return \false;
  63238. }
  63239. return $totalScore;
  63240. }
  63241. /**
  63242. * Returns string representation for wildcard.
  63243. *
  63244. * @return string
  63245. */
  63246. public function __toString()
  63247. {
  63248. if (null === $this->string) {
  63249. $this->string = \implode(', ', \array_map(function ($token) {
  63250. return (string) $token;
  63251. }, $this->tokens));
  63252. }
  63253. return $this->string;
  63254. }
  63255. /**
  63256. * @return array
  63257. */
  63258. public function getTokens()
  63259. {
  63260. return $this->tokens;
  63261. }
  63262. }
  63263. Copyright (c) 2013 Konstantin Kudryashov <ever.zet@gmail.com>
  63264. Marcello Duarte <marcello.duarte@gmail.com>
  63265. Permission is hereby granted, free of charge, to any person
  63266. obtaining a copy of this software and associated documentation
  63267. files (the "Software"), to deal in the Software without
  63268. restriction, including without limitation the rights to use,
  63269. copy, modify, merge, publish, distribute, sublicense, and/or sell
  63270. copies of the Software, and to permit persons to whom the
  63271. Software is furnished to do so, subject to the following
  63272. conditions:
  63273. The above copyright notice and this permission notice shall be
  63274. included in all copies or substantial portions of the Software.
  63275. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  63276. EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
  63277. OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  63278. NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
  63279. HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
  63280. WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  63281. FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  63282. OTHER DEALINGS IN THE SOFTWARE.
  63283. <?php
  63284. declare (strict_types=1);
  63285. /*
  63286. * This file is part of sebastian/diff.
  63287. *
  63288. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  63289. *
  63290. * For the full copyright and license information, please view the LICENSE
  63291. * file that was distributed with this source code.
  63292. */
  63293. namespace PHPUnit\SebastianBergmann\Diff\Output;
  63294. use PHPUnit\SebastianBergmann\Diff\Differ;
  63295. /**
  63296. * Builds a diff string representation in a loose unified diff format
  63297. * listing only changes lines. Does not include line numbers.
  63298. */
  63299. final class DiffOnlyOutputBuilder implements \PHPUnit\SebastianBergmann\Diff\Output\DiffOutputBuilderInterface
  63300. {
  63301. /**
  63302. * @var string
  63303. */
  63304. private $header;
  63305. public function __construct(string $header = "--- Original\n+++ New\n")
  63306. {
  63307. $this->header = $header;
  63308. }
  63309. public function getDiff(array $diff) : string
  63310. {
  63311. $buffer = \fopen('php://memory', 'r+b');
  63312. if ('' !== $this->header) {
  63313. \fwrite($buffer, $this->header);
  63314. if ("\n" !== \substr($this->header, -1, 1)) {
  63315. \fwrite($buffer, "\n");
  63316. }
  63317. }
  63318. foreach ($diff as $diffEntry) {
  63319. if ($diffEntry[1] === \PHPUnit\SebastianBergmann\Diff\Differ::ADDED) {
  63320. \fwrite($buffer, '+' . $diffEntry[0]);
  63321. } elseif ($diffEntry[1] === \PHPUnit\SebastianBergmann\Diff\Differ::REMOVED) {
  63322. \fwrite($buffer, '-' . $diffEntry[0]);
  63323. } elseif ($diffEntry[1] === \PHPUnit\SebastianBergmann\Diff\Differ::DIFF_LINE_END_WARNING) {
  63324. \fwrite($buffer, ' ' . $diffEntry[0]);
  63325. continue;
  63326. // Warnings should not be tested for line break, it will always be there
  63327. } else {
  63328. /* Not changed (old) 0 */
  63329. continue;
  63330. // we didn't write the non changs line, so do not add a line break either
  63331. }
  63332. $lc = \substr($diffEntry[0], -1);
  63333. if ($lc !== "\n" && $lc !== "\r") {
  63334. \fwrite($buffer, "\n");
  63335. // \No newline at end of file
  63336. }
  63337. }
  63338. $diff = \stream_get_contents($buffer, -1, 0);
  63339. \fclose($buffer);
  63340. return $diff;
  63341. }
  63342. }
  63343. <?php
  63344. declare (strict_types=1);
  63345. /*
  63346. * This file is part of sebastian/diff.
  63347. *
  63348. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  63349. *
  63350. * For the full copyright and license information, please view the LICENSE
  63351. * file that was distributed with this source code.
  63352. */
  63353. namespace PHPUnit\SebastianBergmann\Diff\Output;
  63354. /**
  63355. * Defines how an output builder should take a generated
  63356. * diff array and return a string representation of that diff.
  63357. */
  63358. interface DiffOutputBuilderInterface
  63359. {
  63360. public function getDiff(array $diff) : string;
  63361. }
  63362. <?php
  63363. declare (strict_types=1);
  63364. /*
  63365. * This file is part of sebastian/diff.
  63366. *
  63367. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  63368. *
  63369. * For the full copyright and license information, please view the LICENSE
  63370. * file that was distributed with this source code.
  63371. */
  63372. namespace PHPUnit\SebastianBergmann\Diff\Output;
  63373. use PHPUnit\SebastianBergmann\Diff\Differ;
  63374. /**
  63375. * Builds a diff string representation in unified diff format in chunks.
  63376. */
  63377. final class UnifiedDiffOutputBuilder extends \PHPUnit\SebastianBergmann\Diff\Output\AbstractChunkOutputBuilder
  63378. {
  63379. /**
  63380. * @var bool
  63381. */
  63382. private $collapseRanges = \true;
  63383. /**
  63384. * @var int >= 0
  63385. */
  63386. private $commonLineThreshold = 6;
  63387. /**
  63388. * @var int >= 0
  63389. */
  63390. private $contextLines = 3;
  63391. /**
  63392. * @var string
  63393. */
  63394. private $header;
  63395. /**
  63396. * @var bool
  63397. */
  63398. private $addLineNumbers;
  63399. public function __construct(string $header = "--- Original\n+++ New\n", bool $addLineNumbers = \false)
  63400. {
  63401. $this->header = $header;
  63402. $this->addLineNumbers = $addLineNumbers;
  63403. }
  63404. public function getDiff(array $diff) : string
  63405. {
  63406. $buffer = \fopen('php://memory', 'r+b');
  63407. if ('' !== $this->header) {
  63408. \fwrite($buffer, $this->header);
  63409. if ("\n" !== \substr($this->header, -1, 1)) {
  63410. \fwrite($buffer, "\n");
  63411. }
  63412. }
  63413. if (0 !== \count($diff)) {
  63414. $this->writeDiffHunks($buffer, $diff);
  63415. }
  63416. $diff = \stream_get_contents($buffer, -1, 0);
  63417. \fclose($buffer);
  63418. // If the diff is non-empty and last char is not a linebreak: add it.
  63419. // This might happen when both the `from` and `to` do not have a trailing linebreak
  63420. $last = \substr($diff, -1);
  63421. return 0 !== \strlen($diff) && "\n" !== $last && "\r" !== $last ? $diff . "\n" : $diff;
  63422. }
  63423. private function writeDiffHunks($output, array $diff) : void
  63424. {
  63425. // detect "No newline at end of file" and insert into `$diff` if needed
  63426. $upperLimit = \count($diff);
  63427. if (0 === $diff[$upperLimit - 1][1]) {
  63428. $lc = \substr($diff[$upperLimit - 1][0], -1);
  63429. if ("\n" !== $lc) {
  63430. \array_splice($diff, $upperLimit, 0, [["\n\\ No newline at end of file\n", \PHPUnit\SebastianBergmann\Diff\Differ::NO_LINE_END_EOF_WARNING]]);
  63431. }
  63432. } else {
  63433. // search back for the last `+` and `-` line,
  63434. // check if has trailing linebreak, else add under it warning under it
  63435. $toFind = [1 => \true, 2 => \true];
  63436. for ($i = $upperLimit - 1; $i >= 0; --$i) {
  63437. if (isset($toFind[$diff[$i][1]])) {
  63438. unset($toFind[$diff[$i][1]]);
  63439. $lc = \substr($diff[$i][0], -1);
  63440. if ("\n" !== $lc) {
  63441. \array_splice($diff, $i + 1, 0, [["\n\\ No newline at end of file\n", \PHPUnit\SebastianBergmann\Diff\Differ::NO_LINE_END_EOF_WARNING]]);
  63442. }
  63443. if (!\count($toFind)) {
  63444. break;
  63445. }
  63446. }
  63447. }
  63448. }
  63449. // write hunks to output buffer
  63450. $cutOff = \max($this->commonLineThreshold, $this->contextLines);
  63451. $hunkCapture = \false;
  63452. $sameCount = $toRange = $fromRange = 0;
  63453. $toStart = $fromStart = 1;
  63454. $i = 0;
  63455. /** @var int $i */
  63456. foreach ($diff as $i => $entry) {
  63457. if (0 === $entry[1]) {
  63458. // same
  63459. if (\false === $hunkCapture) {
  63460. ++$fromStart;
  63461. ++$toStart;
  63462. continue;
  63463. }
  63464. ++$sameCount;
  63465. ++$toRange;
  63466. ++$fromRange;
  63467. if ($sameCount === $cutOff) {
  63468. $contextStartOffset = $hunkCapture - $this->contextLines < 0 ? $hunkCapture : $this->contextLines;
  63469. // note: $contextEndOffset = $this->contextLines;
  63470. //
  63471. // because we never go beyond the end of the diff.
  63472. // with the cutoff/contextlines here the follow is never true;
  63473. //
  63474. // if ($i - $cutOff + $this->contextLines + 1 > \count($diff)) {
  63475. // $contextEndOffset = count($diff) - 1;
  63476. // }
  63477. //
  63478. // ; that would be true for a trailing incomplete hunk case which is dealt with after this loop
  63479. $this->writeHunk($diff, $hunkCapture - $contextStartOffset, $i - $cutOff + $this->contextLines + 1, $fromStart - $contextStartOffset, $fromRange - $cutOff + $contextStartOffset + $this->contextLines, $toStart - $contextStartOffset, $toRange - $cutOff + $contextStartOffset + $this->contextLines, $output);
  63480. $fromStart += $fromRange;
  63481. $toStart += $toRange;
  63482. $hunkCapture = \false;
  63483. $sameCount = $toRange = $fromRange = 0;
  63484. }
  63485. continue;
  63486. }
  63487. $sameCount = 0;
  63488. if ($entry[1] === \PHPUnit\SebastianBergmann\Diff\Differ::NO_LINE_END_EOF_WARNING) {
  63489. continue;
  63490. }
  63491. if (\false === $hunkCapture) {
  63492. $hunkCapture = $i;
  63493. }
  63494. if (\PHPUnit\SebastianBergmann\Diff\Differ::ADDED === $entry[1]) {
  63495. ++$toRange;
  63496. }
  63497. if (\PHPUnit\SebastianBergmann\Diff\Differ::REMOVED === $entry[1]) {
  63498. ++$fromRange;
  63499. }
  63500. }
  63501. if (\false === $hunkCapture) {
  63502. return;
  63503. }
  63504. // we end here when cutoff (commonLineThreshold) was not reached, but we where capturing a hunk,
  63505. // do not render hunk till end automatically because the number of context lines might be less than the commonLineThreshold
  63506. $contextStartOffset = $hunkCapture - $this->contextLines < 0 ? $hunkCapture : $this->contextLines;
  63507. // prevent trying to write out more common lines than there are in the diff _and_
  63508. // do not write more than configured through the context lines
  63509. $contextEndOffset = \min($sameCount, $this->contextLines);
  63510. $fromRange -= $sameCount;
  63511. $toRange -= $sameCount;
  63512. $this->writeHunk($diff, $hunkCapture - $contextStartOffset, $i - $sameCount + $contextEndOffset + 1, $fromStart - $contextStartOffset, $fromRange + $contextStartOffset + $contextEndOffset, $toStart - $contextStartOffset, $toRange + $contextStartOffset + $contextEndOffset, $output);
  63513. }
  63514. private function writeHunk(array $diff, int $diffStartIndex, int $diffEndIndex, int $fromStart, int $fromRange, int $toStart, int $toRange, $output) : void
  63515. {
  63516. if ($this->addLineNumbers) {
  63517. \fwrite($output, '@@ -' . $fromStart);
  63518. if (!$this->collapseRanges || 1 !== $fromRange) {
  63519. \fwrite($output, ',' . $fromRange);
  63520. }
  63521. \fwrite($output, ' +' . $toStart);
  63522. if (!$this->collapseRanges || 1 !== $toRange) {
  63523. \fwrite($output, ',' . $toRange);
  63524. }
  63525. \fwrite($output, " @@\n");
  63526. } else {
  63527. \fwrite($output, "@@ @@\n");
  63528. }
  63529. for ($i = $diffStartIndex; $i < $diffEndIndex; ++$i) {
  63530. if ($diff[$i][1] === \PHPUnit\SebastianBergmann\Diff\Differ::ADDED) {
  63531. \fwrite($output, '+' . $diff[$i][0]);
  63532. } elseif ($diff[$i][1] === \PHPUnit\SebastianBergmann\Diff\Differ::REMOVED) {
  63533. \fwrite($output, '-' . $diff[$i][0]);
  63534. } elseif ($diff[$i][1] === \PHPUnit\SebastianBergmann\Diff\Differ::OLD) {
  63535. \fwrite($output, ' ' . $diff[$i][0]);
  63536. } elseif ($diff[$i][1] === \PHPUnit\SebastianBergmann\Diff\Differ::NO_LINE_END_EOF_WARNING) {
  63537. \fwrite($output, "\n");
  63538. // $diff[$i][0]
  63539. } else {
  63540. /* Not changed (old) Differ::OLD or Warning Differ::DIFF_LINE_END_WARNING */
  63541. \fwrite($output, ' ' . $diff[$i][0]);
  63542. }
  63543. }
  63544. }
  63545. }
  63546. <?php
  63547. declare (strict_types=1);
  63548. /*
  63549. * This file is part of sebastian/diff.
  63550. *
  63551. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  63552. *
  63553. * For the full copyright and license information, please view the LICENSE
  63554. * file that was distributed with this source code.
  63555. */
  63556. namespace PHPUnit\SebastianBergmann\Diff\Output;
  63557. use PHPUnit\SebastianBergmann\Diff\ConfigurationException;
  63558. use PHPUnit\SebastianBergmann\Diff\Differ;
  63559. /**
  63560. * Strict Unified diff output builder.
  63561. *
  63562. * Generates (strict) Unified diff's (unidiffs) with hunks.
  63563. */
  63564. final class StrictUnifiedDiffOutputBuilder implements \PHPUnit\SebastianBergmann\Diff\Output\DiffOutputBuilderInterface
  63565. {
  63566. private static $default = [
  63567. 'collapseRanges' => \true,
  63568. // ranges of length one are rendered with the trailing `,1`
  63569. 'commonLineThreshold' => 6,
  63570. // number of same lines before ending a new hunk and creating a new one (if needed)
  63571. 'contextLines' => 3,
  63572. // like `diff: -u, -U NUM, --unified[=NUM]`, for patch/git apply compatibility best to keep at least @ 3
  63573. 'fromFile' => null,
  63574. 'fromFileDate' => null,
  63575. 'toFile' => null,
  63576. 'toFileDate' => null,
  63577. ];
  63578. /**
  63579. * @var bool
  63580. */
  63581. private $changed;
  63582. /**
  63583. * @var bool
  63584. */
  63585. private $collapseRanges;
  63586. /**
  63587. * @var int >= 0
  63588. */
  63589. private $commonLineThreshold;
  63590. /**
  63591. * @var string
  63592. */
  63593. private $header;
  63594. /**
  63595. * @var int >= 0
  63596. */
  63597. private $contextLines;
  63598. public function __construct(array $options = [])
  63599. {
  63600. $options = \array_merge(self::$default, $options);
  63601. if (!\is_bool($options['collapseRanges'])) {
  63602. throw new \PHPUnit\SebastianBergmann\Diff\ConfigurationException('collapseRanges', 'a bool', $options['collapseRanges']);
  63603. }
  63604. if (!\is_int($options['contextLines']) || $options['contextLines'] < 0) {
  63605. throw new \PHPUnit\SebastianBergmann\Diff\ConfigurationException('contextLines', 'an int >= 0', $options['contextLines']);
  63606. }
  63607. if (!\is_int($options['commonLineThreshold']) || $options['commonLineThreshold'] <= 0) {
  63608. throw new \PHPUnit\SebastianBergmann\Diff\ConfigurationException('commonLineThreshold', 'an int > 0', $options['commonLineThreshold']);
  63609. }
  63610. $this->assertString($options, 'fromFile');
  63611. $this->assertString($options, 'toFile');
  63612. $this->assertStringOrNull($options, 'fromFileDate');
  63613. $this->assertStringOrNull($options, 'toFileDate');
  63614. $this->header = \sprintf("--- %s%s\n+++ %s%s\n", $options['fromFile'], null === $options['fromFileDate'] ? '' : "\t" . $options['fromFileDate'], $options['toFile'], null === $options['toFileDate'] ? '' : "\t" . $options['toFileDate']);
  63615. $this->collapseRanges = $options['collapseRanges'];
  63616. $this->commonLineThreshold = $options['commonLineThreshold'];
  63617. $this->contextLines = $options['contextLines'];
  63618. }
  63619. public function getDiff(array $diff) : string
  63620. {
  63621. if (0 === \count($diff)) {
  63622. return '';
  63623. }
  63624. $this->changed = \false;
  63625. $buffer = \fopen('php://memory', 'r+b');
  63626. \fwrite($buffer, $this->header);
  63627. $this->writeDiffHunks($buffer, $diff);
  63628. if (!$this->changed) {
  63629. \fclose($buffer);
  63630. return '';
  63631. }
  63632. $diff = \stream_get_contents($buffer, -1, 0);
  63633. \fclose($buffer);
  63634. // If the last char is not a linebreak: add it.
  63635. // This might happen when both the `from` and `to` do not have a trailing linebreak
  63636. $last = \substr($diff, -1);
  63637. return "\n" !== $last && "\r" !== $last ? $diff . "\n" : $diff;
  63638. }
  63639. private function writeDiffHunks($output, array $diff) : void
  63640. {
  63641. // detect "No newline at end of file" and insert into `$diff` if needed
  63642. $upperLimit = \count($diff);
  63643. if (0 === $diff[$upperLimit - 1][1]) {
  63644. $lc = \substr($diff[$upperLimit - 1][0], -1);
  63645. if ("\n" !== $lc) {
  63646. \array_splice($diff, $upperLimit, 0, [["\n\\ No newline at end of file\n", \PHPUnit\SebastianBergmann\Diff\Differ::NO_LINE_END_EOF_WARNING]]);
  63647. }
  63648. } else {
  63649. // search back for the last `+` and `-` line,
  63650. // check if has trailing linebreak, else add under it warning under it
  63651. $toFind = [1 => \true, 2 => \true];
  63652. for ($i = $upperLimit - 1; $i >= 0; --$i) {
  63653. if (isset($toFind[$diff[$i][1]])) {
  63654. unset($toFind[$diff[$i][1]]);
  63655. $lc = \substr($diff[$i][0], -1);
  63656. if ("\n" !== $lc) {
  63657. \array_splice($diff, $i + 1, 0, [["\n\\ No newline at end of file\n", \PHPUnit\SebastianBergmann\Diff\Differ::NO_LINE_END_EOF_WARNING]]);
  63658. }
  63659. if (!\count($toFind)) {
  63660. break;
  63661. }
  63662. }
  63663. }
  63664. }
  63665. // write hunks to output buffer
  63666. $cutOff = \max($this->commonLineThreshold, $this->contextLines);
  63667. $hunkCapture = \false;
  63668. $sameCount = $toRange = $fromRange = 0;
  63669. $toStart = $fromStart = 1;
  63670. $i = 0;
  63671. /** @var int $i */
  63672. foreach ($diff as $i => $entry) {
  63673. if (0 === $entry[1]) {
  63674. // same
  63675. if (\false === $hunkCapture) {
  63676. ++$fromStart;
  63677. ++$toStart;
  63678. continue;
  63679. }
  63680. ++$sameCount;
  63681. ++$toRange;
  63682. ++$fromRange;
  63683. if ($sameCount === $cutOff) {
  63684. $contextStartOffset = $hunkCapture - $this->contextLines < 0 ? $hunkCapture : $this->contextLines;
  63685. // note: $contextEndOffset = $this->contextLines;
  63686. //
  63687. // because we never go beyond the end of the diff.
  63688. // with the cutoff/contextlines here the follow is never true;
  63689. //
  63690. // if ($i - $cutOff + $this->contextLines + 1 > \count($diff)) {
  63691. // $contextEndOffset = count($diff) - 1;
  63692. // }
  63693. //
  63694. // ; that would be true for a trailing incomplete hunk case which is dealt with after this loop
  63695. $this->writeHunk($diff, $hunkCapture - $contextStartOffset, $i - $cutOff + $this->contextLines + 1, $fromStart - $contextStartOffset, $fromRange - $cutOff + $contextStartOffset + $this->contextLines, $toStart - $contextStartOffset, $toRange - $cutOff + $contextStartOffset + $this->contextLines, $output);
  63696. $fromStart += $fromRange;
  63697. $toStart += $toRange;
  63698. $hunkCapture = \false;
  63699. $sameCount = $toRange = $fromRange = 0;
  63700. }
  63701. continue;
  63702. }
  63703. $sameCount = 0;
  63704. if ($entry[1] === \PHPUnit\SebastianBergmann\Diff\Differ::NO_LINE_END_EOF_WARNING) {
  63705. continue;
  63706. }
  63707. $this->changed = \true;
  63708. if (\false === $hunkCapture) {
  63709. $hunkCapture = $i;
  63710. }
  63711. if (\PHPUnit\SebastianBergmann\Diff\Differ::ADDED === $entry[1]) {
  63712. // added
  63713. ++$toRange;
  63714. }
  63715. if (\PHPUnit\SebastianBergmann\Diff\Differ::REMOVED === $entry[1]) {
  63716. // removed
  63717. ++$fromRange;
  63718. }
  63719. }
  63720. if (\false === $hunkCapture) {
  63721. return;
  63722. }
  63723. // we end here when cutoff (commonLineThreshold) was not reached, but we where capturing a hunk,
  63724. // do not render hunk till end automatically because the number of context lines might be less than the commonLineThreshold
  63725. $contextStartOffset = $hunkCapture - $this->contextLines < 0 ? $hunkCapture : $this->contextLines;
  63726. // prevent trying to write out more common lines than there are in the diff _and_
  63727. // do not write more than configured through the context lines
  63728. $contextEndOffset = \min($sameCount, $this->contextLines);
  63729. $fromRange -= $sameCount;
  63730. $toRange -= $sameCount;
  63731. $this->writeHunk($diff, $hunkCapture - $contextStartOffset, $i - $sameCount + $contextEndOffset + 1, $fromStart - $contextStartOffset, $fromRange + $contextStartOffset + $contextEndOffset, $toStart - $contextStartOffset, $toRange + $contextStartOffset + $contextEndOffset, $output);
  63732. }
  63733. private function writeHunk(array $diff, int $diffStartIndex, int $diffEndIndex, int $fromStart, int $fromRange, int $toStart, int $toRange, $output) : void
  63734. {
  63735. \fwrite($output, '@@ -' . $fromStart);
  63736. if (!$this->collapseRanges || 1 !== $fromRange) {
  63737. \fwrite($output, ',' . $fromRange);
  63738. }
  63739. \fwrite($output, ' +' . $toStart);
  63740. if (!$this->collapseRanges || 1 !== $toRange) {
  63741. \fwrite($output, ',' . $toRange);
  63742. }
  63743. \fwrite($output, " @@\n");
  63744. for ($i = $diffStartIndex; $i < $diffEndIndex; ++$i) {
  63745. if ($diff[$i][1] === \PHPUnit\SebastianBergmann\Diff\Differ::ADDED) {
  63746. $this->changed = \true;
  63747. \fwrite($output, '+' . $diff[$i][0]);
  63748. } elseif ($diff[$i][1] === \PHPUnit\SebastianBergmann\Diff\Differ::REMOVED) {
  63749. $this->changed = \true;
  63750. \fwrite($output, '-' . $diff[$i][0]);
  63751. } elseif ($diff[$i][1] === \PHPUnit\SebastianBergmann\Diff\Differ::OLD) {
  63752. \fwrite($output, ' ' . $diff[$i][0]);
  63753. } elseif ($diff[$i][1] === \PHPUnit\SebastianBergmann\Diff\Differ::NO_LINE_END_EOF_WARNING) {
  63754. $this->changed = \true;
  63755. \fwrite($output, $diff[$i][0]);
  63756. }
  63757. //} elseif ($diff[$i][1] === Differ::DIFF_LINE_END_WARNING) { // custom comment inserted by PHPUnit/diff package
  63758. // skip
  63759. //} else {
  63760. // unknown/invalid
  63761. //}
  63762. }
  63763. }
  63764. private function assertString(array $options, string $option) : void
  63765. {
  63766. if (!\is_string($options[$option])) {
  63767. throw new \PHPUnit\SebastianBergmann\Diff\ConfigurationException($option, 'a string', $options[$option]);
  63768. }
  63769. }
  63770. private function assertStringOrNull(array $options, string $option) : void
  63771. {
  63772. if (null !== $options[$option] && !\is_string($options[$option])) {
  63773. throw new \PHPUnit\SebastianBergmann\Diff\ConfigurationException($option, 'a string or <null>', $options[$option]);
  63774. }
  63775. }
  63776. }
  63777. <?php
  63778. declare (strict_types=1);
  63779. /*
  63780. * This file is part of sebastian/diff.
  63781. *
  63782. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  63783. *
  63784. * For the full copyright and license information, please view the LICENSE
  63785. * file that was distributed with this source code.
  63786. */
  63787. namespace PHPUnit\SebastianBergmann\Diff\Output;
  63788. abstract class AbstractChunkOutputBuilder implements \PHPUnit\SebastianBergmann\Diff\Output\DiffOutputBuilderInterface
  63789. {
  63790. /**
  63791. * Takes input of the diff array and returns the common parts.
  63792. * Iterates through diff line by line.
  63793. */
  63794. protected function getCommonChunks(array $diff, int $lineThreshold = 5) : array
  63795. {
  63796. $diffSize = \count($diff);
  63797. $capturing = \false;
  63798. $chunkStart = 0;
  63799. $chunkSize = 0;
  63800. $commonChunks = [];
  63801. for ($i = 0; $i < $diffSize; ++$i) {
  63802. if ($diff[$i][1] === 0) {
  63803. if ($capturing === \false) {
  63804. $capturing = \true;
  63805. $chunkStart = $i;
  63806. $chunkSize = 0;
  63807. } else {
  63808. ++$chunkSize;
  63809. }
  63810. } elseif ($capturing !== \false) {
  63811. if ($chunkSize >= $lineThreshold) {
  63812. $commonChunks[$chunkStart] = $chunkStart + $chunkSize;
  63813. }
  63814. $capturing = \false;
  63815. }
  63816. }
  63817. if ($capturing !== \false && $chunkSize >= $lineThreshold) {
  63818. $commonChunks[$chunkStart] = $chunkStart + $chunkSize;
  63819. }
  63820. return $commonChunks;
  63821. }
  63822. }
  63823. <?php
  63824. declare (strict_types=1);
  63825. /*
  63826. * This file is part of sebastian/diff.
  63827. *
  63828. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  63829. *
  63830. * For the full copyright and license information, please view the LICENSE
  63831. * file that was distributed with this source code.
  63832. */
  63833. namespace PHPUnit\SebastianBergmann\Diff;
  63834. final class ConfigurationException extends \PHPUnit\SebastianBergmann\Diff\InvalidArgumentException
  63835. {
  63836. public function __construct(string $option, string $expected, $value, int $code = 0, \Exception $previous = null)
  63837. {
  63838. parent::__construct(\sprintf('Option "%s" must be %s, got "%s".', $option, $expected, \is_object($value) ? \get_class($value) : (null === $value ? '<null>' : \gettype($value) . '#' . $value)), $code, $previous);
  63839. }
  63840. }
  63841. <?php
  63842. declare (strict_types=1);
  63843. /*
  63844. * This file is part of sebastian/diff.
  63845. *
  63846. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  63847. *
  63848. * For the full copyright and license information, please view the LICENSE
  63849. * file that was distributed with this source code.
  63850. */
  63851. namespace PHPUnit\SebastianBergmann\Diff;
  63852. interface Exception
  63853. {
  63854. }
  63855. <?php
  63856. declare (strict_types=1);
  63857. /*
  63858. * This file is part of sebastian/diff.
  63859. *
  63860. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  63861. *
  63862. * For the full copyright and license information, please view the LICENSE
  63863. * file that was distributed with this source code.
  63864. */
  63865. namespace PHPUnit\SebastianBergmann\Diff;
  63866. class InvalidArgumentException extends \InvalidArgumentException implements \PHPUnit\SebastianBergmann\Diff\Exception
  63867. {
  63868. }
  63869. <?php
  63870. declare (strict_types=1);
  63871. /*
  63872. * This file is part of sebastian/diff.
  63873. *
  63874. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  63875. *
  63876. * For the full copyright and license information, please view the LICENSE
  63877. * file that was distributed with this source code.
  63878. */
  63879. namespace PHPUnit\SebastianBergmann\Diff;
  63880. final class TimeEfficientLongestCommonSubsequenceCalculator implements \PHPUnit\SebastianBergmann\Diff\LongestCommonSubsequenceCalculator
  63881. {
  63882. /**
  63883. * {@inheritdoc}
  63884. */
  63885. public function calculate(array $from, array $to) : array
  63886. {
  63887. $common = [];
  63888. $fromLength = \count($from);
  63889. $toLength = \count($to);
  63890. $width = $fromLength + 1;
  63891. $matrix = new \SplFixedArray($width * ($toLength + 1));
  63892. for ($i = 0; $i <= $fromLength; ++$i) {
  63893. $matrix[$i] = 0;
  63894. }
  63895. for ($j = 0; $j <= $toLength; ++$j) {
  63896. $matrix[$j * $width] = 0;
  63897. }
  63898. for ($i = 1; $i <= $fromLength; ++$i) {
  63899. for ($j = 1; $j <= $toLength; ++$j) {
  63900. $o = $j * $width + $i;
  63901. $matrix[$o] = \max($matrix[$o - 1], $matrix[$o - $width], $from[$i - 1] === $to[$j - 1] ? $matrix[$o - $width - 1] + 1 : 0);
  63902. }
  63903. }
  63904. $i = $fromLength;
  63905. $j = $toLength;
  63906. while ($i > 0 && $j > 0) {
  63907. if ($from[$i - 1] === $to[$j - 1]) {
  63908. $common[] = $from[$i - 1];
  63909. --$i;
  63910. --$j;
  63911. } else {
  63912. $o = $j * $width + $i;
  63913. if ($matrix[$o - $width] > $matrix[$o - 1]) {
  63914. --$j;
  63915. } else {
  63916. --$i;
  63917. }
  63918. }
  63919. }
  63920. return \array_reverse($common);
  63921. }
  63922. }
  63923. <?php
  63924. declare (strict_types=1);
  63925. /*
  63926. * This file is part of sebastian/diff.
  63927. *
  63928. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  63929. *
  63930. * For the full copyright and license information, please view the LICENSE
  63931. * file that was distributed with this source code.
  63932. */
  63933. namespace PHPUnit\SebastianBergmann\Diff;
  63934. final class MemoryEfficientLongestCommonSubsequenceCalculator implements \PHPUnit\SebastianBergmann\Diff\LongestCommonSubsequenceCalculator
  63935. {
  63936. /**
  63937. * {@inheritdoc}
  63938. */
  63939. public function calculate(array $from, array $to) : array
  63940. {
  63941. $cFrom = \count($from);
  63942. $cTo = \count($to);
  63943. if ($cFrom === 0) {
  63944. return [];
  63945. }
  63946. if ($cFrom === 1) {
  63947. if (\in_array($from[0], $to, \true)) {
  63948. return [$from[0]];
  63949. }
  63950. return [];
  63951. }
  63952. $i = (int) ($cFrom / 2);
  63953. $fromStart = \array_slice($from, 0, $i);
  63954. $fromEnd = \array_slice($from, $i);
  63955. $llB = $this->length($fromStart, $to);
  63956. $llE = $this->length(\array_reverse($fromEnd), \array_reverse($to));
  63957. $jMax = 0;
  63958. $max = 0;
  63959. for ($j = 0; $j <= $cTo; $j++) {
  63960. $m = $llB[$j] + $llE[$cTo - $j];
  63961. if ($m >= $max) {
  63962. $max = $m;
  63963. $jMax = $j;
  63964. }
  63965. }
  63966. $toStart = \array_slice($to, 0, $jMax);
  63967. $toEnd = \array_slice($to, $jMax);
  63968. return \array_merge($this->calculate($fromStart, $toStart), $this->calculate($fromEnd, $toEnd));
  63969. }
  63970. private function length(array $from, array $to) : array
  63971. {
  63972. $current = \array_fill(0, \count($to) + 1, 0);
  63973. $cFrom = \count($from);
  63974. $cTo = \count($to);
  63975. for ($i = 0; $i < $cFrom; $i++) {
  63976. $prev = $current;
  63977. for ($j = 0; $j < $cTo; $j++) {
  63978. if ($from[$i] === $to[$j]) {
  63979. $current[$j + 1] = $prev[$j] + 1;
  63980. } else {
  63981. $current[$j + 1] = \max($current[$j], $prev[$j + 1]);
  63982. }
  63983. }
  63984. }
  63985. return $current;
  63986. }
  63987. }
  63988. <?php
  63989. declare (strict_types=1);
  63990. /*
  63991. * This file is part of sebastian/diff.
  63992. *
  63993. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  63994. *
  63995. * For the full copyright and license information, please view the LICENSE
  63996. * file that was distributed with this source code.
  63997. */
  63998. namespace PHPUnit\SebastianBergmann\Diff;
  63999. final class Chunk
  64000. {
  64001. /**
  64002. * @var int
  64003. */
  64004. private $start;
  64005. /**
  64006. * @var int
  64007. */
  64008. private $startRange;
  64009. /**
  64010. * @var int
  64011. */
  64012. private $end;
  64013. /**
  64014. * @var int
  64015. */
  64016. private $endRange;
  64017. /**
  64018. * @var Line[]
  64019. */
  64020. private $lines;
  64021. public function __construct(int $start = 0, int $startRange = 1, int $end = 0, int $endRange = 1, array $lines = [])
  64022. {
  64023. $this->start = $start;
  64024. $this->startRange = $startRange;
  64025. $this->end = $end;
  64026. $this->endRange = $endRange;
  64027. $this->lines = $lines;
  64028. }
  64029. public function getStart() : int
  64030. {
  64031. return $this->start;
  64032. }
  64033. public function getStartRange() : int
  64034. {
  64035. return $this->startRange;
  64036. }
  64037. public function getEnd() : int
  64038. {
  64039. return $this->end;
  64040. }
  64041. public function getEndRange() : int
  64042. {
  64043. return $this->endRange;
  64044. }
  64045. /**
  64046. * @return Line[]
  64047. */
  64048. public function getLines() : array
  64049. {
  64050. return $this->lines;
  64051. }
  64052. /**
  64053. * @param Line[] $lines
  64054. */
  64055. public function setLines(array $lines) : void
  64056. {
  64057. foreach ($lines as $line) {
  64058. if (!$line instanceof \PHPUnit\SebastianBergmann\Diff\Line) {
  64059. throw new \PHPUnit\SebastianBergmann\Diff\InvalidArgumentException();
  64060. }
  64061. }
  64062. $this->lines = $lines;
  64063. }
  64064. }
  64065. <?php
  64066. declare (strict_types=1);
  64067. /*
  64068. * This file is part of sebastian/diff.
  64069. *
  64070. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  64071. *
  64072. * For the full copyright and license information, please view the LICENSE
  64073. * file that was distributed with this source code.
  64074. */
  64075. namespace PHPUnit\SebastianBergmann\Diff;
  64076. final class Diff
  64077. {
  64078. /**
  64079. * @var string
  64080. */
  64081. private $from;
  64082. /**
  64083. * @var string
  64084. */
  64085. private $to;
  64086. /**
  64087. * @var Chunk[]
  64088. */
  64089. private $chunks;
  64090. /**
  64091. * @param Chunk[] $chunks
  64092. */
  64093. public function __construct(string $from, string $to, array $chunks = [])
  64094. {
  64095. $this->from = $from;
  64096. $this->to = $to;
  64097. $this->chunks = $chunks;
  64098. }
  64099. public function getFrom() : string
  64100. {
  64101. return $this->from;
  64102. }
  64103. public function getTo() : string
  64104. {
  64105. return $this->to;
  64106. }
  64107. /**
  64108. * @return Chunk[]
  64109. */
  64110. public function getChunks() : array
  64111. {
  64112. return $this->chunks;
  64113. }
  64114. /**
  64115. * @param Chunk[] $chunks
  64116. */
  64117. public function setChunks(array $chunks) : void
  64118. {
  64119. $this->chunks = $chunks;
  64120. }
  64121. }
  64122. <?php
  64123. declare (strict_types=1);
  64124. /*
  64125. * This file is part of sebastian/diff.
  64126. *
  64127. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  64128. *
  64129. * For the full copyright and license information, please view the LICENSE
  64130. * file that was distributed with this source code.
  64131. */
  64132. namespace PHPUnit\SebastianBergmann\Diff;
  64133. interface LongestCommonSubsequenceCalculator
  64134. {
  64135. /**
  64136. * Calculates the longest common subsequence of two arrays.
  64137. */
  64138. public function calculate(array $from, array $to) : array;
  64139. }
  64140. <?php
  64141. declare (strict_types=1);
  64142. /*
  64143. * This file is part of sebastian/diff.
  64144. *
  64145. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  64146. *
  64147. * For the full copyright and license information, please view the LICENSE
  64148. * file that was distributed with this source code.
  64149. */
  64150. namespace PHPUnit\SebastianBergmann\Diff;
  64151. use PHPUnit\SebastianBergmann\Diff\Output\DiffOutputBuilderInterface;
  64152. use PHPUnit\SebastianBergmann\Diff\Output\UnifiedDiffOutputBuilder;
  64153. /**
  64154. * Diff implementation.
  64155. */
  64156. final class Differ
  64157. {
  64158. public const OLD = 0;
  64159. public const ADDED = 1;
  64160. public const REMOVED = 2;
  64161. public const DIFF_LINE_END_WARNING = 3;
  64162. public const NO_LINE_END_EOF_WARNING = 4;
  64163. /**
  64164. * @var DiffOutputBuilderInterface
  64165. */
  64166. private $outputBuilder;
  64167. /**
  64168. * @param DiffOutputBuilderInterface $outputBuilder
  64169. *
  64170. * @throws InvalidArgumentException
  64171. */
  64172. public function __construct($outputBuilder = null)
  64173. {
  64174. if ($outputBuilder instanceof \PHPUnit\SebastianBergmann\Diff\Output\DiffOutputBuilderInterface) {
  64175. $this->outputBuilder = $outputBuilder;
  64176. } elseif (null === $outputBuilder) {
  64177. $this->outputBuilder = new \PHPUnit\SebastianBergmann\Diff\Output\UnifiedDiffOutputBuilder();
  64178. } elseif (\is_string($outputBuilder)) {
  64179. // PHPUnit 6.1.4, 6.2.0, 6.2.1, 6.2.2, and 6.2.3 support
  64180. // @see https://github.com/sebastianbergmann/phpunit/issues/2734#issuecomment-314514056
  64181. // @deprecated
  64182. $this->outputBuilder = new \PHPUnit\SebastianBergmann\Diff\Output\UnifiedDiffOutputBuilder($outputBuilder);
  64183. } else {
  64184. throw new \PHPUnit\SebastianBergmann\Diff\InvalidArgumentException(\sprintf('Expected builder to be an instance of DiffOutputBuilderInterface, <null> or a string, got %s.', \is_object($outputBuilder) ? 'instance of "' . \get_class($outputBuilder) . '"' : \gettype($outputBuilder) . ' "' . $outputBuilder . '"'));
  64185. }
  64186. }
  64187. /**
  64188. * Returns the diff between two arrays or strings as string.
  64189. *
  64190. * @param array|string $from
  64191. * @param array|string $to
  64192. */
  64193. public function diff($from, $to, \PHPUnit\SebastianBergmann\Diff\LongestCommonSubsequenceCalculator $lcs = null) : string
  64194. {
  64195. $diff = $this->diffToArray($this->normalizeDiffInput($from), $this->normalizeDiffInput($to), $lcs);
  64196. return $this->outputBuilder->getDiff($diff);
  64197. }
  64198. /**
  64199. * Returns the diff between two arrays or strings as array.
  64200. *
  64201. * Each array element contains two elements:
  64202. * - [0] => mixed $token
  64203. * - [1] => 2|1|0
  64204. *
  64205. * - 2: REMOVED: $token was removed from $from
  64206. * - 1: ADDED: $token was added to $from
  64207. * - 0: OLD: $token is not changed in $to
  64208. *
  64209. * @param array|string $from
  64210. * @param array|string $to
  64211. * @param LongestCommonSubsequenceCalculator $lcs
  64212. */
  64213. public function diffToArray($from, $to, \PHPUnit\SebastianBergmann\Diff\LongestCommonSubsequenceCalculator $lcs = null) : array
  64214. {
  64215. if (\is_string($from)) {
  64216. $from = $this->splitStringByLines($from);
  64217. } elseif (!\is_array($from)) {
  64218. throw new \PHPUnit\SebastianBergmann\Diff\InvalidArgumentException('"from" must be an array or string.');
  64219. }
  64220. if (\is_string($to)) {
  64221. $to = $this->splitStringByLines($to);
  64222. } elseif (!\is_array($to)) {
  64223. throw new \PHPUnit\SebastianBergmann\Diff\InvalidArgumentException('"to" must be an array or string.');
  64224. }
  64225. [$from, $to, $start, $end] = self::getArrayDiffParted($from, $to);
  64226. if ($lcs === null) {
  64227. $lcs = $this->selectLcsImplementation($from, $to);
  64228. }
  64229. $common = $lcs->calculate(\array_values($from), \array_values($to));
  64230. $diff = [];
  64231. foreach ($start as $token) {
  64232. $diff[] = [$token, self::OLD];
  64233. }
  64234. \reset($from);
  64235. \reset($to);
  64236. foreach ($common as $token) {
  64237. while (($fromToken = \reset($from)) !== $token) {
  64238. $diff[] = [\array_shift($from), self::REMOVED];
  64239. }
  64240. while (($toToken = \reset($to)) !== $token) {
  64241. $diff[] = [\array_shift($to), self::ADDED];
  64242. }
  64243. $diff[] = [$token, self::OLD];
  64244. \array_shift($from);
  64245. \array_shift($to);
  64246. }
  64247. while (($token = \array_shift($from)) !== null) {
  64248. $diff[] = [$token, self::REMOVED];
  64249. }
  64250. while (($token = \array_shift($to)) !== null) {
  64251. $diff[] = [$token, self::ADDED];
  64252. }
  64253. foreach ($end as $token) {
  64254. $diff[] = [$token, self::OLD];
  64255. }
  64256. if ($this->detectUnmatchedLineEndings($diff)) {
  64257. \array_unshift($diff, ["#Warning: Strings contain different line endings!\n", self::DIFF_LINE_END_WARNING]);
  64258. }
  64259. return $diff;
  64260. }
  64261. /**
  64262. * Casts variable to string if it is not a string or array.
  64263. *
  64264. * @return array|string
  64265. */
  64266. private function normalizeDiffInput($input)
  64267. {
  64268. if (!\is_array($input) && !\is_string($input)) {
  64269. return (string) $input;
  64270. }
  64271. return $input;
  64272. }
  64273. /**
  64274. * Checks if input is string, if so it will split it line-by-line.
  64275. */
  64276. private function splitStringByLines(string $input) : array
  64277. {
  64278. return \preg_split('/(.*\\R)/', $input, -1, \PREG_SPLIT_DELIM_CAPTURE | \PREG_SPLIT_NO_EMPTY);
  64279. }
  64280. private function selectLcsImplementation(array $from, array $to) : \PHPUnit\SebastianBergmann\Diff\LongestCommonSubsequenceCalculator
  64281. {
  64282. // We do not want to use the time-efficient implementation if its memory
  64283. // footprint will probably exceed this value. Note that the footprint
  64284. // calculation is only an estimation for the matrix and the LCS method
  64285. // will typically allocate a bit more memory than this.
  64286. $memoryLimit = 100 * 1024 * 1024;
  64287. if ($this->calculateEstimatedFootprint($from, $to) > $memoryLimit) {
  64288. return new \PHPUnit\SebastianBergmann\Diff\MemoryEfficientLongestCommonSubsequenceCalculator();
  64289. }
  64290. return new \PHPUnit\SebastianBergmann\Diff\TimeEfficientLongestCommonSubsequenceCalculator();
  64291. }
  64292. /**
  64293. * Calculates the estimated memory footprint for the DP-based method.
  64294. *
  64295. * @return float|int
  64296. */
  64297. private function calculateEstimatedFootprint(array $from, array $to)
  64298. {
  64299. $itemSize = \PHP_INT_SIZE === 4 ? 76 : 144;
  64300. return $itemSize * \min(\count($from), \count($to)) ** 2;
  64301. }
  64302. /**
  64303. * Returns true if line ends don't match in a diff.
  64304. */
  64305. private function detectUnmatchedLineEndings(array $diff) : bool
  64306. {
  64307. $newLineBreaks = ['' => \true];
  64308. $oldLineBreaks = ['' => \true];
  64309. foreach ($diff as $entry) {
  64310. if (self::OLD === $entry[1]) {
  64311. $ln = $this->getLinebreak($entry[0]);
  64312. $oldLineBreaks[$ln] = \true;
  64313. $newLineBreaks[$ln] = \true;
  64314. } elseif (self::ADDED === $entry[1]) {
  64315. $newLineBreaks[$this->getLinebreak($entry[0])] = \true;
  64316. } elseif (self::REMOVED === $entry[1]) {
  64317. $oldLineBreaks[$this->getLinebreak($entry[0])] = \true;
  64318. }
  64319. }
  64320. // if either input or output is a single line without breaks than no warning should be raised
  64321. if (['' => \true] === $newLineBreaks || ['' => \true] === $oldLineBreaks) {
  64322. return \false;
  64323. }
  64324. // two way compare
  64325. foreach ($newLineBreaks as $break => $set) {
  64326. if (!isset($oldLineBreaks[$break])) {
  64327. return \true;
  64328. }
  64329. }
  64330. foreach ($oldLineBreaks as $break => $set) {
  64331. if (!isset($newLineBreaks[$break])) {
  64332. return \true;
  64333. }
  64334. }
  64335. return \false;
  64336. }
  64337. private function getLinebreak($line) : string
  64338. {
  64339. if (!\is_string($line)) {
  64340. return '';
  64341. }
  64342. $lc = \substr($line, -1);
  64343. if ("\r" === $lc) {
  64344. return "\r";
  64345. }
  64346. if ("\n" !== $lc) {
  64347. return '';
  64348. }
  64349. if ("\r\n" === \substr($line, -2)) {
  64350. return "\r\n";
  64351. }
  64352. return "\n";
  64353. }
  64354. private static function getArrayDiffParted(array &$from, array &$to) : array
  64355. {
  64356. $start = [];
  64357. $end = [];
  64358. \reset($to);
  64359. foreach ($from as $k => $v) {
  64360. $toK = \key($to);
  64361. if ($toK === $k && $v === $to[$k]) {
  64362. $start[$k] = $v;
  64363. unset($from[$k], $to[$k]);
  64364. } else {
  64365. break;
  64366. }
  64367. }
  64368. \end($from);
  64369. \end($to);
  64370. do {
  64371. $fromK = \key($from);
  64372. $toK = \key($to);
  64373. if (null === $fromK || null === $toK || \current($from) !== \current($to)) {
  64374. break;
  64375. }
  64376. \prev($from);
  64377. \prev($to);
  64378. $end = [$fromK => $from[$fromK]] + $end;
  64379. unset($from[$fromK], $to[$toK]);
  64380. } while (\true);
  64381. return [$from, $to, $start, $end];
  64382. }
  64383. }
  64384. <?php
  64385. declare (strict_types=1);
  64386. /*
  64387. * This file is part of sebastian/diff.
  64388. *
  64389. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  64390. *
  64391. * For the full copyright and license information, please view the LICENSE
  64392. * file that was distributed with this source code.
  64393. */
  64394. namespace PHPUnit\SebastianBergmann\Diff;
  64395. /**
  64396. * Unified diff parser.
  64397. */
  64398. final class Parser
  64399. {
  64400. /**
  64401. * @return Diff[]
  64402. */
  64403. public function parse(string $string) : array
  64404. {
  64405. $lines = \preg_split('(\\r\\n|\\r|\\n)', $string);
  64406. if (!empty($lines) && $lines[\count($lines) - 1] === '') {
  64407. \array_pop($lines);
  64408. }
  64409. $lineCount = \count($lines);
  64410. $diffs = [];
  64411. $diff = null;
  64412. $collected = [];
  64413. for ($i = 0; $i < $lineCount; ++$i) {
  64414. if (\preg_match('(^---\\s+(?P<file>\\S+))', $lines[$i], $fromMatch) && \preg_match('(^\\+\\+\\+\\s+(?P<file>\\S+))', $lines[$i + 1], $toMatch)) {
  64415. if ($diff !== null) {
  64416. $this->parseFileDiff($diff, $collected);
  64417. $diffs[] = $diff;
  64418. $collected = [];
  64419. }
  64420. $diff = new \PHPUnit\SebastianBergmann\Diff\Diff($fromMatch['file'], $toMatch['file']);
  64421. ++$i;
  64422. } else {
  64423. if (\preg_match('/^(?:diff --git |index [\\da-f\\.]+|[+-]{3} [ab])/', $lines[$i])) {
  64424. continue;
  64425. }
  64426. $collected[] = $lines[$i];
  64427. }
  64428. }
  64429. if ($diff !== null && \count($collected)) {
  64430. $this->parseFileDiff($diff, $collected);
  64431. $diffs[] = $diff;
  64432. }
  64433. return $diffs;
  64434. }
  64435. private function parseFileDiff(\PHPUnit\SebastianBergmann\Diff\Diff $diff, array $lines) : void
  64436. {
  64437. $chunks = [];
  64438. $chunk = null;
  64439. $diffLines = [];
  64440. foreach ($lines as $line) {
  64441. if (\preg_match('/^@@\\s+-(?P<start>\\d+)(?:,\\s*(?P<startrange>\\d+))?\\s+\\+(?P<end>\\d+)(?:,\\s*(?P<endrange>\\d+))?\\s+@@/', $line, $match)) {
  64442. $chunk = new \PHPUnit\SebastianBergmann\Diff\Chunk((int) $match['start'], isset($match['startrange']) ? \max(1, (int) $match['startrange']) : 1, (int) $match['end'], isset($match['endrange']) ? \max(1, (int) $match['endrange']) : 1);
  64443. $chunks[] = $chunk;
  64444. $diffLines = [];
  64445. continue;
  64446. }
  64447. if (\preg_match('/^(?P<type>[+ -])?(?P<line>.*)/', $line, $match)) {
  64448. $type = \PHPUnit\SebastianBergmann\Diff\Line::UNCHANGED;
  64449. if ($match['type'] === '+') {
  64450. $type = \PHPUnit\SebastianBergmann\Diff\Line::ADDED;
  64451. } elseif ($match['type'] === '-') {
  64452. $type = \PHPUnit\SebastianBergmann\Diff\Line::REMOVED;
  64453. }
  64454. $diffLines[] = new \PHPUnit\SebastianBergmann\Diff\Line($type, $match['line']);
  64455. if (null !== $chunk) {
  64456. $chunk->setLines($diffLines);
  64457. }
  64458. }
  64459. }
  64460. $diff->setChunks($chunks);
  64461. }
  64462. }
  64463. <?php
  64464. declare (strict_types=1);
  64465. /*
  64466. * This file is part of sebastian/diff.
  64467. *
  64468. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  64469. *
  64470. * For the full copyright and license information, please view the LICENSE
  64471. * file that was distributed with this source code.
  64472. */
  64473. namespace PHPUnit\SebastianBergmann\Diff;
  64474. final class Line
  64475. {
  64476. public const ADDED = 1;
  64477. public const REMOVED = 2;
  64478. public const UNCHANGED = 3;
  64479. /**
  64480. * @var int
  64481. */
  64482. private $type;
  64483. /**
  64484. * @var string
  64485. */
  64486. private $content;
  64487. public function __construct(int $type = self::UNCHANGED, string $content = '')
  64488. {
  64489. $this->type = $type;
  64490. $this->content = $content;
  64491. }
  64492. public function getContent() : string
  64493. {
  64494. return $this->content;
  64495. }
  64496. public function getType() : int
  64497. {
  64498. return $this->type;
  64499. }
  64500. }
  64501. sebastian/diff
  64502. Copyright (c) 2002-2020, Sebastian Bergmann <sebastian@phpunit.de>.
  64503. All rights reserved.
  64504. Redistribution and use in source and binary forms, with or without
  64505. modification, are permitted provided that the following conditions
  64506. are met:
  64507. * Redistributions of source code must retain the above copyright
  64508. notice, this list of conditions and the following disclaimer.
  64509. * Redistributions in binary form must reproduce the above copyright
  64510. notice, this list of conditions and the following disclaimer in
  64511. the documentation and/or other materials provided with the
  64512. distribution.
  64513. * Neither the name of Sebastian Bergmann nor the names of his
  64514. contributors may be used to endorse or promote products derived
  64515. from this software without specific prior written permission.
  64516. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  64517. "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  64518. LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  64519. FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  64520. COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  64521. INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  64522. BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  64523. LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  64524. CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  64525. LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
  64526. ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  64527. POSSIBILITY OF SUCH DAMAGE.
  64528. <?php
  64529. declare (strict_types=1);
  64530. namespace PHPUnit\TheSeer\Tokenizer;
  64531. class Token
  64532. {
  64533. /**
  64534. * @var int
  64535. */
  64536. private $line;
  64537. /**
  64538. * @var string
  64539. */
  64540. private $name;
  64541. /**
  64542. * @var string
  64543. */
  64544. private $value;
  64545. /**
  64546. * Token constructor.
  64547. *
  64548. * @param int $line
  64549. * @param string $name
  64550. * @param string $value
  64551. */
  64552. public function __construct(int $line, string $name, string $value)
  64553. {
  64554. $this->line = $line;
  64555. $this->name = $name;
  64556. $this->value = $value;
  64557. }
  64558. /**
  64559. * @return int
  64560. */
  64561. public function getLine() : int
  64562. {
  64563. return $this->line;
  64564. }
  64565. /**
  64566. * @return string
  64567. */
  64568. public function getName() : string
  64569. {
  64570. return $this->name;
  64571. }
  64572. /**
  64573. * @return string
  64574. */
  64575. public function getValue() : string
  64576. {
  64577. return $this->value;
  64578. }
  64579. }
  64580. <?php
  64581. declare (strict_types=1);
  64582. namespace PHPUnit\TheSeer\Tokenizer;
  64583. class Tokenizer
  64584. {
  64585. /**
  64586. * Token Map for "non-tokens"
  64587. *
  64588. * @var array
  64589. */
  64590. private $map = ['(' => 'T_OPEN_BRACKET', ')' => 'T_CLOSE_BRACKET', '[' => 'T_OPEN_SQUARE', ']' => 'T_CLOSE_SQUARE', '{' => 'T_OPEN_CURLY', '}' => 'T_CLOSE_CURLY', ';' => 'T_SEMICOLON', '.' => 'T_DOT', ',' => 'T_COMMA', '=' => 'T_EQUAL', '<' => 'T_LT', '>' => 'T_GT', '+' => 'T_PLUS', '-' => 'T_MINUS', '*' => 'T_MULT', '/' => 'T_DIV', '?' => 'T_QUESTION_MARK', '!' => 'T_EXCLAMATION_MARK', ':' => 'T_COLON', '"' => 'T_DOUBLE_QUOTES', '@' => 'T_AT', '&' => 'T_AMPERSAND', '%' => 'T_PERCENT', '|' => 'T_PIPE', '$' => 'T_DOLLAR', '^' => 'T_CARET', '~' => 'T_TILDE', '`' => 'T_BACKTICK'];
  64591. public function parse(string $source) : \PHPUnit\TheSeer\Tokenizer\TokenCollection
  64592. {
  64593. $result = new \PHPUnit\TheSeer\Tokenizer\TokenCollection();
  64594. if ($source === '') {
  64595. return $result;
  64596. }
  64597. $tokens = \token_get_all($source);
  64598. $lastToken = new \PHPUnit\TheSeer\Tokenizer\Token($tokens[0][2], 'Placeholder', '');
  64599. foreach ($tokens as $pos => $tok) {
  64600. if (\is_string($tok)) {
  64601. $token = new \PHPUnit\TheSeer\Tokenizer\Token($lastToken->getLine(), $this->map[$tok], $tok);
  64602. $result->addToken($token);
  64603. $lastToken = $token;
  64604. continue;
  64605. }
  64606. $line = $tok[2];
  64607. $values = \preg_split('/\\R+/Uu', $tok[1]);
  64608. foreach ($values as $v) {
  64609. $token = new \PHPUnit\TheSeer\Tokenizer\Token($line, \token_name($tok[0]), $v);
  64610. $result->addToken($token);
  64611. $line++;
  64612. $lastToken = $token;
  64613. }
  64614. }
  64615. return $result;
  64616. }
  64617. }
  64618. <?php
  64619. declare (strict_types=1);
  64620. namespace PHPUnit\TheSeer\Tokenizer;
  64621. class NamespaceUriException extends \PHPUnit\TheSeer\Tokenizer\Exception
  64622. {
  64623. }
  64624. <?php
  64625. declare (strict_types=1);
  64626. namespace PHPUnit\TheSeer\Tokenizer;
  64627. class TokenCollectionException extends \PHPUnit\TheSeer\Tokenizer\Exception
  64628. {
  64629. }
  64630. <?php
  64631. declare (strict_types=1);
  64632. namespace PHPUnit\TheSeer\Tokenizer;
  64633. class Exception extends \Exception
  64634. {
  64635. }
  64636. <?php
  64637. declare (strict_types=1);
  64638. namespace PHPUnit\TheSeer\Tokenizer;
  64639. use DOMDocument;
  64640. class XMLSerializer
  64641. {
  64642. /**
  64643. * @var \XMLWriter
  64644. */
  64645. private $writer;
  64646. /**
  64647. * @var Token
  64648. */
  64649. private $previousToken;
  64650. /**
  64651. * @var NamespaceUri
  64652. */
  64653. private $xmlns;
  64654. /**
  64655. * XMLSerializer constructor.
  64656. *
  64657. * @param NamespaceUri $xmlns
  64658. */
  64659. public function __construct(\PHPUnit\TheSeer\Tokenizer\NamespaceUri $xmlns = null)
  64660. {
  64661. if ($xmlns === null) {
  64662. $xmlns = new \PHPUnit\TheSeer\Tokenizer\NamespaceUri('https://github.com/theseer/tokenizer');
  64663. }
  64664. $this->xmlns = $xmlns;
  64665. }
  64666. /**
  64667. * @param TokenCollection $tokens
  64668. *
  64669. * @return DOMDocument
  64670. */
  64671. public function toDom(\PHPUnit\TheSeer\Tokenizer\TokenCollection $tokens) : \DOMDocument
  64672. {
  64673. $dom = new \DOMDocument();
  64674. $dom->preserveWhiteSpace = \false;
  64675. $dom->loadXML($this->toXML($tokens));
  64676. return $dom;
  64677. }
  64678. /**
  64679. * @param TokenCollection $tokens
  64680. *
  64681. * @return string
  64682. */
  64683. public function toXML(\PHPUnit\TheSeer\Tokenizer\TokenCollection $tokens) : string
  64684. {
  64685. $this->writer = new \XMLWriter();
  64686. $this->writer->openMemory();
  64687. $this->writer->setIndent(\true);
  64688. $this->writer->startDocument();
  64689. $this->writer->startElement('source');
  64690. $this->writer->writeAttribute('xmlns', $this->xmlns->asString());
  64691. if (\count($tokens) > 0) {
  64692. $this->writer->startElement('line');
  64693. $this->writer->writeAttribute('no', '1');
  64694. $this->previousToken = $tokens[0];
  64695. foreach ($tokens as $token) {
  64696. $this->addToken($token);
  64697. }
  64698. }
  64699. $this->writer->endElement();
  64700. $this->writer->endElement();
  64701. $this->writer->endDocument();
  64702. return $this->writer->outputMemory();
  64703. }
  64704. /**
  64705. * @param Token $token
  64706. */
  64707. private function addToken(\PHPUnit\TheSeer\Tokenizer\Token $token)
  64708. {
  64709. if ($this->previousToken->getLine() < $token->getLine()) {
  64710. $this->writer->endElement();
  64711. $this->writer->startElement('line');
  64712. $this->writer->writeAttribute('no', (string) $token->getLine());
  64713. $this->previousToken = $token;
  64714. }
  64715. if ($token->getValue() !== '') {
  64716. $this->writer->startElement('token');
  64717. $this->writer->writeAttribute('name', $token->getName());
  64718. $this->writer->writeRaw(\htmlspecialchars($token->getValue(), \ENT_NOQUOTES | \ENT_DISALLOWED | \ENT_XML1));
  64719. $this->writer->endElement();
  64720. }
  64721. }
  64722. }
  64723. <?php
  64724. declare (strict_types=1);
  64725. namespace PHPUnit\TheSeer\Tokenizer;
  64726. class NamespaceUri
  64727. {
  64728. /** @var string */
  64729. private $value;
  64730. /**
  64731. * @param string $value
  64732. */
  64733. public function __construct(string $value)
  64734. {
  64735. $this->ensureValidUri($value);
  64736. $this->value = $value;
  64737. }
  64738. public function asString() : string
  64739. {
  64740. return $this->value;
  64741. }
  64742. private function ensureValidUri($value)
  64743. {
  64744. if (\strpos($value, ':') === \false) {
  64745. throw new \PHPUnit\TheSeer\Tokenizer\NamespaceUriException(\sprintf("Namespace URI '%s' must contain at least one colon", $value));
  64746. }
  64747. }
  64748. }
  64749. Tokenizer
  64750. Copyright (c) 2017 Arne Blankerts <arne@blankerts.de> and contributors
  64751. All rights reserved.
  64752. Redistribution and use in source and binary forms, with or without modification,
  64753. are permitted provided that the following conditions are met:
  64754. * Redistributions of source code must retain the above copyright notice,
  64755. this list of conditions and the following disclaimer.
  64756. * Redistributions in binary form must reproduce the above copyright notice,
  64757. this list of conditions and the following disclaimer in the documentation
  64758. and/or other materials provided with the distribution.
  64759. * Neither the name of Arne Blankerts nor the names of contributors
  64760. may be used to endorse or promote products derived from this software
  64761. without specific prior written permission.
  64762. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  64763. AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO,
  64764. THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  64765. PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS
  64766. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
  64767. OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  64768. SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  64769. INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  64770. CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  64771. ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  64772. POSSIBILITY OF SUCH DAMAGE.
  64773. <?php
  64774. declare (strict_types=1);
  64775. namespace PHPUnit\TheSeer\Tokenizer;
  64776. class TokenCollection implements \ArrayAccess, \Iterator, \Countable
  64777. {
  64778. /**
  64779. * @var Token[]
  64780. */
  64781. private $tokens = [];
  64782. /**
  64783. * @var int
  64784. */
  64785. private $pos;
  64786. /**
  64787. * @param Token $token
  64788. */
  64789. public function addToken(\PHPUnit\TheSeer\Tokenizer\Token $token)
  64790. {
  64791. $this->tokens[] = $token;
  64792. }
  64793. /**
  64794. * @return Token
  64795. */
  64796. public function current() : \PHPUnit\TheSeer\Tokenizer\Token
  64797. {
  64798. return \current($this->tokens);
  64799. }
  64800. /**
  64801. * @return int
  64802. */
  64803. public function key() : int
  64804. {
  64805. return \key($this->tokens);
  64806. }
  64807. /**
  64808. * @return void
  64809. */
  64810. public function next()
  64811. {
  64812. \next($this->tokens);
  64813. $this->pos++;
  64814. }
  64815. /**
  64816. * @return bool
  64817. */
  64818. public function valid() : bool
  64819. {
  64820. return $this->count() > $this->pos;
  64821. }
  64822. /**
  64823. * @return void
  64824. */
  64825. public function rewind()
  64826. {
  64827. \reset($this->tokens);
  64828. $this->pos = 0;
  64829. }
  64830. /**
  64831. * @return int
  64832. */
  64833. public function count() : int
  64834. {
  64835. return \count($this->tokens);
  64836. }
  64837. /**
  64838. * @param mixed $offset
  64839. *
  64840. * @return bool
  64841. */
  64842. public function offsetExists($offset) : bool
  64843. {
  64844. return isset($this->tokens[$offset]);
  64845. }
  64846. /**
  64847. * @param mixed $offset
  64848. *
  64849. * @return Token
  64850. * @throws TokenCollectionException
  64851. */
  64852. public function offsetGet($offset) : \PHPUnit\TheSeer\Tokenizer\Token
  64853. {
  64854. if (!$this->offsetExists($offset)) {
  64855. throw new \PHPUnit\TheSeer\Tokenizer\TokenCollectionException(\sprintf('No Token at offest %s', $offset));
  64856. }
  64857. return $this->tokens[$offset];
  64858. }
  64859. /**
  64860. * @param mixed $offset
  64861. * @param Token $value
  64862. *
  64863. * @throws TokenCollectionException
  64864. */
  64865. public function offsetSet($offset, $value)
  64866. {
  64867. if (!\is_int($offset)) {
  64868. $type = \gettype($offset);
  64869. throw new \PHPUnit\TheSeer\Tokenizer\TokenCollectionException(\sprintf('Offset must be of type integer, %s given', $type === 'object' ? \get_class($value) : $type));
  64870. }
  64871. if (!$value instanceof \PHPUnit\TheSeer\Tokenizer\Token) {
  64872. $type = \gettype($value);
  64873. throw new \PHPUnit\TheSeer\Tokenizer\TokenCollectionException(\sprintf('Value must be of type %s, %s given', \PHPUnit\TheSeer\Tokenizer\Token::class, $type === 'object' ? \get_class($value) : $type));
  64874. }
  64875. $this->tokens[$offset] = $value;
  64876. }
  64877. /**
  64878. * @param mixed $offset
  64879. */
  64880. public function offsetUnset($offset)
  64881. {
  64882. unset($this->tokens[$offset]);
  64883. }
  64884. }
  64885. Object Enumerator
  64886. Copyright (c) 2016-2020, Sebastian Bergmann <sebastian@phpunit.de>.
  64887. All rights reserved.
  64888. Redistribution and use in source and binary forms, with or without
  64889. modification, are permitted provided that the following conditions
  64890. are met:
  64891. * Redistributions of source code must retain the above copyright
  64892. notice, this list of conditions and the following disclaimer.
  64893. * Redistributions in binary form must reproduce the above copyright
  64894. notice, this list of conditions and the following disclaimer in
  64895. the documentation and/or other materials provided with the
  64896. distribution.
  64897. * Neither the name of Sebastian Bergmann nor the names of his
  64898. contributors may be used to endorse or promote products derived
  64899. from this software without specific prior written permission.
  64900. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  64901. "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  64902. LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  64903. FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  64904. COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  64905. INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  64906. BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  64907. LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  64908. CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  64909. LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
  64910. ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  64911. POSSIBILITY OF SUCH DAMAGE.
  64912. <?php
  64913. declare (strict_types=1);
  64914. /*
  64915. * This file is part of sebastian/code-unit-reverse-lookup.
  64916. *
  64917. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  64918. *
  64919. * For the full copyright and license information, please view the LICENSE
  64920. * file that was distributed with this source code.
  64921. */
  64922. namespace PHPUnit\SebastianBergmann\CodeUnitReverseLookup;
  64923. /**
  64924. * @since Class available since Release 1.0.0
  64925. */
  64926. class Wizard
  64927. {
  64928. /**
  64929. * @var array
  64930. */
  64931. private $lookupTable = [];
  64932. /**
  64933. * @var array
  64934. */
  64935. private $processedClasses = [];
  64936. /**
  64937. * @var array
  64938. */
  64939. private $processedFunctions = [];
  64940. /**
  64941. * @param string $filename
  64942. * @param int $lineNumber
  64943. *
  64944. * @return string
  64945. */
  64946. public function lookup($filename, $lineNumber)
  64947. {
  64948. if (!isset($this->lookupTable[$filename][$lineNumber])) {
  64949. $this->updateLookupTable();
  64950. }
  64951. if (isset($this->lookupTable[$filename][$lineNumber])) {
  64952. return $this->lookupTable[$filename][$lineNumber];
  64953. }
  64954. return $filename . ':' . $lineNumber;
  64955. }
  64956. private function updateLookupTable() : void
  64957. {
  64958. $this->processClassesAndTraits();
  64959. $this->processFunctions();
  64960. }
  64961. private function processClassesAndTraits() : void
  64962. {
  64963. $classes = \get_declared_classes();
  64964. $traits = \get_declared_traits();
  64965. \assert(\is_array($classes));
  64966. \assert(\is_array($traits));
  64967. foreach (\array_merge($classes, $traits) as $classOrTrait) {
  64968. if (isset($this->processedClasses[$classOrTrait])) {
  64969. continue;
  64970. }
  64971. $reflector = new \ReflectionClass($classOrTrait);
  64972. foreach ($reflector->getMethods() as $method) {
  64973. $this->processFunctionOrMethod($method);
  64974. }
  64975. $this->processedClasses[$classOrTrait] = \true;
  64976. }
  64977. }
  64978. private function processFunctions() : void
  64979. {
  64980. foreach (\get_defined_functions()['user'] as $function) {
  64981. if (isset($this->processedFunctions[$function])) {
  64982. continue;
  64983. }
  64984. $this->processFunctionOrMethod(new \ReflectionFunction($function));
  64985. $this->processedFunctions[$function] = \true;
  64986. }
  64987. }
  64988. private function processFunctionOrMethod(\ReflectionFunctionAbstract $functionOrMethod) : void
  64989. {
  64990. if ($functionOrMethod->isInternal()) {
  64991. return;
  64992. }
  64993. $name = $functionOrMethod->getName();
  64994. if ($functionOrMethod instanceof \ReflectionMethod) {
  64995. $name = $functionOrMethod->getDeclaringClass()->getName() . '::' . $name;
  64996. }
  64997. if (!isset($this->lookupTable[$functionOrMethod->getFileName()])) {
  64998. $this->lookupTable[$functionOrMethod->getFileName()] = [];
  64999. }
  65000. foreach (\range($functionOrMethod->getStartLine(), $functionOrMethod->getEndLine()) as $line) {
  65001. $this->lookupTable[$functionOrMethod->getFileName()][$line] = $name;
  65002. }
  65003. }
  65004. }
  65005. code-unit-reverse-lookup
  65006. Copyright (c) 2016-2020, Sebastian Bergmann <sebastian@phpunit.de>.
  65007. All rights reserved.
  65008. Redistribution and use in source and binary forms, with or without
  65009. modification, are permitted provided that the following conditions
  65010. are met:
  65011. * Redistributions of source code must retain the above copyright
  65012. notice, this list of conditions and the following disclaimer.
  65013. * Redistributions in binary form must reproduce the above copyright
  65014. notice, this list of conditions and the following disclaimer in
  65015. the documentation and/or other materials provided with the
  65016. distribution.
  65017. * Neither the name of Sebastian Bergmann nor the names of his
  65018. contributors may be used to endorse or promote products derived
  65019. from this software without specific prior written permission.
  65020. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  65021. "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  65022. LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  65023. FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  65024. COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  65025. INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  65026. BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  65027. LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  65028. CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  65029. LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
  65030. ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  65031. POSSIBILITY OF SUCH DAMAGE.
  65032. <?php
  65033. declare (strict_types=1);
  65034. /*
  65035. * This file is part of the Recursion Context package.
  65036. *
  65037. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  65038. *
  65039. * For the full copyright and license information, please view the LICENSE
  65040. * file that was distributed with this source code.
  65041. */
  65042. namespace PHPUnit\SebastianBergmann\RecursionContext;
  65043. /**
  65044. * A context containing previously processed arrays and objects
  65045. * when recursively processing a value.
  65046. */
  65047. final class Context
  65048. {
  65049. /**
  65050. * @var array[]
  65051. */
  65052. private $arrays;
  65053. /**
  65054. * @var \SplObjectStorage
  65055. */
  65056. private $objects;
  65057. /**
  65058. * Initialises the context
  65059. */
  65060. public function __construct()
  65061. {
  65062. $this->arrays = [];
  65063. $this->objects = new \SplObjectStorage();
  65064. }
  65065. /**
  65066. * @codeCoverageIgnore
  65067. */
  65068. public function __destruct()
  65069. {
  65070. foreach ($this->arrays as &$array) {
  65071. if (\is_array($array)) {
  65072. \array_pop($array);
  65073. \array_pop($array);
  65074. }
  65075. }
  65076. }
  65077. /**
  65078. * Adds a value to the context.
  65079. *
  65080. * @param array|object $value the value to add
  65081. *
  65082. * @throws InvalidArgumentException Thrown if $value is not an array or object
  65083. *
  65084. * @return bool|int|string the ID of the stored value, either as a string or integer
  65085. */
  65086. public function add(&$value)
  65087. {
  65088. if (\is_array($value)) {
  65089. return $this->addArray($value);
  65090. }
  65091. if (\is_object($value)) {
  65092. return $this->addObject($value);
  65093. }
  65094. throw new \PHPUnit\SebastianBergmann\RecursionContext\InvalidArgumentException('Only arrays and objects are supported');
  65095. }
  65096. /**
  65097. * Checks if the given value exists within the context.
  65098. *
  65099. * @param array|object $value the value to check
  65100. *
  65101. * @throws InvalidArgumentException Thrown if $value is not an array or object
  65102. *
  65103. * @return false|int|string the string or integer ID of the stored value if it has already been seen, or false if the value is not stored
  65104. */
  65105. public function contains(&$value)
  65106. {
  65107. if (\is_array($value)) {
  65108. return $this->containsArray($value);
  65109. }
  65110. if (\is_object($value)) {
  65111. return $this->containsObject($value);
  65112. }
  65113. throw new \PHPUnit\SebastianBergmann\RecursionContext\InvalidArgumentException('Only arrays and objects are supported');
  65114. }
  65115. /**
  65116. * @return bool|int
  65117. */
  65118. private function addArray(array &$array)
  65119. {
  65120. $key = $this->containsArray($array);
  65121. if ($key !== \false) {
  65122. return $key;
  65123. }
  65124. $key = \count($this->arrays);
  65125. $this->arrays[] =& $array;
  65126. if (!isset($array[\PHP_INT_MAX]) && !isset($array[\PHP_INT_MAX - 1])) {
  65127. $array[] = $key;
  65128. $array[] = $this->objects;
  65129. } else {
  65130. /* cover the improbable case too */
  65131. do {
  65132. $key = \random_int(\PHP_INT_MIN, \PHP_INT_MAX);
  65133. } while (isset($array[$key]));
  65134. $array[$key] = $key;
  65135. do {
  65136. $key = \random_int(\PHP_INT_MIN, \PHP_INT_MAX);
  65137. } while (isset($array[$key]));
  65138. $array[$key] = $this->objects;
  65139. }
  65140. return $key;
  65141. }
  65142. /**
  65143. * @param object $object
  65144. */
  65145. private function addObject($object) : string
  65146. {
  65147. if (!$this->objects->contains($object)) {
  65148. $this->objects->attach($object);
  65149. }
  65150. return \spl_object_hash($object);
  65151. }
  65152. /**
  65153. * @return false|int
  65154. */
  65155. private function containsArray(array &$array)
  65156. {
  65157. $end = \array_slice($array, -2);
  65158. return isset($end[1]) && $end[1] === $this->objects ? $end[0] : \false;
  65159. }
  65160. /**
  65161. * @param object $value
  65162. *
  65163. * @return false|string
  65164. */
  65165. private function containsObject($value)
  65166. {
  65167. if ($this->objects->contains($value)) {
  65168. return \spl_object_hash($value);
  65169. }
  65170. return \false;
  65171. }
  65172. }
  65173. <?php
  65174. declare (strict_types=1);
  65175. /*
  65176. * This file is part of the Recursion Context package.
  65177. *
  65178. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  65179. *
  65180. * For the full copyright and license information, please view the LICENSE
  65181. * file that was distributed with this source code.
  65182. */
  65183. namespace PHPUnit\SebastianBergmann\RecursionContext;
  65184. interface Exception
  65185. {
  65186. }
  65187. Recursion Context
  65188. Copyright (c) 2002-2020, Sebastian Bergmann <sebastian@phpunit.de>.
  65189. All rights reserved.
  65190. Redistribution and use in source and binary forms, with or without
  65191. modification, are permitted provided that the following conditions
  65192. are met:
  65193. * Redistributions of source code must retain the above copyright
  65194. notice, this list of conditions and the following disclaimer.
  65195. * Redistributions in binary form must reproduce the above copyright
  65196. notice, this list of conditions and the following disclaimer in
  65197. the documentation and/or other materials provided with the
  65198. distribution.
  65199. * Neither the name of Sebastian Bergmann nor the names of his
  65200. contributors may be used to endorse or promote products derived
  65201. from this software without specific prior written permission.
  65202. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  65203. "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  65204. LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  65205. FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  65206. COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  65207. INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  65208. BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  65209. LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  65210. CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  65211. LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
  65212. ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  65213. POSSIBILITY OF SUCH DAMAGE.
  65214. <?php
  65215. declare (strict_types=1);
  65216. /*
  65217. * This file is part of the Recursion Context package.
  65218. *
  65219. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  65220. *
  65221. * For the full copyright and license information, please view the LICENSE
  65222. * file that was distributed with this source code.
  65223. */
  65224. namespace PHPUnit\SebastianBergmann\RecursionContext;
  65225. final class InvalidArgumentException extends \InvalidArgumentException implements \PHPUnit\SebastianBergmann\RecursionContext\Exception
  65226. {
  65227. }
  65228. <�¤d‹=}UXJÀ°&ÛýŽ÷®§���GBMB