123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757575857595760576157625763576457655766576757685769577057715772577357745775577657775778577957805781578257835784578557865787578857895790579157925793579457955796579757985799580058015802580358045805580658075808580958105811581258135814581558165817581858195820582158225823582458255826582758285829583058315832583358345835583658375838583958405841584258435844584558465847584858495850585158525853585458555856585758585859586058615862586358645865586658675868586958705871587258735874587558765877587858795880588158825883588458855886588758885889589058915892589358945895589658975898589959005901590259035904590559065907590859095910591159125913591459155916591759185919592059215922592359245925592659275928592959305931593259335934593559365937593859395940594159425943594459455946594759485949595059515952595359545955595659575958595959605961596259635964596559665967596859695970597159725973597459755976597759785979598059815982598359845985598659875988598959905991599259935994599559965997599859996000600160026003600460056006600760086009601060116012601360146015601660176018601960206021602260236024602560266027602860296030603160326033603460356036603760386039604060416042604360446045604660476048604960506051605260536054605560566057605860596060606160626063606460656066606760686069607060716072607360746075607660776078607960806081608260836084608560866087608860896090609160926093609460956096609760986099610061016102610361046105610661076108610961106111611261136114611561166117611861196120612161226123612461256126612761286129613061316132613361346135613661376138613961406141614261436144614561466147614861496150615161526153615461556156615761586159616061616162616361646165616661676168616961706171617261736174617561766177617861796180618161826183618461856186618761886189619061916192619361946195619661976198619962006201620262036204620562066207620862096210621162126213621462156216621762186219622062216222622362246225622662276228622962306231623262336234623562366237623862396240624162426243624462456246624762486249625062516252625362546255625662576258625962606261626262636264626562666267626862696270627162726273627462756276627762786279628062816282628362846285628662876288628962906291629262936294629562966297629862996300630163026303630463056306630763086309631063116312631363146315631663176318631963206321632263236324632563266327632863296330633163326333633463356336633763386339634063416342634363446345634663476348634963506351635263536354635563566357635863596360636163626363636463656366636763686369637063716372637363746375637663776378637963806381638263836384638563866387638863896390639163926393639463956396639763986399640064016402640364046405640664076408640964106411641264136414641564166417641864196420642164226423642464256426642764286429643064316432643364346435643664376438643964406441644264436444644564466447644864496450645164526453645464556456645764586459646064616462646364646465646664676468646964706471647264736474647564766477647864796480648164826483648464856486648764886489649064916492649364946495649664976498649965006501650265036504650565066507650865096510651165126513651465156516651765186519652065216522652365246525652665276528652965306531653265336534653565366537653865396540654165426543654465456546654765486549655065516552655365546555655665576558655965606561656265636564656565666567656865696570657165726573657465756576657765786579658065816582658365846585658665876588658965906591659265936594659565966597659865996600660166026603660466056606660766086609661066116612661366146615661666176618661966206621662266236624662566266627662866296630663166326633663466356636663766386639664066416642664366446645664666476648664966506651665266536654665566566657665866596660666166626663666466656666666766686669667066716672667366746675667666776678667966806681668266836684668566866687668866896690669166926693669466956696669766986699670067016702670367046705670667076708670967106711671267136714671567166717671867196720672167226723672467256726672767286729673067316732673367346735673667376738673967406741674267436744674567466747674867496750675167526753675467556756675767586759676067616762676367646765676667676768676967706771677267736774677567766777677867796780678167826783678467856786678767886789679067916792679367946795679667976798679968006801680268036804680568066807680868096810681168126813681468156816681768186819682068216822682368246825682668276828682968306831683268336834683568366837683868396840684168426843684468456846684768486849685068516852685368546855685668576858685968606861686268636864686568666867686868696870687168726873687468756876687768786879688068816882688368846885688668876888688968906891689268936894689568966897689868996900690169026903690469056906690769086909691069116912691369146915691669176918691969206921692269236924692569266927692869296930693169326933693469356936693769386939694069416942694369446945694669476948694969506951695269536954695569566957695869596960696169626963696469656966696769686969697069716972697369746975697669776978697969806981698269836984698569866987698869896990699169926993699469956996699769986999700070017002700370047005700670077008700970107011701270137014701570167017701870197020702170227023702470257026702770287029703070317032703370347035703670377038703970407041704270437044704570467047704870497050705170527053705470557056705770587059706070617062706370647065706670677068706970707071707270737074707570767077707870797080708170827083708470857086708770887089709070917092709370947095709670977098709971007101710271037104710571067107710871097110711171127113711471157116711771187119712071217122712371247125712671277128712971307131713271337134713571367137713871397140714171427143714471457146714771487149715071517152715371547155715671577158715971607161716271637164716571667167716871697170717171727173717471757176717771787179718071817182718371847185718671877188718971907191719271937194719571967197719871997200720172027203720472057206720772087209721072117212721372147215721672177218721972207221722272237224722572267227722872297230723172327233723472357236723772387239724072417242724372447245724672477248724972507251725272537254725572567257725872597260726172627263726472657266726772687269727072717272727372747275727672777278727972807281728272837284728572867287728872897290729172927293729472957296729772987299730073017302730373047305730673077308730973107311731273137314731573167317731873197320732173227323732473257326732773287329733073317332733373347335733673377338733973407341734273437344734573467347734873497350735173527353735473557356735773587359736073617362736373647365736673677368736973707371737273737374737573767377737873797380738173827383738473857386738773887389739073917392739373947395739673977398739974007401740274037404740574067407740874097410741174127413741474157416741774187419742074217422742374247425742674277428742974307431743274337434743574367437743874397440744174427443744474457446744774487449745074517452745374547455745674577458745974607461746274637464746574667467746874697470747174727473747474757476747774787479748074817482748374847485748674877488748974907491749274937494749574967497749874997500750175027503750475057506750775087509751075117512751375147515751675177518751975207521752275237524752575267527752875297530753175327533753475357536753775387539754075417542754375447545754675477548754975507551755275537554755575567557755875597560756175627563756475657566756775687569757075717572757375747575757675777578757975807581758275837584758575867587758875897590759175927593759475957596759775987599760076017602760376047605760676077608760976107611761276137614761576167617761876197620762176227623762476257626762776287629763076317632763376347635763676377638763976407641764276437644764576467647764876497650765176527653765476557656765776587659766076617662766376647665766676677668766976707671767276737674767576767677767876797680768176827683768476857686768776887689769076917692769376947695769676977698769977007701770277037704770577067707770877097710771177127713771477157716771777187719772077217722772377247725772677277728772977307731773277337734773577367737773877397740774177427743774477457746774777487749775077517752775377547755775677577758775977607761776277637764776577667767776877697770777177727773777477757776777777787779778077817782778377847785778677877788778977907791779277937794779577967797779877997800780178027803780478057806780778087809781078117812781378147815781678177818781978207821782278237824782578267827782878297830783178327833783478357836783778387839784078417842784378447845784678477848784978507851785278537854785578567857785878597860786178627863786478657866786778687869787078717872787378747875787678777878787978807881788278837884788578867887788878897890789178927893789478957896789778987899790079017902790379047905790679077908790979107911791279137914791579167917791879197920792179227923792479257926792779287929793079317932793379347935793679377938793979407941794279437944794579467947794879497950795179527953795479557956795779587959796079617962796379647965796679677968796979707971797279737974797579767977797879797980798179827983798479857986798779887989799079917992799379947995799679977998799980008001800280038004800580068007800880098010801180128013801480158016801780188019802080218022802380248025802680278028802980308031803280338034803580368037803880398040804180428043804480458046804780488049805080518052805380548055805680578058805980608061806280638064806580668067806880698070807180728073807480758076807780788079808080818082808380848085808680878088808980908091809280938094809580968097809880998100810181028103810481058106810781088109811081118112811381148115811681178118811981208121812281238124812581268127812881298130813181328133813481358136813781388139814081418142814381448145814681478148814981508151815281538154815581568157815881598160816181628163816481658166816781688169817081718172817381748175817681778178817981808181818281838184818581868187818881898190819181928193819481958196819781988199820082018202820382048205820682078208820982108211821282138214821582168217821882198220822182228223822482258226822782288229823082318232823382348235823682378238823982408241824282438244824582468247824882498250825182528253825482558256825782588259826082618262826382648265826682678268826982708271827282738274827582768277827882798280828182828283828482858286828782888289829082918292829382948295829682978298829983008301830283038304830583068307830883098310831183128313831483158316831783188319832083218322832383248325832683278328832983308331833283338334833583368337833883398340834183428343834483458346834783488349835083518352835383548355835683578358835983608361836283638364836583668367836883698370837183728373837483758376837783788379838083818382838383848385838683878388838983908391839283938394839583968397839883998400840184028403840484058406840784088409841084118412841384148415841684178418841984208421842284238424842584268427842884298430843184328433843484358436843784388439844084418442844384448445844684478448844984508451845284538454845584568457845884598460846184628463846484658466846784688469847084718472847384748475847684778478847984808481848284838484848584868487848884898490849184928493849484958496849784988499850085018502850385048505850685078508850985108511851285138514851585168517851885198520852185228523852485258526852785288529853085318532853385348535853685378538853985408541854285438544854585468547854885498550855185528553855485558556855785588559856085618562856385648565856685678568856985708571857285738574857585768577857885798580858185828583858485858586858785888589859085918592859385948595859685978598859986008601860286038604860586068607860886098610861186128613861486158616861786188619862086218622862386248625862686278628862986308631863286338634863586368637863886398640864186428643864486458646864786488649865086518652865386548655865686578658865986608661866286638664866586668667866886698670867186728673867486758676867786788679868086818682868386848685868686878688868986908691869286938694869586968697869886998700870187028703870487058706870787088709871087118712871387148715871687178718871987208721872287238724872587268727872887298730873187328733873487358736873787388739874087418742874387448745874687478748874987508751875287538754875587568757875887598760876187628763876487658766876787688769877087718772877387748775877687778778877987808781878287838784878587868787878887898790879187928793879487958796879787988799880088018802880388048805880688078808880988108811881288138814881588168817881888198820882188228823882488258826882788288829883088318832883388348835883688378838883988408841884288438844884588468847884888498850885188528853885488558856885788588859886088618862886388648865886688678868886988708871887288738874887588768877887888798880888188828883888488858886888788888889889088918892889388948895889688978898889989008901890289038904890589068907890889098910891189128913891489158916891789188919892089218922892389248925892689278928892989308931893289338934893589368937893889398940894189428943894489458946894789488949895089518952895389548955895689578958895989608961896289638964896589668967896889698970897189728973897489758976897789788979898089818982898389848985898689878988898989908991899289938994899589968997899889999000900190029003900490059006900790089009901090119012901390149015901690179018901990209021902290239024902590269027902890299030903190329033903490359036903790389039904090419042904390449045904690479048904990509051905290539054905590569057905890599060906190629063906490659066906790689069907090719072907390749075907690779078907990809081908290839084908590869087908890899090909190929093909490959096909790989099910091019102910391049105910691079108910991109111911291139114911591169117911891199120912191229123912491259126912791289129913091319132913391349135913691379138913991409141914291439144914591469147914891499150915191529153915491559156915791589159916091619162916391649165916691679168916991709171917291739174917591769177917891799180918191829183918491859186918791889189919091919192919391949195919691979198919992009201920292039204920592069207920892099210921192129213921492159216921792189219922092219222922392249225922692279228922992309231923292339234923592369237923892399240924192429243924492459246924792489249925092519252925392549255925692579258925992609261926292639264926592669267926892699270927192729273927492759276927792789279928092819282928392849285928692879288928992909291929292939294929592969297929892999300930193029303930493059306930793089309931093119312931393149315931693179318931993209321932293239324932593269327932893299330933193329333933493359336933793389339934093419342934393449345934693479348934993509351935293539354935593569357935893599360936193629363936493659366936793689369937093719372937393749375937693779378937993809381938293839384938593869387938893899390939193929393939493959396939793989399940094019402940394049405940694079408940994109411941294139414941594169417941894199420942194229423942494259426942794289429943094319432943394349435943694379438943994409441944294439444944594469447944894499450945194529453945494559456945794589459946094619462946394649465946694679468946994709471947294739474947594769477947894799480948194829483948494859486948794889489949094919492949394949495949694979498949995009501950295039504950595069507950895099510951195129513951495159516951795189519952095219522952395249525952695279528952995309531953295339534953595369537953895399540954195429543954495459546954795489549955095519552955395549555955695579558955995609561956295639564956595669567956895699570957195729573957495759576957795789579958095819582958395849585958695879588958995909591959295939594959595969597959895999600960196029603960496059606960796089609961096119612961396149615961696179618961996209621962296239624962596269627962896299630963196329633963496359636963796389639964096419642964396449645964696479648964996509651965296539654965596569657965896599660966196629663966496659666966796689669967096719672967396749675967696779678967996809681968296839684968596869687968896899690969196929693969496959696969796989699970097019702970397049705970697079708970997109711971297139714971597169717971897199720972197229723972497259726972797289729973097319732973397349735973697379738973997409741974297439744974597469747974897499750975197529753975497559756975797589759976097619762976397649765976697679768976997709771977297739774977597769777977897799780978197829783978497859786978797889789979097919792979397949795979697979798979998009801980298039804980598069807980898099810981198129813981498159816981798189819982098219822982398249825982698279828982998309831983298339834983598369837983898399840984198429843984498459846984798489849985098519852985398549855985698579858985998609861986298639864986598669867986898699870987198729873987498759876987798789879988098819882988398849885988698879888988998909891989298939894989598969897989898999900990199029903990499059906990799089909991099119912991399149915991699179918991999209921992299239924992599269927992899299930993199329933993499359936993799389939994099419942994399449945994699479948994999509951995299539954995599569957995899599960996199629963996499659966996799689969997099719972997399749975997699779978997999809981998299839984998599869987998899899990999199929993999499959996999799989999100001000110002100031000410005100061000710008100091001010011100121001310014100151001610017100181001910020100211002210023100241002510026100271002810029100301003110032100331003410035100361003710038100391004010041100421004310044100451004610047100481004910050100511005210053100541005510056100571005810059100601006110062100631006410065100661006710068100691007010071100721007310074100751007610077100781007910080100811008210083100841008510086100871008810089100901009110092100931009410095100961009710098100991010010101101021010310104101051010610107101081010910110101111011210113101141011510116101171011810119101201012110122101231012410125101261012710128101291013010131101321013310134101351013610137101381013910140101411014210143101441014510146101471014810149101501015110152101531015410155101561015710158101591016010161101621016310164101651016610167101681016910170101711017210173101741017510176101771017810179101801018110182101831018410185101861018710188101891019010191101921019310194101951019610197101981019910200102011020210203102041020510206102071020810209102101021110212102131021410215102161021710218102191022010221102221022310224102251022610227102281022910230102311023210233102341023510236102371023810239102401024110242102431024410245102461024710248102491025010251102521025310254102551025610257102581025910260102611026210263102641026510266102671026810269102701027110272102731027410275102761027710278102791028010281102821028310284102851028610287102881028910290102911029210293102941029510296102971029810299103001030110302103031030410305103061030710308103091031010311103121031310314103151031610317103181031910320103211032210323103241032510326103271032810329103301033110332103331033410335103361033710338103391034010341103421034310344103451034610347103481034910350103511035210353103541035510356103571035810359103601036110362103631036410365103661036710368103691037010371103721037310374103751037610377103781037910380103811038210383103841038510386103871038810389103901039110392103931039410395103961039710398103991040010401104021040310404104051040610407104081040910410104111041210413104141041510416104171041810419104201042110422104231042410425104261042710428104291043010431104321043310434104351043610437104381043910440104411044210443104441044510446104471044810449104501045110452104531045410455104561045710458104591046010461104621046310464104651046610467104681046910470104711047210473104741047510476104771047810479104801048110482104831048410485104861048710488104891049010491104921049310494104951049610497104981049910500105011050210503105041050510506105071050810509105101051110512105131051410515105161051710518105191052010521105221052310524105251052610527105281052910530105311053210533105341053510536105371053810539105401054110542105431054410545105461054710548105491055010551105521055310554105551055610557105581055910560105611056210563105641056510566105671056810569105701057110572105731057410575105761057710578105791058010581105821058310584105851058610587105881058910590105911059210593105941059510596105971059810599106001060110602106031060410605106061060710608106091061010611106121061310614106151061610617106181061910620106211062210623106241062510626106271062810629106301063110632106331063410635106361063710638106391064010641106421064310644106451064610647106481064910650106511065210653106541065510656106571065810659106601066110662106631066410665106661066710668106691067010671106721067310674106751067610677106781067910680106811068210683106841068510686106871068810689106901069110692106931069410695106961069710698106991070010701107021070310704107051070610707107081070910710107111071210713107141071510716107171071810719107201072110722107231072410725107261072710728107291073010731107321073310734107351073610737107381073910740107411074210743107441074510746107471074810749107501075110752107531075410755107561075710758107591076010761107621076310764107651076610767107681076910770107711077210773107741077510776107771077810779107801078110782107831078410785107861078710788107891079010791107921079310794107951079610797107981079910800108011080210803108041080510806108071080810809108101081110812108131081410815108161081710818108191082010821108221082310824108251082610827108281082910830108311083210833108341083510836108371083810839108401084110842108431084410845108461084710848108491085010851108521085310854108551085610857108581085910860108611086210863108641086510866108671086810869108701087110872108731087410875108761087710878108791088010881108821088310884108851088610887108881088910890108911089210893108941089510896108971089810899109001090110902109031090410905109061090710908109091091010911109121091310914109151091610917109181091910920109211092210923109241092510926109271092810929109301093110932109331093410935109361093710938109391094010941109421094310944109451094610947109481094910950109511095210953109541095510956109571095810959109601096110962109631096410965109661096710968109691097010971109721097310974109751097610977109781097910980109811098210983109841098510986109871098810989109901099110992109931099410995109961099710998109991100011001110021100311004110051100611007110081100911010110111101211013110141101511016110171101811019110201102111022110231102411025110261102711028110291103011031110321103311034110351103611037110381103911040110411104211043110441104511046110471104811049110501105111052110531105411055110561105711058110591106011061110621106311064110651106611067110681106911070110711107211073110741107511076110771107811079110801108111082110831108411085110861108711088110891109011091110921109311094110951109611097110981109911100111011110211103111041110511106111071110811109111101111111112111131111411115111161111711118111191112011121111221112311124111251112611127111281112911130111311113211133111341113511136111371113811139111401114111142111431114411145111461114711148111491115011151111521115311154111551115611157111581115911160111611116211163111641116511166111671116811169111701117111172111731117411175111761117711178111791118011181111821118311184111851118611187111881118911190111911119211193111941119511196111971119811199112001120111202112031120411205112061120711208112091121011211112121121311214112151121611217112181121911220112211122211223112241122511226112271122811229112301123111232112331123411235112361123711238112391124011241112421124311244112451124611247112481124911250112511125211253112541125511256112571125811259112601126111262112631126411265112661126711268112691127011271112721127311274112751127611277112781127911280112811128211283112841128511286112871128811289112901129111292112931129411295112961129711298112991130011301113021130311304113051130611307113081130911310113111131211313113141131511316113171131811319113201132111322113231132411325113261132711328113291133011331113321133311334113351133611337113381133911340113411134211343113441134511346113471134811349113501135111352113531135411355113561135711358113591136011361113621136311364113651136611367113681136911370113711137211373113741137511376113771137811379113801138111382113831138411385113861138711388113891139011391113921139311394113951139611397113981139911400114011140211403114041140511406114071140811409114101141111412114131141411415114161141711418114191142011421114221142311424114251142611427114281142911430114311143211433114341143511436114371143811439114401144111442114431144411445114461144711448114491145011451114521145311454114551145611457114581145911460114611146211463114641146511466114671146811469114701147111472114731147411475114761147711478114791148011481114821148311484114851148611487114881148911490114911149211493114941149511496114971149811499115001150111502115031150411505115061150711508115091151011511115121151311514115151151611517115181151911520115211152211523115241152511526115271152811529115301153111532115331153411535115361153711538115391154011541115421154311544115451154611547115481154911550115511155211553115541155511556115571155811559115601156111562115631156411565115661156711568115691157011571115721157311574115751157611577115781157911580115811158211583115841158511586115871158811589115901159111592115931159411595115961159711598115991160011601116021160311604116051160611607116081160911610116111161211613116141161511616116171161811619116201162111622116231162411625116261162711628116291163011631116321163311634116351163611637116381163911640116411164211643116441164511646116471164811649116501165111652116531165411655116561165711658116591166011661116621166311664116651166611667116681166911670116711167211673116741167511676116771167811679116801168111682116831168411685116861168711688116891169011691116921169311694116951169611697116981169911700117011170211703117041170511706117071170811709117101171111712117131171411715117161171711718117191172011721117221172311724117251172611727117281172911730117311173211733117341173511736117371173811739117401174111742117431174411745117461174711748117491175011751117521175311754117551175611757117581175911760117611176211763117641176511766117671176811769117701177111772117731177411775117761177711778117791178011781117821178311784117851178611787117881178911790117911179211793117941179511796117971179811799118001180111802118031180411805118061180711808118091181011811118121181311814118151181611817118181181911820118211182211823118241182511826118271182811829118301183111832118331183411835118361183711838118391184011841118421184311844118451184611847118481184911850118511185211853118541185511856118571185811859118601186111862118631186411865118661186711868118691187011871118721187311874118751187611877118781187911880118811188211883118841188511886118871188811889118901189111892118931189411895118961189711898118991190011901119021190311904119051190611907119081190911910119111191211913119141191511916119171191811919119201192111922119231192411925119261192711928119291193011931119321193311934119351193611937119381193911940119411194211943119441194511946119471194811949119501195111952119531195411955119561195711958119591196011961119621196311964119651196611967119681196911970119711197211973119741197511976119771197811979119801198111982119831198411985119861198711988119891199011991119921199311994119951199611997119981199912000120011200212003120041200512006120071200812009120101201112012120131201412015120161201712018120191202012021120221202312024120251202612027120281202912030120311203212033120341203512036120371203812039120401204112042120431204412045120461204712048120491205012051120521205312054120551205612057120581205912060120611206212063120641206512066120671206812069120701207112072120731207412075120761207712078120791208012081120821208312084120851208612087120881208912090120911209212093120941209512096120971209812099121001210112102121031210412105121061210712108121091211012111121121211312114121151211612117121181211912120121211212212123121241212512126121271212812129121301213112132121331213412135121361213712138121391214012141121421214312144121451214612147121481214912150121511215212153121541215512156121571215812159121601216112162121631216412165121661216712168121691217012171121721217312174121751217612177121781217912180121811218212183121841218512186121871218812189121901219112192121931219412195121961219712198121991220012201122021220312204122051220612207122081220912210122111221212213122141221512216122171221812219122201222112222122231222412225122261222712228122291223012231122321223312234122351223612237122381223912240122411224212243122441224512246122471224812249122501225112252122531225412255122561225712258122591226012261122621226312264122651226612267122681226912270122711227212273122741227512276122771227812279122801228112282122831228412285122861228712288122891229012291122921229312294122951229612297122981229912300123011230212303123041230512306123071230812309123101231112312123131231412315123161231712318123191232012321123221232312324123251232612327123281232912330123311233212333123341233512336123371233812339123401234112342123431234412345123461234712348123491235012351123521235312354123551235612357123581235912360123611236212363123641236512366123671236812369123701237112372123731237412375123761237712378123791238012381123821238312384123851238612387123881238912390123911239212393123941239512396123971239812399124001240112402124031240412405124061240712408124091241012411124121241312414124151241612417124181241912420124211242212423124241242512426124271242812429124301243112432124331243412435124361243712438124391244012441124421244312444124451244612447124481244912450124511245212453124541245512456124571245812459124601246112462124631246412465124661246712468124691247012471124721247312474124751247612477124781247912480124811248212483124841248512486124871248812489124901249112492124931249412495124961249712498124991250012501125021250312504125051250612507125081250912510125111251212513125141251512516125171251812519125201252112522125231252412525125261252712528125291253012531125321253312534125351253612537125381253912540125411254212543125441254512546125471254812549125501255112552125531255412555125561255712558125591256012561125621256312564125651256612567125681256912570125711257212573125741257512576125771257812579125801258112582125831258412585125861258712588125891259012591125921259312594125951259612597125981259912600126011260212603126041260512606126071260812609126101261112612126131261412615126161261712618126191262012621126221262312624126251262612627126281262912630126311263212633126341263512636126371263812639126401264112642126431264412645126461264712648126491265012651126521265312654126551265612657126581265912660126611266212663126641266512666126671266812669126701267112672126731267412675126761267712678126791268012681126821268312684126851268612687126881268912690126911269212693126941269512696126971269812699127001270112702127031270412705127061270712708127091271012711127121271312714127151271612717127181271912720127211272212723127241272512726127271272812729127301273112732127331273412735127361273712738127391274012741127421274312744127451274612747127481274912750127511275212753127541275512756127571275812759127601276112762127631276412765127661276712768127691277012771127721277312774127751277612777127781277912780127811278212783127841278512786127871278812789127901279112792127931279412795127961279712798127991280012801128021280312804128051280612807128081280912810128111281212813128141281512816128171281812819128201282112822128231282412825128261282712828128291283012831128321283312834128351283612837128381283912840128411284212843128441284512846128471284812849128501285112852128531285412855128561285712858128591286012861128621286312864128651286612867128681286912870128711287212873128741287512876128771287812879128801288112882128831288412885128861288712888128891289012891128921289312894128951289612897128981289912900129011290212903129041290512906129071290812909129101291112912129131291412915129161291712918129191292012921129221292312924129251292612927129281292912930129311293212933129341293512936129371293812939129401294112942129431294412945129461294712948129491295012951129521295312954129551295612957129581295912960129611296212963129641296512966129671296812969129701297112972129731297412975129761297712978129791298012981129821298312984129851298612987129881298912990129911299212993129941299512996129971299812999130001300113002130031300413005130061300713008130091301013011130121301313014130151301613017130181301913020130211302213023130241302513026130271302813029130301303113032130331303413035130361303713038130391304013041130421304313044130451304613047130481304913050130511305213053130541305513056130571305813059130601306113062130631306413065130661306713068130691307013071130721307313074130751307613077130781307913080130811308213083130841308513086130871308813089130901309113092130931309413095130961309713098130991310013101131021310313104131051310613107131081310913110131111311213113131141311513116131171311813119131201312113122131231312413125131261312713128131291313013131131321313313134131351313613137131381313913140131411314213143131441314513146131471314813149131501315113152131531315413155131561315713158131591316013161131621316313164131651316613167131681316913170131711317213173131741317513176131771317813179131801318113182131831318413185131861318713188131891319013191131921319313194131951319613197131981319913200132011320213203132041320513206132071320813209132101321113212132131321413215132161321713218132191322013221132221322313224132251322613227132281322913230132311323213233132341323513236132371323813239132401324113242132431324413245132461324713248132491325013251132521325313254132551325613257132581325913260132611326213263132641326513266132671326813269132701327113272132731327413275132761327713278132791328013281132821328313284132851328613287132881328913290132911329213293132941329513296132971329813299133001330113302133031330413305133061330713308133091331013311133121331313314133151331613317133181331913320133211332213323133241332513326133271332813329133301333113332133331333413335133361333713338133391334013341133421334313344133451334613347133481334913350133511335213353133541335513356133571335813359133601336113362133631336413365133661336713368133691337013371133721337313374133751337613377133781337913380133811338213383133841338513386133871338813389133901339113392133931339413395133961339713398133991340013401134021340313404134051340613407134081340913410134111341213413134141341513416134171341813419134201342113422134231342413425134261342713428134291343013431134321343313434134351343613437134381343913440134411344213443134441344513446134471344813449134501345113452134531345413455134561345713458134591346013461134621346313464134651346613467134681346913470134711347213473134741347513476134771347813479134801348113482134831348413485134861348713488134891349013491134921349313494134951349613497134981349913500135011350213503135041350513506135071350813509135101351113512135131351413515135161351713518135191352013521135221352313524135251352613527135281352913530135311353213533135341353513536135371353813539135401354113542135431354413545135461354713548135491355013551135521355313554135551355613557135581355913560135611356213563135641356513566135671356813569135701357113572135731357413575135761357713578135791358013581135821358313584135851358613587135881358913590135911359213593135941359513596135971359813599136001360113602136031360413605136061360713608136091361013611136121361313614136151361613617136181361913620136211362213623136241362513626136271362813629136301363113632136331363413635136361363713638136391364013641136421364313644136451364613647136481364913650136511365213653136541365513656136571365813659136601366113662136631366413665136661366713668136691367013671136721367313674136751367613677136781367913680136811368213683136841368513686136871368813689136901369113692136931369413695136961369713698136991370013701137021370313704137051370613707137081370913710137111371213713137141371513716137171371813719137201372113722137231372413725137261372713728137291373013731137321373313734137351373613737137381373913740137411374213743137441374513746137471374813749137501375113752137531375413755137561375713758137591376013761137621376313764137651376613767137681376913770137711377213773137741377513776137771377813779137801378113782137831378413785137861378713788137891379013791137921379313794137951379613797137981379913800138011380213803138041380513806138071380813809138101381113812138131381413815138161381713818138191382013821138221382313824138251382613827138281382913830138311383213833138341383513836138371383813839138401384113842138431384413845138461384713848138491385013851138521385313854138551385613857138581385913860138611386213863138641386513866138671386813869138701387113872138731387413875138761387713878138791388013881138821388313884138851388613887138881388913890138911389213893138941389513896138971389813899139001390113902139031390413905139061390713908139091391013911139121391313914139151391613917139181391913920139211392213923139241392513926139271392813929139301393113932139331393413935139361393713938139391394013941139421394313944139451394613947139481394913950139511395213953139541395513956139571395813959139601396113962139631396413965139661396713968139691397013971139721397313974139751397613977139781397913980139811398213983139841398513986139871398813989139901399113992139931399413995139961399713998139991400014001140021400314004140051400614007140081400914010140111401214013140141401514016140171401814019140201402114022140231402414025140261402714028140291403014031140321403314034140351403614037140381403914040140411404214043140441404514046140471404814049140501405114052140531405414055140561405714058140591406014061140621406314064140651406614067140681406914070140711407214073140741407514076140771407814079140801408114082140831408414085140861408714088140891409014091140921409314094140951409614097140981409914100141011410214103141041410514106141071410814109141101411114112141131411414115141161411714118141191412014121141221412314124141251412614127141281412914130141311413214133141341413514136141371413814139141401414114142141431414414145141461414714148141491415014151141521415314154141551415614157141581415914160141611416214163141641416514166141671416814169141701417114172141731417414175141761417714178141791418014181141821418314184141851418614187141881418914190141911419214193141941419514196141971419814199142001420114202142031420414205142061420714208142091421014211142121421314214142151421614217142181421914220142211422214223142241422514226142271422814229142301423114232142331423414235142361423714238142391424014241142421424314244142451424614247142481424914250142511425214253142541425514256142571425814259142601426114262142631426414265142661426714268142691427014271142721427314274142751427614277142781427914280142811428214283142841428514286142871428814289142901429114292142931429414295142961429714298142991430014301143021430314304143051430614307143081430914310143111431214313143141431514316143171431814319143201432114322143231432414325143261432714328143291433014331143321433314334143351433614337143381433914340143411434214343143441434514346143471434814349143501435114352143531435414355143561435714358143591436014361143621436314364143651436614367143681436914370143711437214373143741437514376143771437814379143801438114382143831438414385143861438714388143891439014391143921439314394143951439614397143981439914400144011440214403144041440514406144071440814409144101441114412144131441414415144161441714418144191442014421144221442314424144251442614427144281442914430144311443214433144341443514436144371443814439144401444114442144431444414445144461444714448144491445014451144521445314454144551445614457144581445914460144611446214463144641446514466144671446814469144701447114472144731447414475144761447714478144791448014481144821448314484144851448614487144881448914490144911449214493144941449514496144971449814499145001450114502145031450414505145061450714508145091451014511145121451314514145151451614517145181451914520145211452214523145241452514526145271452814529145301453114532145331453414535145361453714538145391454014541145421454314544145451454614547145481454914550145511455214553145541455514556145571455814559145601456114562145631456414565145661456714568145691457014571145721457314574145751457614577145781457914580145811458214583145841458514586145871458814589145901459114592145931459414595145961459714598145991460014601146021460314604146051460614607146081460914610146111461214613146141461514616146171461814619146201462114622146231462414625146261462714628146291463014631146321463314634146351463614637146381463914640146411464214643146441464514646146471464814649146501465114652146531465414655146561465714658146591466014661146621466314664146651466614667146681466914670146711467214673146741467514676146771467814679146801468114682146831468414685146861468714688146891469014691146921469314694146951469614697146981469914700147011470214703147041470514706147071470814709147101471114712147131471414715147161471714718147191472014721147221472314724147251472614727147281472914730147311473214733147341473514736147371473814739147401474114742147431474414745147461474714748147491475014751147521475314754147551475614757147581475914760147611476214763147641476514766147671476814769147701477114772147731477414775147761477714778147791478014781147821478314784147851478614787147881478914790147911479214793147941479514796147971479814799148001480114802148031480414805148061480714808148091481014811148121481314814148151481614817148181481914820148211482214823148241482514826148271482814829148301483114832148331483414835148361483714838148391484014841148421484314844148451484614847148481484914850148511485214853148541485514856148571485814859148601486114862148631486414865148661486714868148691487014871148721487314874148751487614877148781487914880148811488214883148841488514886148871488814889148901489114892148931489414895148961489714898148991490014901149021490314904149051490614907149081490914910149111491214913149141491514916149171491814919149201492114922149231492414925149261492714928149291493014931149321493314934149351493614937149381493914940149411494214943149441494514946149471494814949149501495114952149531495414955149561495714958149591496014961149621496314964149651496614967149681496914970149711497214973149741497514976149771497814979149801498114982149831498414985149861498714988149891499014991149921499314994149951499614997149981499915000150011500215003150041500515006150071500815009150101501115012150131501415015150161501715018150191502015021150221502315024150251502615027150281502915030150311503215033150341503515036150371503815039150401504115042150431504415045150461504715048150491505015051150521505315054150551505615057150581505915060150611506215063150641506515066150671506815069150701507115072150731507415075150761507715078150791508015081150821508315084150851508615087150881508915090150911509215093150941509515096150971509815099151001510115102151031510415105151061510715108151091511015111151121511315114151151511615117151181511915120151211512215123151241512515126151271512815129151301513115132151331513415135151361513715138151391514015141151421514315144151451514615147151481514915150151511515215153151541515515156151571515815159151601516115162151631516415165151661516715168151691517015171151721517315174151751517615177151781517915180151811518215183151841518515186151871518815189151901519115192151931519415195151961519715198151991520015201152021520315204152051520615207152081520915210152111521215213152141521515216152171521815219152201522115222152231522415225152261522715228152291523015231152321523315234152351523615237152381523915240152411524215243152441524515246152471524815249152501525115252152531525415255152561525715258152591526015261152621526315264152651526615267152681526915270152711527215273152741527515276152771527815279152801528115282152831528415285152861528715288152891529015291152921529315294152951529615297152981529915300153011530215303153041530515306153071530815309153101531115312153131531415315153161531715318153191532015321153221532315324153251532615327153281532915330153311533215333153341533515336153371533815339153401534115342153431534415345153461534715348153491535015351153521535315354153551535615357153581535915360153611536215363153641536515366153671536815369153701537115372153731537415375153761537715378153791538015381153821538315384153851538615387153881538915390153911539215393153941539515396153971539815399154001540115402154031540415405154061540715408154091541015411154121541315414154151541615417154181541915420154211542215423154241542515426154271542815429154301543115432154331543415435154361543715438154391544015441154421544315444154451544615447154481544915450154511545215453154541545515456154571545815459154601546115462154631546415465154661546715468154691547015471154721547315474154751547615477154781547915480154811548215483154841548515486154871548815489154901549115492154931549415495154961549715498154991550015501155021550315504155051550615507155081550915510155111551215513155141551515516155171551815519155201552115522155231552415525155261552715528155291553015531155321553315534155351553615537155381553915540155411554215543155441554515546155471554815549155501555115552155531555415555155561555715558155591556015561155621556315564155651556615567155681556915570155711557215573155741557515576155771557815579155801558115582155831558415585155861558715588155891559015591155921559315594155951559615597155981559915600156011560215603156041560515606156071560815609156101561115612156131561415615156161561715618156191562015621156221562315624156251562615627156281562915630156311563215633156341563515636156371563815639156401564115642156431564415645156461564715648156491565015651156521565315654156551565615657156581565915660156611566215663156641566515666156671566815669156701567115672156731567415675156761567715678156791568015681156821568315684156851568615687156881568915690156911569215693156941569515696156971569815699157001570115702157031570415705157061570715708157091571015711157121571315714157151571615717157181571915720157211572215723157241572515726157271572815729157301573115732157331573415735157361573715738157391574015741157421574315744157451574615747157481574915750157511575215753157541575515756157571575815759157601576115762157631576415765157661576715768157691577015771157721577315774157751577615777157781577915780157811578215783157841578515786157871578815789157901579115792157931579415795157961579715798157991580015801158021580315804158051580615807158081580915810158111581215813158141581515816158171581815819158201582115822158231582415825158261582715828158291583015831158321583315834158351583615837158381583915840158411584215843158441584515846158471584815849158501585115852158531585415855158561585715858158591586015861158621586315864158651586615867158681586915870158711587215873158741587515876158771587815879158801588115882158831588415885158861588715888158891589015891158921589315894158951589615897158981589915900159011590215903159041590515906159071590815909159101591115912159131591415915159161591715918159191592015921159221592315924159251592615927159281592915930159311593215933159341593515936159371593815939159401594115942159431594415945159461594715948159491595015951159521595315954159551595615957159581595915960159611596215963159641596515966159671596815969159701597115972159731597415975159761597715978159791598015981159821598315984159851598615987159881598915990159911599215993159941599515996159971599815999160001600116002160031600416005160061600716008160091601016011160121601316014160151601616017160181601916020160211602216023160241602516026160271602816029160301603116032160331603416035160361603716038160391604016041160421604316044160451604616047160481604916050160511605216053160541605516056160571605816059160601606116062160631606416065160661606716068160691607016071160721607316074160751607616077160781607916080160811608216083160841608516086160871608816089160901609116092160931609416095160961609716098160991610016101161021610316104161051610616107161081610916110161111611216113161141611516116161171611816119161201612116122161231612416125161261612716128161291613016131161321613316134161351613616137161381613916140161411614216143161441614516146161471614816149161501615116152161531615416155161561615716158161591616016161161621616316164161651616616167161681616916170161711617216173161741617516176161771617816179161801618116182161831618416185161861618716188161891619016191161921619316194161951619616197161981619916200162011620216203162041620516206162071620816209162101621116212162131621416215162161621716218162191622016221162221622316224162251622616227162281622916230162311623216233162341623516236162371623816239162401624116242162431624416245162461624716248162491625016251162521625316254162551625616257162581625916260162611626216263162641626516266162671626816269162701627116272162731627416275162761627716278162791628016281162821628316284162851628616287162881628916290162911629216293162941629516296162971629816299163001630116302163031630416305163061630716308163091631016311163121631316314163151631616317163181631916320163211632216323163241632516326163271632816329163301633116332163331633416335163361633716338163391634016341163421634316344163451634616347163481634916350163511635216353163541635516356163571635816359163601636116362163631636416365163661636716368163691637016371163721637316374163751637616377163781637916380163811638216383163841638516386163871638816389163901639116392163931639416395163961639716398163991640016401164021640316404164051640616407164081640916410164111641216413164141641516416164171641816419164201642116422164231642416425164261642716428164291643016431164321643316434164351643616437164381643916440164411644216443164441644516446164471644816449164501645116452164531645416455164561645716458164591646016461164621646316464164651646616467164681646916470164711647216473164741647516476164771647816479164801648116482164831648416485164861648716488164891649016491164921649316494164951649616497164981649916500165011650216503165041650516506165071650816509165101651116512165131651416515165161651716518165191652016521165221652316524165251652616527165281652916530165311653216533165341653516536165371653816539165401654116542165431654416545165461654716548165491655016551165521655316554165551655616557165581655916560165611656216563165641656516566165671656816569165701657116572165731657416575165761657716578165791658016581165821658316584165851658616587165881658916590165911659216593165941659516596165971659816599166001660116602166031660416605166061660716608166091661016611166121661316614166151661616617166181661916620166211662216623166241662516626166271662816629166301663116632166331663416635166361663716638166391664016641166421664316644166451664616647166481664916650166511665216653166541665516656166571665816659166601666116662166631666416665166661666716668166691667016671166721667316674166751667616677166781667916680166811668216683166841668516686166871668816689166901669116692166931669416695166961669716698166991670016701167021670316704167051670616707167081670916710167111671216713167141671516716167171671816719167201672116722167231672416725167261672716728167291673016731167321673316734167351673616737167381673916740167411674216743167441674516746167471674816749167501675116752167531675416755167561675716758167591676016761167621676316764167651676616767167681676916770167711677216773167741677516776167771677816779167801678116782167831678416785167861678716788167891679016791167921679316794167951679616797167981679916800168011680216803168041680516806168071680816809168101681116812168131681416815168161681716818168191682016821168221682316824168251682616827168281682916830168311683216833168341683516836168371683816839168401684116842168431684416845168461684716848168491685016851168521685316854168551685616857168581685916860168611686216863168641686516866168671686816869168701687116872168731687416875168761687716878168791688016881168821688316884168851688616887168881688916890168911689216893168941689516896168971689816899169001690116902169031690416905169061690716908169091691016911169121691316914169151691616917169181691916920169211692216923169241692516926169271692816929169301693116932169331693416935169361693716938169391694016941169421694316944169451694616947169481694916950169511695216953169541695516956169571695816959169601696116962169631696416965169661696716968169691697016971169721697316974169751697616977169781697916980169811698216983169841698516986169871698816989169901699116992169931699416995169961699716998169991700017001170021700317004170051700617007170081700917010170111701217013170141701517016170171701817019170201702117022170231702417025170261702717028170291703017031170321703317034170351703617037170381703917040170411704217043170441704517046170471704817049170501705117052170531705417055170561705717058170591706017061170621706317064170651706617067170681706917070170711707217073170741707517076170771707817079170801708117082170831708417085170861708717088170891709017091170921709317094170951709617097170981709917100171011710217103171041710517106171071710817109171101711117112171131711417115171161711717118171191712017121171221712317124171251712617127171281712917130171311713217133171341713517136171371713817139171401714117142171431714417145171461714717148171491715017151171521715317154171551715617157171581715917160171611716217163171641716517166171671716817169171701717117172171731717417175171761717717178171791718017181171821718317184171851718617187171881718917190171911719217193171941719517196171971719817199172001720117202172031720417205172061720717208172091721017211172121721317214172151721617217172181721917220172211722217223172241722517226172271722817229172301723117232172331723417235172361723717238172391724017241172421724317244172451724617247172481724917250172511725217253172541725517256172571725817259172601726117262172631726417265172661726717268172691727017271172721727317274172751727617277172781727917280172811728217283172841728517286172871728817289172901729117292172931729417295172961729717298172991730017301173021730317304173051730617307173081730917310173111731217313173141731517316173171731817319173201732117322173231732417325173261732717328173291733017331173321733317334173351733617337173381733917340173411734217343173441734517346173471734817349173501735117352173531735417355173561735717358173591736017361173621736317364173651736617367173681736917370173711737217373173741737517376173771737817379173801738117382173831738417385173861738717388173891739017391173921739317394173951739617397173981739917400174011740217403174041740517406174071740817409174101741117412174131741417415174161741717418174191742017421174221742317424174251742617427174281742917430174311743217433174341743517436174371743817439174401744117442174431744417445174461744717448174491745017451174521745317454174551745617457174581745917460174611746217463174641746517466174671746817469174701747117472174731747417475174761747717478174791748017481174821748317484174851748617487174881748917490174911749217493174941749517496174971749817499175001750117502175031750417505175061750717508175091751017511175121751317514175151751617517175181751917520175211752217523175241752517526175271752817529175301753117532175331753417535175361753717538175391754017541175421754317544175451754617547175481754917550175511755217553175541755517556175571755817559175601756117562175631756417565175661756717568175691757017571175721757317574175751757617577175781757917580175811758217583175841758517586175871758817589175901759117592175931759417595175961759717598175991760017601176021760317604176051760617607176081760917610176111761217613176141761517616176171761817619176201762117622176231762417625176261762717628176291763017631176321763317634176351763617637176381763917640176411764217643176441764517646176471764817649176501765117652176531765417655176561765717658176591766017661176621766317664176651766617667176681766917670176711767217673176741767517676176771767817679176801768117682176831768417685176861768717688176891769017691176921769317694176951769617697176981769917700177011770217703177041770517706177071770817709177101771117712177131771417715177161771717718177191772017721177221772317724177251772617727177281772917730177311773217733177341773517736177371773817739177401774117742177431774417745177461774717748177491775017751177521775317754177551775617757177581775917760177611776217763177641776517766177671776817769177701777117772177731777417775177761777717778177791778017781177821778317784177851778617787177881778917790177911779217793177941779517796177971779817799178001780117802178031780417805178061780717808178091781017811178121781317814178151781617817178181781917820178211782217823178241782517826178271782817829178301783117832178331783417835178361783717838178391784017841178421784317844178451784617847178481784917850178511785217853178541785517856178571785817859178601786117862178631786417865178661786717868178691787017871178721787317874178751787617877178781787917880178811788217883178841788517886178871788817889178901789117892178931789417895178961789717898178991790017901179021790317904179051790617907179081790917910179111791217913179141791517916179171791817919179201792117922179231792417925179261792717928179291793017931179321793317934179351793617937179381793917940179411794217943179441794517946179471794817949179501795117952179531795417955179561795717958179591796017961179621796317964179651796617967179681796917970179711797217973179741797517976179771797817979179801798117982179831798417985179861798717988179891799017991179921799317994179951799617997179981799918000180011800218003180041800518006180071800818009180101801118012180131801418015180161801718018180191802018021180221802318024180251802618027180281802918030180311803218033180341803518036180371803818039180401804118042180431804418045180461804718048180491805018051180521805318054180551805618057180581805918060180611806218063180641806518066180671806818069180701807118072180731807418075180761807718078180791808018081180821808318084180851808618087180881808918090180911809218093180941809518096180971809818099181001810118102181031810418105181061810718108181091811018111181121811318114181151811618117181181811918120181211812218123181241812518126181271812818129181301813118132181331813418135181361813718138181391814018141181421814318144181451814618147181481814918150181511815218153181541815518156181571815818159181601816118162181631816418165181661816718168181691817018171181721817318174181751817618177181781817918180181811818218183181841818518186181871818818189181901819118192181931819418195181961819718198181991820018201182021820318204182051820618207182081820918210182111821218213182141821518216182171821818219182201822118222182231822418225182261822718228182291823018231182321823318234182351823618237182381823918240182411824218243182441824518246182471824818249182501825118252182531825418255182561825718258182591826018261182621826318264182651826618267182681826918270182711827218273182741827518276182771827818279182801828118282182831828418285182861828718288182891829018291182921829318294182951829618297182981829918300183011830218303183041830518306183071830818309183101831118312183131831418315183161831718318183191832018321183221832318324183251832618327183281832918330183311833218333183341833518336183371833818339183401834118342183431834418345183461834718348183491835018351183521835318354183551835618357183581835918360183611836218363183641836518366183671836818369183701837118372183731837418375183761837718378183791838018381183821838318384183851838618387183881838918390183911839218393183941839518396183971839818399184001840118402184031840418405184061840718408184091841018411184121841318414184151841618417184181841918420184211842218423184241842518426184271842818429184301843118432184331843418435184361843718438184391844018441184421844318444184451844618447184481844918450184511845218453184541845518456184571845818459184601846118462184631846418465184661846718468184691847018471184721847318474184751847618477184781847918480184811848218483184841848518486184871848818489184901849118492184931849418495184961849718498184991850018501185021850318504185051850618507185081850918510185111851218513185141851518516185171851818519185201852118522185231852418525185261852718528185291853018531185321853318534185351853618537185381853918540185411854218543185441854518546185471854818549185501855118552185531855418555185561855718558185591856018561185621856318564185651856618567185681856918570185711857218573185741857518576185771857818579185801858118582185831858418585185861858718588185891859018591185921859318594185951859618597185981859918600186011860218603186041860518606186071860818609186101861118612186131861418615186161861718618186191862018621186221862318624186251862618627186281862918630186311863218633186341863518636186371863818639186401864118642186431864418645186461864718648186491865018651186521865318654186551865618657186581865918660186611866218663186641866518666186671866818669186701867118672186731867418675186761867718678186791868018681186821868318684186851868618687186881868918690186911869218693186941869518696186971869818699187001870118702187031870418705187061870718708187091871018711187121871318714187151871618717187181871918720187211872218723187241872518726187271872818729187301873118732187331873418735187361873718738187391874018741187421874318744187451874618747187481874918750187511875218753187541875518756187571875818759187601876118762187631876418765187661876718768187691877018771187721877318774187751877618777187781877918780187811878218783187841878518786187871878818789187901879118792187931879418795187961879718798187991880018801188021880318804188051880618807188081880918810188111881218813188141881518816188171881818819188201882118822188231882418825188261882718828188291883018831188321883318834188351883618837188381883918840188411884218843188441884518846188471884818849188501885118852188531885418855188561885718858188591886018861188621886318864188651886618867188681886918870188711887218873188741887518876188771887818879188801888118882188831888418885188861888718888188891889018891188921889318894188951889618897188981889918900189011890218903189041890518906189071890818909189101891118912189131891418915189161891718918189191892018921189221892318924189251892618927189281892918930189311893218933189341893518936189371893818939189401894118942189431894418945189461894718948189491895018951189521895318954189551895618957189581895918960189611896218963189641896518966189671896818969189701897118972189731897418975189761897718978189791898018981189821898318984189851898618987189881898918990189911899218993189941899518996189971899818999190001900119002190031900419005190061900719008190091901019011190121901319014190151901619017190181901919020190211902219023190241902519026190271902819029190301903119032190331903419035190361903719038190391904019041190421904319044190451904619047190481904919050190511905219053190541905519056190571905819059190601906119062190631906419065190661906719068190691907019071190721907319074190751907619077190781907919080190811908219083190841908519086190871908819089190901909119092190931909419095190961909719098190991910019101191021910319104191051910619107191081910919110191111911219113191141911519116191171911819119191201912119122191231912419125191261912719128191291913019131191321913319134191351913619137191381913919140191411914219143191441914519146191471914819149191501915119152191531915419155191561915719158191591916019161191621916319164191651916619167191681916919170191711917219173191741917519176191771917819179191801918119182191831918419185191861918719188191891919019191191921919319194191951919619197191981919919200192011920219203192041920519206192071920819209192101921119212192131921419215192161921719218192191922019221192221922319224192251922619227192281922919230192311923219233192341923519236192371923819239192401924119242192431924419245192461924719248192491925019251192521925319254192551925619257192581925919260192611926219263192641926519266192671926819269192701927119272192731927419275192761927719278192791928019281192821928319284192851928619287192881928919290192911929219293192941929519296192971929819299193001930119302193031930419305193061930719308193091931019311193121931319314193151931619317193181931919320193211932219323193241932519326193271932819329193301933119332193331933419335193361933719338193391934019341193421934319344193451934619347193481934919350193511935219353193541935519356193571935819359193601936119362193631936419365193661936719368193691937019371193721937319374193751937619377193781937919380193811938219383193841938519386193871938819389193901939119392193931939419395193961939719398193991940019401194021940319404194051940619407194081940919410194111941219413194141941519416194171941819419194201942119422194231942419425194261942719428194291943019431194321943319434194351943619437194381943919440194411944219443194441944519446194471944819449194501945119452194531945419455194561945719458194591946019461194621946319464194651946619467194681946919470194711947219473194741947519476194771947819479194801948119482194831948419485194861948719488194891949019491194921949319494194951949619497194981949919500195011950219503195041950519506195071950819509195101951119512195131951419515195161951719518195191952019521195221952319524195251952619527195281952919530195311953219533195341953519536195371953819539195401954119542195431954419545195461954719548195491955019551195521955319554195551955619557195581955919560195611956219563195641956519566195671956819569195701957119572195731957419575195761957719578195791958019581195821958319584195851958619587195881958919590195911959219593195941959519596195971959819599196001960119602196031960419605196061960719608196091961019611196121961319614196151961619617196181961919620196211962219623196241962519626196271962819629196301963119632196331963419635196361963719638196391964019641196421964319644196451964619647196481964919650196511965219653196541965519656196571965819659196601966119662196631966419665196661966719668196691967019671196721967319674196751967619677196781967919680196811968219683196841968519686196871968819689196901969119692196931969419695196961969719698196991970019701197021970319704197051970619707197081970919710197111971219713197141971519716197171971819719197201972119722197231972419725197261972719728197291973019731197321973319734197351973619737197381973919740197411974219743197441974519746197471974819749197501975119752197531975419755197561975719758197591976019761197621976319764197651976619767197681976919770197711977219773197741977519776197771977819779197801978119782197831978419785197861978719788197891979019791197921979319794197951979619797197981979919800198011980219803198041980519806198071980819809198101981119812198131981419815198161981719818198191982019821198221982319824198251982619827198281982919830198311983219833198341983519836198371983819839198401984119842198431984419845198461984719848198491985019851198521985319854198551985619857198581985919860198611986219863198641986519866198671986819869198701987119872198731987419875198761987719878198791988019881198821988319884198851988619887198881988919890198911989219893198941989519896198971989819899199001990119902199031990419905199061990719908199091991019911199121991319914199151991619917199181991919920199211992219923199241992519926199271992819929199301993119932199331993419935199361993719938199391994019941199421994319944199451994619947199481994919950199511995219953199541995519956199571995819959199601996119962199631996419965199661996719968199691997019971199721997319974199751997619977199781997919980199811998219983199841998519986199871998819989199901999119992199931999419995199961999719998199992000020001200022000320004200052000620007200082000920010200112001220013200142001520016200172001820019200202002120022200232002420025200262002720028200292003020031200322003320034200352003620037200382003920040200412004220043200442004520046200472004820049200502005120052200532005420055200562005720058200592006020061200622006320064200652006620067200682006920070200712007220073200742007520076200772007820079200802008120082200832008420085200862008720088200892009020091200922009320094200952009620097200982009920100201012010220103201042010520106201072010820109201102011120112201132011420115201162011720118201192012020121201222012320124201252012620127201282012920130201312013220133201342013520136201372013820139201402014120142201432014420145201462014720148201492015020151201522015320154201552015620157201582015920160201612016220163201642016520166201672016820169201702017120172201732017420175201762017720178201792018020181201822018320184201852018620187201882018920190201912019220193201942019520196201972019820199202002020120202202032020420205202062020720208202092021020211202122021320214202152021620217202182021920220202212022220223202242022520226202272022820229202302023120232202332023420235202362023720238202392024020241202422024320244202452024620247202482024920250202512025220253202542025520256202572025820259202602026120262202632026420265202662026720268202692027020271202722027320274202752027620277202782027920280202812028220283202842028520286202872028820289202902029120292202932029420295202962029720298202992030020301203022030320304203052030620307203082030920310203112031220313203142031520316203172031820319203202032120322203232032420325203262032720328203292033020331203322033320334203352033620337203382033920340203412034220343203442034520346203472034820349203502035120352203532035420355203562035720358203592036020361203622036320364203652036620367203682036920370203712037220373203742037520376203772037820379203802038120382203832038420385203862038720388203892039020391203922039320394203952039620397203982039920400204012040220403204042040520406204072040820409204102041120412204132041420415204162041720418204192042020421204222042320424204252042620427204282042920430204312043220433204342043520436204372043820439204402044120442204432044420445204462044720448204492045020451204522045320454204552045620457204582045920460204612046220463204642046520466204672046820469204702047120472204732047420475204762047720478204792048020481204822048320484204852048620487204882048920490204912049220493204942049520496204972049820499205002050120502205032050420505205062050720508205092051020511205122051320514205152051620517205182051920520205212052220523205242052520526205272052820529205302053120532205332053420535205362053720538205392054020541205422054320544205452054620547205482054920550205512055220553205542055520556205572055820559205602056120562205632056420565205662056720568205692057020571205722057320574205752057620577205782057920580205812058220583205842058520586205872058820589205902059120592205932059420595205962059720598205992060020601206022060320604206052060620607206082060920610206112061220613206142061520616206172061820619206202062120622206232062420625206262062720628206292063020631206322063320634206352063620637206382063920640206412064220643206442064520646206472064820649206502065120652206532065420655206562065720658206592066020661206622066320664206652066620667206682066920670206712067220673206742067520676206772067820679206802068120682206832068420685206862068720688206892069020691206922069320694206952069620697206982069920700207012070220703207042070520706207072070820709207102071120712207132071420715207162071720718207192072020721207222072320724207252072620727207282072920730207312073220733207342073520736207372073820739207402074120742207432074420745207462074720748207492075020751207522075320754207552075620757207582075920760207612076220763207642076520766207672076820769207702077120772207732077420775207762077720778207792078020781207822078320784207852078620787207882078920790207912079220793207942079520796207972079820799208002080120802208032080420805208062080720808208092081020811208122081320814208152081620817208182081920820208212082220823208242082520826208272082820829208302083120832208332083420835208362083720838208392084020841208422084320844208452084620847208482084920850208512085220853208542085520856208572085820859208602086120862208632086420865208662086720868208692087020871208722087320874208752087620877208782087920880208812088220883208842088520886208872088820889208902089120892208932089420895208962089720898208992090020901209022090320904209052090620907209082090920910209112091220913209142091520916209172091820919209202092120922209232092420925209262092720928209292093020931209322093320934209352093620937209382093920940209412094220943209442094520946209472094820949209502095120952209532095420955209562095720958209592096020961209622096320964209652096620967209682096920970209712097220973209742097520976209772097820979209802098120982209832098420985209862098720988209892099020991209922099320994209952099620997209982099921000210012100221003210042100521006210072100821009210102101121012210132101421015210162101721018210192102021021210222102321024210252102621027210282102921030210312103221033210342103521036210372103821039210402104121042210432104421045210462104721048210492105021051210522105321054210552105621057210582105921060210612106221063210642106521066210672106821069210702107121072210732107421075210762107721078210792108021081210822108321084210852108621087210882108921090210912109221093210942109521096210972109821099211002110121102211032110421105211062110721108211092111021111211122111321114211152111621117211182111921120211212112221123211242112521126211272112821129211302113121132211332113421135211362113721138211392114021141211422114321144211452114621147211482114921150211512115221153211542115521156211572115821159211602116121162211632116421165211662116721168211692117021171211722117321174211752117621177211782117921180211812118221183211842118521186211872118821189211902119121192211932119421195211962119721198211992120021201212022120321204212052120621207212082120921210212112121221213212142121521216212172121821219212202122121222212232122421225212262122721228212292123021231212322123321234212352123621237212382123921240212412124221243212442124521246212472124821249212502125121252212532125421255212562125721258212592126021261212622126321264212652126621267212682126921270212712127221273212742127521276212772127821279212802128121282212832128421285212862128721288212892129021291212922129321294212952129621297212982129921300213012130221303213042130521306213072130821309213102131121312213132131421315213162131721318213192132021321213222132321324213252132621327213282132921330213312133221333213342133521336213372133821339213402134121342213432134421345213462134721348213492135021351213522135321354213552135621357213582135921360213612136221363213642136521366213672136821369213702137121372213732137421375213762137721378213792138021381213822138321384213852138621387213882138921390213912139221393213942139521396213972139821399214002140121402214032140421405214062140721408214092141021411214122141321414214152141621417214182141921420214212142221423214242142521426214272142821429214302143121432214332143421435214362143721438214392144021441214422144321444214452144621447214482144921450214512145221453214542145521456214572145821459214602146121462214632146421465214662146721468214692147021471214722147321474214752147621477214782147921480214812148221483214842148521486214872148821489214902149121492214932149421495214962149721498214992150021501215022150321504215052150621507215082150921510215112151221513215142151521516215172151821519215202152121522215232152421525215262152721528215292153021531215322153321534215352153621537215382153921540215412154221543215442154521546215472154821549215502155121552215532155421555215562155721558215592156021561215622156321564215652156621567215682156921570215712157221573215742157521576215772157821579215802158121582215832158421585215862158721588215892159021591215922159321594215952159621597215982159921600216012160221603216042160521606216072160821609216102161121612216132161421615216162161721618216192162021621216222162321624216252162621627216282162921630216312163221633216342163521636216372163821639216402164121642216432164421645216462164721648216492165021651216522165321654216552165621657216582165921660216612166221663216642166521666216672166821669216702167121672216732167421675216762167721678216792168021681216822168321684216852168621687216882168921690216912169221693216942169521696216972169821699217002170121702217032170421705217062170721708217092171021711217122171321714217152171621717217182171921720217212172221723217242172521726217272172821729217302173121732217332173421735217362173721738217392174021741217422174321744217452174621747217482174921750217512175221753217542175521756217572175821759217602176121762217632176421765217662176721768217692177021771217722177321774217752177621777217782177921780217812178221783217842178521786217872178821789217902179121792217932179421795217962179721798217992180021801218022180321804218052180621807218082180921810218112181221813218142181521816218172181821819218202182121822218232182421825218262182721828218292183021831218322183321834218352183621837218382183921840218412184221843218442184521846218472184821849218502185121852218532185421855218562185721858218592186021861218622186321864218652186621867218682186921870218712187221873218742187521876218772187821879218802188121882218832188421885218862188721888218892189021891218922189321894218952189621897218982189921900219012190221903219042190521906219072190821909219102191121912219132191421915219162191721918219192192021921219222192321924219252192621927219282192921930219312193221933219342193521936219372193821939219402194121942219432194421945219462194721948219492195021951219522195321954219552195621957219582195921960219612196221963219642196521966219672196821969219702197121972219732197421975219762197721978219792198021981219822198321984219852198621987219882198921990219912199221993219942199521996219972199821999220002200122002220032200422005220062200722008220092201022011220122201322014220152201622017220182201922020220212202222023220242202522026220272202822029220302203122032220332203422035220362203722038220392204022041220422204322044220452204622047220482204922050220512205222053220542205522056220572205822059220602206122062220632206422065220662206722068220692207022071220722207322074220752207622077220782207922080220812208222083220842208522086220872208822089220902209122092220932209422095220962209722098220992210022101221022210322104221052210622107221082210922110221112211222113221142211522116221172211822119221202212122122221232212422125221262212722128221292213022131221322213322134221352213622137221382213922140221412214222143221442214522146221472214822149221502215122152221532215422155221562215722158221592216022161221622216322164221652216622167221682216922170221712217222173221742217522176221772217822179221802218122182221832218422185221862218722188221892219022191221922219322194221952219622197221982219922200222012220222203222042220522206222072220822209222102221122212222132221422215222162221722218222192222022221222222222322224222252222622227222282222922230222312223222233222342223522236222372223822239222402224122242222432224422245222462224722248222492225022251222522225322254222552225622257222582225922260222612226222263222642226522266222672226822269222702227122272222732227422275222762227722278222792228022281222822228322284222852228622287222882228922290222912229222293222942229522296222972229822299223002230122302223032230422305223062230722308223092231022311223122231322314223152231622317223182231922320223212232222323223242232522326223272232822329223302233122332223332233422335223362233722338223392234022341223422234322344223452234622347223482234922350223512235222353223542235522356223572235822359223602236122362223632236422365223662236722368223692237022371223722237322374223752237622377223782237922380223812238222383223842238522386223872238822389223902239122392223932239422395223962239722398223992240022401224022240322404224052240622407224082240922410224112241222413224142241522416224172241822419224202242122422224232242422425224262242722428224292243022431224322243322434224352243622437224382243922440224412244222443224442244522446224472244822449224502245122452224532245422455224562245722458224592246022461224622246322464224652246622467224682246922470224712247222473224742247522476224772247822479224802248122482224832248422485224862248722488224892249022491224922249322494224952249622497224982249922500225012250222503225042250522506225072250822509225102251122512225132251422515225162251722518225192252022521225222252322524225252252622527225282252922530225312253222533225342253522536225372253822539225402254122542225432254422545225462254722548225492255022551225522255322554225552255622557225582255922560225612256222563225642256522566225672256822569225702257122572225732257422575225762257722578225792258022581225822258322584225852258622587225882258922590225912259222593225942259522596225972259822599226002260122602226032260422605226062260722608226092261022611226122261322614226152261622617226182261922620226212262222623226242262522626226272262822629226302263122632226332263422635226362263722638226392264022641226422264322644226452264622647226482264922650226512265222653226542265522656226572265822659226602266122662226632266422665226662266722668226692267022671226722267322674226752267622677226782267922680226812268222683226842268522686226872268822689226902269122692226932269422695226962269722698226992270022701227022270322704227052270622707227082270922710227112271222713227142271522716227172271822719227202272122722227232272422725227262272722728227292273022731227322273322734227352273622737227382273922740227412274222743227442274522746227472274822749227502275122752227532275422755227562275722758227592276022761227622276322764227652276622767227682276922770227712277222773227742277522776227772277822779227802278122782227832278422785227862278722788227892279022791227922279322794227952279622797227982279922800228012280222803228042280522806228072280822809228102281122812228132281422815228162281722818228192282022821228222282322824228252282622827228282282922830228312283222833228342283522836228372283822839228402284122842228432284422845228462284722848228492285022851228522285322854228552285622857228582285922860228612286222863228642286522866228672286822869228702287122872228732287422875228762287722878228792288022881228822288322884228852288622887228882288922890228912289222893228942289522896228972289822899229002290122902229032290422905229062290722908229092291022911229122291322914229152291622917229182291922920229212292222923229242292522926229272292822929229302293122932229332293422935229362293722938229392294022941229422294322944229452294622947229482294922950229512295222953229542295522956229572295822959229602296122962229632296422965229662296722968229692297022971229722297322974229752297622977229782297922980229812298222983229842298522986229872298822989229902299122992229932299422995229962299722998229992300023001230022300323004230052300623007230082300923010230112301223013230142301523016230172301823019230202302123022230232302423025230262302723028230292303023031230322303323034230352303623037230382303923040230412304223043230442304523046230472304823049230502305123052230532305423055230562305723058230592306023061230622306323064230652306623067230682306923070230712307223073230742307523076230772307823079230802308123082230832308423085230862308723088230892309023091230922309323094230952309623097230982309923100231012310223103231042310523106231072310823109231102311123112231132311423115231162311723118231192312023121231222312323124231252312623127231282312923130231312313223133231342313523136231372313823139231402314123142231432314423145231462314723148231492315023151231522315323154231552315623157231582315923160231612316223163231642316523166231672316823169231702317123172231732317423175231762317723178231792318023181231822318323184231852318623187231882318923190231912319223193231942319523196231972319823199232002320123202232032320423205232062320723208232092321023211232122321323214232152321623217232182321923220232212322223223232242322523226232272322823229232302323123232232332323423235232362323723238232392324023241232422324323244232452324623247232482324923250232512325223253232542325523256232572325823259232602326123262232632326423265232662326723268232692327023271232722327323274232752327623277232782327923280232812328223283232842328523286232872328823289232902329123292232932329423295232962329723298232992330023301233022330323304233052330623307233082330923310233112331223313233142331523316233172331823319233202332123322233232332423325233262332723328233292333023331233322333323334233352333623337233382333923340233412334223343233442334523346233472334823349233502335123352233532335423355233562335723358233592336023361233622336323364233652336623367233682336923370233712337223373233742337523376233772337823379233802338123382233832338423385233862338723388233892339023391233922339323394233952339623397233982339923400234012340223403234042340523406234072340823409234102341123412234132341423415234162341723418234192342023421234222342323424234252342623427234282342923430234312343223433234342343523436234372343823439234402344123442234432344423445234462344723448234492345023451234522345323454234552345623457234582345923460234612346223463234642346523466234672346823469234702347123472234732347423475234762347723478234792348023481234822348323484234852348623487234882348923490234912349223493234942349523496234972349823499235002350123502235032350423505235062350723508235092351023511235122351323514235152351623517235182351923520235212352223523235242352523526235272352823529235302353123532235332353423535235362353723538235392354023541235422354323544235452354623547235482354923550235512355223553235542355523556235572355823559235602356123562235632356423565235662356723568235692357023571235722357323574235752357623577235782357923580235812358223583235842358523586235872358823589235902359123592235932359423595235962359723598235992360023601236022360323604236052360623607236082360923610236112361223613236142361523616236172361823619236202362123622236232362423625236262362723628236292363023631236322363323634236352363623637236382363923640236412364223643236442364523646236472364823649236502365123652236532365423655236562365723658236592366023661236622366323664236652366623667236682366923670236712367223673236742367523676236772367823679236802368123682236832368423685236862368723688236892369023691236922369323694236952369623697236982369923700237012370223703237042370523706237072370823709237102371123712237132371423715237162371723718237192372023721237222372323724237252372623727237282372923730237312373223733237342373523736237372373823739237402374123742237432374423745237462374723748237492375023751237522375323754237552375623757237582375923760237612376223763237642376523766237672376823769237702377123772237732377423775237762377723778237792378023781237822378323784237852378623787237882378923790237912379223793237942379523796237972379823799238002380123802238032380423805238062380723808238092381023811238122381323814238152381623817238182381923820238212382223823238242382523826238272382823829238302383123832238332383423835238362383723838238392384023841238422384323844238452384623847238482384923850238512385223853238542385523856238572385823859238602386123862238632386423865238662386723868238692387023871238722387323874238752387623877238782387923880238812388223883238842388523886238872388823889238902389123892238932389423895238962389723898238992390023901239022390323904239052390623907239082390923910239112391223913239142391523916239172391823919239202392123922239232392423925239262392723928239292393023931239322393323934239352393623937239382393923940239412394223943239442394523946239472394823949239502395123952239532395423955239562395723958239592396023961239622396323964239652396623967239682396923970239712397223973239742397523976239772397823979239802398123982239832398423985239862398723988239892399023991239922399323994239952399623997239982399924000240012400224003240042400524006240072400824009240102401124012240132401424015240162401724018240192402024021240222402324024240252402624027240282402924030240312403224033240342403524036240372403824039240402404124042240432404424045240462404724048240492405024051240522405324054240552405624057240582405924060240612406224063240642406524066240672406824069240702407124072240732407424075240762407724078240792408024081240822408324084240852408624087240882408924090240912409224093240942409524096240972409824099241002410124102241032410424105241062410724108241092411024111241122411324114241152411624117241182411924120241212412224123241242412524126241272412824129241302413124132241332413424135241362413724138241392414024141241422414324144241452414624147241482414924150241512415224153241542415524156241572415824159241602416124162241632416424165241662416724168241692417024171241722417324174241752417624177241782417924180241812418224183241842418524186241872418824189241902419124192241932419424195241962419724198241992420024201242022420324204242052420624207242082420924210242112421224213242142421524216242172421824219242202422124222242232422424225242262422724228242292423024231242322423324234242352423624237242382423924240242412424224243242442424524246242472424824249242502425124252242532425424255242562425724258242592426024261242622426324264242652426624267242682426924270242712427224273242742427524276242772427824279242802428124282242832428424285242862428724288242892429024291242922429324294242952429624297242982429924300243012430224303243042430524306243072430824309243102431124312243132431424315243162431724318243192432024321243222432324324243252432624327243282432924330243312433224333243342433524336243372433824339243402434124342243432434424345243462434724348243492435024351243522435324354243552435624357243582435924360243612436224363243642436524366243672436824369243702437124372243732437424375243762437724378243792438024381243822438324384243852438624387243882438924390243912439224393243942439524396243972439824399244002440124402244032440424405244062440724408244092441024411244122441324414244152441624417244182441924420244212442224423244242442524426244272442824429244302443124432244332443424435244362443724438244392444024441244422444324444244452444624447244482444924450244512445224453244542445524456244572445824459244602446124462244632446424465244662446724468244692447024471244722447324474244752447624477244782447924480244812448224483244842448524486244872448824489244902449124492244932449424495244962449724498244992450024501245022450324504245052450624507245082450924510245112451224513245142451524516245172451824519245202452124522245232452424525245262452724528245292453024531245322453324534245352453624537245382453924540245412454224543245442454524546245472454824549245502455124552245532455424555245562455724558245592456024561245622456324564245652456624567245682456924570245712457224573245742457524576245772457824579245802458124582245832458424585245862458724588245892459024591245922459324594245952459624597245982459924600246012460224603246042460524606246072460824609246102461124612246132461424615246162461724618246192462024621246222462324624246252462624627246282462924630246312463224633246342463524636246372463824639246402464124642246432464424645246462464724648246492465024651246522465324654246552465624657246582465924660246612466224663246642466524666246672466824669246702467124672246732467424675246762467724678246792468024681246822468324684246852468624687246882468924690246912469224693246942469524696246972469824699247002470124702247032470424705247062470724708247092471024711247122471324714247152471624717247182471924720247212472224723247242472524726247272472824729247302473124732247332473424735247362473724738247392474024741247422474324744247452474624747247482474924750247512475224753247542475524756247572475824759247602476124762247632476424765247662476724768247692477024771247722477324774247752477624777247782477924780247812478224783247842478524786247872478824789247902479124792247932479424795247962479724798247992480024801248022480324804248052480624807248082480924810248112481224813248142481524816248172481824819248202482124822248232482424825248262482724828248292483024831248322483324834248352483624837248382483924840248412484224843248442484524846248472484824849248502485124852248532485424855248562485724858248592486024861248622486324864248652486624867248682486924870248712487224873248742487524876248772487824879248802488124882248832488424885248862488724888248892489024891248922489324894248952489624897248982489924900249012490224903249042490524906249072490824909249102491124912249132491424915249162491724918249192492024921249222492324924249252492624927249282492924930249312493224933249342493524936249372493824939249402494124942249432494424945249462494724948249492495024951249522495324954249552495624957249582495924960249612496224963249642496524966249672496824969249702497124972249732497424975249762497724978249792498024981249822498324984249852498624987249882498924990249912499224993249942499524996249972499824999250002500125002250032500425005250062500725008250092501025011250122501325014250152501625017250182501925020250212502225023250242502525026250272502825029250302503125032250332503425035250362503725038250392504025041250422504325044250452504625047250482504925050250512505225053250542505525056250572505825059250602506125062250632506425065250662506725068250692507025071250722507325074250752507625077250782507925080250812508225083250842508525086250872508825089250902509125092250932509425095250962509725098250992510025101251022510325104251052510625107251082510925110251112511225113251142511525116251172511825119251202512125122251232512425125251262512725128251292513025131251322513325134251352513625137251382513925140251412514225143251442514525146251472514825149251502515125152251532515425155251562515725158251592516025161251622516325164251652516625167251682516925170251712517225173251742517525176251772517825179251802518125182251832518425185251862518725188251892519025191251922519325194251952519625197251982519925200252012520225203252042520525206252072520825209252102521125212252132521425215252162521725218252192522025221252222522325224252252522625227252282522925230252312523225233252342523525236252372523825239252402524125242252432524425245252462524725248252492525025251252522525325254252552525625257252582525925260252612526225263252642526525266252672526825269252702527125272252732527425275252762527725278252792528025281252822528325284252852528625287252882528925290252912529225293252942529525296252972529825299253002530125302253032530425305253062530725308253092531025311253122531325314253152531625317253182531925320253212532225323253242532525326253272532825329253302533125332253332533425335253362533725338253392534025341253422534325344253452534625347253482534925350253512535225353253542535525356253572535825359253602536125362253632536425365253662536725368253692537025371253722537325374253752537625377253782537925380253812538225383253842538525386253872538825389253902539125392253932539425395253962539725398253992540025401254022540325404254052540625407254082540925410254112541225413254142541525416254172541825419254202542125422254232542425425254262542725428254292543025431254322543325434254352543625437254382543925440254412544225443254442544525446254472544825449254502545125452254532545425455254562545725458254592546025461254622546325464254652546625467254682546925470254712547225473254742547525476254772547825479254802548125482254832548425485254862548725488254892549025491254922549325494254952549625497254982549925500255012550225503255042550525506255072550825509255102551125512255132551425515255162551725518255192552025521255222552325524255252552625527255282552925530255312553225533255342553525536255372553825539255402554125542255432554425545255462554725548255492555025551255522555325554255552555625557255582555925560255612556225563255642556525566255672556825569255702557125572255732557425575255762557725578255792558025581255822558325584255852558625587255882558925590255912559225593255942559525596255972559825599256002560125602256032560425605256062560725608256092561025611256122561325614256152561625617256182561925620256212562225623256242562525626256272562825629256302563125632256332563425635256362563725638256392564025641256422564325644256452564625647256482564925650256512565225653256542565525656256572565825659256602566125662256632566425665256662566725668256692567025671256722567325674256752567625677256782567925680256812568225683256842568525686256872568825689256902569125692256932569425695256962569725698256992570025701257022570325704257052570625707257082570925710257112571225713257142571525716257172571825719257202572125722257232572425725257262572725728257292573025731257322573325734257352573625737257382573925740257412574225743257442574525746257472574825749257502575125752257532575425755257562575725758257592576025761257622576325764257652576625767257682576925770257712577225773257742577525776257772577825779257802578125782257832578425785257862578725788257892579025791257922579325794257952579625797257982579925800258012580225803258042580525806258072580825809258102581125812258132581425815258162581725818258192582025821258222582325824258252582625827258282582925830258312583225833258342583525836258372583825839258402584125842258432584425845258462584725848258492585025851258522585325854258552585625857258582585925860258612586225863258642586525866258672586825869258702587125872258732587425875258762587725878258792588025881258822588325884258852588625887258882588925890258912589225893258942589525896258972589825899259002590125902259032590425905259062590725908259092591025911259122591325914259152591625917259182591925920259212592225923259242592525926259272592825929259302593125932259332593425935259362593725938259392594025941259422594325944259452594625947259482594925950259512595225953259542595525956259572595825959259602596125962259632596425965259662596725968259692597025971259722597325974259752597625977259782597925980259812598225983259842598525986259872598825989259902599125992259932599425995259962599725998259992600026001260022600326004260052600626007260082600926010260112601226013260142601526016260172601826019260202602126022260232602426025260262602726028260292603026031260322603326034260352603626037260382603926040260412604226043260442604526046260472604826049260502605126052260532605426055260562605726058260592606026061260622606326064260652606626067260682606926070260712607226073260742607526076260772607826079260802608126082260832608426085260862608726088260892609026091260922609326094260952609626097260982609926100261012610226103261042610526106261072610826109261102611126112261132611426115261162611726118261192612026121261222612326124261252612626127261282612926130261312613226133261342613526136261372613826139261402614126142261432614426145261462614726148261492615026151261522615326154261552615626157261582615926160261612616226163261642616526166261672616826169261702617126172261732617426175261762617726178261792618026181261822618326184261852618626187261882618926190261912619226193261942619526196261972619826199262002620126202262032620426205262062620726208262092621026211262122621326214262152621626217262182621926220262212622226223262242622526226262272622826229262302623126232262332623426235262362623726238262392624026241262422624326244262452624626247262482624926250262512625226253262542625526256262572625826259262602626126262262632626426265262662626726268262692627026271262722627326274262752627626277262782627926280262812628226283262842628526286262872628826289262902629126292262932629426295262962629726298262992630026301263022630326304263052630626307263082630926310263112631226313263142631526316263172631826319263202632126322263232632426325263262632726328263292633026331263322633326334263352633626337263382633926340263412634226343263442634526346263472634826349263502635126352263532635426355263562635726358263592636026361263622636326364263652636626367263682636926370263712637226373263742637526376263772637826379263802638126382263832638426385263862638726388263892639026391263922639326394263952639626397263982639926400264012640226403264042640526406264072640826409264102641126412264132641426415264162641726418264192642026421264222642326424264252642626427264282642926430264312643226433264342643526436264372643826439264402644126442264432644426445264462644726448264492645026451264522645326454264552645626457264582645926460264612646226463264642646526466264672646826469264702647126472264732647426475264762647726478264792648026481264822648326484264852648626487264882648926490264912649226493264942649526496264972649826499265002650126502265032650426505265062650726508265092651026511265122651326514265152651626517265182651926520265212652226523265242652526526265272652826529265302653126532265332653426535265362653726538265392654026541265422654326544265452654626547265482654926550265512655226553265542655526556265572655826559265602656126562265632656426565265662656726568265692657026571265722657326574265752657626577265782657926580265812658226583265842658526586265872658826589265902659126592265932659426595265962659726598265992660026601266022660326604266052660626607266082660926610266112661226613266142661526616266172661826619266202662126622266232662426625266262662726628266292663026631266322663326634266352663626637266382663926640266412664226643266442664526646266472664826649266502665126652266532665426655266562665726658266592666026661266622666326664266652666626667266682666926670266712667226673266742667526676266772667826679266802668126682266832668426685266862668726688266892669026691266922669326694266952669626697266982669926700267012670226703267042670526706267072670826709267102671126712267132671426715267162671726718267192672026721267222672326724267252672626727267282672926730267312673226733267342673526736267372673826739267402674126742267432674426745267462674726748267492675026751267522675326754267552675626757267582675926760267612676226763267642676526766267672676826769267702677126772267732677426775267762677726778267792678026781267822678326784267852678626787267882678926790267912679226793267942679526796267972679826799268002680126802268032680426805268062680726808268092681026811268122681326814268152681626817268182681926820268212682226823268242682526826268272682826829268302683126832268332683426835268362683726838268392684026841268422684326844268452684626847268482684926850268512685226853268542685526856268572685826859268602686126862268632686426865268662686726868268692687026871268722687326874268752687626877268782687926880268812688226883268842688526886268872688826889268902689126892268932689426895268962689726898268992690026901269022690326904269052690626907269082690926910269112691226913269142691526916269172691826919269202692126922269232692426925269262692726928269292693026931269322693326934269352693626937269382693926940269412694226943269442694526946269472694826949269502695126952269532695426955269562695726958269592696026961269622696326964269652696626967269682696926970269712697226973269742697526976269772697826979269802698126982269832698426985269862698726988269892699026991269922699326994269952699626997269982699927000270012700227003270042700527006270072700827009270102701127012270132701427015270162701727018270192702027021270222702327024270252702627027270282702927030270312703227033270342703527036270372703827039270402704127042270432704427045270462704727048270492705027051270522705327054270552705627057270582705927060270612706227063270642706527066270672706827069270702707127072270732707427075270762707727078270792708027081270822708327084270852708627087270882708927090270912709227093270942709527096270972709827099271002710127102271032710427105271062710727108271092711027111271122711327114271152711627117271182711927120271212712227123271242712527126271272712827129271302713127132271332713427135271362713727138271392714027141271422714327144271452714627147271482714927150271512715227153271542715527156271572715827159271602716127162271632716427165271662716727168271692717027171271722717327174271752717627177271782717927180271812718227183271842718527186271872718827189271902719127192271932719427195271962719727198271992720027201272022720327204272052720627207272082720927210272112721227213272142721527216272172721827219272202722127222272232722427225272262722727228272292723027231272322723327234272352723627237272382723927240272412724227243272442724527246272472724827249272502725127252272532725427255272562725727258272592726027261272622726327264272652726627267272682726927270272712727227273272742727527276272772727827279272802728127282272832728427285272862728727288272892729027291272922729327294272952729627297272982729927300273012730227303273042730527306273072730827309273102731127312273132731427315273162731727318273192732027321273222732327324273252732627327273282732927330273312733227333273342733527336273372733827339273402734127342273432734427345273462734727348273492735027351273522735327354273552735627357273582735927360273612736227363273642736527366273672736827369273702737127372273732737427375273762737727378273792738027381273822738327384273852738627387273882738927390273912739227393273942739527396273972739827399274002740127402274032740427405274062740727408274092741027411274122741327414274152741627417274182741927420274212742227423274242742527426274272742827429274302743127432274332743427435274362743727438274392744027441274422744327444274452744627447274482744927450274512745227453274542745527456274572745827459274602746127462274632746427465274662746727468274692747027471274722747327474274752747627477274782747927480274812748227483274842748527486274872748827489274902749127492274932749427495274962749727498274992750027501275022750327504275052750627507275082750927510275112751227513275142751527516275172751827519275202752127522275232752427525275262752727528275292753027531275322753327534275352753627537275382753927540275412754227543275442754527546275472754827549275502755127552275532755427555275562755727558275592756027561275622756327564275652756627567275682756927570275712757227573275742757527576275772757827579275802758127582275832758427585275862758727588275892759027591275922759327594275952759627597275982759927600276012760227603276042760527606276072760827609276102761127612276132761427615276162761727618276192762027621276222762327624276252762627627276282762927630276312763227633276342763527636276372763827639276402764127642276432764427645276462764727648276492765027651276522765327654276552765627657276582765927660276612766227663276642766527666276672766827669276702767127672276732767427675276762767727678276792768027681276822768327684276852768627687276882768927690276912769227693276942769527696276972769827699277002770127702277032770427705277062770727708277092771027711277122771327714277152771627717277182771927720277212772227723277242772527726277272772827729277302773127732277332773427735277362773727738277392774027741277422774327744277452774627747277482774927750277512775227753277542775527756277572775827759277602776127762277632776427765277662776727768277692777027771277722777327774277752777627777277782777927780277812778227783277842778527786277872778827789277902779127792277932779427795277962779727798277992780027801278022780327804278052780627807278082780927810278112781227813278142781527816278172781827819278202782127822278232782427825278262782727828278292783027831278322783327834278352783627837278382783927840278412784227843278442784527846278472784827849278502785127852278532785427855278562785727858278592786027861278622786327864278652786627867278682786927870278712787227873278742787527876278772787827879278802788127882278832788427885278862788727888278892789027891278922789327894278952789627897278982789927900279012790227903279042790527906279072790827909279102791127912279132791427915279162791727918279192792027921279222792327924279252792627927279282792927930279312793227933279342793527936279372793827939279402794127942279432794427945279462794727948279492795027951279522795327954279552795627957279582795927960279612796227963279642796527966279672796827969279702797127972279732797427975279762797727978279792798027981279822798327984279852798627987279882798927990279912799227993279942799527996279972799827999280002800128002280032800428005280062800728008280092801028011280122801328014280152801628017280182801928020280212802228023280242802528026280272802828029280302803128032280332803428035280362803728038280392804028041280422804328044280452804628047280482804928050280512805228053280542805528056280572805828059280602806128062280632806428065280662806728068280692807028071280722807328074280752807628077280782807928080280812808228083280842808528086280872808828089280902809128092280932809428095280962809728098280992810028101281022810328104281052810628107281082810928110281112811228113281142811528116281172811828119281202812128122281232812428125281262812728128281292813028131281322813328134281352813628137281382813928140281412814228143281442814528146281472814828149281502815128152281532815428155281562815728158281592816028161281622816328164281652816628167281682816928170281712817228173281742817528176281772817828179281802818128182281832818428185281862818728188281892819028191281922819328194281952819628197281982819928200282012820228203282042820528206282072820828209282102821128212282132821428215282162821728218282192822028221282222822328224282252822628227282282822928230282312823228233282342823528236282372823828239282402824128242282432824428245282462824728248282492825028251282522825328254282552825628257282582825928260282612826228263282642826528266282672826828269282702827128272282732827428275282762827728278282792828028281282822828328284282852828628287282882828928290282912829228293282942829528296282972829828299283002830128302283032830428305283062830728308283092831028311283122831328314283152831628317283182831928320283212832228323283242832528326283272832828329283302833128332283332833428335283362833728338283392834028341283422834328344283452834628347283482834928350283512835228353283542835528356283572835828359283602836128362283632836428365283662836728368283692837028371283722837328374283752837628377283782837928380283812838228383283842838528386283872838828389283902839128392283932839428395283962839728398283992840028401284022840328404284052840628407284082840928410284112841228413284142841528416284172841828419284202842128422284232842428425284262842728428284292843028431284322843328434284352843628437284382843928440284412844228443284442844528446284472844828449284502845128452284532845428455284562845728458284592846028461284622846328464284652846628467284682846928470284712847228473284742847528476284772847828479284802848128482284832848428485284862848728488284892849028491284922849328494284952849628497284982849928500285012850228503285042850528506285072850828509285102851128512285132851428515285162851728518285192852028521285222852328524285252852628527285282852928530285312853228533285342853528536285372853828539285402854128542285432854428545285462854728548285492855028551285522855328554285552855628557285582855928560285612856228563285642856528566285672856828569285702857128572285732857428575285762857728578285792858028581285822858328584285852858628587285882858928590285912859228593285942859528596285972859828599286002860128602286032860428605286062860728608286092861028611286122861328614286152861628617286182861928620286212862228623286242862528626286272862828629286302863128632286332863428635286362863728638286392864028641286422864328644286452864628647286482864928650286512865228653286542865528656286572865828659286602866128662286632866428665286662866728668286692867028671286722867328674286752867628677286782867928680286812868228683286842868528686286872868828689286902869128692286932869428695286962869728698286992870028701287022870328704287052870628707287082870928710287112871228713287142871528716287172871828719287202872128722287232872428725287262872728728287292873028731287322873328734287352873628737287382873928740287412874228743287442874528746287472874828749287502875128752287532875428755287562875728758287592876028761287622876328764287652876628767287682876928770287712877228773287742877528776287772877828779287802878128782287832878428785287862878728788287892879028791287922879328794287952879628797287982879928800288012880228803288042880528806288072880828809288102881128812288132881428815288162881728818288192882028821288222882328824288252882628827288282882928830288312883228833288342883528836288372883828839288402884128842288432884428845288462884728848288492885028851288522885328854288552885628857288582885928860288612886228863288642886528866288672886828869288702887128872288732887428875288762887728878288792888028881288822888328884288852888628887288882888928890288912889228893288942889528896288972889828899289002890128902289032890428905289062890728908289092891028911289122891328914289152891628917289182891928920289212892228923289242892528926289272892828929289302893128932289332893428935289362893728938289392894028941289422894328944289452894628947289482894928950289512895228953289542895528956289572895828959289602896128962289632896428965289662896728968289692897028971289722897328974289752897628977289782897928980289812898228983289842898528986289872898828989289902899128992289932899428995289962899728998289992900029001290022900329004290052900629007290082900929010290112901229013290142901529016290172901829019290202902129022290232902429025290262902729028290292903029031290322903329034290352903629037290382903929040290412904229043290442904529046290472904829049290502905129052290532905429055290562905729058290592906029061290622906329064290652906629067290682906929070290712907229073290742907529076290772907829079290802908129082290832908429085290862908729088290892909029091290922909329094290952909629097290982909929100291012910229103291042910529106291072910829109291102911129112291132911429115291162911729118291192912029121291222912329124291252912629127291282912929130291312913229133291342913529136291372913829139291402914129142291432914429145291462914729148291492915029151291522915329154291552915629157291582915929160291612916229163291642916529166291672916829169291702917129172291732917429175291762917729178291792918029181291822918329184291852918629187291882918929190291912919229193291942919529196291972919829199292002920129202292032920429205292062920729208292092921029211292122921329214292152921629217292182921929220292212922229223292242922529226292272922829229292302923129232292332923429235292362923729238292392924029241292422924329244292452924629247292482924929250292512925229253292542925529256292572925829259292602926129262292632926429265292662926729268292692927029271292722927329274292752927629277292782927929280292812928229283292842928529286292872928829289292902929129292292932929429295292962929729298292992930029301293022930329304293052930629307293082930929310293112931229313293142931529316293172931829319293202932129322293232932429325293262932729328293292933029331293322933329334293352933629337293382933929340293412934229343293442934529346293472934829349293502935129352293532935429355293562935729358293592936029361293622936329364293652936629367293682936929370293712937229373293742937529376293772937829379293802938129382293832938429385293862938729388293892939029391293922939329394293952939629397293982939929400294012940229403294042940529406294072940829409294102941129412294132941429415294162941729418294192942029421294222942329424294252942629427294282942929430294312943229433294342943529436294372943829439294402944129442294432944429445294462944729448294492945029451294522945329454294552945629457294582945929460294612946229463294642946529466294672946829469294702947129472294732947429475294762947729478294792948029481294822948329484294852948629487294882948929490294912949229493294942949529496294972949829499295002950129502295032950429505295062950729508295092951029511295122951329514295152951629517295182951929520295212952229523295242952529526295272952829529295302953129532295332953429535295362953729538295392954029541295422954329544295452954629547295482954929550295512955229553295542955529556295572955829559295602956129562295632956429565295662956729568295692957029571295722957329574295752957629577295782957929580295812958229583295842958529586295872958829589295902959129592295932959429595295962959729598295992960029601296022960329604296052960629607296082960929610296112961229613296142961529616296172961829619296202962129622296232962429625296262962729628296292963029631296322963329634296352963629637296382963929640296412964229643296442964529646296472964829649296502965129652296532965429655296562965729658296592966029661296622966329664296652966629667296682966929670296712967229673296742967529676296772967829679296802968129682296832968429685296862968729688296892969029691296922969329694296952969629697296982969929700297012970229703297042970529706297072970829709297102971129712297132971429715297162971729718297192972029721297222972329724297252972629727297282972929730297312973229733297342973529736297372973829739297402974129742297432974429745297462974729748297492975029751297522975329754297552975629757297582975929760297612976229763297642976529766297672976829769297702977129772297732977429775297762977729778297792978029781297822978329784297852978629787297882978929790297912979229793297942979529796297972979829799298002980129802298032980429805298062980729808298092981029811298122981329814298152981629817298182981929820298212982229823298242982529826298272982829829298302983129832298332983429835298362983729838298392984029841298422984329844298452984629847298482984929850298512985229853298542985529856298572985829859298602986129862298632986429865298662986729868298692987029871298722987329874298752987629877298782987929880298812988229883298842988529886298872988829889298902989129892298932989429895298962989729898298992990029901299022990329904299052990629907299082990929910299112991229913299142991529916299172991829919299202992129922299232992429925299262992729928299292993029931299322993329934299352993629937299382993929940299412994229943299442994529946299472994829949299502995129952299532995429955299562995729958299592996029961299622996329964299652996629967299682996929970299712997229973299742997529976299772997829979299802998129982299832998429985299862998729988299892999029991299922999329994299952999629997299982999930000300013000230003300043000530006300073000830009300103001130012300133001430015300163001730018300193002030021300223002330024300253002630027300283002930030300313003230033300343003530036300373003830039300403004130042300433004430045300463004730048300493005030051300523005330054300553005630057300583005930060300613006230063300643006530066300673006830069300703007130072300733007430075300763007730078300793008030081300823008330084300853008630087300883008930090300913009230093300943009530096300973009830099301003010130102301033010430105301063010730108301093011030111301123011330114301153011630117301183011930120301213012230123301243012530126301273012830129301303013130132301333013430135301363013730138301393014030141301423014330144301453014630147301483014930150301513015230153301543015530156301573015830159301603016130162301633016430165301663016730168301693017030171301723017330174301753017630177301783017930180301813018230183301843018530186301873018830189301903019130192301933019430195301963019730198301993020030201302023020330204302053020630207302083020930210302113021230213302143021530216302173021830219302203022130222302233022430225302263022730228302293023030231302323023330234302353023630237302383023930240302413024230243302443024530246302473024830249302503025130252302533025430255302563025730258302593026030261302623026330264302653026630267302683026930270302713027230273302743027530276302773027830279302803028130282302833028430285302863028730288302893029030291302923029330294302953029630297302983029930300303013030230303303043030530306303073030830309303103031130312303133031430315303163031730318303193032030321303223032330324303253032630327303283032930330303313033230333303343033530336303373033830339303403034130342303433034430345303463034730348303493035030351303523035330354303553035630357303583035930360303613036230363303643036530366303673036830369303703037130372303733037430375303763037730378303793038030381303823038330384303853038630387303883038930390303913039230393303943039530396303973039830399304003040130402304033040430405304063040730408304093041030411304123041330414304153041630417304183041930420304213042230423304243042530426304273042830429304303043130432304333043430435304363043730438304393044030441304423044330444304453044630447304483044930450304513045230453304543045530456304573045830459304603046130462304633046430465304663046730468304693047030471304723047330474304753047630477304783047930480304813048230483304843048530486304873048830489304903049130492304933049430495304963049730498304993050030501305023050330504305053050630507305083050930510305113051230513305143051530516305173051830519305203052130522305233052430525305263052730528305293053030531305323053330534305353053630537305383053930540305413054230543305443054530546305473054830549305503055130552305533055430555305563055730558305593056030561305623056330564305653056630567305683056930570305713057230573305743057530576305773057830579305803058130582305833058430585305863058730588305893059030591305923059330594305953059630597305983059930600306013060230603306043060530606306073060830609306103061130612306133061430615306163061730618306193062030621306223062330624306253062630627306283062930630306313063230633306343063530636306373063830639306403064130642306433064430645306463064730648306493065030651306523065330654306553065630657306583065930660306613066230663306643066530666306673066830669306703067130672306733067430675306763067730678306793068030681306823068330684306853068630687306883068930690306913069230693306943069530696306973069830699307003070130702307033070430705307063070730708307093071030711307123071330714307153071630717307183071930720307213072230723307243072530726307273072830729307303073130732307333073430735307363073730738307393074030741307423074330744307453074630747307483074930750307513075230753307543075530756307573075830759307603076130762307633076430765307663076730768307693077030771307723077330774307753077630777307783077930780307813078230783307843078530786307873078830789307903079130792307933079430795307963079730798307993080030801308023080330804308053080630807308083080930810308113081230813308143081530816308173081830819308203082130822308233082430825308263082730828308293083030831308323083330834308353083630837308383083930840308413084230843308443084530846308473084830849308503085130852308533085430855308563085730858308593086030861308623086330864308653086630867308683086930870308713087230873308743087530876308773087830879308803088130882308833088430885308863088730888308893089030891308923089330894308953089630897308983089930900309013090230903309043090530906309073090830909309103091130912309133091430915309163091730918309193092030921309223092330924309253092630927309283092930930309313093230933309343093530936309373093830939309403094130942309433094430945309463094730948309493095030951309523095330954309553095630957309583095930960309613096230963309643096530966309673096830969309703097130972309733097430975309763097730978309793098030981309823098330984309853098630987309883098930990309913099230993309943099530996309973099830999310003100131002310033100431005310063100731008310093101031011310123101331014310153101631017310183101931020310213102231023310243102531026310273102831029310303103131032310333103431035310363103731038310393104031041310423104331044310453104631047310483104931050310513105231053310543105531056310573105831059310603106131062310633106431065310663106731068310693107031071310723107331074310753107631077310783107931080310813108231083310843108531086310873108831089310903109131092310933109431095310963109731098310993110031101311023110331104311053110631107311083110931110311113111231113311143111531116311173111831119311203112131122311233112431125311263112731128311293113031131311323113331134311353113631137311383113931140311413114231143311443114531146311473114831149311503115131152311533115431155311563115731158311593116031161311623116331164311653116631167311683116931170311713117231173311743117531176311773117831179311803118131182311833118431185311863118731188311893119031191311923119331194311953119631197311983119931200312013120231203312043120531206312073120831209312103121131212312133121431215312163121731218312193122031221312223122331224312253122631227312283122931230312313123231233312343123531236312373123831239312403124131242312433124431245312463124731248312493125031251312523125331254312553125631257312583125931260312613126231263312643126531266312673126831269312703127131272312733127431275312763127731278312793128031281312823128331284312853128631287312883128931290312913129231293312943129531296312973129831299313003130131302313033130431305313063130731308313093131031311313123131331314313153131631317313183131931320313213132231323313243132531326313273132831329313303133131332313333133431335313363133731338313393134031341313423134331344313453134631347313483134931350313513135231353313543135531356313573135831359313603136131362313633136431365313663136731368313693137031371313723137331374313753137631377313783137931380313813138231383313843138531386313873138831389313903139131392313933139431395313963139731398313993140031401314023140331404314053140631407314083140931410314113141231413314143141531416314173141831419314203142131422314233142431425314263142731428314293143031431314323143331434314353143631437314383143931440314413144231443314443144531446314473144831449314503145131452314533145431455314563145731458314593146031461314623146331464314653146631467314683146931470314713147231473314743147531476314773147831479314803148131482314833148431485314863148731488314893149031491314923149331494314953149631497314983149931500315013150231503315043150531506315073150831509315103151131512315133151431515315163151731518315193152031521315223152331524315253152631527315283152931530315313153231533315343153531536315373153831539315403154131542315433154431545315463154731548315493155031551315523155331554315553155631557315583155931560315613156231563315643156531566315673156831569315703157131572315733157431575315763157731578315793158031581315823158331584315853158631587315883158931590315913159231593315943159531596315973159831599316003160131602316033160431605316063160731608316093161031611316123161331614316153161631617316183161931620316213162231623316243162531626316273162831629316303163131632316333163431635316363163731638316393164031641316423164331644316453164631647316483164931650316513165231653316543165531656316573165831659316603166131662316633166431665316663166731668316693167031671316723167331674316753167631677316783167931680316813168231683316843168531686316873168831689316903169131692316933169431695316963169731698316993170031701317023170331704317053170631707317083170931710317113171231713317143171531716317173171831719317203172131722317233172431725317263172731728317293173031731317323173331734317353173631737317383173931740317413174231743317443174531746317473174831749317503175131752317533175431755317563175731758317593176031761317623176331764317653176631767317683176931770317713177231773317743177531776317773177831779317803178131782317833178431785317863178731788317893179031791317923179331794317953179631797317983179931800318013180231803318043180531806318073180831809318103181131812318133181431815318163181731818318193182031821318223182331824318253182631827318283182931830318313183231833318343183531836318373183831839318403184131842318433184431845318463184731848318493185031851318523185331854318553185631857318583185931860318613186231863318643186531866318673186831869318703187131872318733187431875318763187731878318793188031881318823188331884318853188631887318883188931890318913189231893318943189531896318973189831899319003190131902319033190431905319063190731908319093191031911319123191331914319153191631917319183191931920319213192231923319243192531926319273192831929319303193131932319333193431935319363193731938319393194031941319423194331944319453194631947319483194931950319513195231953319543195531956319573195831959319603196131962319633196431965319663196731968319693197031971319723197331974319753197631977319783197931980319813198231983319843198531986319873198831989319903199131992319933199431995319963199731998319993200032001320023200332004320053200632007320083200932010320113201232013320143201532016320173201832019320203202132022320233202432025320263202732028320293203032031320323203332034320353203632037320383203932040320413204232043320443204532046320473204832049320503205132052320533205432055320563205732058320593206032061320623206332064320653206632067320683206932070320713207232073320743207532076320773207832079320803208132082320833208432085320863208732088320893209032091320923209332094320953209632097320983209932100321013210232103321043210532106321073210832109321103211132112321133211432115321163211732118321193212032121321223212332124321253212632127321283212932130321313213232133321343213532136321373213832139321403214132142321433214432145321463214732148321493215032151321523215332154321553215632157321583215932160321613216232163321643216532166321673216832169321703217132172321733217432175321763217732178321793218032181321823218332184321853218632187321883218932190321913219232193321943219532196321973219832199322003220132202322033220432205322063220732208322093221032211322123221332214322153221632217322183221932220322213222232223322243222532226322273222832229322303223132232322333223432235322363223732238322393224032241322423224332244322453224632247322483224932250322513225232253322543225532256322573225832259322603226132262322633226432265322663226732268322693227032271322723227332274322753227632277322783227932280322813228232283322843228532286322873228832289322903229132292322933229432295322963229732298322993230032301323023230332304323053230632307323083230932310323113231232313323143231532316323173231832319323203232132322323233232432325323263232732328323293233032331323323233332334323353233632337323383233932340323413234232343323443234532346323473234832349323503235132352323533235432355323563235732358323593236032361323623236332364323653236632367323683236932370323713237232373323743237532376323773237832379323803238132382323833238432385323863238732388323893239032391323923239332394323953239632397323983239932400324013240232403324043240532406324073240832409324103241132412324133241432415324163241732418324193242032421324223242332424324253242632427324283242932430324313243232433324343243532436324373243832439324403244132442324433244432445324463244732448324493245032451324523245332454324553245632457324583245932460324613246232463324643246532466324673246832469324703247132472324733247432475324763247732478324793248032481324823248332484324853248632487324883248932490324913249232493324943249532496324973249832499325003250132502325033250432505325063250732508325093251032511325123251332514325153251632517325183251932520325213252232523325243252532526325273252832529325303253132532325333253432535325363253732538325393254032541325423254332544325453254632547325483254932550325513255232553325543255532556325573255832559325603256132562325633256432565325663256732568325693257032571325723257332574325753257632577325783257932580325813258232583325843258532586325873258832589325903259132592325933259432595325963259732598325993260032601326023260332604326053260632607326083260932610326113261232613326143261532616326173261832619326203262132622326233262432625326263262732628326293263032631326323263332634326353263632637326383263932640326413264232643326443264532646326473264832649326503265132652326533265432655326563265732658326593266032661326623266332664326653266632667326683266932670326713267232673326743267532676326773267832679326803268132682326833268432685326863268732688326893269032691326923269332694326953269632697326983269932700327013270232703327043270532706327073270832709327103271132712327133271432715327163271732718327193272032721327223272332724327253272632727327283272932730327313273232733327343273532736327373273832739327403274132742327433274432745327463274732748327493275032751327523275332754327553275632757327583275932760327613276232763327643276532766327673276832769327703277132772327733277432775327763277732778327793278032781327823278332784327853278632787327883278932790327913279232793327943279532796327973279832799328003280132802328033280432805328063280732808328093281032811328123281332814328153281632817328183281932820328213282232823328243282532826328273282832829328303283132832328333283432835328363283732838328393284032841328423284332844328453284632847328483284932850328513285232853328543285532856328573285832859328603286132862328633286432865328663286732868328693287032871328723287332874328753287632877328783287932880328813288232883328843288532886328873288832889328903289132892328933289432895328963289732898328993290032901329023290332904329053290632907329083290932910329113291232913329143291532916329173291832919329203292132922329233292432925329263292732928329293293032931329323293332934329353293632937329383293932940329413294232943329443294532946329473294832949329503295132952329533295432955329563295732958329593296032961329623296332964329653296632967329683296932970329713297232973329743297532976329773297832979329803298132982329833298432985329863298732988329893299032991329923299332994329953299632997329983299933000330013300233003330043300533006330073300833009330103301133012330133301433015330163301733018330193302033021330223302333024330253302633027330283302933030330313303233033330343303533036330373303833039330403304133042330433304433045330463304733048330493305033051330523305333054330553305633057330583305933060330613306233063330643306533066330673306833069330703307133072330733307433075330763307733078330793308033081330823308333084330853308633087330883308933090330913309233093330943309533096330973309833099331003310133102331033310433105331063310733108331093311033111331123311333114331153311633117331183311933120331213312233123331243312533126331273312833129331303313133132331333313433135331363313733138331393314033141331423314333144331453314633147331483314933150331513315233153331543315533156331573315833159331603316133162331633316433165331663316733168331693317033171331723317333174331753317633177331783317933180331813318233183331843318533186331873318833189331903319133192331933319433195331963319733198331993320033201332023320333204332053320633207332083320933210332113321233213332143321533216332173321833219332203322133222332233322433225332263322733228332293323033231332323323333234332353323633237332383323933240332413324233243332443324533246332473324833249332503325133252332533325433255332563325733258332593326033261332623326333264332653326633267332683326933270332713327233273332743327533276332773327833279332803328133282332833328433285332863328733288332893329033291332923329333294332953329633297332983329933300333013330233303333043330533306333073330833309333103331133312333133331433315333163331733318333193332033321333223332333324333253332633327333283332933330333313333233333333343333533336333373333833339333403334133342333433334433345333463334733348333493335033351333523335333354333553335633357333583335933360333613336233363333643336533366333673336833369333703337133372333733337433375333763337733378333793338033381333823338333384333853338633387333883338933390333913339233393333943339533396333973339833399334003340133402334033340433405334063340733408334093341033411334123341333414334153341633417334183341933420334213342233423334243342533426334273342833429334303343133432334333343433435334363343733438334393344033441334423344333444334453344633447334483344933450334513345233453334543345533456334573345833459334603346133462334633346433465334663346733468334693347033471334723347333474334753347633477334783347933480334813348233483334843348533486334873348833489334903349133492334933349433495334963349733498334993350033501335023350333504335053350633507335083350933510335113351233513335143351533516335173351833519335203352133522335233352433525335263352733528335293353033531335323353333534335353353633537335383353933540335413354233543335443354533546335473354833549335503355133552335533355433555335563355733558335593356033561335623356333564335653356633567335683356933570335713357233573335743357533576335773357833579335803358133582335833358433585335863358733588335893359033591335923359333594335953359633597335983359933600336013360233603336043360533606336073360833609336103361133612336133361433615336163361733618336193362033621336223362333624336253362633627336283362933630336313363233633336343363533636336373363833639336403364133642336433364433645336463364733648336493365033651336523365333654336553365633657336583365933660336613366233663336643366533666336673366833669336703367133672336733367433675336763367733678336793368033681336823368333684336853368633687336883368933690336913369233693336943369533696336973369833699337003370133702337033370433705337063370733708337093371033711337123371333714337153371633717337183371933720337213372233723337243372533726337273372833729337303373133732337333373433735337363373733738337393374033741337423374333744337453374633747337483374933750337513375233753337543375533756337573375833759337603376133762337633376433765337663376733768337693377033771337723377333774337753377633777337783377933780337813378233783337843378533786337873378833789337903379133792337933379433795337963379733798337993380033801338023380333804338053380633807338083380933810338113381233813338143381533816338173381833819338203382133822338233382433825338263382733828338293383033831338323383333834338353383633837338383383933840338413384233843338443384533846338473384833849338503385133852338533385433855338563385733858338593386033861338623386333864338653386633867338683386933870338713387233873338743387533876338773387833879338803388133882338833388433885338863388733888338893389033891338923389333894338953389633897338983389933900339013390233903339043390533906339073390833909339103391133912339133391433915339163391733918339193392033921339223392333924339253392633927339283392933930339313393233933339343393533936339373393833939339403394133942339433394433945339463394733948339493395033951339523395333954339553395633957339583395933960339613396233963339643396533966339673396833969339703397133972339733397433975339763397733978339793398033981339823398333984339853398633987339883398933990339913399233993339943399533996339973399833999340003400134002340033400434005340063400734008340093401034011340123401334014340153401634017340183401934020340213402234023340243402534026340273402834029340303403134032340333403434035340363403734038340393404034041340423404334044340453404634047340483404934050340513405234053340543405534056340573405834059340603406134062340633406434065340663406734068340693407034071340723407334074340753407634077340783407934080340813408234083340843408534086340873408834089340903409134092340933409434095340963409734098340993410034101341023410334104341053410634107341083410934110341113411234113341143411534116341173411834119341203412134122341233412434125341263412734128341293413034131341323413334134341353413634137341383413934140341413414234143341443414534146341473414834149341503415134152341533415434155341563415734158341593416034161341623416334164341653416634167341683416934170341713417234173341743417534176341773417834179341803418134182341833418434185341863418734188341893419034191341923419334194341953419634197341983419934200342013420234203342043420534206342073420834209342103421134212342133421434215342163421734218342193422034221342223422334224342253422634227342283422934230342313423234233342343423534236342373423834239342403424134242342433424434245342463424734248342493425034251342523425334254342553425634257342583425934260342613426234263342643426534266342673426834269342703427134272342733427434275342763427734278342793428034281342823428334284342853428634287342883428934290342913429234293342943429534296342973429834299343003430134302343033430434305343063430734308343093431034311343123431334314343153431634317343183431934320343213432234323343243432534326343273432834329343303433134332343333433434335343363433734338343393434034341343423434334344343453434634347343483434934350343513435234353343543435534356343573435834359343603436134362343633436434365343663436734368343693437034371343723437334374343753437634377343783437934380343813438234383343843438534386343873438834389343903439134392343933439434395343963439734398343993440034401344023440334404344053440634407344083440934410344113441234413344143441534416344173441834419344203442134422344233442434425344263442734428344293443034431344323443334434344353443634437344383443934440344413444234443344443444534446344473444834449344503445134452344533445434455344563445734458344593446034461344623446334464344653446634467344683446934470344713447234473344743447534476344773447834479344803448134482344833448434485344863448734488344893449034491344923449334494344953449634497344983449934500345013450234503345043450534506345073450834509345103451134512345133451434515345163451734518345193452034521345223452334524345253452634527345283452934530345313453234533345343453534536345373453834539345403454134542345433454434545345463454734548345493455034551345523455334554345553455634557345583455934560345613456234563345643456534566345673456834569345703457134572345733457434575345763457734578345793458034581345823458334584345853458634587345883458934590345913459234593345943459534596345973459834599346003460134602346033460434605346063460734608346093461034611346123461334614346153461634617346183461934620346213462234623346243462534626346273462834629346303463134632346333463434635346363463734638346393464034641346423464334644346453464634647346483464934650346513465234653346543465534656346573465834659346603466134662346633466434665346663466734668346693467034671346723467334674346753467634677346783467934680346813468234683346843468534686346873468834689346903469134692346933469434695346963469734698346993470034701347023470334704347053470634707347083470934710347113471234713347143471534716347173471834719347203472134722347233472434725347263472734728347293473034731347323473334734347353473634737347383473934740347413474234743347443474534746347473474834749347503475134752347533475434755347563475734758347593476034761347623476334764347653476634767347683476934770347713477234773347743477534776347773477834779347803478134782347833478434785347863478734788347893479034791347923479334794347953479634797347983479934800348013480234803348043480534806348073480834809348103481134812348133481434815348163481734818348193482034821348223482334824348253482634827348283482934830348313483234833348343483534836348373483834839348403484134842348433484434845348463484734848348493485034851348523485334854348553485634857348583485934860348613486234863348643486534866348673486834869348703487134872348733487434875348763487734878348793488034881348823488334884348853488634887348883488934890348913489234893348943489534896348973489834899349003490134902349033490434905349063490734908349093491034911349123491334914349153491634917349183491934920349213492234923349243492534926349273492834929349303493134932349333493434935349363493734938349393494034941349423494334944349453494634947349483494934950349513495234953349543495534956349573495834959349603496134962349633496434965349663496734968349693497034971349723497334974349753497634977349783497934980349813498234983349843498534986349873498834989349903499134992349933499434995349963499734998349993500035001350023500335004350053500635007350083500935010350113501235013350143501535016350173501835019350203502135022350233502435025350263502735028350293503035031350323503335034350353503635037350383503935040350413504235043350443504535046350473504835049350503505135052350533505435055350563505735058350593506035061350623506335064350653506635067350683506935070350713507235073350743507535076350773507835079350803508135082350833508435085350863508735088350893509035091350923509335094350953509635097350983509935100351013510235103351043510535106351073510835109351103511135112351133511435115351163511735118351193512035121351223512335124351253512635127351283512935130351313513235133351343513535136351373513835139351403514135142351433514435145351463514735148351493515035151351523515335154351553515635157351583515935160351613516235163351643516535166351673516835169351703517135172351733517435175351763517735178351793518035181351823518335184351853518635187351883518935190351913519235193351943519535196351973519835199352003520135202352033520435205352063520735208352093521035211352123521335214352153521635217352183521935220352213522235223352243522535226352273522835229352303523135232352333523435235352363523735238352393524035241352423524335244352453524635247352483524935250352513525235253352543525535256352573525835259352603526135262352633526435265352663526735268352693527035271352723527335274352753527635277352783527935280352813528235283352843528535286352873528835289352903529135292352933529435295352963529735298352993530035301353023530335304353053530635307353083530935310353113531235313353143531535316353173531835319353203532135322353233532435325353263532735328353293533035331353323533335334353353533635337353383533935340353413534235343353443534535346353473534835349353503535135352353533535435355353563535735358353593536035361353623536335364353653536635367353683536935370353713537235373353743537535376353773537835379353803538135382353833538435385353863538735388353893539035391353923539335394353953539635397353983539935400354013540235403354043540535406354073540835409354103541135412354133541435415354163541735418354193542035421354223542335424354253542635427354283542935430354313543235433354343543535436354373543835439354403544135442354433544435445354463544735448354493545035451354523545335454354553545635457354583545935460354613546235463354643546535466354673546835469354703547135472354733547435475354763547735478354793548035481354823548335484354853548635487354883548935490354913549235493354943549535496354973549835499355003550135502355033550435505355063550735508355093551035511355123551335514355153551635517355183551935520355213552235523355243552535526355273552835529355303553135532355333553435535355363553735538355393554035541355423554335544355453554635547355483554935550355513555235553355543555535556355573555835559355603556135562355633556435565355663556735568355693557035571355723557335574355753557635577355783557935580355813558235583355843558535586355873558835589355903559135592355933559435595355963559735598355993560035601356023560335604356053560635607356083560935610356113561235613356143561535616356173561835619356203562135622356233562435625356263562735628356293563035631356323563335634356353563635637356383563935640356413564235643356443564535646356473564835649356503565135652356533565435655356563565735658356593566035661356623566335664356653566635667356683566935670356713567235673356743567535676356773567835679356803568135682356833568435685356863568735688356893569035691356923569335694356953569635697356983569935700357013570235703357043570535706357073570835709357103571135712357133571435715357163571735718357193572035721357223572335724357253572635727357283572935730357313573235733357343573535736357373573835739357403574135742357433574435745357463574735748357493575035751357523575335754357553575635757357583575935760357613576235763357643576535766357673576835769357703577135772357733577435775357763577735778357793578035781357823578335784357853578635787357883578935790357913579235793357943579535796357973579835799358003580135802358033580435805358063580735808358093581035811358123581335814358153581635817358183581935820358213582235823358243582535826358273582835829358303583135832358333583435835358363583735838358393584035841358423584335844358453584635847358483584935850358513585235853358543585535856358573585835859358603586135862358633586435865358663586735868358693587035871358723587335874358753587635877358783587935880358813588235883358843588535886358873588835889358903589135892358933589435895358963589735898358993590035901359023590335904359053590635907359083590935910359113591235913359143591535916359173591835919359203592135922359233592435925359263592735928359293593035931359323593335934359353593635937359383593935940359413594235943359443594535946359473594835949359503595135952359533595435955359563595735958359593596035961359623596335964359653596635967359683596935970359713597235973359743597535976359773597835979359803598135982359833598435985359863598735988359893599035991359923599335994359953599635997359983599936000360013600236003360043600536006360073600836009360103601136012360133601436015360163601736018360193602036021360223602336024360253602636027360283602936030360313603236033360343603536036360373603836039360403604136042360433604436045360463604736048360493605036051360523605336054360553605636057360583605936060360613606236063360643606536066360673606836069360703607136072360733607436075360763607736078360793608036081360823608336084360853608636087360883608936090360913609236093360943609536096360973609836099361003610136102361033610436105361063610736108361093611036111361123611336114361153611636117361183611936120361213612236123361243612536126361273612836129361303613136132361333613436135361363613736138361393614036141361423614336144361453614636147361483614936150361513615236153361543615536156361573615836159361603616136162361633616436165361663616736168361693617036171361723617336174361753617636177361783617936180361813618236183361843618536186361873618836189361903619136192361933619436195361963619736198361993620036201362023620336204362053620636207362083620936210362113621236213362143621536216362173621836219362203622136222362233622436225362263622736228362293623036231362323623336234362353623636237362383623936240362413624236243362443624536246362473624836249362503625136252362533625436255362563625736258362593626036261362623626336264362653626636267362683626936270362713627236273362743627536276362773627836279362803628136282362833628436285362863628736288362893629036291362923629336294362953629636297362983629936300363013630236303363043630536306363073630836309363103631136312363133631436315363163631736318363193632036321363223632336324363253632636327363283632936330363313633236333363343633536336363373633836339363403634136342363433634436345363463634736348363493635036351363523635336354363553635636357363583635936360363613636236363363643636536366363673636836369363703637136372363733637436375363763637736378363793638036381363823638336384363853638636387363883638936390363913639236393363943639536396363973639836399364003640136402364033640436405364063640736408364093641036411364123641336414364153641636417364183641936420364213642236423364243642536426364273642836429364303643136432364333643436435364363643736438364393644036441364423644336444364453644636447364483644936450364513645236453364543645536456364573645836459364603646136462364633646436465364663646736468364693647036471364723647336474364753647636477364783647936480364813648236483364843648536486364873648836489364903649136492364933649436495364963649736498364993650036501365023650336504365053650636507365083650936510365113651236513365143651536516365173651836519365203652136522365233652436525365263652736528365293653036531365323653336534365353653636537365383653936540365413654236543365443654536546365473654836549365503655136552365533655436555365563655736558365593656036561365623656336564365653656636567365683656936570365713657236573365743657536576365773657836579365803658136582365833658436585365863658736588365893659036591365923659336594365953659636597365983659936600366013660236603366043660536606366073660836609366103661136612366133661436615366163661736618366193662036621366223662336624366253662636627366283662936630366313663236633366343663536636366373663836639366403664136642366433664436645366463664736648366493665036651366523665336654366553665636657366583665936660366613666236663366643666536666366673666836669366703667136672366733667436675366763667736678366793668036681366823668336684366853668636687366883668936690366913669236693366943669536696366973669836699367003670136702367033670436705367063670736708367093671036711367123671336714367153671636717367183671936720367213672236723367243672536726367273672836729367303673136732367333673436735367363673736738367393674036741367423674336744367453674636747367483674936750367513675236753367543675536756367573675836759367603676136762367633676436765367663676736768367693677036771367723677336774367753677636777367783677936780367813678236783367843678536786367873678836789367903679136792367933679436795367963679736798367993680036801368023680336804368053680636807368083680936810368113681236813368143681536816368173681836819368203682136822368233682436825368263682736828368293683036831368323683336834368353683636837368383683936840368413684236843368443684536846368473684836849368503685136852368533685436855368563685736858368593686036861368623686336864368653686636867368683686936870368713687236873368743687536876368773687836879368803688136882368833688436885368863688736888368893689036891368923689336894368953689636897368983689936900369013690236903369043690536906369073690836909369103691136912369133691436915369163691736918369193692036921369223692336924369253692636927369283692936930369313693236933369343693536936369373693836939369403694136942369433694436945369463694736948369493695036951369523695336954369553695636957369583695936960369613696236963369643696536966369673696836969369703697136972369733697436975369763697736978369793698036981369823698336984369853698636987369883698936990369913699236993369943699536996369973699836999370003700137002370033700437005370063700737008370093701037011370123701337014370153701637017370183701937020370213702237023370243702537026370273702837029370303703137032370333703437035370363703737038370393704037041370423704337044370453704637047370483704937050370513705237053370543705537056370573705837059370603706137062370633706437065370663706737068370693707037071370723707337074370753707637077370783707937080370813708237083370843708537086370873708837089370903709137092370933709437095370963709737098370993710037101371023710337104371053710637107371083710937110371113711237113371143711537116371173711837119371203712137122371233712437125371263712737128371293713037131371323713337134371353713637137371383713937140371413714237143371443714537146371473714837149371503715137152371533715437155371563715737158371593716037161371623716337164371653716637167371683716937170371713717237173371743717537176371773717837179371803718137182371833718437185371863718737188371893719037191371923719337194371953719637197371983719937200372013720237203372043720537206372073720837209372103721137212372133721437215372163721737218372193722037221372223722337224372253722637227372283722937230372313723237233372343723537236372373723837239372403724137242372433724437245372463724737248372493725037251372523725337254372553725637257372583725937260372613726237263372643726537266372673726837269372703727137272372733727437275372763727737278372793728037281372823728337284372853728637287372883728937290372913729237293372943729537296372973729837299373003730137302373033730437305373063730737308373093731037311373123731337314373153731637317373183731937320373213732237323373243732537326373273732837329373303733137332373333733437335373363733737338373393734037341373423734337344373453734637347373483734937350373513735237353373543735537356373573735837359373603736137362373633736437365373663736737368373693737037371373723737337374373753737637377373783737937380373813738237383373843738537386373873738837389373903739137392373933739437395373963739737398373993740037401374023740337404374053740637407374083740937410374113741237413374143741537416374173741837419374203742137422374233742437425374263742737428374293743037431374323743337434374353743637437374383743937440374413744237443374443744537446374473744837449374503745137452374533745437455374563745737458374593746037461374623746337464374653746637467374683746937470374713747237473374743747537476374773747837479374803748137482374833748437485374863748737488374893749037491374923749337494374953749637497374983749937500375013750237503375043750537506375073750837509375103751137512375133751437515375163751737518375193752037521375223752337524375253752637527375283752937530375313753237533375343753537536375373753837539375403754137542375433754437545375463754737548375493755037551375523755337554375553755637557375583755937560375613756237563375643756537566375673756837569375703757137572375733757437575375763757737578375793758037581375823758337584375853758637587375883758937590375913759237593375943759537596375973759837599376003760137602376033760437605376063760737608376093761037611376123761337614376153761637617376183761937620376213762237623376243762537626376273762837629376303763137632376333763437635376363763737638376393764037641376423764337644376453764637647376483764937650376513765237653376543765537656376573765837659376603766137662376633766437665376663766737668376693767037671376723767337674376753767637677376783767937680376813768237683376843768537686376873768837689376903769137692376933769437695376963769737698376993770037701377023770337704377053770637707377083770937710377113771237713377143771537716377173771837719377203772137722377233772437725377263772737728377293773037731377323773337734377353773637737377383773937740377413774237743377443774537746377473774837749377503775137752377533775437755377563775737758377593776037761377623776337764377653776637767377683776937770377713777237773377743777537776377773777837779377803778137782377833778437785377863778737788377893779037791377923779337794377953779637797377983779937800378013780237803378043780537806378073780837809378103781137812378133781437815378163781737818378193782037821378223782337824378253782637827378283782937830378313783237833378343783537836378373783837839378403784137842378433784437845378463784737848378493785037851378523785337854378553785637857378583785937860378613786237863378643786537866378673786837869378703787137872378733787437875378763787737878378793788037881378823788337884378853788637887378883788937890378913789237893378943789537896378973789837899379003790137902379033790437905379063790737908379093791037911379123791337914379153791637917379183791937920379213792237923379243792537926379273792837929379303793137932379333793437935379363793737938379393794037941379423794337944379453794637947379483794937950379513795237953379543795537956379573795837959379603796137962379633796437965379663796737968379693797037971379723797337974379753797637977379783797937980379813798237983379843798537986379873798837989379903799137992379933799437995379963799737998379993800038001380023800338004380053800638007380083800938010380113801238013380143801538016380173801838019380203802138022380233802438025380263802738028380293803038031380323803338034380353803638037380383803938040380413804238043380443804538046380473804838049380503805138052380533805438055380563805738058380593806038061380623806338064380653806638067380683806938070380713807238073380743807538076380773807838079380803808138082380833808438085380863808738088380893809038091380923809338094380953809638097380983809938100381013810238103381043810538106381073810838109381103811138112381133811438115381163811738118381193812038121381223812338124381253812638127381283812938130381313813238133381343813538136381373813838139381403814138142381433814438145381463814738148381493815038151381523815338154381553815638157381583815938160381613816238163381643816538166381673816838169381703817138172381733817438175381763817738178381793818038181381823818338184381853818638187381883818938190381913819238193381943819538196381973819838199382003820138202382033820438205382063820738208382093821038211382123821338214382153821638217382183821938220382213822238223382243822538226382273822838229382303823138232382333823438235382363823738238382393824038241382423824338244382453824638247382483824938250382513825238253382543825538256382573825838259382603826138262382633826438265382663826738268382693827038271382723827338274382753827638277382783827938280382813828238283382843828538286382873828838289382903829138292382933829438295382963829738298382993830038301383023830338304383053830638307383083830938310383113831238313383143831538316383173831838319383203832138322383233832438325383263832738328383293833038331383323833338334383353833638337383383833938340383413834238343383443834538346383473834838349383503835138352383533835438355383563835738358383593836038361383623836338364383653836638367383683836938370383713837238373383743837538376383773837838379383803838138382383833838438385383863838738388383893839038391383923839338394383953839638397383983839938400384013840238403384043840538406384073840838409384103841138412384133841438415384163841738418384193842038421384223842338424384253842638427384283842938430384313843238433384343843538436384373843838439384403844138442384433844438445384463844738448384493845038451384523845338454384553845638457384583845938460384613846238463384643846538466384673846838469384703847138472384733847438475384763847738478384793848038481384823848338484384853848638487384883848938490384913849238493384943849538496384973849838499385003850138502385033850438505385063850738508385093851038511385123851338514385153851638517385183851938520385213852238523385243852538526385273852838529385303853138532385333853438535385363853738538385393854038541385423854338544385453854638547385483854938550385513855238553385543855538556385573855838559385603856138562385633856438565385663856738568385693857038571385723857338574385753857638577385783857938580385813858238583385843858538586385873858838589385903859138592385933859438595385963859738598385993860038601386023860338604386053860638607386083860938610386113861238613386143861538616386173861838619386203862138622386233862438625386263862738628386293863038631386323863338634386353863638637386383863938640386413864238643386443864538646386473864838649386503865138652386533865438655386563865738658386593866038661386623866338664386653866638667386683866938670386713867238673386743867538676386773867838679386803868138682386833868438685386863868738688386893869038691386923869338694386953869638697386983869938700387013870238703387043870538706387073870838709387103871138712387133871438715387163871738718387193872038721387223872338724387253872638727387283872938730387313873238733387343873538736387373873838739387403874138742387433874438745387463874738748387493875038751387523875338754387553875638757387583875938760387613876238763387643876538766387673876838769387703877138772387733877438775387763877738778387793878038781387823878338784387853878638787387883878938790387913879238793387943879538796387973879838799388003880138802388033880438805388063880738808388093881038811388123881338814388153881638817388183881938820388213882238823388243882538826388273882838829388303883138832388333883438835388363883738838388393884038841388423884338844388453884638847388483884938850388513885238853388543885538856388573885838859388603886138862388633886438865388663886738868388693887038871388723887338874388753887638877388783887938880388813888238883388843888538886388873888838889388903889138892388933889438895388963889738898388993890038901389023890338904389053890638907389083890938910389113891238913389143891538916389173891838919389203892138922389233892438925389263892738928389293893038931389323893338934389353893638937389383893938940389413894238943389443894538946389473894838949389503895138952389533895438955389563895738958389593896038961389623896338964389653896638967389683896938970389713897238973389743897538976389773897838979389803898138982389833898438985389863898738988389893899038991389923899338994389953899638997389983899939000390013900239003390043900539006390073900839009390103901139012390133901439015390163901739018390193902039021390223902339024390253902639027390283902939030390313903239033390343903539036390373903839039390403904139042390433904439045390463904739048390493905039051390523905339054390553905639057390583905939060390613906239063390643906539066390673906839069390703907139072390733907439075390763907739078390793908039081390823908339084390853908639087390883908939090390913909239093390943909539096390973909839099391003910139102391033910439105391063910739108391093911039111391123911339114391153911639117391183911939120391213912239123391243912539126391273912839129391303913139132391333913439135391363913739138391393914039141391423914339144391453914639147391483914939150391513915239153391543915539156391573915839159391603916139162391633916439165391663916739168391693917039171391723917339174391753917639177391783917939180391813918239183391843918539186391873918839189391903919139192391933919439195391963919739198391993920039201392023920339204392053920639207392083920939210392113921239213392143921539216392173921839219392203922139222392233922439225392263922739228392293923039231392323923339234392353923639237392383923939240392413924239243392443924539246392473924839249392503925139252392533925439255392563925739258392593926039261392623926339264392653926639267392683926939270392713927239273392743927539276392773927839279392803928139282392833928439285392863928739288392893929039291392923929339294392953929639297392983929939300393013930239303393043930539306393073930839309393103931139312393133931439315393163931739318393193932039321393223932339324393253932639327393283932939330393313933239333393343933539336393373933839339393403934139342393433934439345393463934739348393493935039351393523935339354393553935639357393583935939360393613936239363393643936539366393673936839369393703937139372393733937439375393763937739378393793938039381393823938339384393853938639387393883938939390393913939239393393943939539396393973939839399394003940139402394033940439405394063940739408394093941039411394123941339414394153941639417394183941939420394213942239423394243942539426394273942839429394303943139432394333943439435394363943739438394393944039441394423944339444394453944639447394483944939450394513945239453394543945539456394573945839459394603946139462394633946439465394663946739468394693947039471394723947339474394753947639477394783947939480394813948239483394843948539486394873948839489394903949139492394933949439495394963949739498394993950039501395023950339504395053950639507395083950939510395113951239513395143951539516395173951839519395203952139522395233952439525395263952739528395293953039531395323953339534395353953639537395383953939540395413954239543395443954539546395473954839549395503955139552395533955439555395563955739558395593956039561395623956339564395653956639567395683956939570395713957239573395743957539576395773957839579395803958139582395833958439585395863958739588395893959039591395923959339594395953959639597395983959939600396013960239603396043960539606396073960839609396103961139612396133961439615396163961739618396193962039621396223962339624396253962639627396283962939630396313963239633396343963539636396373963839639396403964139642396433964439645396463964739648396493965039651396523965339654396553965639657396583965939660396613966239663396643966539666396673966839669396703967139672396733967439675396763967739678396793968039681396823968339684396853968639687396883968939690396913969239693396943969539696396973969839699397003970139702397033970439705397063970739708397093971039711397123971339714397153971639717397183971939720397213972239723397243972539726397273972839729397303973139732397333973439735397363973739738397393974039741397423974339744397453974639747397483974939750397513975239753397543975539756397573975839759397603976139762397633976439765397663976739768397693977039771397723977339774397753977639777397783977939780397813978239783397843978539786397873978839789397903979139792397933979439795397963979739798397993980039801398023980339804398053980639807398083980939810398113981239813398143981539816398173981839819398203982139822398233982439825398263982739828398293983039831398323983339834398353983639837398383983939840398413984239843398443984539846398473984839849398503985139852398533985439855398563985739858398593986039861398623986339864398653986639867398683986939870398713987239873398743987539876398773987839879398803988139882398833988439885398863988739888398893989039891398923989339894398953989639897398983989939900399013990239903399043990539906399073990839909399103991139912399133991439915399163991739918399193992039921399223992339924399253992639927399283992939930399313993239933399343993539936399373993839939399403994139942399433994439945399463994739948399493995039951399523995339954399553995639957399583995939960399613996239963399643996539966399673996839969399703997139972399733997439975399763997739978399793998039981399823998339984399853998639987399883998939990399913999239993399943999539996399973999839999400004000140002400034000440005400064000740008400094001040011400124001340014400154001640017400184001940020400214002240023400244002540026400274002840029400304003140032400334003440035400364003740038400394004040041400424004340044400454004640047400484004940050400514005240053400544005540056400574005840059400604006140062400634006440065400664006740068400694007040071400724007340074400754007640077400784007940080400814008240083400844008540086400874008840089400904009140092400934009440095400964009740098400994010040101401024010340104401054010640107401084010940110401114011240113401144011540116401174011840119401204012140122401234012440125401264012740128401294013040131401324013340134401354013640137401384013940140401414014240143401444014540146401474014840149401504015140152401534015440155401564015740158401594016040161401624016340164401654016640167401684016940170401714017240173401744017540176401774017840179401804018140182401834018440185401864018740188401894019040191401924019340194401954019640197401984019940200402014020240203402044020540206402074020840209402104021140212402134021440215402164021740218402194022040221402224022340224402254022640227402284022940230402314023240233402344023540236402374023840239402404024140242402434024440245402464024740248402494025040251402524025340254402554025640257402584025940260402614026240263402644026540266402674026840269402704027140272402734027440275402764027740278402794028040281402824028340284402854028640287402884028940290402914029240293402944029540296402974029840299403004030140302403034030440305403064030740308403094031040311403124031340314403154031640317403184031940320403214032240323403244032540326403274032840329403304033140332403334033440335403364033740338403394034040341403424034340344403454034640347403484034940350403514035240353403544035540356403574035840359403604036140362403634036440365403664036740368403694037040371403724037340374403754037640377403784037940380403814038240383403844038540386403874038840389403904039140392403934039440395403964039740398403994040040401404024040340404404054040640407404084040940410404114041240413404144041540416404174041840419404204042140422404234042440425404264042740428404294043040431404324043340434404354043640437404384043940440404414044240443404444044540446404474044840449404504045140452404534045440455404564045740458404594046040461404624046340464404654046640467404684046940470404714047240473404744047540476404774047840479404804048140482404834048440485404864048740488404894049040491404924049340494404954049640497404984049940500405014050240503405044050540506405074050840509405104051140512405134051440515405164051740518405194052040521405224052340524405254052640527405284052940530405314053240533405344053540536405374053840539405404054140542405434054440545405464054740548405494055040551405524055340554405554055640557405584055940560405614056240563405644056540566405674056840569405704057140572405734057440575405764057740578405794058040581405824058340584405854058640587405884058940590405914059240593405944059540596405974059840599406004060140602406034060440605406064060740608406094061040611406124061340614406154061640617406184061940620406214062240623406244062540626406274062840629406304063140632406334063440635406364063740638406394064040641406424064340644406454064640647406484064940650406514065240653406544065540656406574065840659406604066140662406634066440665406664066740668406694067040671406724067340674406754067640677406784067940680406814068240683406844068540686406874068840689406904069140692406934069440695406964069740698406994070040701407024070340704407054070640707407084070940710407114071240713407144071540716407174071840719407204072140722407234072440725407264072740728407294073040731407324073340734407354073640737407384073940740407414074240743407444074540746407474074840749407504075140752407534075440755407564075740758407594076040761407624076340764407654076640767407684076940770407714077240773407744077540776407774077840779407804078140782407834078440785407864078740788407894079040791407924079340794407954079640797407984079940800408014080240803408044080540806408074080840809408104081140812408134081440815408164081740818408194082040821408224082340824408254082640827408284082940830408314083240833408344083540836408374083840839408404084140842408434084440845408464084740848408494085040851408524085340854408554085640857408584085940860408614086240863408644086540866408674086840869408704087140872408734087440875408764087740878408794088040881408824088340884408854088640887408884088940890408914089240893408944089540896408974089840899409004090140902409034090440905409064090740908409094091040911409124091340914409154091640917409184091940920409214092240923409244092540926409274092840929409304093140932409334093440935409364093740938409394094040941409424094340944409454094640947409484094940950409514095240953409544095540956409574095840959409604096140962409634096440965409664096740968409694097040971409724097340974409754097640977409784097940980409814098240983409844098540986409874098840989409904099140992409934099440995409964099740998409994100041001410024100341004410054100641007410084100941010410114101241013410144101541016410174101841019410204102141022410234102441025410264102741028410294103041031410324103341034410354103641037410384103941040410414104241043410444104541046410474104841049410504105141052410534105441055410564105741058410594106041061410624106341064410654106641067410684106941070410714107241073410744107541076410774107841079410804108141082410834108441085410864108741088410894109041091410924109341094410954109641097410984109941100411014110241103411044110541106411074110841109411104111141112411134111441115411164111741118411194112041121411224112341124411254112641127411284112941130411314113241133411344113541136411374113841139411404114141142411434114441145411464114741148411494115041151411524115341154411554115641157411584115941160411614116241163411644116541166411674116841169411704117141172411734117441175411764117741178411794118041181411824118341184411854118641187411884118941190411914119241193411944119541196411974119841199412004120141202412034120441205412064120741208412094121041211412124121341214412154121641217412184121941220412214122241223412244122541226412274122841229412304123141232412334123441235412364123741238412394124041241412424124341244412454124641247412484124941250412514125241253412544125541256412574125841259412604126141262412634126441265412664126741268412694127041271412724127341274412754127641277412784127941280412814128241283412844128541286412874128841289412904129141292412934129441295412964129741298412994130041301413024130341304413054130641307413084130941310413114131241313413144131541316413174131841319413204132141322413234132441325413264132741328413294133041331413324133341334413354133641337413384133941340413414134241343413444134541346413474134841349413504135141352413534135441355413564135741358413594136041361413624136341364413654136641367413684136941370413714137241373413744137541376413774137841379413804138141382413834138441385413864138741388413894139041391413924139341394413954139641397413984139941400414014140241403414044140541406414074140841409414104141141412414134141441415414164141741418414194142041421414224142341424414254142641427414284142941430414314143241433414344143541436414374143841439414404144141442414434144441445414464144741448414494145041451414524145341454414554145641457414584145941460414614146241463414644146541466414674146841469414704147141472414734147441475414764147741478414794148041481414824148341484414854148641487414884148941490414914149241493414944149541496414974149841499415004150141502415034150441505415064150741508415094151041511415124151341514415154151641517415184151941520415214152241523415244152541526415274152841529415304153141532415334153441535415364153741538415394154041541415424154341544415454154641547415484154941550415514155241553415544155541556415574155841559415604156141562415634156441565415664156741568415694157041571415724157341574415754157641577415784157941580415814158241583415844158541586415874158841589415904159141592415934159441595415964159741598415994160041601416024160341604416054160641607416084160941610416114161241613416144161541616416174161841619416204162141622416234162441625416264162741628416294163041631416324163341634416354163641637416384163941640416414164241643416444164541646416474164841649416504165141652416534165441655416564165741658416594166041661416624166341664416654166641667416684166941670416714167241673416744167541676416774167841679416804168141682416834168441685416864168741688416894169041691416924169341694416954169641697416984169941700417014170241703417044170541706417074170841709417104171141712417134171441715417164171741718417194172041721417224172341724417254172641727417284172941730417314173241733417344173541736417374173841739417404174141742417434174441745417464174741748417494175041751417524175341754417554175641757417584175941760417614176241763417644176541766417674176841769417704177141772417734177441775417764177741778417794178041781417824178341784417854178641787417884178941790417914179241793417944179541796417974179841799418004180141802418034180441805418064180741808418094181041811418124181341814418154181641817418184181941820418214182241823418244182541826418274182841829418304183141832418334183441835418364183741838418394184041841418424184341844418454184641847418484184941850418514185241853418544185541856418574185841859418604186141862418634186441865418664186741868418694187041871418724187341874418754187641877418784187941880418814188241883418844188541886418874188841889418904189141892418934189441895418964189741898418994190041901419024190341904419054190641907419084190941910419114191241913419144191541916419174191841919419204192141922419234192441925419264192741928419294193041931419324193341934419354193641937419384193941940419414194241943419444194541946419474194841949419504195141952419534195441955419564195741958419594196041961419624196341964419654196641967419684196941970419714197241973419744197541976419774197841979419804198141982419834198441985419864198741988419894199041991419924199341994419954199641997419984199942000420014200242003420044200542006420074200842009420104201142012420134201442015420164201742018420194202042021420224202342024420254202642027420284202942030420314203242033420344203542036420374203842039420404204142042420434204442045420464204742048420494205042051420524205342054420554205642057420584205942060420614206242063420644206542066420674206842069420704207142072420734207442075420764207742078420794208042081420824208342084420854208642087420884208942090420914209242093420944209542096420974209842099421004210142102421034210442105421064210742108421094211042111421124211342114421154211642117421184211942120421214212242123421244212542126421274212842129421304213142132421334213442135421364213742138421394214042141421424214342144421454214642147421484214942150421514215242153421544215542156421574215842159421604216142162421634216442165421664216742168421694217042171421724217342174421754217642177421784217942180421814218242183421844218542186421874218842189421904219142192421934219442195421964219742198421994220042201422024220342204422054220642207422084220942210422114221242213422144221542216422174221842219422204222142222422234222442225422264222742228422294223042231422324223342234422354223642237422384223942240422414224242243422444224542246422474224842249422504225142252422534225442255422564225742258422594226042261422624226342264422654226642267422684226942270422714227242273422744227542276422774227842279422804228142282422834228442285422864228742288422894229042291422924229342294422954229642297422984229942300423014230242303423044230542306423074230842309423104231142312423134231442315423164231742318423194232042321423224232342324423254232642327423284232942330423314233242333423344233542336423374233842339423404234142342423434234442345423464234742348423494235042351423524235342354423554235642357423584235942360423614236242363423644236542366423674236842369423704237142372423734237442375423764237742378423794238042381423824238342384423854238642387423884238942390423914239242393423944239542396423974239842399424004240142402424034240442405424064240742408424094241042411424124241342414424154241642417424184241942420424214242242423424244242542426424274242842429424304243142432424334243442435424364243742438424394244042441424424244342444424454244642447424484244942450424514245242453424544245542456424574245842459424604246142462424634246442465424664246742468424694247042471424724247342474424754247642477424784247942480424814248242483424844248542486424874248842489424904249142492424934249442495424964249742498424994250042501425024250342504425054250642507425084250942510425114251242513425144251542516425174251842519425204252142522425234252442525425264252742528425294253042531425324253342534425354253642537425384253942540425414254242543425444254542546425474254842549425504255142552425534255442555425564255742558425594256042561425624256342564425654256642567425684256942570425714257242573425744257542576425774257842579425804258142582425834258442585425864258742588425894259042591425924259342594425954259642597425984259942600426014260242603426044260542606426074260842609426104261142612426134261442615426164261742618426194262042621426224262342624426254262642627426284262942630426314263242633426344263542636426374263842639426404264142642426434264442645426464264742648426494265042651426524265342654426554265642657426584265942660426614266242663426644266542666426674266842669426704267142672426734267442675426764267742678426794268042681426824268342684426854268642687426884268942690426914269242693426944269542696426974269842699427004270142702427034270442705427064270742708427094271042711427124271342714427154271642717427184271942720427214272242723427244272542726427274272842729427304273142732427334273442735427364273742738427394274042741427424274342744427454274642747427484274942750427514275242753427544275542756427574275842759427604276142762427634276442765427664276742768427694277042771427724277342774427754277642777427784277942780427814278242783427844278542786427874278842789427904279142792427934279442795427964279742798427994280042801428024280342804428054280642807428084280942810428114281242813428144281542816428174281842819428204282142822428234282442825428264282742828428294283042831428324283342834428354283642837428384283942840428414284242843428444284542846428474284842849428504285142852428534285442855428564285742858428594286042861428624286342864428654286642867428684286942870428714287242873428744287542876428774287842879428804288142882428834288442885428864288742888428894289042891428924289342894428954289642897428984289942900429014290242903429044290542906429074290842909429104291142912429134291442915429164291742918429194292042921429224292342924429254292642927429284292942930429314293242933429344293542936429374293842939429404294142942429434294442945429464294742948429494295042951429524295342954429554295642957429584295942960429614296242963429644296542966429674296842969429704297142972429734297442975429764297742978429794298042981429824298342984429854298642987429884298942990429914299242993429944299542996429974299842999430004300143002430034300443005430064300743008430094301043011430124301343014430154301643017430184301943020430214302243023430244302543026430274302843029430304303143032430334303443035430364303743038430394304043041430424304343044430454304643047430484304943050430514305243053430544305543056430574305843059430604306143062430634306443065430664306743068430694307043071430724307343074430754307643077430784307943080430814308243083430844308543086430874308843089430904309143092430934309443095430964309743098430994310043101431024310343104431054310643107431084310943110431114311243113431144311543116431174311843119431204312143122431234312443125431264312743128431294313043131431324313343134431354313643137431384313943140431414314243143431444314543146431474314843149431504315143152431534315443155431564315743158431594316043161431624316343164431654316643167431684316943170431714317243173431744317543176431774317843179431804318143182431834318443185431864318743188431894319043191431924319343194431954319643197431984319943200432014320243203432044320543206432074320843209432104321143212432134321443215432164321743218432194322043221432224322343224432254322643227432284322943230432314323243233432344323543236432374323843239432404324143242432434324443245432464324743248432494325043251432524325343254432554325643257432584325943260432614326243263432644326543266432674326843269432704327143272432734327443275432764327743278432794328043281432824328343284432854328643287432884328943290432914329243293432944329543296432974329843299433004330143302433034330443305433064330743308433094331043311433124331343314433154331643317433184331943320433214332243323433244332543326433274332843329433304333143332433334333443335433364333743338433394334043341433424334343344433454334643347433484334943350433514335243353433544335543356433574335843359433604336143362433634336443365433664336743368433694337043371433724337343374433754337643377433784337943380433814338243383433844338543386433874338843389433904339143392433934339443395433964339743398433994340043401434024340343404434054340643407434084340943410434114341243413434144341543416434174341843419434204342143422434234342443425434264342743428434294343043431434324343343434434354343643437434384343943440434414344243443434444344543446434474344843449434504345143452434534345443455434564345743458434594346043461434624346343464434654346643467434684346943470434714347243473434744347543476434774347843479434804348143482434834348443485434864348743488434894349043491434924349343494434954349643497434984349943500435014350243503435044350543506435074350843509435104351143512435134351443515435164351743518435194352043521435224352343524435254352643527435284352943530435314353243533435344353543536435374353843539435404354143542435434354443545435464354743548435494355043551435524355343554435554355643557435584355943560435614356243563435644356543566435674356843569435704357143572435734357443575435764357743578435794358043581435824358343584435854358643587435884358943590435914359243593435944359543596435974359843599436004360143602436034360443605436064360743608436094361043611436124361343614436154361643617436184361943620436214362243623436244362543626436274362843629436304363143632436334363443635436364363743638436394364043641436424364343644436454364643647436484364943650436514365243653436544365543656436574365843659436604366143662436634366443665436664366743668436694367043671436724367343674436754367643677436784367943680436814368243683436844368543686436874368843689436904369143692436934369443695436964369743698436994370043701437024370343704437054370643707437084370943710437114371243713437144371543716437174371843719437204372143722437234372443725437264372743728437294373043731437324373343734437354373643737437384373943740437414374243743437444374543746437474374843749437504375143752437534375443755437564375743758437594376043761437624376343764437654376643767437684376943770437714377243773437744377543776437774377843779437804378143782437834378443785437864378743788437894379043791437924379343794437954379643797437984379943800438014380243803438044380543806438074380843809438104381143812438134381443815438164381743818438194382043821438224382343824438254382643827438284382943830438314383243833438344383543836438374383843839438404384143842438434384443845438464384743848438494385043851438524385343854438554385643857438584385943860438614386243863438644386543866438674386843869438704387143872438734387443875438764387743878438794388043881438824388343884438854388643887438884388943890438914389243893438944389543896438974389843899439004390143902439034390443905439064390743908439094391043911439124391343914439154391643917439184391943920439214392243923439244392543926439274392843929439304393143932439334393443935439364393743938439394394043941439424394343944439454394643947439484394943950439514395243953439544395543956439574395843959439604396143962439634396443965439664396743968439694397043971439724397343974439754397643977439784397943980439814398243983439844398543986439874398843989439904399143992439934399443995439964399743998439994400044001440024400344004440054400644007440084400944010440114401244013440144401544016440174401844019440204402144022440234402444025440264402744028440294403044031440324403344034440354403644037440384403944040440414404244043440444404544046440474404844049440504405144052440534405444055440564405744058440594406044061440624406344064440654406644067440684406944070440714407244073440744407544076440774407844079440804408144082440834408444085440864408744088440894409044091440924409344094440954409644097440984409944100441014410244103441044410544106441074410844109441104411144112441134411444115441164411744118441194412044121441224412344124441254412644127441284412944130441314413244133441344413544136441374413844139441404414144142441434414444145441464414744148441494415044151441524415344154441554415644157441584415944160441614416244163441644416544166441674416844169441704417144172441734417444175441764417744178441794418044181441824418344184441854418644187441884418944190441914419244193441944419544196441974419844199442004420144202442034420444205442064420744208442094421044211442124421344214442154421644217442184421944220442214422244223442244422544226442274422844229442304423144232442334423444235442364423744238442394424044241442424424344244442454424644247442484424944250442514425244253442544425544256442574425844259442604426144262442634426444265442664426744268442694427044271442724427344274442754427644277442784427944280442814428244283442844428544286442874428844289442904429144292442934429444295442964429744298442994430044301443024430344304443054430644307443084430944310443114431244313443144431544316443174431844319443204432144322443234432444325443264432744328443294433044331443324433344334443354433644337443384433944340443414434244343443444434544346443474434844349443504435144352443534435444355443564435744358443594436044361443624436344364443654436644367443684436944370443714437244373443744437544376443774437844379443804438144382443834438444385443864438744388443894439044391443924439344394443954439644397443984439944400444014440244403444044440544406444074440844409444104441144412444134441444415444164441744418444194442044421444224442344424444254442644427444284442944430444314443244433444344443544436444374443844439444404444144442444434444444445444464444744448444494445044451444524445344454444554445644457444584445944460444614446244463444644446544466444674446844469444704447144472444734447444475444764447744478444794448044481444824448344484444854448644487444884448944490444914449244493444944449544496444974449844499445004450144502445034450444505445064450744508445094451044511445124451344514445154451644517445184451944520445214452244523445244452544526445274452844529445304453144532445334453444535445364453744538445394454044541445424454344544445454454644547445484454944550445514455244553445544455544556445574455844559445604456144562445634456444565445664456744568445694457044571445724457344574445754457644577445784457944580445814458244583445844458544586445874458844589445904459144592445934459444595445964459744598445994460044601446024460344604446054460644607446084460944610446114461244613446144461544616446174461844619446204462144622446234462444625446264462744628446294463044631446324463344634446354463644637446384463944640446414464244643446444464544646446474464844649446504465144652446534465444655446564465744658446594466044661446624466344664446654466644667446684466944670446714467244673446744467544676446774467844679446804468144682446834468444685446864468744688446894469044691446924469344694446954469644697446984469944700447014470244703447044470544706447074470844709447104471144712447134471444715447164471744718447194472044721447224472344724447254472644727447284472944730447314473244733447344473544736447374473844739447404474144742447434474444745447464474744748447494475044751447524475344754447554475644757447584475944760447614476244763447644476544766447674476844769447704477144772447734477444775447764477744778447794478044781447824478344784447854478644787447884478944790447914479244793447944479544796447974479844799448004480144802448034480444805448064480744808448094481044811448124481344814448154481644817448184481944820448214482244823448244482544826448274482844829448304483144832448334483444835448364483744838448394484044841448424484344844448454484644847448484484944850448514485244853448544485544856448574485844859448604486144862448634486444865448664486744868448694487044871448724487344874448754487644877448784487944880448814488244883448844488544886448874488844889448904489144892448934489444895448964489744898448994490044901449024490344904449054490644907449084490944910449114491244913449144491544916449174491844919449204492144922449234492444925449264492744928449294493044931449324493344934449354493644937449384493944940449414494244943449444494544946449474494844949449504495144952449534495444955449564495744958449594496044961449624496344964449654496644967449684496944970449714497244973449744497544976449774497844979449804498144982449834498444985449864498744988449894499044991449924499344994449954499644997449984499945000450014500245003450044500545006450074500845009450104501145012450134501445015450164501745018450194502045021450224502345024450254502645027450284502945030450314503245033450344503545036450374503845039450404504145042450434504445045450464504745048450494505045051450524505345054450554505645057450584505945060450614506245063450644506545066450674506845069450704507145072450734507445075450764507745078450794508045081450824508345084450854508645087450884508945090450914509245093450944509545096450974509845099451004510145102451034510445105451064510745108451094511045111451124511345114451154511645117451184511945120451214512245123451244512545126451274512845129451304513145132451334513445135451364513745138451394514045141451424514345144451454514645147451484514945150451514515245153451544515545156451574515845159451604516145162451634516445165451664516745168451694517045171451724517345174451754517645177451784517945180451814518245183451844518545186451874518845189451904519145192451934519445195451964519745198451994520045201452024520345204452054520645207452084520945210452114521245213452144521545216452174521845219452204522145222452234522445225452264522745228452294523045231452324523345234452354523645237452384523945240452414524245243452444524545246452474524845249452504525145252452534525445255452564525745258452594526045261452624526345264452654526645267452684526945270452714527245273452744527545276452774527845279452804528145282452834528445285452864528745288452894529045291452924529345294452954529645297452984529945300453014530245303453044530545306453074530845309453104531145312453134531445315453164531745318453194532045321453224532345324453254532645327453284532945330453314533245333453344533545336453374533845339453404534145342453434534445345453464534745348453494535045351453524535345354453554535645357453584535945360453614536245363453644536545366453674536845369453704537145372453734537445375453764537745378453794538045381453824538345384453854538645387453884538945390453914539245393453944539545396453974539845399454004540145402454034540445405454064540745408454094541045411454124541345414454154541645417454184541945420454214542245423454244542545426454274542845429454304543145432454334543445435454364543745438454394544045441454424544345444454454544645447454484544945450454514545245453454544545545456454574545845459454604546145462454634546445465454664546745468454694547045471454724547345474454754547645477454784547945480454814548245483454844548545486454874548845489454904549145492454934549445495454964549745498454994550045501455024550345504455054550645507455084550945510455114551245513455144551545516455174551845519455204552145522455234552445525455264552745528455294553045531455324553345534455354553645537455384553945540455414554245543455444554545546455474554845549455504555145552455534555445555455564555745558455594556045561455624556345564455654556645567455684556945570455714557245573455744557545576455774557845579455804558145582455834558445585455864558745588455894559045591455924559345594455954559645597455984559945600456014560245603456044560545606456074560845609456104561145612456134561445615456164561745618456194562045621456224562345624456254562645627456284562945630456314563245633456344563545636456374563845639456404564145642456434564445645456464564745648456494565045651456524565345654456554565645657456584565945660456614566245663456644566545666456674566845669456704567145672456734567445675456764567745678456794568045681456824568345684456854568645687456884568945690456914569245693456944569545696456974569845699457004570145702457034570445705457064570745708457094571045711457124571345714457154571645717457184571945720457214572245723457244572545726457274572845729457304573145732457334573445735457364573745738457394574045741457424574345744457454574645747457484574945750457514575245753457544575545756457574575845759457604576145762457634576445765457664576745768457694577045771457724577345774457754577645777457784577945780457814578245783457844578545786457874578845789457904579145792457934579445795457964579745798457994580045801458024580345804458054580645807458084580945810458114581245813458144581545816458174581845819458204582145822458234582445825458264582745828458294583045831458324583345834458354583645837458384583945840458414584245843458444584545846458474584845849458504585145852458534585445855458564585745858458594586045861458624586345864458654586645867458684586945870458714587245873458744587545876458774587845879458804588145882458834588445885458864588745888458894589045891458924589345894458954589645897458984589945900459014590245903459044590545906459074590845909459104591145912459134591445915459164591745918459194592045921459224592345924459254592645927459284592945930459314593245933459344593545936459374593845939459404594145942459434594445945459464594745948459494595045951459524595345954459554595645957459584595945960459614596245963459644596545966459674596845969459704597145972459734597445975459764597745978459794598045981459824598345984459854598645987459884598945990459914599245993459944599545996459974599845999460004600146002460034600446005460064600746008460094601046011460124601346014460154601646017460184601946020460214602246023460244602546026460274602846029460304603146032460334603446035460364603746038460394604046041460424604346044460454604646047460484604946050460514605246053460544605546056460574605846059460604606146062460634606446065460664606746068460694607046071460724607346074460754607646077460784607946080460814608246083460844608546086460874608846089460904609146092460934609446095460964609746098460994610046101461024610346104461054610646107461084610946110461114611246113461144611546116461174611846119461204612146122461234612446125461264612746128461294613046131461324613346134461354613646137461384613946140461414614246143461444614546146461474614846149461504615146152461534615446155461564615746158461594616046161461624616346164461654616646167461684616946170461714617246173461744617546176461774617846179461804618146182461834618446185461864618746188461894619046191461924619346194461954619646197461984619946200462014620246203462044620546206462074620846209462104621146212462134621446215462164621746218462194622046221462224622346224462254622646227462284622946230462314623246233462344623546236462374623846239462404624146242462434624446245462464624746248462494625046251462524625346254462554625646257462584625946260462614626246263462644626546266462674626846269462704627146272462734627446275462764627746278462794628046281462824628346284462854628646287462884628946290462914629246293462944629546296462974629846299463004630146302463034630446305463064630746308463094631046311463124631346314463154631646317463184631946320463214632246323463244632546326463274632846329463304633146332463334633446335463364633746338463394634046341463424634346344463454634646347463484634946350463514635246353463544635546356463574635846359463604636146362463634636446365463664636746368463694637046371463724637346374463754637646377463784637946380463814638246383463844638546386463874638846389463904639146392463934639446395463964639746398463994640046401464024640346404464054640646407464084640946410464114641246413464144641546416464174641846419464204642146422464234642446425464264642746428464294643046431464324643346434464354643646437464384643946440464414644246443464444644546446464474644846449464504645146452464534645446455464564645746458464594646046461464624646346464464654646646467464684646946470464714647246473464744647546476464774647846479464804648146482464834648446485464864648746488464894649046491464924649346494464954649646497464984649946500465014650246503465044650546506465074650846509465104651146512465134651446515465164651746518465194652046521465224652346524465254652646527465284652946530465314653246533465344653546536465374653846539465404654146542465434654446545465464654746548465494655046551465524655346554465554655646557465584655946560465614656246563465644656546566465674656846569465704657146572465734657446575465764657746578465794658046581465824658346584465854658646587465884658946590465914659246593465944659546596465974659846599466004660146602466034660446605466064660746608466094661046611466124661346614466154661646617466184661946620466214662246623466244662546626466274662846629466304663146632466334663446635466364663746638466394664046641466424664346644466454664646647466484664946650466514665246653466544665546656466574665846659466604666146662466634666446665466664666746668466694667046671466724667346674466754667646677466784667946680466814668246683466844668546686466874668846689466904669146692466934669446695466964669746698466994670046701467024670346704467054670646707467084670946710467114671246713467144671546716467174671846719467204672146722467234672446725467264672746728467294673046731467324673346734467354673646737467384673946740467414674246743467444674546746467474674846749467504675146752467534675446755467564675746758467594676046761467624676346764467654676646767467684676946770467714677246773467744677546776467774677846779467804678146782467834678446785467864678746788467894679046791467924679346794467954679646797467984679946800468014680246803468044680546806468074680846809468104681146812468134681446815468164681746818468194682046821468224682346824468254682646827468284682946830468314683246833468344683546836468374683846839468404684146842468434684446845468464684746848468494685046851468524685346854468554685646857468584685946860468614686246863468644686546866468674686846869468704687146872468734687446875468764687746878468794688046881468824688346884468854688646887468884688946890468914689246893468944689546896468974689846899469004690146902469034690446905469064690746908469094691046911469124691346914469154691646917469184691946920469214692246923469244692546926469274692846929469304693146932469334693446935469364693746938469394694046941469424694346944469454694646947469484694946950469514695246953469544695546956469574695846959469604696146962469634696446965469664696746968469694697046971469724697346974469754697646977469784697946980469814698246983469844698546986469874698846989469904699146992469934699446995469964699746998469994700047001470024700347004470054700647007470084700947010470114701247013470144701547016470174701847019470204702147022470234702447025470264702747028470294703047031470324703347034470354703647037470384703947040470414704247043470444704547046470474704847049470504705147052470534705447055470564705747058470594706047061470624706347064470654706647067470684706947070470714707247073470744707547076470774707847079470804708147082470834708447085470864708747088470894709047091470924709347094470954709647097470984709947100471014710247103471044710547106471074710847109471104711147112471134711447115471164711747118471194712047121471224712347124471254712647127471284712947130471314713247133471344713547136471374713847139471404714147142471434714447145471464714747148471494715047151471524715347154471554715647157471584715947160471614716247163471644716547166471674716847169471704717147172471734717447175471764717747178471794718047181471824718347184471854718647187471884718947190471914719247193471944719547196471974719847199472004720147202472034720447205472064720747208472094721047211472124721347214472154721647217472184721947220472214722247223472244722547226472274722847229472304723147232472334723447235472364723747238472394724047241472424724347244472454724647247472484724947250472514725247253472544725547256472574725847259472604726147262472634726447265472664726747268472694727047271472724727347274472754727647277472784727947280472814728247283472844728547286472874728847289472904729147292472934729447295472964729747298472994730047301473024730347304473054730647307473084730947310473114731247313473144731547316473174731847319473204732147322473234732447325473264732747328473294733047331473324733347334473354733647337473384733947340473414734247343473444734547346473474734847349473504735147352473534735447355473564735747358473594736047361473624736347364473654736647367473684736947370473714737247373473744737547376473774737847379473804738147382473834738447385473864738747388473894739047391473924739347394473954739647397473984739947400474014740247403474044740547406474074740847409474104741147412474134741447415474164741747418474194742047421474224742347424474254742647427474284742947430474314743247433474344743547436474374743847439474404744147442474434744447445474464744747448474494745047451474524745347454474554745647457474584745947460474614746247463474644746547466474674746847469474704747147472474734747447475474764747747478474794748047481474824748347484474854748647487474884748947490474914749247493474944749547496474974749847499475004750147502475034750447505475064750747508475094751047511475124751347514475154751647517475184751947520475214752247523475244752547526475274752847529475304753147532475334753447535475364753747538475394754047541475424754347544475454754647547475484754947550475514755247553475544755547556475574755847559475604756147562475634756447565475664756747568475694757047571475724757347574475754757647577475784757947580475814758247583475844758547586475874758847589475904759147592475934759447595475964759747598475994760047601476024760347604476054760647607476084760947610476114761247613476144761547616476174761847619476204762147622476234762447625476264762747628476294763047631476324763347634476354763647637476384763947640476414764247643476444764547646476474764847649476504765147652476534765447655476564765747658476594766047661476624766347664476654766647667476684766947670476714767247673476744767547676476774767847679476804768147682476834768447685476864768747688476894769047691476924769347694476954769647697476984769947700477014770247703477044770547706477074770847709477104771147712477134771447715477164771747718477194772047721477224772347724477254772647727477284772947730477314773247733477344773547736477374773847739477404774147742477434774447745477464774747748477494775047751477524775347754477554775647757477584775947760477614776247763477644776547766477674776847769477704777147772477734777447775477764777747778477794778047781477824778347784477854778647787477884778947790477914779247793477944779547796477974779847799478004780147802478034780447805478064780747808478094781047811478124781347814478154781647817478184781947820478214782247823478244782547826478274782847829478304783147832478334783447835478364783747838478394784047841478424784347844478454784647847478484784947850478514785247853478544785547856478574785847859478604786147862478634786447865478664786747868478694787047871478724787347874478754787647877478784787947880478814788247883478844788547886478874788847889478904789147892478934789447895478964789747898478994790047901479024790347904479054790647907479084790947910479114791247913479144791547916479174791847919479204792147922479234792447925479264792747928479294793047931479324793347934479354793647937479384793947940479414794247943479444794547946479474794847949479504795147952479534795447955479564795747958479594796047961479624796347964479654796647967479684796947970479714797247973479744797547976479774797847979479804798147982479834798447985479864798747988479894799047991479924799347994479954799647997479984799948000480014800248003480044800548006480074800848009480104801148012480134801448015480164801748018480194802048021480224802348024480254802648027480284802948030480314803248033480344803548036480374803848039480404804148042480434804448045480464804748048480494805048051480524805348054480554805648057480584805948060480614806248063480644806548066480674806848069480704807148072480734807448075480764807748078480794808048081480824808348084480854808648087480884808948090480914809248093480944809548096480974809848099481004810148102481034810448105481064810748108481094811048111481124811348114481154811648117481184811948120481214812248123481244812548126481274812848129481304813148132481334813448135481364813748138481394814048141481424814348144481454814648147481484814948150481514815248153481544815548156481574815848159481604816148162481634816448165481664816748168481694817048171481724817348174481754817648177481784817948180481814818248183481844818548186481874818848189481904819148192481934819448195481964819748198481994820048201482024820348204482054820648207482084820948210482114821248213482144821548216482174821848219482204822148222482234822448225482264822748228482294823048231482324823348234482354823648237482384823948240482414824248243482444824548246482474824848249482504825148252482534825448255482564825748258482594826048261482624826348264482654826648267482684826948270482714827248273482744827548276482774827848279482804828148282482834828448285482864828748288482894829048291482924829348294482954829648297482984829948300483014830248303483044830548306483074830848309483104831148312483134831448315483164831748318483194832048321483224832348324483254832648327483284832948330483314833248333483344833548336483374833848339483404834148342483434834448345483464834748348483494835048351483524835348354483554835648357483584835948360483614836248363483644836548366483674836848369483704837148372483734837448375483764837748378483794838048381483824838348384483854838648387483884838948390483914839248393483944839548396483974839848399484004840148402484034840448405484064840748408484094841048411484124841348414484154841648417484184841948420484214842248423484244842548426484274842848429484304843148432484334843448435484364843748438484394844048441484424844348444484454844648447484484844948450484514845248453484544845548456484574845848459484604846148462484634846448465484664846748468484694847048471484724847348474484754847648477484784847948480484814848248483484844848548486484874848848489484904849148492484934849448495484964849748498484994850048501485024850348504485054850648507485084850948510485114851248513485144851548516485174851848519485204852148522485234852448525485264852748528485294853048531485324853348534485354853648537485384853948540485414854248543485444854548546485474854848549485504855148552485534855448555485564855748558485594856048561485624856348564485654856648567485684856948570485714857248573485744857548576485774857848579485804858148582485834858448585485864858748588485894859048591485924859348594485954859648597485984859948600486014860248603486044860548606486074860848609486104861148612486134861448615486164861748618486194862048621486224862348624486254862648627486284862948630486314863248633486344863548636486374863848639486404864148642486434864448645486464864748648486494865048651486524865348654486554865648657486584865948660486614866248663486644866548666486674866848669486704867148672486734867448675486764867748678486794868048681486824868348684486854868648687486884868948690486914869248693486944869548696486974869848699487004870148702487034870448705487064870748708487094871048711487124871348714487154871648717487184871948720487214872248723487244872548726487274872848729487304873148732487334873448735487364873748738487394874048741487424874348744487454874648747487484874948750487514875248753487544875548756487574875848759487604876148762487634876448765487664876748768487694877048771487724877348774487754877648777487784877948780487814878248783487844878548786487874878848789487904879148792487934879448795487964879748798487994880048801488024880348804488054880648807488084880948810488114881248813488144881548816488174881848819488204882148822488234882448825488264882748828488294883048831488324883348834488354883648837488384883948840488414884248843488444884548846488474884848849488504885148852488534885448855488564885748858488594886048861488624886348864488654886648867488684886948870488714887248873488744887548876488774887848879488804888148882488834888448885488864888748888488894889048891488924889348894488954889648897488984889948900489014890248903489044890548906489074890848909489104891148912489134891448915489164891748918489194892048921489224892348924489254892648927489284892948930489314893248933489344893548936489374893848939489404894148942489434894448945489464894748948489494895048951489524895348954489554895648957489584895948960489614896248963489644896548966489674896848969489704897148972489734897448975489764897748978489794898048981489824898348984489854898648987489884898948990489914899248993489944899548996489974899848999490004900149002490034900449005490064900749008490094901049011490124901349014490154901649017490184901949020490214902249023490244902549026490274902849029490304903149032490334903449035490364903749038490394904049041490424904349044490454904649047490484904949050490514905249053490544905549056490574905849059490604906149062490634906449065490664906749068490694907049071490724907349074490754907649077490784907949080490814908249083490844908549086490874908849089490904909149092490934909449095490964909749098490994910049101491024910349104491054910649107491084910949110491114911249113491144911549116491174911849119491204912149122491234912449125491264912749128491294913049131491324913349134491354913649137491384913949140491414914249143491444914549146491474914849149491504915149152491534915449155491564915749158491594916049161491624916349164491654916649167491684916949170491714917249173491744917549176491774917849179491804918149182491834918449185491864918749188491894919049191491924919349194491954919649197491984919949200492014920249203492044920549206492074920849209492104921149212492134921449215492164921749218492194922049221492224922349224492254922649227492284922949230492314923249233492344923549236492374923849239492404924149242492434924449245492464924749248492494925049251492524925349254492554925649257492584925949260492614926249263492644926549266492674926849269492704927149272492734927449275492764927749278492794928049281492824928349284492854928649287492884928949290492914929249293492944929549296492974929849299493004930149302493034930449305493064930749308493094931049311493124931349314493154931649317493184931949320493214932249323493244932549326493274932849329493304933149332493334933449335493364933749338493394934049341493424934349344493454934649347493484934949350493514935249353493544935549356493574935849359493604936149362493634936449365493664936749368493694937049371493724937349374493754937649377493784937949380493814938249383493844938549386493874938849389493904939149392493934939449395493964939749398493994940049401494024940349404494054940649407494084940949410494114941249413494144941549416494174941849419494204942149422494234942449425494264942749428494294943049431494324943349434494354943649437494384943949440494414944249443494444944549446494474944849449494504945149452494534945449455494564945749458494594946049461494624946349464494654946649467494684946949470494714947249473494744947549476494774947849479494804948149482494834948449485494864948749488494894949049491494924949349494494954949649497494984949949500495014950249503495044950549506495074950849509495104951149512495134951449515495164951749518495194952049521495224952349524495254952649527495284952949530495314953249533495344953549536495374953849539495404954149542495434954449545495464954749548495494955049551495524955349554495554955649557495584955949560495614956249563495644956549566495674956849569495704957149572495734957449575495764957749578495794958049581495824958349584495854958649587495884958949590495914959249593495944959549596495974959849599496004960149602496034960449605496064960749608496094961049611496124961349614496154961649617496184961949620496214962249623496244962549626496274962849629496304963149632496334963449635496364963749638496394964049641496424964349644496454964649647496484964949650496514965249653496544965549656496574965849659496604966149662496634966449665496664966749668496694967049671496724967349674496754967649677496784967949680496814968249683496844968549686496874968849689496904969149692496934969449695496964969749698496994970049701497024970349704497054970649707497084970949710497114971249713497144971549716497174971849719497204972149722497234972449725497264972749728497294973049731497324973349734497354973649737497384973949740497414974249743497444974549746497474974849749497504975149752497534975449755497564975749758497594976049761497624976349764497654976649767497684976949770497714977249773497744977549776497774977849779497804978149782497834978449785497864978749788497894979049791497924979349794497954979649797497984979949800498014980249803498044980549806498074980849809498104981149812498134981449815498164981749818498194982049821498224982349824498254982649827498284982949830498314983249833498344983549836498374983849839498404984149842498434984449845498464984749848498494985049851498524985349854498554985649857498584985949860498614986249863498644986549866498674986849869498704987149872498734987449875498764987749878498794988049881498824988349884498854988649887498884988949890498914989249893498944989549896498974989849899499004990149902499034990449905499064990749908499094991049911499124991349914499154991649917499184991949920499214992249923499244992549926499274992849929499304993149932499334993449935499364993749938499394994049941499424994349944499454994649947499484994949950499514995249953499544995549956499574995849959499604996149962499634996449965499664996749968499694997049971499724997349974499754997649977499784997949980499814998249983499844998549986499874998849989499904999149992499934999449995499964999749998499995000050001500025000350004500055000650007500085000950010500115001250013500145001550016500175001850019500205002150022500235002450025500265002750028500295003050031500325003350034500355003650037500385003950040500415004250043500445004550046500475004850049500505005150052500535005450055500565005750058500595006050061500625006350064500655006650067500685006950070500715007250073500745007550076500775007850079500805008150082500835008450085500865008750088500895009050091500925009350094500955009650097500985009950100501015010250103501045010550106501075010850109501105011150112501135011450115501165011750118501195012050121501225012350124501255012650127501285012950130501315013250133501345013550136501375013850139501405014150142501435014450145501465014750148501495015050151501525015350154501555015650157501585015950160501615016250163501645016550166501675016850169501705017150172501735017450175501765017750178501795018050181501825018350184501855018650187501885018950190501915019250193501945019550196501975019850199502005020150202502035020450205502065020750208502095021050211502125021350214502155021650217502185021950220502215022250223502245022550226502275022850229502305023150232502335023450235502365023750238502395024050241502425024350244502455024650247502485024950250502515025250253502545025550256502575025850259502605026150262502635026450265502665026750268502695027050271502725027350274502755027650277502785027950280502815028250283502845028550286502875028850289502905029150292502935029450295502965029750298502995030050301503025030350304503055030650307503085030950310503115031250313503145031550316503175031850319503205032150322503235032450325503265032750328503295033050331503325033350334503355033650337503385033950340503415034250343503445034550346503475034850349503505035150352503535035450355503565035750358503595036050361503625036350364503655036650367503685036950370503715037250373503745037550376503775037850379503805038150382503835038450385503865038750388503895039050391503925039350394503955039650397503985039950400504015040250403504045040550406504075040850409504105041150412504135041450415504165041750418504195042050421504225042350424504255042650427504285042950430504315043250433504345043550436504375043850439504405044150442504435044450445504465044750448504495045050451504525045350454504555045650457504585045950460504615046250463504645046550466504675046850469504705047150472504735047450475504765047750478504795048050481504825048350484504855048650487504885048950490504915049250493504945049550496504975049850499505005050150502505035050450505505065050750508505095051050511505125051350514505155051650517505185051950520505215052250523505245052550526505275052850529505305053150532505335053450535505365053750538505395054050541505425054350544505455054650547505485054950550505515055250553505545055550556505575055850559505605056150562505635056450565505665056750568505695057050571505725057350574505755057650577505785057950580505815058250583505845058550586505875058850589505905059150592505935059450595505965059750598505995060050601506025060350604506055060650607506085060950610506115061250613506145061550616506175061850619506205062150622506235062450625506265062750628506295063050631506325063350634506355063650637506385063950640506415064250643506445064550646506475064850649506505065150652506535065450655506565065750658506595066050661506625066350664506655066650667506685066950670506715067250673506745067550676506775067850679506805068150682506835068450685506865068750688506895069050691506925069350694506955069650697506985069950700507015070250703507045070550706507075070850709507105071150712507135071450715507165071750718507195072050721507225072350724507255072650727507285072950730507315073250733507345073550736507375073850739507405074150742507435074450745507465074750748507495075050751507525075350754507555075650757507585075950760507615076250763507645076550766507675076850769507705077150772507735077450775507765077750778507795078050781507825078350784507855078650787507885078950790507915079250793507945079550796507975079850799508005080150802508035080450805508065080750808508095081050811508125081350814508155081650817508185081950820508215082250823508245082550826508275082850829508305083150832508335083450835508365083750838508395084050841508425084350844508455084650847508485084950850508515085250853508545085550856508575085850859508605086150862508635086450865508665086750868508695087050871508725087350874508755087650877508785087950880508815088250883508845088550886508875088850889508905089150892508935089450895508965089750898508995090050901509025090350904509055090650907509085090950910509115091250913509145091550916509175091850919509205092150922509235092450925509265092750928509295093050931509325093350934509355093650937509385093950940509415094250943509445094550946509475094850949509505095150952509535095450955509565095750958509595096050961509625096350964509655096650967509685096950970509715097250973509745097550976509775097850979509805098150982509835098450985509865098750988509895099050991509925099350994509955099650997509985099951000510015100251003510045100551006510075100851009510105101151012510135101451015510165101751018510195102051021510225102351024510255102651027510285102951030510315103251033510345103551036510375103851039510405104151042510435104451045510465104751048510495105051051510525105351054510555105651057510585105951060510615106251063510645106551066510675106851069510705107151072510735107451075510765107751078510795108051081510825108351084510855108651087510885108951090510915109251093510945109551096510975109851099511005110151102511035110451105511065110751108511095111051111511125111351114511155111651117511185111951120511215112251123511245112551126511275112851129511305113151132511335113451135511365113751138511395114051141511425114351144511455114651147511485114951150511515115251153511545115551156511575115851159511605116151162511635116451165511665116751168511695117051171511725117351174511755117651177511785117951180511815118251183511845118551186511875118851189511905119151192511935119451195511965119751198511995120051201512025120351204512055120651207512085120951210512115121251213512145121551216512175121851219512205122151222512235122451225512265122751228512295123051231512325123351234512355123651237512385123951240512415124251243512445124551246512475124851249512505125151252512535125451255512565125751258512595126051261512625126351264512655126651267512685126951270512715127251273512745127551276512775127851279512805128151282512835128451285512865128751288512895129051291512925129351294512955129651297512985129951300513015130251303513045130551306513075130851309513105131151312513135131451315513165131751318513195132051321513225132351324513255132651327513285132951330513315133251333513345133551336513375133851339513405134151342513435134451345513465134751348513495135051351513525135351354513555135651357513585135951360513615136251363513645136551366513675136851369513705137151372513735137451375513765137751378513795138051381513825138351384513855138651387513885138951390513915139251393513945139551396513975139851399514005140151402514035140451405514065140751408514095141051411514125141351414514155141651417514185141951420514215142251423514245142551426514275142851429514305143151432514335143451435514365143751438514395144051441514425144351444514455144651447514485144951450514515145251453514545145551456514575145851459514605146151462514635146451465514665146751468514695147051471514725147351474514755147651477514785147951480514815148251483514845148551486514875148851489514905149151492514935149451495514965149751498514995150051501515025150351504515055150651507515085150951510515115151251513515145151551516515175151851519515205152151522515235152451525515265152751528515295153051531515325153351534515355153651537515385153951540515415154251543515445154551546515475154851549515505155151552515535155451555515565155751558515595156051561515625156351564515655156651567515685156951570515715157251573515745157551576515775157851579515805158151582515835158451585515865158751588515895159051591515925159351594515955159651597515985159951600516015160251603516045160551606516075160851609516105161151612516135161451615516165161751618516195162051621516225162351624516255162651627516285162951630516315163251633516345163551636516375163851639516405164151642516435164451645516465164751648516495165051651516525165351654516555165651657516585165951660516615166251663516645166551666516675166851669516705167151672516735167451675516765167751678516795168051681516825168351684516855168651687516885168951690516915169251693516945169551696516975169851699517005170151702517035170451705517065170751708517095171051711517125171351714517155171651717517185171951720517215172251723517245172551726517275172851729517305173151732517335173451735517365173751738517395174051741517425174351744517455174651747517485174951750517515175251753517545175551756517575175851759517605176151762517635176451765517665176751768517695177051771517725177351774517755177651777517785177951780517815178251783517845178551786517875178851789517905179151792517935179451795517965179751798517995180051801518025180351804518055180651807518085180951810518115181251813518145181551816518175181851819518205182151822518235182451825518265182751828518295183051831518325183351834518355183651837518385183951840518415184251843518445184551846518475184851849518505185151852518535185451855518565185751858518595186051861518625186351864518655186651867518685186951870518715187251873518745187551876518775187851879518805188151882518835188451885518865188751888518895189051891518925189351894518955189651897518985189951900519015190251903519045190551906519075190851909519105191151912519135191451915519165191751918519195192051921519225192351924519255192651927519285192951930519315193251933519345193551936519375193851939519405194151942519435194451945519465194751948519495195051951519525195351954519555195651957519585195951960519615196251963519645196551966519675196851969519705197151972519735197451975519765197751978519795198051981519825198351984519855198651987519885198951990519915199251993519945199551996519975199851999520005200152002520035200452005520065200752008520095201052011520125201352014520155201652017520185201952020520215202252023520245202552026520275202852029520305203152032520335203452035520365203752038520395204052041520425204352044520455204652047520485204952050520515205252053520545205552056520575205852059520605206152062520635206452065520665206752068520695207052071520725207352074520755207652077520785207952080520815208252083520845208552086520875208852089520905209152092520935209452095520965209752098520995210052101521025210352104521055210652107521085210952110521115211252113521145211552116521175211852119521205212152122521235212452125521265212752128521295213052131521325213352134521355213652137521385213952140521415214252143521445214552146521475214852149521505215152152521535215452155521565215752158521595216052161521625216352164521655216652167521685216952170521715217252173521745217552176521775217852179521805218152182521835218452185521865218752188521895219052191521925219352194521955219652197521985219952200522015220252203522045220552206522075220852209522105221152212522135221452215522165221752218522195222052221522225222352224522255222652227522285222952230522315223252233522345223552236522375223852239522405224152242522435224452245522465224752248522495225052251522525225352254522555225652257522585225952260522615226252263522645226552266522675226852269522705227152272522735227452275522765227752278522795228052281522825228352284522855228652287522885228952290522915229252293522945229552296522975229852299523005230152302523035230452305523065230752308523095231052311523125231352314523155231652317523185231952320523215232252323523245232552326523275232852329523305233152332523335233452335523365233752338523395234052341523425234352344523455234652347523485234952350523515235252353523545235552356523575235852359523605236152362523635236452365523665236752368523695237052371523725237352374523755237652377523785237952380523815238252383523845238552386523875238852389523905239152392523935239452395523965239752398523995240052401524025240352404524055240652407524085240952410524115241252413524145241552416524175241852419524205242152422524235242452425524265242752428524295243052431524325243352434524355243652437524385243952440524415244252443524445244552446524475244852449524505245152452524535245452455524565245752458524595246052461524625246352464524655246652467524685246952470524715247252473524745247552476524775247852479524805248152482524835248452485524865248752488524895249052491524925249352494524955249652497524985249952500525015250252503525045250552506525075250852509525105251152512525135251452515525165251752518525195252052521525225252352524525255252652527525285252952530525315253252533525345253552536525375253852539525405254152542525435254452545525465254752548525495255052551525525255352554525555255652557525585255952560525615256252563525645256552566525675256852569525705257152572525735257452575525765257752578525795258052581525825258352584525855258652587525885258952590525915259252593525945259552596525975259852599526005260152602526035260452605526065260752608526095261052611526125261352614526155261652617526185261952620526215262252623526245262552626526275262852629526305263152632526335263452635526365263752638526395264052641526425264352644526455264652647526485264952650526515265252653526545265552656526575265852659526605266152662526635266452665526665266752668526695267052671526725267352674526755267652677526785267952680526815268252683526845268552686526875268852689526905269152692526935269452695526965269752698526995270052701527025270352704527055270652707527085270952710527115271252713527145271552716527175271852719527205272152722527235272452725527265272752728527295273052731527325273352734527355273652737527385273952740527415274252743527445274552746527475274852749527505275152752527535275452755527565275752758527595276052761527625276352764527655276652767527685276952770527715277252773527745277552776527775277852779527805278152782527835278452785527865278752788527895279052791527925279352794527955279652797527985279952800528015280252803528045280552806528075280852809528105281152812528135281452815528165281752818528195282052821528225282352824528255282652827528285282952830528315283252833528345283552836528375283852839528405284152842528435284452845528465284752848528495285052851528525285352854528555285652857528585285952860528615286252863528645286552866528675286852869528705287152872528735287452875528765287752878528795288052881528825288352884528855288652887528885288952890528915289252893528945289552896528975289852899529005290152902529035290452905529065290752908529095291052911529125291352914529155291652917529185291952920529215292252923529245292552926529275292852929529305293152932529335293452935529365293752938529395294052941529425294352944529455294652947529485294952950529515295252953529545295552956529575295852959529605296152962529635296452965529665296752968529695297052971529725297352974529755297652977529785297952980529815298252983529845298552986529875298852989529905299152992529935299452995529965299752998529995300053001530025300353004530055300653007530085300953010530115301253013530145301553016530175301853019530205302153022530235302453025530265302753028530295303053031530325303353034530355303653037530385303953040530415304253043530445304553046530475304853049530505305153052530535305453055530565305753058530595306053061530625306353064530655306653067530685306953070530715307253073530745307553076530775307853079530805308153082530835308453085530865308753088530895309053091530925309353094530955309653097530985309953100531015310253103531045310553106531075310853109531105311153112531135311453115531165311753118531195312053121531225312353124531255312653127531285312953130531315313253133531345313553136531375313853139531405314153142531435314453145531465314753148531495315053151531525315353154531555315653157531585315953160531615316253163531645316553166531675316853169531705317153172531735317453175531765317753178531795318053181531825318353184531855318653187531885318953190531915319253193531945319553196531975319853199532005320153202532035320453205532065320753208532095321053211532125321353214532155321653217532185321953220532215322253223532245322553226532275322853229532305323153232532335323453235532365323753238532395324053241532425324353244532455324653247532485324953250532515325253253532545325553256532575325853259532605326153262532635326453265532665326753268532695327053271532725327353274532755327653277532785327953280532815328253283532845328553286532875328853289532905329153292532935329453295532965329753298532995330053301533025330353304533055330653307533085330953310533115331253313533145331553316533175331853319533205332153322533235332453325533265332753328533295333053331533325333353334533355333653337533385333953340533415334253343533445334553346533475334853349533505335153352533535335453355533565335753358533595336053361533625336353364533655336653367533685336953370533715337253373533745337553376533775337853379533805338153382533835338453385533865338753388533895339053391533925339353394533955339653397533985339953400534015340253403534045340553406534075340853409534105341153412534135341453415534165341753418534195342053421534225342353424534255342653427534285342953430534315343253433534345343553436534375343853439534405344153442534435344453445534465344753448534495345053451534525345353454534555345653457534585345953460534615346253463534645346553466534675346853469534705347153472534735347453475534765347753478534795348053481534825348353484534855348653487534885348953490534915349253493534945349553496534975349853499535005350153502535035350453505535065350753508535095351053511535125351353514535155351653517535185351953520535215352253523535245352553526535275352853529535305353153532535335353453535535365353753538535395354053541535425354353544535455354653547535485354953550535515355253553535545355553556535575355853559535605356153562535635356453565535665356753568535695357053571535725357353574535755357653577535785357953580535815358253583535845358553586535875358853589535905359153592535935359453595535965359753598535995360053601536025360353604536055360653607536085360953610536115361253613536145361553616536175361853619536205362153622536235362453625536265362753628536295363053631536325363353634536355363653637536385363953640536415364253643536445364553646536475364853649536505365153652536535365453655536565365753658536595366053661536625366353664536655366653667536685366953670536715367253673536745367553676536775367853679536805368153682536835368453685536865368753688536895369053691536925369353694536955369653697536985369953700537015370253703537045370553706537075370853709537105371153712537135371453715537165371753718537195372053721537225372353724537255372653727537285372953730537315373253733537345373553736537375373853739537405374153742537435374453745537465374753748537495375053751537525375353754537555375653757537585375953760537615376253763537645376553766537675376853769537705377153772537735377453775537765377753778537795378053781537825378353784537855378653787537885378953790537915379253793537945379553796537975379853799538005380153802538035380453805538065380753808538095381053811538125381353814538155381653817538185381953820538215382253823538245382553826538275382853829538305383153832538335383453835538365383753838538395384053841538425384353844538455384653847538485384953850538515385253853538545385553856538575385853859538605386153862538635386453865538665386753868538695387053871538725387353874538755387653877538785387953880538815388253883538845388553886538875388853889538905389153892538935389453895538965389753898538995390053901539025390353904539055390653907539085390953910539115391253913539145391553916539175391853919539205392153922539235392453925539265392753928539295393053931539325393353934539355393653937539385393953940539415394253943539445394553946539475394853949539505395153952539535395453955539565395753958539595396053961539625396353964539655396653967539685396953970539715397253973539745397553976539775397853979539805398153982539835398453985539865398753988539895399053991539925399353994539955399653997539985399954000540015400254003540045400554006540075400854009540105401154012540135401454015540165401754018540195402054021540225402354024540255402654027540285402954030540315403254033540345403554036540375403854039540405404154042540435404454045540465404754048540495405054051540525405354054540555405654057540585405954060540615406254063540645406554066540675406854069540705407154072540735407454075540765407754078540795408054081540825408354084540855408654087540885408954090540915409254093540945409554096540975409854099541005410154102541035410454105541065410754108541095411054111541125411354114541155411654117541185411954120541215412254123541245412554126541275412854129541305413154132541335413454135541365413754138541395414054141541425414354144541455414654147541485414954150541515415254153541545415554156541575415854159541605416154162541635416454165541665416754168541695417054171541725417354174541755417654177541785417954180541815418254183541845418554186541875418854189541905419154192541935419454195541965419754198541995420054201542025420354204542055420654207542085420954210542115421254213542145421554216542175421854219542205422154222542235422454225542265422754228542295423054231542325423354234542355423654237542385423954240542415424254243542445424554246542475424854249542505425154252542535425454255542565425754258542595426054261542625426354264542655426654267542685426954270542715427254273542745427554276542775427854279542805428154282542835428454285542865428754288542895429054291542925429354294542955429654297542985429954300543015430254303543045430554306543075430854309543105431154312543135431454315543165431754318543195432054321543225432354324543255432654327543285432954330543315433254333543345433554336543375433854339543405434154342543435434454345543465434754348543495435054351543525435354354543555435654357543585435954360543615436254363543645436554366543675436854369543705437154372543735437454375543765437754378543795438054381543825438354384543855438654387543885438954390543915439254393543945439554396543975439854399544005440154402544035440454405544065440754408544095441054411544125441354414544155441654417544185441954420544215442254423544245442554426544275442854429544305443154432544335443454435544365443754438544395444054441544425444354444544455444654447544485444954450544515445254453544545445554456544575445854459544605446154462544635446454465544665446754468544695447054471544725447354474544755447654477544785447954480544815448254483544845448554486544875448854489544905449154492544935449454495544965449754498544995450054501545025450354504545055450654507545085450954510545115451254513545145451554516545175451854519545205452154522545235452454525545265452754528545295453054531545325453354534545355453654537545385453954540545415454254543545445454554546545475454854549545505455154552545535455454555545565455754558545595456054561545625456354564545655456654567545685456954570545715457254573545745457554576545775457854579545805458154582545835458454585545865458754588545895459054591545925459354594545955459654597545985459954600546015460254603546045460554606546075460854609546105461154612546135461454615546165461754618546195462054621546225462354624546255462654627546285462954630546315463254633546345463554636546375463854639546405464154642546435464454645546465464754648546495465054651546525465354654546555465654657546585465954660546615466254663546645466554666546675466854669546705467154672546735467454675546765467754678546795468054681546825468354684546855468654687546885468954690546915469254693546945469554696546975469854699547005470154702547035470454705547065470754708547095471054711547125471354714547155471654717547185471954720547215472254723547245472554726547275472854729547305473154732547335473454735547365473754738547395474054741547425474354744547455474654747547485474954750547515475254753547545475554756547575475854759547605476154762547635476454765547665476754768547695477054771547725477354774547755477654777547785477954780547815478254783547845478554786547875478854789547905479154792547935479454795547965479754798547995480054801548025480354804548055480654807548085480954810548115481254813548145481554816548175481854819548205482154822548235482454825548265482754828548295483054831548325483354834548355483654837548385483954840548415484254843548445484554846548475484854849548505485154852548535485454855548565485754858548595486054861548625486354864548655486654867548685486954870548715487254873548745487554876548775487854879548805488154882548835488454885548865488754888548895489054891548925489354894548955489654897548985489954900549015490254903549045490554906549075490854909549105491154912549135491454915549165491754918549195492054921549225492354924549255492654927549285492954930549315493254933549345493554936549375493854939549405494154942549435494454945549465494754948549495495054951549525495354954549555495654957549585495954960549615496254963549645496554966549675496854969549705497154972549735497454975549765497754978549795498054981549825498354984549855498654987549885498954990549915499254993549945499554996549975499854999550005500155002550035500455005550065500755008550095501055011550125501355014550155501655017550185501955020550215502255023550245502555026550275502855029550305503155032550335503455035550365503755038550395504055041550425504355044550455504655047550485504955050550515505255053550545505555056550575505855059550605506155062550635506455065550665506755068550695507055071550725507355074550755507655077550785507955080550815508255083550845508555086550875508855089550905509155092550935509455095550965509755098550995510055101551025510355104551055510655107551085510955110551115511255113551145511555116551175511855119551205512155122551235512455125551265512755128551295513055131551325513355134551355513655137551385513955140551415514255143551445514555146551475514855149551505515155152551535515455155551565515755158551595516055161551625516355164551655516655167551685516955170551715517255173551745517555176551775517855179551805518155182551835518455185551865518755188551895519055191551925519355194551955519655197551985519955200552015520255203552045520555206552075520855209552105521155212552135521455215552165521755218552195522055221552225522355224552255522655227552285522955230552315523255233552345523555236552375523855239552405524155242552435524455245552465524755248552495525055251552525525355254552555525655257552585525955260552615526255263552645526555266552675526855269552705527155272552735527455275552765527755278552795528055281552825528355284552855528655287552885528955290552915529255293552945529555296552975529855299553005530155302553035530455305553065530755308553095531055311553125531355314553155531655317553185531955320553215532255323553245532555326553275532855329553305533155332553335533455335553365533755338553395534055341553425534355344553455534655347553485534955350553515535255353553545535555356553575535855359553605536155362553635536455365553665536755368553695537055371553725537355374553755537655377553785537955380553815538255383553845538555386553875538855389553905539155392553935539455395553965539755398553995540055401554025540355404554055540655407554085540955410554115541255413554145541555416554175541855419554205542155422554235542455425554265542755428554295543055431554325543355434554355543655437554385543955440554415544255443554445544555446554475544855449554505545155452554535545455455554565545755458554595546055461554625546355464554655546655467554685546955470554715547255473554745547555476554775547855479554805548155482554835548455485554865548755488554895549055491554925549355494554955549655497554985549955500555015550255503555045550555506555075550855509555105551155512555135551455515555165551755518555195552055521555225552355524555255552655527555285552955530555315553255533555345553555536555375553855539555405554155542555435554455545555465554755548555495555055551555525555355554555555555655557555585555955560555615556255563555645556555566555675556855569555705557155572555735557455575555765557755578555795558055581555825558355584555855558655587555885558955590555915559255593555945559555596555975559855599556005560155602556035560455605556065560755608556095561055611556125561355614556155561655617556185561955620556215562255623556245562555626556275562855629556305563155632556335563455635556365563755638556395564055641556425564355644556455564655647556485564955650556515565255653556545565555656556575565855659556605566155662556635566455665556665566755668556695567055671556725567355674556755567655677556785567955680556815568255683556845568555686556875568855689556905569155692556935569455695556965569755698556995570055701557025570355704557055570655707557085570955710557115571255713557145571555716557175571855719557205572155722557235572455725557265572755728557295573055731557325573355734557355573655737557385573955740557415574255743557445574555746557475574855749557505575155752557535575455755557565575755758557595576055761557625576355764557655576655767557685576955770557715577255773557745577555776557775577855779557805578155782557835578455785557865578755788557895579055791557925579355794557955579655797557985579955800558015580255803558045580555806558075580855809558105581155812558135581455815558165581755818558195582055821558225582355824558255582655827558285582955830558315583255833558345583555836558375583855839558405584155842558435584455845558465584755848558495585055851558525585355854558555585655857558585585955860558615586255863558645586555866558675586855869558705587155872558735587455875558765587755878558795588055881558825588355884558855588655887558885588955890558915589255893558945589555896558975589855899559005590155902559035590455905559065590755908559095591055911559125591355914559155591655917559185591955920559215592255923559245592555926559275592855929559305593155932559335593455935559365593755938559395594055941559425594355944559455594655947559485594955950559515595255953559545595555956559575595855959559605596155962559635596455965559665596755968559695597055971559725597355974559755597655977559785597955980559815598255983559845598555986559875598855989559905599155992559935599455995559965599755998559995600056001560025600356004560055600656007560085600956010560115601256013560145601556016560175601856019560205602156022560235602456025560265602756028560295603056031560325603356034560355603656037560385603956040560415604256043560445604556046560475604856049560505605156052560535605456055560565605756058560595606056061560625606356064560655606656067560685606956070560715607256073560745607556076560775607856079560805608156082560835608456085560865608756088560895609056091560925609356094560955609656097560985609956100561015610256103561045610556106561075610856109561105611156112561135611456115561165611756118561195612056121561225612356124561255612656127561285612956130561315613256133561345613556136561375613856139561405614156142561435614456145561465614756148561495615056151561525615356154561555615656157561585615956160561615616256163561645616556166561675616856169561705617156172561735617456175561765617756178561795618056181561825618356184561855618656187561885618956190561915619256193561945619556196561975619856199562005620156202562035620456205562065620756208562095621056211562125621356214562155621656217562185621956220562215622256223562245622556226562275622856229562305623156232562335623456235562365623756238562395624056241562425624356244562455624656247562485624956250562515625256253562545625556256562575625856259562605626156262562635626456265562665626756268562695627056271562725627356274562755627656277562785627956280562815628256283562845628556286562875628856289562905629156292562935629456295562965629756298562995630056301563025630356304563055630656307563085630956310563115631256313563145631556316563175631856319563205632156322563235632456325563265632756328563295633056331563325633356334563355633656337563385633956340563415634256343563445634556346563475634856349563505635156352563535635456355563565635756358563595636056361563625636356364563655636656367563685636956370563715637256373563745637556376563775637856379563805638156382563835638456385563865638756388563895639056391563925639356394563955639656397563985639956400564015640256403564045640556406564075640856409564105641156412564135641456415564165641756418564195642056421564225642356424564255642656427564285642956430564315643256433564345643556436564375643856439564405644156442564435644456445564465644756448564495645056451564525645356454564555645656457564585645956460564615646256463564645646556466564675646856469564705647156472564735647456475564765647756478564795648056481564825648356484564855648656487564885648956490564915649256493564945649556496564975649856499565005650156502565035650456505565065650756508565095651056511565125651356514565155651656517565185651956520565215652256523565245652556526565275652856529565305653156532565335653456535565365653756538565395654056541565425654356544565455654656547565485654956550565515655256553565545655556556565575655856559565605656156562565635656456565565665656756568565695657056571565725657356574565755657656577565785657956580565815658256583565845658556586565875658856589565905659156592565935659456595565965659756598565995660056601566025660356604566055660656607566085660956610566115661256613566145661556616566175661856619566205662156622566235662456625566265662756628566295663056631566325663356634566355663656637566385663956640566415664256643566445664556646566475664856649566505665156652566535665456655566565665756658566595666056661566625666356664566655666656667566685666956670566715667256673566745667556676566775667856679566805668156682566835668456685566865668756688566895669056691566925669356694566955669656697566985669956700567015670256703567045670556706567075670856709567105671156712567135671456715567165671756718567195672056721567225672356724567255672656727567285672956730567315673256733567345673556736567375673856739567405674156742567435674456745567465674756748567495675056751567525675356754567555675656757567585675956760567615676256763567645676556766567675676856769567705677156772567735677456775567765677756778567795678056781567825678356784567855678656787567885678956790567915679256793567945679556796567975679856799568005680156802568035680456805568065680756808568095681056811568125681356814568155681656817568185681956820568215682256823568245682556826568275682856829568305683156832568335683456835568365683756838568395684056841568425684356844568455684656847568485684956850568515685256853568545685556856568575685856859568605686156862568635686456865568665686756868568695687056871568725687356874568755687656877568785687956880568815688256883568845688556886568875688856889568905689156892568935689456895568965689756898568995690056901569025690356904569055690656907569085690956910569115691256913569145691556916569175691856919569205692156922569235692456925569265692756928569295693056931569325693356934569355693656937569385693956940569415694256943569445694556946569475694856949569505695156952569535695456955569565695756958569595696056961569625696356964569655696656967569685696956970569715697256973569745697556976569775697856979569805698156982569835698456985569865698756988569895699056991569925699356994569955699656997569985699957000570015700257003570045700557006570075700857009570105701157012570135701457015570165701757018570195702057021570225702357024570255702657027570285702957030570315703257033570345703557036570375703857039570405704157042570435704457045570465704757048570495705057051570525705357054570555705657057570585705957060570615706257063570645706557066570675706857069570705707157072570735707457075570765707757078570795708057081570825708357084570855708657087570885708957090570915709257093570945709557096570975709857099571005710157102571035710457105571065710757108571095711057111571125711357114571155711657117571185711957120571215712257123571245712557126571275712857129571305713157132571335713457135571365713757138571395714057141571425714357144571455714657147571485714957150571515715257153571545715557156571575715857159571605716157162571635716457165571665716757168571695717057171571725717357174571755717657177571785717957180571815718257183571845718557186571875718857189571905719157192571935719457195571965719757198571995720057201572025720357204572055720657207572085720957210572115721257213572145721557216572175721857219572205722157222572235722457225572265722757228572295723057231572325723357234572355723657237572385723957240572415724257243572445724557246572475724857249572505725157252572535725457255572565725757258572595726057261572625726357264572655726657267572685726957270572715727257273572745727557276572775727857279572805728157282572835728457285572865728757288572895729057291572925729357294572955729657297572985729957300573015730257303573045730557306573075730857309573105731157312573135731457315573165731757318573195732057321573225732357324573255732657327573285732957330573315733257333573345733557336573375733857339573405734157342573435734457345573465734757348573495735057351573525735357354573555735657357573585735957360573615736257363573645736557366573675736857369573705737157372573735737457375573765737757378573795738057381573825738357384573855738657387573885738957390573915739257393573945739557396573975739857399574005740157402574035740457405574065740757408574095741057411574125741357414574155741657417574185741957420574215742257423574245742557426574275742857429574305743157432574335743457435574365743757438574395744057441574425744357444574455744657447574485744957450574515745257453574545745557456574575745857459574605746157462574635746457465574665746757468574695747057471574725747357474574755747657477574785747957480574815748257483574845748557486574875748857489574905749157492574935749457495574965749757498574995750057501575025750357504575055750657507575085750957510575115751257513575145751557516575175751857519575205752157522575235752457525575265752757528575295753057531575325753357534575355753657537575385753957540575415754257543575445754557546575475754857549575505755157552575535755457555575565755757558575595756057561575625756357564575655756657567575685756957570575715757257573575745757557576575775757857579575805758157582575835758457585575865758757588575895759057591575925759357594575955759657597575985759957600576015760257603576045760557606576075760857609576105761157612576135761457615576165761757618576195762057621576225762357624576255762657627576285762957630576315763257633576345763557636576375763857639576405764157642576435764457645576465764757648576495765057651576525765357654576555765657657576585765957660576615766257663576645766557666576675766857669576705767157672576735767457675576765767757678576795768057681576825768357684576855768657687576885768957690576915769257693576945769557696576975769857699577005770157702577035770457705577065770757708577095771057711577125771357714577155771657717577185771957720577215772257723577245772557726577275772857729577305773157732577335773457735577365773757738577395774057741577425774357744577455774657747577485774957750577515775257753577545775557756577575775857759577605776157762577635776457765577665776757768577695777057771577725777357774577755777657777577785777957780577815778257783577845778557786577875778857789577905779157792577935779457795577965779757798577995780057801578025780357804578055780657807578085780957810578115781257813578145781557816578175781857819578205782157822578235782457825578265782757828578295783057831578325783357834578355783657837578385783957840578415784257843578445784557846578475784857849578505785157852578535785457855578565785757858578595786057861578625786357864578655786657867578685786957870578715787257873578745787557876578775787857879578805788157882578835788457885578865788757888578895789057891578925789357894578955789657897578985789957900579015790257903579045790557906579075790857909579105791157912579135791457915579165791757918579195792057921579225792357924579255792657927579285792957930579315793257933579345793557936579375793857939579405794157942579435794457945579465794757948579495795057951579525795357954579555795657957579585795957960579615796257963579645796557966579675796857969579705797157972579735797457975579765797757978579795798057981579825798357984579855798657987579885798957990579915799257993579945799557996579975799857999580005800158002580035800458005580065800758008580095801058011580125801358014580155801658017580185801958020580215802258023580245802558026580275802858029580305803158032580335803458035580365803758038580395804058041580425804358044580455804658047580485804958050580515805258053580545805558056580575805858059580605806158062580635806458065580665806758068580695807058071580725807358074580755807658077580785807958080580815808258083580845808558086580875808858089580905809158092580935809458095580965809758098580995810058101581025810358104581055810658107581085810958110581115811258113581145811558116581175811858119581205812158122581235812458125581265812758128581295813058131581325813358134581355813658137581385813958140581415814258143581445814558146581475814858149581505815158152581535815458155581565815758158581595816058161581625816358164581655816658167581685816958170581715817258173581745817558176581775817858179581805818158182581835818458185581865818758188581895819058191581925819358194581955819658197581985819958200582015820258203582045820558206582075820858209582105821158212582135821458215582165821758218582195822058221582225822358224582255822658227582285822958230582315823258233582345823558236582375823858239582405824158242582435824458245582465824758248582495825058251582525825358254582555825658257582585825958260582615826258263582645826558266582675826858269582705827158272582735827458275582765827758278582795828058281582825828358284582855828658287582885828958290582915829258293582945829558296582975829858299583005830158302583035830458305583065830758308583095831058311583125831358314583155831658317583185831958320583215832258323583245832558326583275832858329583305833158332583335833458335583365833758338583395834058341583425834358344583455834658347583485834958350583515835258353583545835558356583575835858359583605836158362583635836458365583665836758368583695837058371583725837358374583755837658377583785837958380583815838258383583845838558386583875838858389583905839158392583935839458395583965839758398583995840058401584025840358404584055840658407584085840958410584115841258413584145841558416584175841858419584205842158422584235842458425584265842758428584295843058431584325843358434584355843658437584385843958440584415844258443584445844558446584475844858449584505845158452584535845458455584565845758458584595846058461584625846358464584655846658467584685846958470584715847258473584745847558476584775847858479584805848158482584835848458485584865848758488584895849058491584925849358494584955849658497584985849958500585015850258503585045850558506585075850858509585105851158512585135851458515585165851758518585195852058521585225852358524585255852658527585285852958530585315853258533585345853558536585375853858539585405854158542585435854458545585465854758548585495855058551585525855358554585555855658557585585855958560585615856258563585645856558566585675856858569585705857158572585735857458575585765857758578585795858058581585825858358584585855858658587585885858958590585915859258593585945859558596585975859858599586005860158602586035860458605586065860758608586095861058611586125861358614586155861658617586185861958620586215862258623586245862558626586275862858629586305863158632586335863458635586365863758638586395864058641586425864358644586455864658647586485864958650586515865258653586545865558656586575865858659586605866158662586635866458665586665866758668586695867058671586725867358674586755867658677586785867958680586815868258683586845868558686586875868858689586905869158692586935869458695586965869758698586995870058701587025870358704587055870658707587085870958710587115871258713587145871558716587175871858719587205872158722587235872458725587265872758728587295873058731587325873358734587355873658737587385873958740587415874258743587445874558746587475874858749587505875158752587535875458755587565875758758587595876058761587625876358764587655876658767587685876958770587715877258773587745877558776587775877858779587805878158782587835878458785587865878758788587895879058791587925879358794587955879658797587985879958800588015880258803588045880558806588075880858809588105881158812588135881458815588165881758818588195882058821588225882358824588255882658827588285882958830588315883258833588345883558836588375883858839588405884158842588435884458845588465884758848588495885058851588525885358854588555885658857588585885958860588615886258863588645886558866588675886858869588705887158872588735887458875588765887758878588795888058881588825888358884588855888658887588885888958890588915889258893588945889558896588975889858899589005890158902589035890458905589065890758908589095891058911589125891358914589155891658917589185891958920589215892258923589245892558926589275892858929589305893158932589335893458935589365893758938589395894058941589425894358944589455894658947589485894958950589515895258953589545895558956589575895858959589605896158962589635896458965589665896758968589695897058971589725897358974589755897658977589785897958980589815898258983589845898558986589875898858989589905899158992589935899458995589965899758998589995900059001590025900359004590055900659007590085900959010590115901259013590145901559016590175901859019590205902159022590235902459025590265902759028590295903059031590325903359034590355903659037590385903959040590415904259043590445904559046590475904859049590505905159052590535905459055590565905759058590595906059061590625906359064590655906659067590685906959070590715907259073590745907559076590775907859079590805908159082590835908459085590865908759088590895909059091590925909359094590955909659097590985909959100591015910259103591045910559106591075910859109591105911159112591135911459115591165911759118591195912059121591225912359124591255912659127591285912959130591315913259133591345913559136591375913859139591405914159142591435914459145591465914759148591495915059151591525915359154591555915659157591585915959160591615916259163591645916559166591675916859169591705917159172591735917459175591765917759178591795918059181591825918359184591855918659187591885918959190591915919259193591945919559196591975919859199592005920159202592035920459205592065920759208592095921059211592125921359214592155921659217592185921959220592215922259223592245922559226592275922859229592305923159232592335923459235592365923759238592395924059241592425924359244592455924659247592485924959250592515925259253592545925559256592575925859259592605926159262592635926459265592665926759268592695927059271592725927359274592755927659277592785927959280592815928259283592845928559286592875928859289592905929159292592935929459295592965929759298592995930059301593025930359304593055930659307593085930959310593115931259313593145931559316593175931859319593205932159322593235932459325593265932759328593295933059331593325933359334593355933659337593385933959340593415934259343593445934559346593475934859349593505935159352593535935459355593565935759358593595936059361593625936359364593655936659367593685936959370593715937259373593745937559376593775937859379593805938159382593835938459385593865938759388593895939059391593925939359394593955939659397593985939959400594015940259403594045940559406594075940859409594105941159412594135941459415594165941759418594195942059421594225942359424594255942659427594285942959430594315943259433594345943559436594375943859439594405944159442594435944459445594465944759448594495945059451594525945359454594555945659457594585945959460594615946259463594645946559466594675946859469594705947159472594735947459475594765947759478594795948059481594825948359484594855948659487594885948959490594915949259493594945949559496594975949859499595005950159502595035950459505595065950759508595095951059511595125951359514595155951659517595185951959520595215952259523595245952559526595275952859529595305953159532595335953459535595365953759538595395954059541595425954359544595455954659547595485954959550595515955259553595545955559556595575955859559595605956159562595635956459565595665956759568595695957059571595725957359574595755957659577595785957959580595815958259583595845958559586595875958859589595905959159592595935959459595595965959759598595995960059601596025960359604596055960659607596085960959610596115961259613596145961559616596175961859619596205962159622596235962459625596265962759628596295963059631596325963359634596355963659637596385963959640596415964259643596445964559646596475964859649596505965159652596535965459655596565965759658596595966059661596625966359664596655966659667596685966959670596715967259673596745967559676596775967859679596805968159682596835968459685596865968759688596895969059691596925969359694596955969659697596985969959700597015970259703597045970559706597075970859709597105971159712597135971459715597165971759718597195972059721597225972359724597255972659727597285972959730597315973259733597345973559736597375973859739597405974159742597435974459745597465974759748597495975059751597525975359754597555975659757597585975959760597615976259763597645976559766597675976859769597705977159772597735977459775597765977759778597795978059781597825978359784597855978659787597885978959790597915979259793597945979559796597975979859799598005980159802598035980459805598065980759808598095981059811598125981359814598155981659817598185981959820598215982259823598245982559826598275982859829598305983159832598335983459835598365983759838598395984059841598425984359844598455984659847598485984959850598515985259853598545985559856598575985859859598605986159862598635986459865598665986759868598695987059871598725987359874598755987659877598785987959880598815988259883598845988559886598875988859889598905989159892598935989459895598965989759898598995990059901599025990359904599055990659907599085990959910599115991259913599145991559916599175991859919599205992159922599235992459925599265992759928599295993059931599325993359934599355993659937599385993959940599415994259943599445994559946599475994859949599505995159952599535995459955599565995759958599595996059961599625996359964599655996659967599685996959970599715997259973599745997559976599775997859979599805998159982599835998459985599865998759988599895999059991599925999359994599955999659997599985999960000600016000260003600046000560006600076000860009600106001160012600136001460015600166001760018600196002060021600226002360024600256002660027600286002960030600316003260033600346003560036600376003860039600406004160042600436004460045600466004760048600496005060051600526005360054600556005660057600586005960060600616006260063600646006560066600676006860069600706007160072600736007460075600766007760078600796008060081600826008360084600856008660087600886008960090600916009260093600946009560096600976009860099601006010160102601036010460105601066010760108601096011060111601126011360114601156011660117601186011960120601216012260123601246012560126601276012860129601306013160132601336013460135601366013760138601396014060141601426014360144601456014660147601486014960150601516015260153601546015560156601576015860159601606016160162601636016460165601666016760168601696017060171601726017360174601756017660177601786017960180601816018260183601846018560186601876018860189601906019160192601936019460195601966019760198601996020060201602026020360204602056020660207602086020960210602116021260213602146021560216602176021860219602206022160222602236022460225602266022760228602296023060231602326023360234602356023660237602386023960240602416024260243602446024560246602476024860249602506025160252602536025460255602566025760258602596026060261602626026360264602656026660267602686026960270602716027260273602746027560276602776027860279602806028160282602836028460285602866028760288602896029060291602926029360294602956029660297602986029960300603016030260303603046030560306603076030860309603106031160312603136031460315603166031760318603196032060321603226032360324603256032660327603286032960330603316033260333603346033560336603376033860339603406034160342603436034460345603466034760348603496035060351603526035360354603556035660357603586035960360603616036260363603646036560366603676036860369603706037160372603736037460375603766037760378603796038060381603826038360384603856038660387603886038960390603916039260393603946039560396603976039860399604006040160402604036040460405604066040760408604096041060411604126041360414604156041660417604186041960420604216042260423604246042560426604276042860429604306043160432604336043460435604366043760438604396044060441604426044360444604456044660447604486044960450604516045260453604546045560456604576045860459604606046160462604636046460465604666046760468604696047060471604726047360474604756047660477604786047960480604816048260483604846048560486604876048860489604906049160492604936049460495604966049760498604996050060501605026050360504605056050660507605086050960510605116051260513605146051560516605176051860519605206052160522605236052460525605266052760528605296053060531605326053360534605356053660537605386053960540605416054260543605446054560546605476054860549605506055160552605536055460555605566055760558605596056060561605626056360564605656056660567605686056960570605716057260573605746057560576605776057860579605806058160582605836058460585605866058760588605896059060591605926059360594605956059660597605986059960600606016060260603606046060560606606076060860609606106061160612606136061460615606166061760618606196062060621606226062360624606256062660627606286062960630606316063260633606346063560636606376063860639606406064160642606436064460645606466064760648606496065060651606526065360654606556065660657606586065960660606616066260663606646066560666606676066860669606706067160672606736067460675606766067760678606796068060681606826068360684606856068660687606886068960690606916069260693606946069560696606976069860699607006070160702607036070460705607066070760708607096071060711607126071360714607156071660717607186071960720607216072260723607246072560726607276072860729607306073160732607336073460735607366073760738607396074060741607426074360744607456074660747607486074960750607516075260753607546075560756607576075860759607606076160762607636076460765607666076760768607696077060771607726077360774607756077660777607786077960780607816078260783607846078560786607876078860789607906079160792607936079460795607966079760798607996080060801608026080360804608056080660807608086080960810608116081260813608146081560816608176081860819608206082160822608236082460825608266082760828608296083060831608326083360834 |
- #!/usr/bin/env php
- <?php
- /*
- * This file is part of Composer.
- *
- * (c) Nils Adermann <naderman@naderman.de>
- * Jordi Boggiano <j.boggiano@seld.be>
- *
- * For the full copyright and license information, please view
- * the license that is located at the bottom of this file.
- */
- // Avoid APC causing random fatal errors per https://github.com/composer/composer/issues/264
- if (extension_loaded('apc') && ini_get('apc.enable_cli') && ini_get('apc.cache_by_default')) {
- if (version_compare(phpversion('apc'), '3.0.12', '>=')) {
- ini_set('apc.cache_by_default', 0);
- } else {
- fwrite(STDERR, 'Warning: APC <= 3.0.12 may cause fatal errors when running composer commands.'.PHP_EOL);
- fwrite(STDERR, 'Update APC, or set apc.enable_cli or apc.cache_by_default to 0 in your php.ini.'.PHP_EOL);
- }
- }
- Phar::mapPhar('composer.phar');
- define('COMPOSER_DEV_WARNING_TIME', 1431294610);
- require 'phar://composer.phar/bin/composer';
- __HALT_COMPILER(); ?>
- ®x��s������
���composer.phar�������src/bootstrap.phpÅ��’E(UÅ��¨¯2�¶������+���src/Composer/Autoload/AutoloadGenerator.phpxD��’E(UxD��´¡ &¶������+���src/Composer/Autoload/ClassMapGenerator.phpJ��’E(UJ��y¾±K¶���������src/Composer/Cache.php*��’E(U*��–užÁ¶������%���src/Composer/Command/AboutCommand.php»��’E(U»��#{ik¶������'���src/Composer/Command/ArchiveCommand.php��’E(U��¸Uöª¶������*���src/Composer/Command/ClearCacheCommand.phpZ��’E(UZ��‰ì>¶������ ���src/Composer/Command/Command.php‰��’E(U‰��µvJ¶������&���src/Composer/Command/ConfigCommand.php4��’E(U4��r�Ó¶������-���src/Composer/Command/CreateProjectCommand.php=1��’E(U=1��ºžÑ›¶������'���src/Composer/Command/DependsCommand.php„
- ��’E(U„
- ��È!"¶������(���src/Composer/Command/DiagnoseCommand.phpg:��’E(Ug:��9ˆìæ¶������,���src/Composer/Command/DumpAutoloadCommand.phpÿ��’E(Uÿ��FZ¶������&���src/Composer/Command/GlobalCommand.php��’E(U��©¨@•¶������,���src/Composer/Command/Helper/DialogHelper.phpž��’E(Už��•‚Œ&¶������$���src/Composer/Command/HomeCommand.php+��’E(U+��^š¶������$���src/Composer/Command/InitCommand.php 7��’E(U 7��$Îñ¶������'���src/Composer/Command/InstallCommand.php#��’E(U#��=J%¶������(���src/Composer/Command/LicensesCommand.phpÏ��’E(UÏ�� ¶������&���src/Composer/Command/RemoveCommand.php”��’E(U”��¹>1œ¶������'���src/Composer/Command/RequireCommand.php~��’E(U~��¡ú„¾¶������)���src/Composer/Command/RunScriptCommand.phpk��’E(Uk��ÃõR¶������+���src/Composer/Command/ScriptAliasCommand.php���’E(U���¢ò9J¶������&���src/Composer/Command/SearchCommand.phpl ��’E(Ul ��¶K4¶������*���src/Composer/Command/SelfUpdateCommand.php#��’E(U#��¡#ˆ)¶������$���src/Composer/Command/ShowCommand.php50��’E(U50��¹‰„¶������&���src/Composer/Command/StatusCommand.phpo ��’E(Uo ��—²Î¶������&���src/Composer/Command/UpdateCommand.php*��’E(U*��Í
- #ö������(���src/Composer/Command/ValidateCommand.php��’E(U��yw‚¶���������src/Composer/Composer.php) ��’E(U) ��Ò�ݘ¶������-���src/Composer/Config/ConfigSourceInterface.php®��’E(U®��6J[ª¶������(���src/Composer/Config/JsonConfigSource.php}��’E(U}��èÇ ¶���������src/Composer/Config.phpÿ��’E(Uÿ��/ª�¶������$���src/Composer/Console/Application.php"��’E(U"��”LTܶ������,���src/Composer/Console/HtmlOutputFormatter.phpÎ��’E(UÎ��๟„¶������/���src/Composer/DependencyResolver/DebugSolver.php‰��’E(U‰��£Ò…¶������-���src/Composer/DependencyResolver/Decisions.phpQ��’E(UQ��?˜¬$¶������1���src/Composer/DependencyResolver/DefaultPolicy.php��’E(U��‰&—¶������>���src/Composer/DependencyResolver/Operation/InstallOperation.phpC��’E(UC��´\õ*¶������I���src/Composer/DependencyResolver/Operation/MarkAliasInstalledOperation.phpÐ��’E(UÐ��xUZa¶������K���src/Composer/DependencyResolver/Operation/MarkAliasUninstalledOperation.phpÖ��’E(UÖ��_iÇ«¶������@���src/Composer/DependencyResolver/Operation/OperationInterface.phpÓ���’E(UÓ���Ùâ&ä¶������=���src/Composer/DependencyResolver/Operation/SolverOperation.phpë��’E(Uë��ħݔ¶������@���src/Composer/DependencyResolver/Operation/UninstallOperation.phpI��’E(UI��FûÂɶ������=���src/Composer/DependencyResolver/Operation/UpdateOperation.phph��’E(Uh��öSÕ]¶������3���src/Composer/DependencyResolver/PolicyInterface.php‘��’E(U‘��BŸ¶¶������(���src/Composer/DependencyResolver/Pool.php'"��’E(U'"��Ø›x¶������+���src/Composer/DependencyResolver/Problem.php��’E(U��È S�¶������+���src/Composer/DependencyResolver/Request.phpÌ��’E(UÌ��™¦òä¶������(���src/Composer/DependencyResolver/Rule.php��’E(U��Á[”¶������+���src/Composer/DependencyResolver/RuleSet.php%
- ��’E(U%
- ��9z ¶������4���src/Composer/DependencyResolver/RuleSetGenerator.php]��’E(U]��4“Ñ9¶������3���src/Composer/DependencyResolver/RuleSetIterator.php��’E(U��}õÇù¶������2���src/Composer/DependencyResolver/RuleWatchChain.phpi��’E(Ui��hïš,¶������2���src/Composer/DependencyResolver/RuleWatchGraph.phpÜ��’E(UÜ��‰8¶������1���src/Composer/DependencyResolver/RuleWatchNode.phpç��’E(Uç��—Þȶ������*���src/Composer/DependencyResolver/Solver.php 7��’E(U 7��&„°¶������6���src/Composer/DependencyResolver/SolverBugException.php˜��’E(U˜��"qN¶������;���src/Composer/DependencyResolver/SolverProblemsException.php%��’E(U%��TíP¶������/���src/Composer/DependencyResolver/Transaction.phpÔ��’E(UÔ�� 3ô¶������-���src/Composer/Downloader/ArchiveDownloader.php
��’E(U
��жTj¶������1���src/Composer/Downloader/ChangeReportInterface.phpÌ���’E(UÌ���¯à¨¿¶������/���src/Composer/Downloader/DownloaderInterface.phpÊ��’E(UÊ��gs!l¶������+���src/Composer/Downloader/DownloadManager.php‘��’E(U‘��'oÅb¶������*���src/Composer/Downloader/FileDownloader.php¦��’E(U¦��c‹Î¶������/���src/Composer/Downloader/FilesystemException.php��’E(U��]T½ˆ¶������)���src/Composer/Downloader/GitDownloader.phpf#��’E(Uf#��”dõ̶������*���src/Composer/Downloader/GzipDownloader.phpÈ��’E(UÈ��äßж������(���src/Composer/Downloader/HgDownloader.phpc��’E(Uc��‡‚T„¶������0���src/Composer/Downloader/PearPackageExtractor.phpa��’E(Ua��@ÔØ#¶������.���src/Composer/Downloader/PerforceDownloader.phpx��’E(Ux��<éc¶������*���src/Composer/Downloader/PharDownloader.phpå���’E(Uå���ÞÉç¶������)���src/Composer/Downloader/RarDownloader.phpß��’E(Uß��¾¼¶������)���src/Composer/Downloader/SvnDownloader.php\��’E(U\��¨Ž=¶������)���src/Composer/Downloader/TarDownloader.phpã���’E(Uã���Í’X?¶������.���src/Composer/Downloader/TransportException.php–��’E(U–��h"Br¶������)���src/Composer/Downloader/VcsDownloader.php÷��’E(U÷��«‘ßò¶������)���src/Composer/Downloader/ZipDownloader.phpC��’E(UC��]^+¶������&���src/Composer/EventDispatcher/Event.php ��’E(U ��±™jï¶������0���src/Composer/EventDispatcher/EventDispatcher.phpš��’E(Uš��W¶������9���src/Composer/EventDispatcher/EventSubscriberInterface.php©���’E(U©���h·0¶���������src/Composer/Factory.php�-��’E(U�-��ËpFà¶������.���src/Composer/Installer/InstallationManager.php@��’E(U@��›ö«¶������)���src/Composer/Installer/InstallerEvent.php��’E(U��lÔzi¶������*���src/Composer/Installer/InstallerEvents.phpÞ���’E(UÞ���ìŸ@G¶������-���src/Composer/Installer/InstallerInterface.phpÅ��’E(UÅ��HS“¡¶������+���src/Composer/Installer/LibraryInstaller.phpˆ��’E(Uˆ��
- nB†¶������/���src/Composer/Installer/MetapackageInstaller.phpœ��’E(Uœ��ÆÅ!¶������(���src/Composer/Installer/NoopInstaller.php+��’E(U+��À·M}¶������'���src/Composer/Installer/PackageEvent.php‰��’E(U‰��‘: ¶������(���src/Composer/Installer/PackageEvents.php¸��’E(U¸��dbØs¶������(���src/Composer/Installer/PearInstaller.phpV��’E(UV���zð¶������*���src/Composer/Installer/PluginInstaller.phpJ��’E(UJ��«èV¶������+���src/Composer/Installer/ProjectInstaller.php��’E(U��*0@P¶���������src/Composer/Installer.php…u��’E(U…u��$š ϶���������src/Composer/IO/BaseIO.php—��’E(U—��
- n¶���������src/Composer/IO/BufferIO.php��’E(U��hvá¶���������src/Composer/IO/ConsoleIO.php��’E(U��jd5í¶���������src/Composer/IO/IOInterface.php‡��’E(U‡��Ÿp‡y¶���������src/Composer/IO/NullIO.php³��’E(U³��~1Ķ���������src/Composer/Json/JsonFile.phpy��’E(Uy��¼èî¶������#���src/Composer/Json/JsonFormatter.php��’E(U��c–]Y¶������%���src/Composer/Json/JsonManipulator.php¡'��’E(U¡'��ìßæl¶������-���src/Composer/Json/JsonValidationException.php\��’E(U\��.Xóܶ������%���src/Composer/Package/AliasPackage.phpW��’E(UW��T/YÁ¶������7���src/Composer/Package/Archiver/ArchivableFilesFinder.php¿��’E(U¿��ŽcEl¶������0���src/Composer/Package/Archiver/ArchiveManager.php'��’E(U'��é‰ô¶������3���src/Composer/Package/Archiver/ArchiverInterface.phpï���’E(Uï���<ʸ¶������3���src/Composer/Package/Archiver/BaseExcludeFilter.php‘��’E(U‘��Mù¶������7���src/Composer/Package/Archiver/ComposerExcludeFilter.php��’E(U��‹SZ0¶������2���src/Composer/Package/Archiver/GitExcludeFilter.phpw��’E(Uw��LgU»¶������1���src/Composer/Package/Archiver/HgExcludeFilter.php��’E(U��~”¸¶������.���src/Composer/Package/Archiver/PharArchiver.php[��’E(U[��Ê5Íø¶������$���src/Composer/Package/BasePackage.phpM��’E(UM��·%þ¶������(���src/Composer/Package/CompletePackage.phpÿ��’E(Uÿ��o+ã ¶������1���src/Composer/Package/CompletePackageInterface.phpõ��’E(Uõ��¦Ê�ò¶������+���src/Composer/Package/Dumper/ArrayDumper.phpì��’E(Uì��ª–æ¶���������src/Composer/Package/Link.php*��’E(U*��_’…¶������7���src/Composer/Package/LinkConstraint/EmptyConstraint.phpê��’E(Uê���쾶������?���src/Composer/Package/LinkConstraint/LinkConstraintInterface.php��’E(U��åþ‡¢¶������7���src/Composer/Package/LinkConstraint/MultiConstraint.phpg��’E(Ug��s3¶������:���src/Composer/Package/LinkConstraint/SpecificConstraint.phpp��’E(Up��_„ˆY¶������9���src/Composer/Package/LinkConstraint/VersionConstraint.phpÉ��’E(UÉ��y?³Ø¶������+���src/Composer/Package/Loader/ArrayLoader.php��’E(U��GY Š¶������7���src/Composer/Package/Loader/InvalidPackageException.phpE��’E(UE��xb¾¶������*���src/Composer/Package/Loader/JsonLoader.phpù��’E(Uù��!~ˆ{¶������/���src/Composer/Package/Loader/LoaderInterface.php²���’E(U²���¦}úζ������1���src/Composer/Package/Loader/RootPackageLoader.phpS"��’E(US"��ð¨<¶������5���src/Composer/Package/Loader/ValidatingArrayLoader.phpÙ/��’E(UÙ/��1¯…K¶���������src/Composer/Package/Locker.phpÞ��’E(UÞ��6hж������ ���src/Composer/Package/Package.phpÄ��’E(UÄ��„ô¶������)���src/Composer/Package/PackageInterface.php_��’E(U_��戹‚¶������)���src/Composer/Package/RootAliasPackage.phpÞ��’E(UÞ��Õ>¶������$���src/Composer/Package/RootPackage.phpn��’E(Un��áACO¶������-���src/Composer/Package/RootPackageInterface.php´��’E(U´��êqKж������.���src/Composer/Package/Version/VersionParser.php.��’E(U.��/@V¶������0���src/Composer/Package/Version/VersionSelector.phpü��’E(Uü��íM¬¶������$���src/Composer/Plugin/CommandEvent.phpâ��’E(Uâ��³ÆÇW¶������$���src/Composer/Plugin/PluginEvents.php¤���’E(U¤���0ïÞX¶������'���src/Composer/Plugin/PluginInterface.phpô���’E(Uô���1‰%¶������%���src/Composer/Plugin/PluginManager.phpv��’E(Uv��šU�i¶������,���src/Composer/Plugin/PreFileDownloadEvent.php`��’E(U`���9-ζ������+���src/Composer/Repository/ArrayRepository.php��’E(U��´¯Þ/¶������.���src/Composer/Repository/ArtifactRepository.phpë
- ��’E(Uë
- ��šÏoð¶������.���src/Composer/Repository/ComposerRepository.php¤>��’E(U¤>��Þè¶������/���src/Composer/Repository/CompositeRepository.php ��’E(U ��4úE¶������0���src/Composer/Repository/FilesystemRepository.phpÀ��’E(UÀ��&xb£¶������4���src/Composer/Repository/InstalledArrayRepository.php£���’E(U£���/ö~>¶������9���src/Composer/Repository/InstalledFilesystemRepository.php£���’E(U£���V
- •_¶������8���src/Composer/Repository/InstalledRepositoryInterface.php‡���’E(U‡���£9p¶������6���src/Composer/Repository/InvalidRepositoryException.phpn���’E(Un���à“똶������-���src/Composer/Repository/PackageRepository.phpG��’E(UG��í:k¶������2���src/Composer/Repository/Pear/BaseChannelReader.php6��’E(U6��.fi!¶������,���src/Composer/Repository/Pear/ChannelInfo.phpÄ��’E(UÄ��:T*ɶ������.���src/Composer/Repository/Pear/ChannelReader.phpn��’E(Un��š8¶������4���src/Composer/Repository/Pear/ChannelRest10Reader.phpÁ ��’E(UÁ ��O€ë¶������4���src/Composer/Repository/Pear/ChannelRest11Reader.php& ��’E(U& ��òUb¶������5���src/Composer/Repository/Pear/DependencyConstraint.phpq��’E(Uq��9=¶������/���src/Composer/Repository/Pear/DependencyInfo.phpq��’E(Uq��fºTò¶������8���src/Composer/Repository/Pear/PackageDependencyParser.php%��’E(U%��j?“¶������,���src/Composer/Repository/Pear/PackageInfo.php°��’E(U°��Ÿ
¸¶������,���src/Composer/Repository/Pear/ReleaseInfo.php’��’E(U’��o“ŠÃ¶������*���src/Composer/Repository/PearRepository.php°��’E(U°��
- ,B·¶������.���src/Composer/Repository/PlatformRepository.php���’E(U���µáÇض������/���src/Composer/Repository/RepositoryInterface.phpÔ��’E(UÔ��ò�ŸÉ¶������-���src/Composer/Repository/RepositoryManager.php³��’E(U³��33¸ï¶������7���src/Composer/Repository/RepositorySecurityException.phpo���’E(Uo���pÕ«ª¶������2���src/Composer/Repository/Vcs/GitBitbucketDriver.phpì��’E(Uì��Fÿô¶������)���src/Composer/Repository/Vcs/GitDriver.php��’E(U��\îï¶������,���src/Composer/Repository/Vcs/GitHubDriver.phpr'��’E(Ur'��".j0¶������,���src/Composer/Repository/Vcs/GitLabDriver.php%��’E(U%��d¼+ò¶������1���src/Composer/Repository/Vcs/HgBitbucketDriver.phpô
��’E(Uô
��˜áWõ¶������(���src/Composer/Repository/Vcs/HgDriver.phpà��’E(Uà��ñ‘綶������.���src/Composer/Repository/Vcs/PerforceDriver.php!
- ��’E(U!
- ���€Ùk¶������)���src/Composer/Repository/Vcs/SvnDriver.php²��’E(U²��Ë W¶������)���src/Composer/Repository/Vcs/VcsDriver.phpÑ��’E(UÑ��å%R¶������2���src/Composer/Repository/Vcs/VcsDriverInterface.php‰��’E(U‰��pO㤶������)���src/Composer/Repository/VcsRepository.phpt��’E(Ut���5²Ü¶������3���src/Composer/Repository/WritableArrayRepository.php��’E(U��¾G*¶������7���src/Composer/Repository/WritableRepositoryInterface.php‰��’E(U‰��‘/sï¶������$���src/Composer/Script/CommandEvent.phpW���’E(UW���£VZt¶���������src/Composer/Script/Event.phpµ��’E(Uµ��lt¦M¶������$���src/Composer/Script/PackageEvent.phpœ���’E(Uœ���§ÿÉ
¶������$���src/Composer/Script/ScriptEvents.phpP��’E(UP���ìhQ¶������ ���src/Composer/Util/AuthHelper.phpÌ��’E(UÌ��œ¼�À¶������$���src/Composer/Util/ComposerMirror.php±��’E(U±��½øض������%���src/Composer/Util/ConfigValidator.php2��’E(U2��ö7.¶������"���src/Composer/Util/ErrorHandler.php��’E(U��´@…æ¶������ ���src/Composer/Util/Filesystem.php4&��’E(U4&��Rl—‡¶���������src/Composer/Util/Git.php“��’E(U“���-X`¶���������src/Composer/Util/GitHub.php^��’E(U^��ŒùX¶���������src/Composer/Util/GitLab.php’��’E(U’��s«3¶������$���src/Composer/Util/NoProxyPattern.php¾��’E(U¾��Z+°m¶���������src/Composer/Util/Perforce.php3��’E(U3��‚=e.¶������%���src/Composer/Util/ProcessExecutor.phpî��’E(Uî��ÔÀ¶������&���src/Composer/Util/RemoteFilesystem.phpR*��’E(UR*��ùLf¶������+���src/Composer/Util/SpdxLicenseIdentifier.php6
- ��’E(U6
- ��Ä6»o¶������*���src/Composer/Util/StreamContextFactory.phpâ��’E(Uâ��ÐB¶���������src/Composer/Util/Svn.php!��’E(U!��˜¦-[¶������%���src/Composer/Autoload/ClassLoader.php”0��’E(U”0��¸Lh¦¶���������res/composer-schema.jsonÁQ��’E(UÁQ���Œ¸Ú¶���������res/spdx-identifier.jsonD��’E(UD��*Oiò¶���������src/Composer/IO/hiddeninput.exe�$��’E(U�$��•�¥v¶������@���vendor/symfony/console/Symfony/Component/Console/Application.php¶R��’E(U¶R��”.ö(¶������D���vendor/symfony/console/Symfony/Component/Console/Command/Command.phpì��’E(Uì��·ò´¶������H���vendor/symfony/console/Symfony/Component/Console/Command/HelpCommand.php1��’E(U1��ý€”¶������H���vendor/symfony/console/Symfony/Component/Console/Command/ListCommand.php³��’E(U³��VÓé¶������B���vendor/symfony/console/Symfony/Component/Console/ConsoleEvents.phpï���’E(Uï���
ÕH¸¶������V���vendor/symfony/console/Symfony/Component/Console/Descriptor/ApplicationDescription.phpù��’E(Uù��‰>O¶������J���vendor/symfony/console/Symfony/Component/Console/Descriptor/Descriptor.php\��’E(U\��WJ[í¶������S���vendor/symfony/console/Symfony/Component/Console/Descriptor/DescriptorInterface.phpü���’E(Uü���±Qµ¶������N���vendor/symfony/console/Symfony/Component/Console/Descriptor/JsonDescriptor.php2
��’E(U2
��†ca¶������R���vendor/symfony/console/Symfony/Component/Console/Descriptor/MarkdownDescriptor.php
- ��’E(U
- ���LÛ*¶������N���vendor/symfony/console/Symfony/Component/Console/Descriptor/TextDescriptor.php6��’E(U6��zo¡¶������M���vendor/symfony/console/Symfony/Component/Console/Descriptor/XmlDescriptor.php ��’E(U ��…{îm¶������N���vendor/symfony/console/Symfony/Component/Console/Event/ConsoleCommandEvent.php²��’E(U²��Zk‰2¶������G���vendor/symfony/console/Symfony/Component/Console/Event/ConsoleEvent.phpÅ��’E(UÅ��ÒxÛ\¶������P���vendor/symfony/console/Symfony/Component/Console/Event/ConsoleExceptionEvent.php��’E(U��á2é¶������P���vendor/symfony/console/Symfony/Component/Console/Event/ConsoleTerminateEvent.phpz��’E(Uz��³,îL¶������N���vendor/symfony/console/Symfony/Component/Console/Formatter/OutputFormatter.phpˆ��’E(Uˆ��+ÂF5¶������W���vendor/symfony/console/Symfony/Component/Console/Formatter/OutputFormatterInterface.php˜��’E(U˜��3l~´¶������S���vendor/symfony/console/Symfony/Component/Console/Formatter/OutputFormatterStyle.phpÄ��’E(UÄ��Xy¶������\���vendor/symfony/console/Symfony/Component/Console/Formatter/OutputFormatterStyleInterface.phpŽ��’E(UŽ��öëÄ=¶������X���vendor/symfony/console/Symfony/Component/Console/Formatter/OutputFormatterStyleStack.php��’E(U��yI'¶������P���vendor/symfony/console/Symfony/Component/Console/Helper/DebugFormatterHelper.phpm��’E(Um��ò¯s>¶������L���vendor/symfony/console/Symfony/Component/Console/Helper/DescriptorHelper.php9��’E(U9��ûùäð¶������H���vendor/symfony/console/Symfony/Component/Console/Helper/DialogHelper.phpÊ��’E(UÊ��lÕHl¶������K���vendor/symfony/console/Symfony/Component/Console/Helper/FormatterHelper.php��’E(U��žI‚�¶������B���vendor/symfony/console/Symfony/Component/Console/Helper/Helper.phpß��’E(Uß��o¾ã¶������K���vendor/symfony/console/Symfony/Component/Console/Helper/HelperInterface.phpï���’E(Uï���=e¶������E���vendor/symfony/console/Symfony/Component/Console/Helper/HelperSet.php/��’E(U/��âw�d¶������L���vendor/symfony/console/Symfony/Component/Console/Helper/InputAwareHelper.phpc��’E(Uc��ñø�|¶������I���vendor/symfony/console/Symfony/Component/Console/Helper/ProcessHelper.phpâ��’E(Uâ��|̼¶������G���vendor/symfony/console/Symfony/Component/Console/Helper/ProgressBar.php$��’E(U$��2Œ5J¶������J���vendor/symfony/console/Symfony/Component/Console/Helper/ProgressHelper.phpƒ��’E(Uƒ��êëä¶������J���vendor/symfony/console/Symfony/Component/Console/Helper/QuestionHelper.php��’E(U��RŠ¶������A���vendor/symfony/console/Symfony/Component/Console/Helper/Table.php��’E(U��?{êǶ������G���vendor/symfony/console/Symfony/Component/Console/Helper/TableHelper.phpØ
- ��’E(UØ
- ��,
¶������J���vendor/symfony/console/Symfony/Component/Console/Helper/TableSeparator.php[���’E(U[���LV¡¶������F���vendor/symfony/console/Symfony/Component/Console/Helper/TableStyle.phpÕ��’E(UÕ��æ"ðù¶������D���vendor/symfony/console/Symfony/Component/Console/Input/ArgvInput.phpÙ��’E(UÙ��ËkE¶������E���vendor/symfony/console/Symfony/Component/Console/Input/ArrayInput.phpõ ��’E(Uõ ��É×�™¶������@���vendor/symfony/console/Symfony/Component/Console/Input/Input.php
- ��’E(U
- ��ÇýT¶������H���vendor/symfony/console/Symfony/Component/Console/Input/InputArgument.phpž��’E(Už��K]ìi¶������N���vendor/symfony/console/Symfony/Component/Console/Input/InputAwareInterface.phpš���’E(Uš���‡jTŸ¶������J���vendor/symfony/console/Symfony/Component/Console/Input/InputDefinition.php��’E(U��˜£JM¶������I���vendor/symfony/console/Symfony/Component/Console/Input/InputInterface.php ��’E(U ��9”øǶ������F���vendor/symfony/console/Symfony/Component/Console/Input/InputOption.php«��’E(U«��ꆮ½¶������F���vendor/symfony/console/Symfony/Component/Console/Input/StringInput.php‹��’E(U‹��†uný¶������8���vendor/symfony/console/Symfony/Component/Console/LICENSE)��’E(U)��ë&•¶������I���vendor/symfony/console/Symfony/Component/Console/Logger/ConsoleLogger.php; ��’E(U; ��#ØB~¶������J���vendor/symfony/console/Symfony/Component/Console/Output/BufferedOutput.php_��’E(U_��ûBÍ·¶������I���vendor/symfony/console/Symfony/Component/Console/Output/ConsoleOutput.php��’E(U��j嬶������R���vendor/symfony/console/Symfony/Component/Console/Output/ConsoleOutputInterface.phpå���’E(Uå���rNô�¶������F���vendor/symfony/console/Symfony/Component/Console/Output/NullOutput.php¿��’E(U¿��`5E˶������B���vendor/symfony/console/Symfony/Component/Console/Output/Output.php§��’E(U§��Ú _¶������K���vendor/symfony/console/Symfony/Component/Console/Output/OutputInterface.phpI��’E(UI��ÈâãB¶������H���vendor/symfony/console/Symfony/Component/Console/Output/StreamOutput.php¢��’E(U¢��ü0¶������L���vendor/symfony/console/Symfony/Component/Console/Question/ChoiceQuestion.phpf��’E(Uf��Ôh¶������R���vendor/symfony/console/Symfony/Component/Console/Question/ConfirmationQuestion.phpK��’E(UK��õÃTȶ������F���vendor/symfony/console/Symfony/Component/Console/Question/Question.php®��’E(U®��.e8Ö¶������:���vendor/symfony/console/Symfony/Component/Console/Shell.php.��’E(U.��þÉŽ‡¶������M���vendor/symfony/console/Symfony/Component/Console/Tester/ApplicationTester.phpÔ��’E(UÔ��¬ì¤d¶������I���vendor/symfony/console/Symfony/Component/Console/Tester/CommandTester.php���’E(U���H»â`¶������J���vendor/symfony/finder/Symfony/Component/Finder/Adapter/AbstractAdapter.php¤
- ��’E(U¤
- ��¢)z9¶������N���vendor/symfony/finder/Symfony/Component/Finder/Adapter/AbstractFindAdapter.phpÛ��’E(UÛ��SõT´¶������K���vendor/symfony/finder/Symfony/Component/Finder/Adapter/AdapterInterface.php¯��’E(U¯��‹éȶ������I���vendor/symfony/finder/Symfony/Component/Finder/Adapter/BsdFindAdapter.php{��’E(U{��Q,D2¶������I���vendor/symfony/finder/Symfony/Component/Finder/Adapter/GnuFindAdapter.php^��’E(U^��ßz˜r¶������E���vendor/symfony/finder/Symfony/Component/Finder/Adapter/PhpAdapter.php+��’E(U+��&˜îÒ¶������H���vendor/symfony/finder/Symfony/Component/Finder/Comparator/Comparator.phpŒ��’E(UŒ��wþT¶������L���vendor/symfony/finder/Symfony/Component/Finder/Comparator/DateComparator.php%��’E(U%��L¿EǶ������N���vendor/symfony/finder/Symfony/Component/Finder/Comparator/NumberComparator.phpx��’E(Ux��½™5¶������R���vendor/symfony/finder/Symfony/Component/Finder/Exception/AccessDeniedException.php„���’E(U„���½¾sœ¶������T���vendor/symfony/finder/Symfony/Component/Finder/Exception/AdapterFailureException.php��’E(U��mŒ_,¶������O���vendor/symfony/finder/Symfony/Component/Finder/Exception/ExceptionInterface.php„���’E(U„���Gz-¶������Z���vendor/symfony/finder/Symfony/Component/Finder/Exception/OperationNotPermitedException.phpŠ���’E(UŠ���U88¶������Y���vendor/symfony/finder/Symfony/Component/Finder/Exception/ShellCommandFailureException.php$��’E(U$��C”sÓ¶������H���vendor/symfony/finder/Symfony/Component/Finder/Expression/Expression.php}��’E(U}��/·cð¶������B���vendor/symfony/finder/Symfony/Component/Finder/Expression/Glob.php¡��’E(U¡�� V¿¶������C���vendor/symfony/finder/Symfony/Component/Finder/Expression/Regex.php���’E(U���S7Pæ¶������L���vendor/symfony/finder/Symfony/Component/Finder/Expression/ValueInterface.php;��’E(U;��îãÓ¶������9���vendor/symfony/finder/Symfony/Component/Finder/Finder.php6#��’E(U6#��ÕÔG¶������7���vendor/symfony/finder/Symfony/Component/Finder/Glob.php
��’E(U
��z�ø
- ¶������P���vendor/symfony/finder/Symfony/Component/Finder/Iterator/CustomFilterIterator.php]��’E(U]��tà±µ¶������S���vendor/symfony/finder/Symfony/Component/Finder/Iterator/DateRangeFilterIterator.phpz��’E(Uz��}¢¶������T���vendor/symfony/finder/Symfony/Component/Finder/Iterator/DepthRangeFilterIterator.phpð��’E(Uð��ß0™¶������Z���vendor/symfony/finder/Symfony/Component/Finder/Iterator/ExcludeDirectoryFilterIterator.php”��’E(U”��"ÖóÁ¶������U���vendor/symfony/finder/Symfony/Component/Finder/Iterator/FilecontentFilterIterator.php#��’E(U#��Ú_VǶ������R���vendor/symfony/finder/Symfony/Component/Finder/Iterator/FilenameFilterIterator.php‡��’E(U‡��F ’¶������M���vendor/symfony/finder/Symfony/Component/Finder/Iterator/FilePathsIterator.php���’E(U���ýòäQ¶������R���vendor/symfony/finder/Symfony/Component/Finder/Iterator/FileTypeFilterIterator.php\��’E(U\��p‘'˜¶������J���vendor/symfony/finder/Symfony/Component/Finder/Iterator/FilterIterator.php†��’E(U†��0£¾Ô¶������V���vendor/symfony/finder/Symfony/Component/Finder/Iterator/MultiplePcreFilterIterator.phpØ��’E(UØ��Òù“¶������N���vendor/symfony/finder/Symfony/Component/Finder/Iterator/PathFilterIterator.php¸��’E(U¸��E*E¶������V���vendor/symfony/finder/Symfony/Component/Finder/Iterator/RecursiveDirectoryIterator.phpY��’E(UY��êÓÊܶ������S���vendor/symfony/finder/Symfony/Component/Finder/Iterator/SizeRangeFilterIterator.phpg��’E(Ug��!Ô—é¶������L���vendor/symfony/finder/Symfony/Component/Finder/Iterator/SortableIterator.phpÞ��’E(UÞ��ö³%¶������6���vendor/symfony/finder/Symfony/Component/Finder/LICENSE)��’E(U)��ë&•¶������@���vendor/symfony/finder/Symfony/Component/Finder/Shell/Command.php£
- ��’E(U£
- ��Ö<ÊT¶������>���vendor/symfony/finder/Symfony/Component/Finder/Shell/Shell.phpé��’E(Ué��¿ëÛ•¶������>���vendor/symfony/finder/Symfony/Component/Finder/SplFileInfo.phpû��’E(Uû��‘†6¶������Q���vendor/symfony/process/Symfony/Component/Process/Exception/ExceptionInterface.phpf���’E(Uf���]ö>T¶������W���vendor/symfony/process/Symfony/Component/Process/Exception/InvalidArgumentException.php¨���’E(U¨���ÐÀ+_¶������M���vendor/symfony/process/Symfony/Component/Process/Exception/LogicException.php”���’E(U”��� ³ãñ¶������U���vendor/symfony/process/Symfony/Component/Process/Exception/ProcessFailedException.php<��’E(U<��"wÛn¶������W���vendor/symfony/process/Symfony/Component/Process/Exception/ProcessTimedOutException.php��’E(U��. Ãá¶������O���vendor/symfony/process/Symfony/Component/Process/Exception/RuntimeException.php˜���’E(U˜���¢Ø:¶������E���vendor/symfony/process/Symfony/Component/Process/ExecutableFinder.php~��’E(U~��+…¶������8���vendor/symfony/process/Symfony/Component/Process/LICENSE)��’E(U)��ë&•¶������H���vendor/symfony/process/Symfony/Component/Process/PhpExecutableFinder.php��’E(U��ûÔM>¶������?���vendor/symfony/process/Symfony/Component/Process/PhpProcess.php��’E(U��8ZÔ·¶������H���vendor/symfony/process/Symfony/Component/Process/Pipes/AbstractPipes.php���’E(U���˜|¥¾¶������I���vendor/symfony/process/Symfony/Component/Process/Pipes/PipesInterface.phpD��’E(UD��vØ������D���vendor/symfony/process/Symfony/Component/Process/Pipes/UnixPipes.php¤��’E(U¤��øUt¶������G���vendor/symfony/process/Symfony/Component/Process/Pipes/WindowsPipes.php½��’E(U½���.X£¶������<���vendor/symfony/process/Symfony/Component/Process/Process.phpJN��’E(UJN��¹§´¶������C���vendor/symfony/process/Symfony/Component/Process/ProcessBuilder.php��’E(U��„8<²¶������A���vendor/symfony/process/Symfony/Component/Process/ProcessUtils.phpŒ��’E(UŒ��ÈbÝv¶������5���vendor/symfony/yaml/Symfony/Component/Yaml/Dumper.php ��’E(U ���ÿǶ������6���vendor/symfony/yaml/Symfony/Component/Yaml/Escaper.phpR��’E(UR��Ñlö6¶������F���vendor/symfony/yaml/Symfony/Component/Yaml/Exception/DumpException.phpu���’E(Uu���e*n¶������K���vendor/symfony/yaml/Symfony/Component/Yaml/Exception/ExceptionInterface.phpe���’E(Ue���Îcº¶������G���vendor/symfony/yaml/Symfony/Component/Yaml/Exception/ParseException.phpŸ��’E(UŸ��PˆA=¶������I���vendor/symfony/yaml/Symfony/Component/Yaml/Exception/RuntimeException.php—���’E(U—���‡õ�¶������5���vendor/symfony/yaml/Symfony/Component/Yaml/Inline.phpå&��’E(Uå&��i*{f¶������2���vendor/symfony/yaml/Symfony/Component/Yaml/LICENSE)��’E(U)��ë&•¶������5���vendor/symfony/yaml/Symfony/Component/Yaml/Parser.phpk7��’E(Uk7��æ̶������8���vendor/symfony/yaml/Symfony/Component/Yaml/Unescaper.phpž��’E(Už���:ø'¶������3���vendor/symfony/yaml/Symfony/Component/Yaml/Yaml.phpË��’E(UË��äó¶���������vendor/seld/jsonlint/LICENSE"��’E(U"��aƒsy¶������5���vendor/seld/jsonlint/src/Seld/JsonLint/JsonParser.php)1��’E(U)1��?5R3¶������0���vendor/seld/jsonlint/src/Seld/JsonLint/Lexer.php��’E(U��‰„m!¶������;���vendor/seld/jsonlint/src/Seld/JsonLint/ParsingException.php��’E(U��‰²ñ¶������4���vendor/seld/jsonlint/src/Seld/JsonLint/Undefined.php>���’E(U>���ÿqŸŸ¶������(���vendor/justinrainbow/json-schema/LICENSE÷��’E(U÷��xÞxt¶������J���vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/Collection.phpý��’E(Uý��Ç;ÿ¶������J���vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/Constraint.php9��’E(U9��éð°#¶������S���vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/ConstraintInterface.phpN��’E(UN��øÆMy¶������D���vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/Enum.phpè��’E(Uè��êvĶ������F���vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/Format.phpí
��’E(Uí
��á”
¶������F���vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/Number.php«��’E(U«��›çI)¶������F���vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/Object.php¾
- ��’E(U¾
- ��|Ò\F¶������F���vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/Schema.php��’E(U��]ÜÙ¶������F���vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/String.phpŸ��’E(UŸ���ˆpå¶������D���vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/Type.phph��’E(Uh��õd϶������I���vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/Undefined.phpl��’E(Ul��ƒ
Ή¶������V���vendor/justinrainbow/json-schema/src/JsonSchema/Exception/InvalidArgumentException.phpv���’E(Uv���¬ «"¶������]���vendor/justinrainbow/json-schema/src/JsonSchema/Exception/InvalidSchemaMediaTypeException.phpv���’E(Uv���ŠCÓ¶������W���vendor/justinrainbow/json-schema/src/JsonSchema/Exception/InvalidSourceUriException.phpw���’E(Uw���N-ò[¶������S���vendor/justinrainbow/json-schema/src/JsonSchema/Exception/JsonDecodingException.phpÞ��’E(UÞ��†¾©‘¶������W���vendor/justinrainbow/json-schema/src/JsonSchema/Exception/ResourceNotFoundException.phpo���’E(Uo���Æ$"Ŷ������R���vendor/justinrainbow/json-schema/src/JsonSchema/Exception/UriResolverException.phpj���’E(Uj���SÓdz¶������?���vendor/justinrainbow/json-schema/src/JsonSchema/RefResolver.php|
- ��’E(U|
- ��™&
i¶������T���vendor/justinrainbow/json-schema/src/JsonSchema/Uri/Retrievers/AbstractRetriever.phpÜ���’E(UÜ���]j¶������G���vendor/justinrainbow/json-schema/src/JsonSchema/Uri/Retrievers/Curl.phpt��’E(Ut��I·ý�¶������R���vendor/justinrainbow/json-schema/src/JsonSchema/Uri/Retrievers/FileGetContents.phpÑ��’E(UÑ��懨¶������R���vendor/justinrainbow/json-schema/src/JsonSchema/Uri/Retrievers/PredefinedArray.php^��’E(U^��"ß6o¶������X���vendor/justinrainbow/json-schema/src/JsonSchema/Uri/Retrievers/UriRetrieverInterface.php©���’E(U©���CO¶������C���vendor/justinrainbow/json-schema/src/JsonSchema/Uri/UriResolver.php® ��’E(U® ��àP¾¡¶������D���vendor/justinrainbow/json-schema/src/JsonSchema/Uri/UriRetriever.php–��’E(U–��ªÿ¨Ü¶������=���vendor/justinrainbow/json-schema/src/JsonSchema/Validator.phps��’E(Us��ô„=¶���������vendor/autoload.php‘���’E(U‘���ð.â¶������'���vendor/composer/autoload_namespaces.php��’E(U��T Ùö¶������!���vendor/composer/autoload_psr4.php²���’E(U²���Ô�¨Ð¶������%���vendor/composer/autoload_classmap.php#¢��’E(U#¢��°l¤è¶������!���vendor/composer/autoload_real.phpþ��’E(Uþ��”®9¶������!���vendor/composer/include_paths.phpÝ���’E(UÝ���™Ÿ³¶���������vendor/composer/ClassLoader.phpB��’E(UB��é”í¶���������bin/composern��’E(Un��–…W¶���������LICENSE3��’E(U3���2¶������<?php
- function includeIfExists($file)
- {
- return file_exists($file) ? include $file : false;
- }
- if ((!$loader = includeIfExists(__DIR__.'/../vendor/autoload.php')) && (!$loader = includeIfExists(__DIR__.'/../../../autoload.php'))) {
- echo 'You must set up the project dependencies, run the following commands:'.PHP_EOL.
- 'curl -sS https://getcomposer.org/installer | php'.PHP_EOL.
- 'php composer.phar install'.PHP_EOL;
- exit(1);
- }
- return $loader;
- <?php
- namespace Composer\Autoload;
- use Composer\Config;
- use Composer\EventDispatcher\EventDispatcher;
- use Composer\Installer\InstallationManager;
- use Composer\IO\IOInterface;
- use Composer\Package\AliasPackage;
- use Composer\Package\PackageInterface;
- use Composer\Repository\InstalledRepositoryInterface;
- use Composer\Util\Filesystem;
- use Composer\Script\ScriptEvents;
- class AutoloadGenerator
- {
- private $eventDispatcher;
- private $io;
- private $devMode = false;
- public function __construct(EventDispatcher $eventDispatcher, IOInterface $io = null)
- {
- $this->eventDispatcher = $eventDispatcher;
- $this->io = $io;
- }
- public function setDevMode($devMode = true)
- {
- $this->devMode = (boolean) $devMode;
- }
- public function dump(Config $config, InstalledRepositoryInterface $localRepo, PackageInterface $mainPackage, InstallationManager $installationManager, $targetDir, $scanPsr0Packages = false, $suffix = '')
- {
- $this->eventDispatcher->dispatchScript(ScriptEvents::PRE_AUTOLOAD_DUMP, $this->devMode, array(), array(
- 'optimize' => (bool) $scanPsr0Packages,
- ));
- $filesystem = new Filesystem();
- $filesystem->ensureDirectoryExists($config->get('vendor-dir'));
- $basePath = $filesystem->normalizePath(realpath(getcwd()));
- $vendorPath = $filesystem->normalizePath(realpath($config->get('vendor-dir')));
- $useGlobalIncludePath = (bool) $config->get('use-include-path');
- $prependAutoloader = $config->get('prepend-autoloader') === false ? 'false' : 'true';
- $classMapAuthoritative = $config->get('classmap-authoritative');
- $targetDir = $vendorPath.'/'.$targetDir;
- $filesystem->ensureDirectoryExists($targetDir);
- $vendorPathCode = $filesystem->findShortestPathCode(realpath($targetDir), $vendorPath, true);
- $vendorPathCode52 = str_replace('__DIR__', 'dirname(__FILE__)', $vendorPathCode);
- $vendorPathToTargetDirCode = $filesystem->findShortestPathCode($vendorPath, realpath($targetDir), true);
- $appBaseDirCode = $filesystem->findShortestPathCode($vendorPath, $basePath, true);
- $appBaseDirCode = str_replace('__DIR__', '$vendorDir', $appBaseDirCode);
- $namespacesFile = <<<EOF
- <?php
- // autoload_namespaces.php @generated by Composer
- \$vendorDir = $vendorPathCode52;
- \$baseDir = $appBaseDirCode;
- return array(
- EOF;
- $psr4File = <<<EOF
- <?php
- // autoload_psr4.php @generated by Composer
- \$vendorDir = $vendorPathCode52;
- \$baseDir = $appBaseDirCode;
- return array(
- EOF;
- $packageMap = $this->buildPackageMap($installationManager, $mainPackage, $localRepo->getCanonicalPackages());
- $autoloads = $this->parseAutoloads($packageMap, $mainPackage);
- foreach ($autoloads['psr-0'] as $namespace => $paths) {
- $exportedPaths = array();
- foreach ($paths as $path) {
- $exportedPaths[] = $this->getPathCode($filesystem, $basePath, $vendorPath, $path);
- }
- $exportedPrefix = var_export($namespace, true);
- $namespacesFile .= " $exportedPrefix => ";
- $namespacesFile .= "array(".implode(', ', $exportedPaths)."),\n";
- }
- $namespacesFile .= ");\n";
- foreach ($autoloads['psr-4'] as $namespace => $paths) {
- $exportedPaths = array();
- foreach ($paths as $path) {
- $exportedPaths[] = $this->getPathCode($filesystem, $basePath, $vendorPath, $path);
- }
- $exportedPrefix = var_export($namespace, true);
- $psr4File .= " $exportedPrefix => ";
- $psr4File .= "array(".implode(', ', $exportedPaths)."),\n";
- }
- $psr4File .= ");\n";
- $classmapFile = <<<EOF
- <?php
- // autoload_classmap.php @generated by Composer
- \$vendorDir = $vendorPathCode52;
- \$baseDir = $appBaseDirCode;
- return array(
- EOF;
- $targetDirLoader = null;
- $mainAutoload = $mainPackage->getAutoload();
- if ($mainPackage->getTargetDir() && !empty($mainAutoload['psr-0'])) {
- $levels = count(explode('/', $filesystem->normalizePath($mainPackage->getTargetDir())));
- $prefixes = implode(', ', array_map(function ($prefix) {
- return var_export($prefix, true);
- }, array_keys($mainAutoload['psr-0'])));
- $baseDirFromTargetDirCode = $filesystem->findShortestPathCode($targetDir, $basePath, true);
- $targetDirLoader = <<<EOF
- public static function autoload(\$class)
- {
- \$dir = $baseDirFromTargetDirCode . '/';
- \$prefixes = array($prefixes);
- foreach (\$prefixes as \$prefix) {
- if (0 !== strpos(\$class, \$prefix)) {
- continue;
- }
- \$path = \$dir . implode('/', array_slice(explode('\\\\', \$class), $levels)).'.php';
- if (!\$path = stream_resolve_include_path(\$path)) {
- return false;
- }
- require \$path;
- return true;
- }
- }
- EOF;
- }
- $classMap = array();
- if ($scanPsr0Packages) {
- foreach (array('psr-0', 'psr-4') as $psrType) {
- foreach ($autoloads[$psrType] as $namespace => $paths) {
- foreach ($paths as $dir) {
- $dir = $filesystem->normalizePath($filesystem->isAbsolutePath($dir) ? $dir : $basePath.'/'.$dir);
- if (!is_dir($dir)) {
- continue;
- }
- $whitelist = sprintf(
- '{%s/%s.+(?<!(?<!/)Test\.php)$}',
- preg_quote($dir),
- ($psrType === 'psr-0' && strpos($namespace, '_') === false) ? preg_quote(strtr($namespace, '\\', '/')) : ''
- );
- $namespaceFilter = $namespace === '' ? null : $namespace;
- foreach (ClassMapGenerator::createMap($dir, $whitelist, $this->io, $namespaceFilter) as $class => $path) {
- if (!isset($classMap[$class])) {
- $path = $this->getPathCode($filesystem, $basePath, $vendorPath, $path);
- $classMap[$class] = $path.",\n";
- }
- }
- }
- }
- }
- }
- foreach ($autoloads['classmap'] as $dir) {
- foreach (ClassMapGenerator::createMap($dir, null, $this->io) as $class => $path) {
- $path = $this->getPathCode($filesystem, $basePath, $vendorPath, $path);
- $classMap[$class] = $path.",\n";
- }
- }
- ksort($classMap);
- foreach ($classMap as $class => $code) {
- $classmapFile .= ' '.var_export($class, true).' => '.$code;
- }
- $classmapFile .= ");\n";
- if (!$suffix) {
- $suffix = $config->get('autoloader-suffix') ?: md5(uniqid('', true));
- }
- file_put_contents($targetDir.'/autoload_namespaces.php', $namespacesFile);
- file_put_contents($targetDir.'/autoload_psr4.php', $psr4File);
- file_put_contents($targetDir.'/autoload_classmap.php', $classmapFile);
- if ($includePathFile = $this->getIncludePathsFile($packageMap, $filesystem, $basePath, $vendorPath, $vendorPathCode52, $appBaseDirCode)) {
- file_put_contents($targetDir.'/include_paths.php', $includePathFile);
- }
- if ($includeFilesFile = $this->getIncludeFilesFile($autoloads['files'], $filesystem, $basePath, $vendorPath, $vendorPathCode52, $appBaseDirCode)) {
- file_put_contents($targetDir.'/autoload_files.php', $includeFilesFile);
- }
- file_put_contents($vendorPath.'/autoload.php', $this->getAutoloadFile($vendorPathToTargetDirCode, $suffix));
- file_put_contents($targetDir.'/autoload_real.php', $this->getAutoloadRealFile(true, (bool) $includePathFile, $targetDirLoader, (bool) $includeFilesFile, $vendorPathCode, $appBaseDirCode, $suffix, $useGlobalIncludePath, $prependAutoloader, $classMapAuthoritative));
-
- $sourceLoader = fopen(__DIR__.'/ClassLoader.php', 'r');
- $targetLoader = fopen($targetDir.'/ClassLoader.php', 'w+');
- stream_copy_to_stream($sourceLoader, $targetLoader);
- fclose($sourceLoader);
- fclose($targetLoader);
- unset($sourceLoader, $targetLoader);
- $this->eventDispatcher->dispatchScript(ScriptEvents::POST_AUTOLOAD_DUMP, $this->devMode, array(), array(
- 'optimize' => (bool) $scanPsr0Packages,
- ));
- }
- public function buildPackageMap(InstallationManager $installationManager, PackageInterface $mainPackage, array $packages)
- {
- $packageMap = array(array($mainPackage, ''));
- foreach ($packages as $package) {
- if ($package instanceof AliasPackage) {
- continue;
- }
- $this->validatePackage($package);
- $packageMap[] = array(
- $package,
- $installationManager->getInstallPath($package),
- );
- }
- return $packageMap;
- }
- protected function validatePackage(PackageInterface $package)
- {
- $autoload = $package->getAutoload();
- if (!empty($autoload['psr-4']) && null !== $package->getTargetDir()) {
- $name = $package->getName();
- $package->getTargetDir();
- throw new \InvalidArgumentException("PSR-4 autoloading is incompatible with the target-dir property, remove the target-dir in package '$name'.");
- }
- if (!empty($autoload['psr-4'])) {
- foreach ($autoload['psr-4'] as $namespace => $dirs) {
- if ($namespace !== '' && '\\' !== substr($namespace, -1)) {
- throw new \InvalidArgumentException("psr-4 namespaces must end with a namespace separator, '$namespace' does not, use '$namespace\\'.");
- }
- }
- }
- }
- public function parseAutoloads(array $packageMap, PackageInterface $mainPackage)
- {
- $mainPackageMap = array_shift($packageMap);
- $sortedPackageMap = $this->sortPackageMap($packageMap);
- $sortedPackageMap[] = $mainPackageMap;
- array_unshift($packageMap, $mainPackageMap);
- $psr0 = $this->parseAutoloadsType($packageMap, 'psr-0', $mainPackage);
- $psr4 = $this->parseAutoloadsType($packageMap, 'psr-4', $mainPackage);
- $classmap = $this->parseAutoloadsType($sortedPackageMap, 'classmap', $mainPackage);
- $files = $this->parseAutoloadsType($sortedPackageMap, 'files', $mainPackage);
- krsort($psr0);
- krsort($psr4);
- return array('psr-0' => $psr0, 'psr-4' => $psr4, 'classmap' => $classmap, 'files' => $files);
- }
- public function createLoader(array $autoloads)
- {
- $loader = new ClassLoader();
- if (isset($autoloads['psr-0'])) {
- foreach ($autoloads['psr-0'] as $namespace => $path) {
- $loader->add($namespace, $path);
- }
- }
- if (isset($autoloads['psr-4'])) {
- foreach ($autoloads['psr-4'] as $namespace => $path) {
- $loader->addPsr4($namespace, $path);
- }
- }
- return $loader;
- }
- protected function getIncludePathsFile(array $packageMap, Filesystem $filesystem, $basePath, $vendorPath, $vendorPathCode, $appBaseDirCode)
- {
- $includePaths = array();
- foreach ($packageMap as $item) {
- list($package, $installPath) = $item;
- if (null !== $package->getTargetDir() && strlen($package->getTargetDir()) > 0) {
- $installPath = substr($installPath, 0, -strlen('/'.$package->getTargetDir()));
- }
- foreach ($package->getIncludePaths() as $includePath) {
- $includePath = trim($includePath, '/');
- $includePaths[] = empty($installPath) ? $includePath : $installPath.'/'.$includePath;
- }
- }
- if (!$includePaths) {
- return;
- }
- $includePathsCode = '';
- foreach ($includePaths as $path) {
- $includePathsCode .= " " . $this->getPathCode($filesystem, $basePath, $vendorPath, $path) . ",\n";
- }
- return <<<EOF
- <?php
- // include_paths.php @generated by Composer
- \$vendorDir = $vendorPathCode;
- \$baseDir = $appBaseDirCode;
- return array(
- $includePathsCode);
- EOF;
- }
- protected function getIncludeFilesFile(array $files, Filesystem $filesystem, $basePath, $vendorPath, $vendorPathCode, $appBaseDirCode)
- {
- $filesCode = '';
- foreach ($files as $functionFile) {
- $filesCode .= ' '.$this->getPathCode($filesystem, $basePath, $vendorPath, $functionFile).",\n";
- }
- if (!$filesCode) {
- return false;
- }
- return <<<EOF
- <?php
- // autoload_files.php @generated by Composer
- \$vendorDir = $vendorPathCode;
- \$baseDir = $appBaseDirCode;
- return array(
- $filesCode);
- EOF;
- }
- protected function getPathCode(Filesystem $filesystem, $basePath, $vendorPath, $path)
- {
- if (!$filesystem->isAbsolutePath($path)) {
- $path = $basePath . '/' . $path;
- }
- $path = $filesystem->normalizePath($path);
- $baseDir = '';
- if (strpos($path.'/', $vendorPath.'/') === 0) {
- $path = substr($path, strlen($vendorPath));
- $baseDir = '$vendorDir';
- if ($path !== false) {
- $baseDir .= " . ";
- }
- } else {
- $path = $filesystem->normalizePath($filesystem->findShortestPath($basePath, $path, true));
- if (!$filesystem->isAbsolutePath($path)) {
- $baseDir = '$baseDir . ';
- $path = '/' . $path;
- }
- }
- if (preg_match('/\.phar$/', $path)) {
- $baseDir = "'phar://' . " . $baseDir;
- }
- return $baseDir . (($path !== false) ? var_export($path, true) : "");
- }
- protected function getAutoloadFile($vendorPathToTargetDirCode, $suffix)
- {
- return <<<AUTOLOAD
- <?php
- // autoload.php @generated by Composer
- require_once $vendorPathToTargetDirCode . '/autoload_real.php';
- return ComposerAutoloaderInit$suffix::getLoader();
- AUTOLOAD;
- }
- protected function getAutoloadRealFile($useClassMap, $useIncludePath, $targetDirLoader, $useIncludeFiles, $vendorPathCode, $appBaseDirCode, $suffix, $useGlobalIncludePath, $prependAutoloader, $classMapAuthoritative)
- {
-
-
-
-
-
- $file = <<<HEADER
- <?php
- // autoload_real.php @generated by Composer
- class ComposerAutoloaderInit$suffix
- {
- private static \$loader;
- public static function loadClassLoader(\$class)
- {
- if ('Composer\\Autoload\\ClassLoader' === \$class) {
- require __DIR__ . '/ClassLoader.php';
- }
- }
- public static function getLoader()
- {
- if (null !== self::\$loader) {
- return self::\$loader;
- }
- spl_autoload_register(array('ComposerAutoloaderInit$suffix', 'loadClassLoader'), true, $prependAutoloader);
- self::\$loader = \$loader = new \\Composer\\Autoload\\ClassLoader();
- spl_autoload_unregister(array('ComposerAutoloaderInit$suffix', 'loadClassLoader'));
- HEADER;
- if ($useIncludePath) {
- $file .= <<<'INCLUDE_PATH'
- $includePaths = require __DIR__ . '/include_paths.php';
- array_push($includePaths, get_include_path());
- set_include_path(join(PATH_SEPARATOR, $includePaths));
- INCLUDE_PATH;
- }
- $file .= <<<'PSR0'
- $map = require __DIR__ . '/autoload_namespaces.php';
- foreach ($map as $namespace => $path) {
- $loader->set($namespace, $path);
- }
- PSR0;
- $file .= <<<'PSR4'
- $map = require __DIR__ . '/autoload_psr4.php';
- foreach ($map as $namespace => $path) {
- $loader->setPsr4($namespace, $path);
- }
- PSR4;
- if ($useClassMap) {
- $file .= <<<'CLASSMAP'
- $classMap = require __DIR__ . '/autoload_classmap.php';
- if ($classMap) {
- $loader->addClassMap($classMap);
- }
- CLASSMAP;
- }
- if ($classMapAuthoritative) {
- $file .= <<<'CLASSMAPAUTHORITATIVE'
- $loader->setClassMapAuthoritative(true);
- CLASSMAPAUTHORITATIVE;
- }
- if ($useGlobalIncludePath) {
- $file .= <<<'INCLUDEPATH'
- $loader->setUseIncludePath(true);
- INCLUDEPATH;
- }
- if ($targetDirLoader) {
- $file .= <<<REGISTER_AUTOLOAD
- spl_autoload_register(array('ComposerAutoloaderInit$suffix', 'autoload'), true, true);
- REGISTER_AUTOLOAD;
- }
- $file .= <<<REGISTER_LOADER
- \$loader->register($prependAutoloader);
- REGISTER_LOADER;
- if ($useIncludeFiles) {
- $file .= <<<INCLUDE_FILES
- \$includeFiles = require __DIR__ . '/autoload_files.php';
- foreach (\$includeFiles as \$file) {
- composerRequire$suffix(\$file);
- }
- INCLUDE_FILES;
- }
- $file .= <<<METHOD_FOOTER
- return \$loader;
- }
- METHOD_FOOTER;
- $file .= $targetDirLoader;
- return $file . <<<FOOTER
- }
- function composerRequire$suffix(\$file)
- {
- require \$file;
- }
- FOOTER;
- }
- protected function parseAutoloadsType(array $packageMap, $type, PackageInterface $mainPackage)
- {
- $autoloads = array();
- foreach ($packageMap as $item) {
- list($package, $installPath) = $item;
- $autoload = $package->getAutoload();
- if ($this->devMode && $package === $mainPackage) {
- $autoload = array_merge_recursive($autoload, $package->getDevAutoload());
- }
- if (!isset($autoload[$type]) || !is_array($autoload[$type])) {
- continue;
- }
- if (null !== $package->getTargetDir() && $package !== $mainPackage) {
- $installPath = substr($installPath, 0, -strlen('/'.$package->getTargetDir()));
- }
- foreach ($autoload[$type] as $namespace => $paths) {
- foreach ((array) $paths as $path) {
- if (($type === 'files' || $type === 'classmap') && $package->getTargetDir() && !is_readable($installPath.'/'.$path)) {
- if ($package === $mainPackage) {
- $targetDir = str_replace('\\<dirsep\\>', '[\\\\/]', preg_quote(str_replace(array('/', '\\'), '<dirsep>', $package->getTargetDir())));
- $path = ltrim(preg_replace('{^'.$targetDir.'}', '', ltrim($path, '\\/')), '\\/');
- } else {
- $path = $package->getTargetDir() . '/' . $path;
- }
- }
- $relativePath = empty($installPath) ? (empty($path) ? '.' : $path) : $installPath.'/'.$path;
- if ($type === 'files' || $type === 'classmap') {
- $autoloads[] = $relativePath;
- continue;
- }
- $autoloads[$namespace][] = $relativePath;
- }
- }
- }
- return $autoloads;
- }
- protected function sortPackageMap(array $packageMap)
- {
- $packages = array();
- $paths = array();
- $usageList = array();
- foreach ($packageMap as $item) {
- list($package, $path) = $item;
- $name = $package->getName();
- $packages[$name] = $package;
- $paths[$name] = $path;
- foreach (array_merge($package->getRequires(), $package->getDevRequires()) as $link) {
- $target = $link->getTarget();
- $usageList[$target][] = $name;
- }
- }
- $computing = array();
- $computed = array();
- $computeImportance = function ($name) use (&$computeImportance, &$computing, &$computed, $usageList) {
- if (isset($computed[$name])) {
- return $computed[$name];
- }
- if (isset($computing[$name])) {
- return 0;
- }
- $computing[$name] = true;
- $weight = 0;
- if (isset($usageList[$name])) {
- foreach ($usageList[$name] as $user) {
- $weight -= 1 - $computeImportance($user);
- }
- }
- unset($computing[$name]);
- $computed[$name] = $weight;
- return $weight;
- };
- $weightList = array();
- foreach ($packages as $name => $package) {
- $weight = $computeImportance($name);
- $weightList[$name] = $weight;
- }
- $stable_sort = function (&$array) {
- static $transform, $restore;
- $i = 0;
- if (!$transform) {
- $transform = function (&$v, $k) use (&$i) {
- $v = array($v, ++$i, $k, $v);
- };
- $restore = function (&$v, $k) {
- $v = $v[3];
- };
- }
- array_walk($array, $transform);
- asort($array);
- array_walk($array, $restore);
- };
- $stable_sort($weightList);
- $sortedPackageMap = array();
- foreach (array_keys($weightList) as $name) {
- $sortedPackageMap[] = array($packages[$name], $paths[$name]);
- }
- return $sortedPackageMap;
- }
- }
- <?php
- namespace Composer\Autoload;
- use Symfony\Component\Finder\Finder;
- use Composer\IO\IOInterface;
- class ClassMapGenerator
- {
- public static function dump($dirs, $file)
- {
- $maps = array();
- foreach ($dirs as $dir) {
- $maps = array_merge($maps, static::createMap($dir));
- }
- file_put_contents($file, sprintf('<?php return %s;', var_export($maps, true)));
- }
- public static function createMap($path, $whitelist = null, IOInterface $io = null, $namespace = null)
- {
- if (is_string($path)) {
- if (is_file($path)) {
- $path = array(new \SplFileInfo($path));
- } elseif (is_dir($path)) {
- $path = Finder::create()->files()->followLinks()->name('/\.(php|inc|hh)$/')->in($path);
- } else {
- throw new \RuntimeException(
- 'Could not scan for classes inside "'.$path.
- '" which does not appear to be a file nor a folder'
- );
- }
- }
- $map = array();
- foreach ($path as $file) {
- $filePath = $file->getRealPath();
- if (!in_array(pathinfo($filePath, PATHINFO_EXTENSION), array('php', 'inc', 'hh'))) {
- continue;
- }
- if ($whitelist && !preg_match($whitelist, strtr($filePath, '\\', '/'))) {
- continue;
- }
- $classes = self::findClasses($filePath);
- foreach ($classes as $class) {
- if (null !== $namespace && 0 !== strpos($class, $namespace)) {
- continue;
- }
- if (!isset($map[$class])) {
- $map[$class] = $filePath;
- } elseif ($io && $map[$class] !== $filePath && !preg_match('{/(test|fixture|example)s?/}i', strtr($map[$class].' '.$filePath, '\\', '/'))) {
- $io->writeError(
- '<warning>Warning: Ambiguous class resolution, "'.$class.'"'.
- ' was found in both "'.$map[$class].'" and "'.$filePath.'", the first will be used.</warning>'
- );
- }
- }
- }
- return $map;
- }
- private static function findClasses($path)
- {
- $traits = version_compare(PHP_VERSION, '5.4', '<') ? '' : '|trait';
- try {
- $contents = @php_strip_whitespace($path);
- if (!$contents) {
- if (!file_exists($path)) {
- throw new \Exception('File does not exist');
- }
- if (!is_readable($path)) {
- throw new \Exception('File is not readable');
- }
- }
- } catch (\Exception $e) {
- throw new \RuntimeException('Could not scan for classes inside '.$path.": \n".$e->getMessage(), 0, $e);
- }
- if (!preg_match('{\b(?:class|interface'.$traits.')\s}i', $contents)) {
- return array();
- }
- $contents = preg_replace('{<<<\s*(\'?)(\w+)\\1(?:\r\n|\n|\r)(?:.*?)(?:\r\n|\n|\r)\\2(?=\r\n|\n|\r|;)}s', 'null', $contents);
- $contents = preg_replace('{"[^"\\\\]*(\\\\.[^"\\\\]*)*"|\'[^\'\\\\]*(\\\\.[^\'\\\\]*)*\'}s', 'null', $contents);
- if (substr($contents, 0, 2) !== '<?') {
- $contents = preg_replace('{^.+?<\?}s', '<?', $contents, 1, $replacements);
- if ($replacements === 0) {
- return array();
- }
- }
- $contents = preg_replace('{\?>.+<\?}s', '?><?', $contents);
- $pos = strrpos($contents, '?>');
- if (false !== $pos && false === strpos(substr($contents, $pos), '<?')) {
- $contents = substr($contents, 0, $pos);
- }
- preg_match_all('{
- (?:
- \b(?<![\$:>])(?P<type>class|interface'.$traits.') \s+ (?P<name>[a-zA-Z_\x7f-\xff:][a-zA-Z0-9_\x7f-\xff:\-]*)
- | \b(?<![\$:>])(?P<ns>namespace) (?P<nsname>\s+[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*(?:\s*\\\\\s*[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)*)? \s*[\{;]
- )
- }ix', $contents, $matches);
- $classes = array();
- $namespace = '';
- for ($i = 0, $len = count($matches['type']); $i < $len; $i++) {
- if (!empty($matches['ns'][$i])) {
- $namespace = str_replace(array(' ', "\t", "\r", "\n"), '', $matches['nsname'][$i]) . '\\';
- } else {
- $name = $matches['name'][$i];
- if ($name[0] === ':') {
- $name = 'xhp'.substr(str_replace(array('-', ':'), array('_', '__'), $name), 1);
- }
- $classes[] = ltrim($namespace . $name, '\\');
- }
- }
- return $classes;
- }
- }
- <?php
- namespace Composer;
- use Composer\IO\IOInterface;
- use Composer\Util\Filesystem;
- use Symfony\Component\Finder\Finder;
- class Cache
- {
- private static $cacheCollected = false;
- private $io;
- private $root;
- private $enabled = true;
- private $whitelist;
- private $filesystem;
- public function __construct(IOInterface $io, $cacheDir, $whitelist = 'a-z0-9.', Filesystem $filesystem = null)
- {
- $this->io = $io;
- $this->root = rtrim($cacheDir, '/\\') . '/';
- $this->whitelist = $whitelist;
- $this->filesystem = $filesystem ?: new Filesystem();
- if (!is_dir($this->root)) {
- if (!@mkdir($this->root, 0777, true)) {
- $this->enabled = false;
- }
- }
- }
- public function isEnabled()
- {
- return $this->enabled;
- }
- public function getRoot()
- {
- return $this->root;
- }
- public function read($file)
- {
- $file = preg_replace('{[^'.$this->whitelist.']}i', '-', $file);
- if ($this->enabled && file_exists($this->root . $file)) {
- if ($this->io->isDebug()) {
- $this->io->writeError('Reading '.$this->root . $file.' from cache');
- }
- return file_get_contents($this->root . $file);
- }
- return false;
- }
- public function write($file, $contents)
- {
- if ($this->enabled) {
- $file = preg_replace('{[^'.$this->whitelist.']}i', '-', $file);
- if ($this->io->isDebug()) {
- $this->io->writeError('Writing '.$this->root . $file.' into cache');
- }
- try {
- return file_put_contents($this->root . $file, $contents);
- } catch (\ErrorException $e) {
- if (preg_match('{^file_put_contents\(\): Only ([0-9]+) of ([0-9]+) bytes written}', $e->getMessage(), $m)) {
- unlink($this->root . $file);
- $message = sprintf(
- '<warning>Writing %1$s into cache failed after %2$u of %3$u bytes written, only %4$u bytes of free space available</warning>',
- $this->root . $file,
- $m[1],
- $m[2],
- @disk_free_space($this->root . dirname($file))
- );
- $this->io->writeError($message);
- return false;
- }
- throw $e;
- }
- }
- return false;
- }
- public function copyFrom($file, $source)
- {
- if ($this->enabled) {
- $file = preg_replace('{[^'.$this->whitelist.']}i', '-', $file);
- $this->filesystem->ensureDirectoryExists(dirname($this->root . $file));
- if ($this->io->isDebug()) {
- $this->io->writeError('Writing '.$this->root . $file.' into cache');
- }
- return copy($source, $this->root . $file);
- }
- return false;
- }
- public function copyTo($file, $target)
- {
- $file = preg_replace('{[^'.$this->whitelist.']}i', '-', $file);
- if ($this->enabled && file_exists($this->root . $file)) {
- touch($this->root . $file);
- if ($this->io->isDebug()) {
- $this->io->writeError('Reading '.$this->root . $file.' from cache');
- }
- return copy($this->root . $file, $target);
- }
- return false;
- }
- public function gcIsNecessary()
- {
- return (!self::$cacheCollected && !mt_rand(0, 50));
- }
- public function remove($file)
- {
- $file = preg_replace('{[^'.$this->whitelist.']}i', '-', $file);
- if ($this->enabled && file_exists($this->root . $file)) {
- return $this->filesystem->unlink($this->root . $file);
- }
- return false;
- }
- public function gc($ttl, $maxSize)
- {
- if ($this->enabled) {
- $expire = new \DateTime();
- $expire->modify('-'.$ttl.' seconds');
- $finder = $this->getFinder()->date('until '.$expire->format('Y-m-d H:i:s'));
- foreach ($finder as $file) {
- $this->filesystem->unlink($file->getPathname());
- }
- $totalSize = $this->filesystem->size($this->root);
- if ($totalSize > $maxSize) {
- $iterator = $this->getFinder()->sortByAccessedTime()->getIterator();
- while ($totalSize > $maxSize && $iterator->valid()) {
- $filepath = $iterator->current()->getPathname();
- $totalSize -= $this->filesystem->size($filepath);
- $this->filesystem->unlink($filepath);
- $iterator->next();
- }
- }
- self::$cacheCollected = true;
- return true;
- }
- return false;
- }
- public function sha1($file)
- {
- $file = preg_replace('{[^'.$this->whitelist.']}i', '-', $file);
- if ($this->enabled && file_exists($this->root . $file)) {
- return sha1_file($this->root . $file);
- }
- return false;
- }
- public function sha256($file)
- {
- $file = preg_replace('{[^'.$this->whitelist.']}i', '-', $file);
- if ($this->enabled && file_exists($this->root . $file)) {
- return hash_file('sha256', $this->root . $file);
- }
- return false;
- }
- protected function getFinder()
- {
- return Finder::create()->in($this->root)->files();
- }
- }
- <?php
- namespace Composer\Command;
- use Symfony\Component\Console\Input\InputInterface;
- use Symfony\Component\Console\Output\OutputInterface;
- class AboutCommand extends Command
- {
- protected function configure()
- {
- $this
- ->setName('about')
- ->setDescription('Short information about Composer')
- ->setHelp(<<<EOT
- <info>php composer.phar about</info>
- EOT
- )
- ;
- }
- protected function execute(InputInterface $input, OutputInterface $output)
- {
- $this->getIO()->write(<<<EOT
- <info>Composer - Package Management for PHP</info>
- <comment>Composer is a dependency manager tracking local dependencies of your projects and libraries.
- See http://getcomposer.org/ for more information.</comment>
- EOT
- );
- }
- }
- <?php
- namespace Composer\Command;
- use Composer\Factory;
- use Composer\IO\IOInterface;
- use Composer\DependencyResolver\Pool;
- use Composer\Repository\CompositeRepository;
- use Composer\Script\ScriptEvents;
- use Composer\Plugin\CommandEvent;
- use Composer\Plugin\PluginEvents;
- use Composer\Package\Version\VersionParser;
- use Symfony\Component\Console\Input\InputArgument;
- use Symfony\Component\Console\Input\InputInterface;
- use Symfony\Component\Console\Input\InputOption;
- use Symfony\Component\Console\Output\OutputInterface;
- class ArchiveCommand extends Command
- {
- protected function configure()
- {
- $this
- ->setName('archive')
- ->setDescription('Create an archive of this composer package')
- ->setDefinition(array(
- new InputArgument('package', InputArgument::OPTIONAL, 'The package to archive instead of the current project'),
- new InputArgument('version', InputArgument::OPTIONAL, 'A version constraint to find the package to archive'),
- new InputOption('format', 'f', InputOption::VALUE_REQUIRED, 'Format of the resulting archive: tar or zip', 'tar'),
- new InputOption('dir', false, InputOption::VALUE_REQUIRED, 'Write the archive to this directory', '.'),
- ))
- ->setHelp(<<<EOT
- The <info>archive</info> command creates an archive of the specified format
- containing the files and directories of the Composer project or the specified
- package in the specified version and writes it to the specified directory.
- <info>php composer.phar archive [--format=zip] [--dir=/foo] [package [version]]</info>
- EOT
- )
- ;
- }
- protected function execute(InputInterface $input, OutputInterface $output)
- {
- $composer = $this->getComposer(false);
- if ($composer) {
- $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'archive', $input, $output);
- $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
- $composer->getEventDispatcher()->dispatchScript(ScriptEvents::PRE_ARCHIVE_CMD);
- }
- $returnCode = $this->archive(
- $this->getIO(),
- $input->getArgument('package'),
- $input->getArgument('version'),
- $input->getOption('format'),
- $input->getOption('dir')
- );
- if (0 === $returnCode && $composer) {
- $composer->getEventDispatcher()->dispatchScript(ScriptEvents::POST_ARCHIVE_CMD);
- }
- return $returnCode;
- }
- protected function archive(IOInterface $io, $packageName = null, $version = null, $format = 'tar', $dest = '.')
- {
- $config = Factory::createConfig();
- $factory = new Factory;
- $downloadManager = $factory->createDownloadManager($io, $config);
- $archiveManager = $factory->createArchiveManager($config, $downloadManager);
- if ($packageName) {
- $package = $this->selectPackage($io, $packageName, $version);
- if (!$package) {
- return 1;
- }
- } else {
- $package = $this->getComposer()->getPackage();
- }
- $io->writeError('<info>Creating the archive.</info>');
- $archiveManager->archive($package, $format, $dest);
- return 0;
- }
- protected function selectPackage(IOInterface $io, $packageName, $version = null)
- {
- $io->writeError('<info>Searching for the specified package.</info>');
- if ($composer = $this->getComposer(false)) {
- $localRepo = $composer->getRepositoryManager()->getLocalRepository();
- $repos = new CompositeRepository(array_merge(array($localRepo), $composer->getRepositoryManager()->getRepositories()));
- } else {
- $defaultRepos = Factory::createDefaultRepositories($this->getIO());
- $io->writeError('No composer.json found in the current directory, searching packages from ' . implode(', ', array_keys($defaultRepos)));
- $repos = new CompositeRepository($defaultRepos);
- }
- $pool = new Pool();
- $pool->addRepository($repos);
- $parser = new VersionParser();
- $constraint = ($version) ? $parser->parseConstraints($version) : null;
- $packages = $pool->whatProvides($packageName, $constraint, true);
- if (count($packages) > 1) {
- $package = reset($packages);
- $io->writeError('<info>Found multiple matches, selected '.$package->getPrettyString().'.</info>');
- $io->writeError('Alternatives were '.implode(', ', array_map(function ($p) { return $p->getPrettyString(); }, $packages)).'.');
- $io->writeError('<comment>Please use a more specific constraint to pick a different package.</comment>');
- } elseif ($packages) {
- $package = reset($packages);
- $io->writeError('<info>Found an exact match '.$package->getPrettyString().'.</info>');
- } else {
- $io->writeError('<error>Could not find a package matching '.$packageName.'.</error>');
- return false;
- }
- return $package;
- }
- }
- <?php
- namespace Composer\Command;
- use Composer\Cache;
- use Composer\Factory;
- use Symfony\Component\Console\Input\InputInterface;
- use Symfony\Component\Console\Output\OutputInterface;
- class ClearCacheCommand extends Command
- {
- protected function configure()
- {
- $this
- ->setName('clear-cache')
- ->setAliases(array('clearcache'))
- ->setDescription('Clears composer\'s internal package cache.')
- ->setHelp(<<<EOT
- The <info>clear-cache</info> deletes all cached packages from composer's
- cache directory.
- EOT
- )
- ;
- }
- protected function execute(InputInterface $input, OutputInterface $output)
- {
- $config = Factory::createConfig();
- $io = $this->getIO();
- $cachePaths = array(
- 'cache-dir' => $config->get('cache-dir'),
- 'cache-files-dir' => $config->get('cache-files-dir'),
- 'cache-repo-dir' => $config->get('cache-repo-dir'),
- 'cache-vcs-dir' => $config->get('cache-vcs-dir'),
- );
- foreach ($cachePaths as $key => $cachePath) {
- $cachePath = realpath($cachePath);
- if (!$cachePath) {
- $io->writeError("<info>Cache directory does not exist ($key): $cachePath</info>");
- continue;
- }
- $cache = new Cache($io, $cachePath);
- if (!$cache->isEnabled()) {
- $io->writeError("<info>Cache is not enabled ($key): $cachePath</info>");
- continue;
- }
- $io->writeError("<info>Clearing cache ($key): $cachePath</info>");
- $cache->gc(0, 0);
- }
- $io->writeError('<info>All caches cleared.</info>');
- }
- }
- <?php
- namespace Composer\Command;
- use Composer\Composer;
- use Composer\Console\Application;
- use Composer\IO\IOInterface;
- use Composer\IO\NullIO;
- use Symfony\Component\Console\Input\InputInterface;
- use Symfony\Component\Console\Output\OutputInterface;
- use Symfony\Component\Console\Command\Command as BaseCommand;
- abstract class Command extends BaseCommand
- {
- private $composer;
- private $io;
- public function getComposer($required = true, $disablePlugins = false)
- {
- if (null === $this->composer) {
- $application = $this->getApplication();
- if ($application instanceof Application) {
- $this->composer = $application->getComposer($required, $disablePlugins);
- } elseif ($required) {
- throw new \RuntimeException(
- 'Could not create a Composer\Composer instance, you must inject '.
- 'one if this command is not used with a Composer\Console\Application instance'
- );
- }
- }
- return $this->composer;
- }
- public function setComposer(Composer $composer)
- {
- $this->composer = $composer;
- }
- public function resetComposer()
- {
- $this->composer = null;
- $this->getApplication()->resetComposer();
- }
- public function getIO()
- {
- if (null === $this->io) {
- $application = $this->getApplication();
- if ($application instanceof Application) {
- $this->io = $application->getIO();
- } else {
- $this->io = new NullIO();
- }
- }
- return $this->io;
- }
- public function setIO(IOInterface $io)
- {
- $this->io = $io;
- }
- protected function initialize(InputInterface $input, OutputInterface $output)
- {
- if (true === $input->hasParameterOption(array('--no-ansi')) && $input->hasOption('no-progress')) {
- $input->setOption('no-progress', true);
- }
- parent::initialize($input, $output);
- }
- }
- <?php
- namespace Composer\Command;
- use Symfony\Component\Console\Input\InputInterface;
- use Symfony\Component\Console\Input\InputArgument;
- use Symfony\Component\Console\Input\InputOption;
- use Symfony\Component\Console\Output\OutputInterface;
- use Composer\Config;
- use Composer\Config\JsonConfigSource;
- use Composer\Factory;
- use Composer\Json\JsonFile;
- class ConfigCommand extends Command
- {
- protected $config;
- protected $configFile;
- protected $configSource;
- protected $authConfigFile;
- protected $authConfigSource;
- protected function configure()
- {
- $this
- ->setName('config')
- ->setDescription('Set config options')
- ->setDefinition(array(
- new InputOption('global', 'g', InputOption::VALUE_NONE, 'Apply command to the global config file'),
- new InputOption('editor', 'e', InputOption::VALUE_NONE, 'Open editor'),
- new InputOption('auth', 'a', InputOption::VALUE_NONE, 'Affect auth config file (only used for --editor)'),
- new InputOption('unset', null, InputOption::VALUE_NONE, 'Unset the given setting-key'),
- new InputOption('list', 'l', InputOption::VALUE_NONE, 'List configuration settings'),
- new InputOption('file', 'f', InputOption::VALUE_REQUIRED, 'If you want to choose a different composer.json or config.json', 'composer.json'),
- new InputOption('absolute', null, InputOption::VALUE_NONE, 'Returns absolute paths when fetching *-dir config values instead of relative'),
- new InputArgument('setting-key', null, 'Setting key'),
- new InputArgument('setting-value', InputArgument::IS_ARRAY, 'Setting value'),
- ))
- ->setHelp(<<<EOT
- This command allows you to edit some basic composer settings in either the
- local composer.json file or the global config.json file.
- To set a config setting:
- <comment>%command.full_name% bin-dir bin/</comment>
- To read a config setting:
- <comment>%command.full_name% bin-dir</comment>
- Outputs: <info>bin</info>
- To edit the global config.json file:
- <comment>%command.full_name% --global</comment>
- To add a repository:
- <comment>%command.full_name% repositories.foo vcs http://bar.com</comment>
- To remove a repository (repo is a short alias for repositories):
- <comment>%command.full_name% --unset repo.foo</comment>
- To disable packagist:
- <comment>%command.full_name% repo.packagist false</comment>
- You can alter repositories in the global config.json file by passing in the
- <info>--global</info> option.
- To edit the file in an external editor:
- <comment>%command.full_name% --editor</comment>
- To choose your editor you can set the "EDITOR" env variable.
- To get a list of configuration values in the file:
- <comment>%command.full_name% --list</comment>
- You can always pass more than one option. As an example, if you want to edit the
- global config.json file.
- <comment>%command.full_name% --editor --global</comment>
- EOT
- )
- ;
- }
- protected function initialize(InputInterface $input, OutputInterface $output)
- {
- parent::initialize($input, $output);
- if ($input->getOption('global') && 'composer.json' !== $input->getOption('file')) {
- throw new \RuntimeException('--file and --global can not be combined');
- }
- $this->config = Factory::createConfig($this->getIO());
-
- $configFile = $input->getOption('global')
- ? ($this->config->get('home') . '/config.json')
- : $input->getOption('file');
- $this->configFile = new JsonFile($configFile);
- $this->configSource = new JsonConfigSource($this->configFile);
- $authConfigFile = $input->getOption('global')
- ? ($this->config->get('home') . '/auth.json')
- : dirname(realpath($input->getOption('file'))) . '/auth.json';
- $this->authConfigFile = new JsonFile($authConfigFile);
- $this->authConfigSource = new JsonConfigSource($this->authConfigFile, true);
- if ($input->getOption('global') && !$this->configFile->exists()) {
- touch($this->configFile->getPath());
- $this->configFile->write(array('config' => new \ArrayObject));
- @chmod($this->configFile->getPath(), 0600);
- }
- if ($input->getOption('global') && !$this->authConfigFile->exists()) {
- touch($this->authConfigFile->getPath());
- $this->authConfigFile->write(array('http-basic' => new \ArrayObject, 'github-oauth' => new \ArrayObject));
- @chmod($this->authConfigFile->getPath(), 0600);
- }
- if (!$this->configFile->exists()) {
- throw new \RuntimeException(sprintf('File "%s" cannot be found in the current directory', $configFile));
- }
- }
- protected function execute(InputInterface $input, OutputInterface $output)
- {
- if ($input->getOption('editor')) {
- $editor = escapeshellcmd(getenv('EDITOR'));
- if (!$editor) {
- if (defined('PHP_WINDOWS_VERSION_BUILD')) {
- $editor = 'notepad';
- } else {
- foreach (array('vim', 'vi', 'nano', 'pico', 'ed') as $candidate) {
- if (exec('which '.$candidate)) {
- $editor = $candidate;
- break;
- }
- }
- }
- }
- $file = $input->getOption('auth') ? $this->authConfigFile->getPath() : $this->configFile->getPath();
- system($editor . ' ' . $file . (defined('PHP_WINDOWS_VERSION_BUILD') ? '' : ' > `tty`'));
- return 0;
- }
- if (!$input->getOption('global')) {
- $this->config->merge($this->configFile->read());
- $this->config->merge(array('config' => $this->authConfigFile->exists() ? $this->authConfigFile->read() : array()));
- }
- if ($input->getOption('list')) {
- $this->listConfiguration($this->config->all(), $this->config->raw(), $output);
- return 0;
- }
- $settingKey = $input->getArgument('setting-key');
- if (!$settingKey) {
- return 0;
- }
- if (array() !== $input->getArgument('setting-value') && $input->getOption('unset')) {
- throw new \RuntimeException('You can not combine a setting value with --unset');
- }
- if (array() === $input->getArgument('setting-value') && !$input->getOption('unset')) {
- $data = $this->config->all();
- if (preg_match('/^repos?(?:itories)?(?:\.(.+))?/', $settingKey, $matches)) {
- if (empty($matches[1])) {
- $value = isset($data['repositories']) ? $data['repositories'] : array();
- } else {
- if (!isset($data['repositories'][$matches[1]])) {
- throw new \InvalidArgumentException('There is no '.$matches[1].' repository defined');
- }
- $value = $data['repositories'][$matches[1]];
- }
- } elseif (strpos($settingKey, '.')) {
- $bits = explode('.', $settingKey);
- $data = $data['config'];
- foreach ($bits as $bit) {
- if (isset($data[$bit])) {
- $data = $data[$bit];
- } elseif (isset($data[implode('.', $bits)])) {
- $data = $data[implode('.', $bits)];
- break;
- } else {
- throw new \RuntimeException($settingKey.' is not defined');
- }
- array_shift($bits);
- }
- $value = $data;
- } elseif (isset($data['config'][$settingKey])) {
- $value = $this->config->get($settingKey, $input->getOption('absolute') ? 0 : Config::RELATIVE_PATHS);
- } else {
- throw new \RuntimeException($settingKey.' is not defined');
- }
- if (is_array($value)) {
- $value = json_encode($value);
- }
- $this->getIO()->write($value);
- return 0;
- }
- $values = $input->getArgument('setting-value');
- $booleanValidator = function ($val) { return in_array($val, array('true', 'false', '1', '0'), true); };
- $booleanNormalizer = function ($val) { return $val !== 'false' && (bool) $val; };
- $uniqueConfigValues = array(
- 'process-timeout' => array('is_numeric', 'intval'),
- 'use-include-path' => array($booleanValidator, $booleanNormalizer),
- 'preferred-install' => array(
- function ($val) { return in_array($val, array('auto', 'source', 'dist'), true); },
- function ($val) { return $val; }
- ),
- 'store-auths' => array(
- function ($val) { return in_array($val, array('true', 'false', 'prompt'), true); },
- function ($val) {
- if ('prompt' === $val) {
- return 'prompt';
- }
- return $val !== 'false' && (bool) $val;
- }
- ),
- 'notify-on-install' => array($booleanValidator, $booleanNormalizer),
- 'vendor-dir' => array('is_string', function ($val) { return $val; }),
- 'bin-dir' => array('is_string', function ($val) { return $val; }),
- 'cache-dir' => array('is_string', function ($val) { return $val; }),
- 'cache-files-dir' => array('is_string', function ($val) { return $val; }),
- 'cache-repo-dir' => array('is_string', function ($val) { return $val; }),
- 'cache-vcs-dir' => array('is_string', function ($val) { return $val; }),
- 'cache-ttl' => array('is_numeric', 'intval'),
- 'cache-files-ttl' => array('is_numeric', 'intval'),
- 'cache-files-maxsize' => array(
- function ($val) { return preg_match('/^\s*([0-9.]+)\s*(?:([kmg])(?:i?b)?)?\s*$/i', $val) > 0; },
- function ($val) { return $val; }
- ),
- 'discard-changes' => array(
- function ($val) { return in_array($val, array('stash', 'true', 'false', '1', '0'), true); },
- function ($val) {
- if ('stash' === $val) {
- return 'stash';
- }
- return $val !== 'false' && (bool) $val;
- }
- ),
- 'autoloader-suffix' => array('is_string', function ($val) { return $val === 'null' ? null : $val; }),
- 'optimize-autoloader' => array($booleanValidator, $booleanNormalizer),
- 'classmap-authoritative' => array($booleanValidator, $booleanNormalizer),
- 'prepend-autoloader' => array($booleanValidator, $booleanNormalizer),
- 'github-expose-hostname' => array($booleanValidator, $booleanNormalizer),
- );
- $multiConfigValues = array(
- 'github-protocols' => array(
- function ($vals) {
- if (!is_array($vals)) {
- return 'array expected';
- }
- foreach ($vals as $val) {
- if (!in_array($val, array('git', 'https', 'ssh'))) {
- return 'valid protocols include: git, https, ssh';
- }
- }
- return true;
- },
- function ($vals) {
- return $vals;
- }
- ),
- 'github-domains' => array(
- function ($vals) {
- if (!is_array($vals)) {
- return 'array expected';
- }
- return true;
- },
- function ($vals) {
- return $vals;
- }
- ),
- );
- foreach ($uniqueConfigValues as $name => $callbacks) {
- if ($settingKey === $name) {
- if ($input->getOption('unset')) {
- return $this->configSource->removeConfigSetting($settingKey);
- }
- list($validator, $normalizer) = $callbacks;
- if (1 !== count($values)) {
- throw new \RuntimeException('You can only pass one value. Example: php composer.phar config process-timeout 300');
- }
- if (true !== $validation = $validator($values[0])) {
- throw new \RuntimeException(sprintf(
- '"%s" is an invalid value'.($validation ? ' ('.$validation.')' : ''),
- $values[0]
- ));
- }
- return $this->configSource->addConfigSetting($settingKey, $normalizer($values[0]));
- }
- }
- foreach ($multiConfigValues as $name => $callbacks) {
- if ($settingKey === $name) {
- if ($input->getOption('unset')) {
- return $this->configSource->removeConfigSetting($settingKey);
- }
- list($validator, $normalizer) = $callbacks;
- if (true !== $validation = $validator($values)) {
- throw new \RuntimeException(sprintf(
- '%s is an invalid value'.($validation ? ' ('.$validation.')' : ''),
- json_encode($values)
- ));
- }
- return $this->configSource->addConfigSetting($settingKey, $normalizer($values));
- }
- }
- if (preg_match('/^repos?(?:itories)?\.(.+)/', $settingKey, $matches)) {
- if ($input->getOption('unset')) {
- return $this->configSource->removeRepository($matches[1]);
- }
- if (2 === count($values)) {
- return $this->configSource->addRepository($matches[1], array(
- 'type' => $values[0],
- 'url' => $values[1],
- ));
- }
- if (1 === count($values)) {
- $bool = strtolower($values[0]);
- if (true === $booleanValidator($bool) && false === $booleanNormalizer($bool)) {
- return $this->configSource->addRepository($matches[1], false);
- }
- }
- throw new \RuntimeException('You must pass the type and a url. Example: php composer.phar config repositories.foo vcs http://bar.com');
- }
- if (preg_match('/^(github-oauth|http-basic)\.(.+)/', $settingKey, $matches)) {
- if ($input->getOption('unset')) {
- $this->authConfigSource->removeConfigSetting($matches[1].'.'.$matches[2]);
- $this->configSource->removeConfigSetting($matches[1].'.'.$matches[2]);
- return;
- }
- if ($matches[1] === 'github-oauth') {
- if (1 !== count($values)) {
- throw new \RuntimeException('Too many arguments, expected only one token');
- }
- $this->configSource->removeConfigSetting($matches[1].'.'.$matches[2]);
- $this->authConfigSource->addConfigSetting($matches[1].'.'.$matches[2], $values[0]);
- } elseif ($matches[1] === 'http-basic') {
- if (2 !== count($values)) {
- throw new \RuntimeException('Expected two arguments (username, password), got '.count($values));
- }
- $this->configSource->removeConfigSetting($matches[1].'.'.$matches[2]);
- $this->authConfigSource->addConfigSetting($matches[1].'.'.$matches[2], array('username' => $values[0], 'password' => $values[1]));
- }
- return;
- }
- throw new \InvalidArgumentException('Setting '.$settingKey.' does not exist or is not supported by this command');
- }
- protected function listConfiguration(array $contents, array $rawContents, OutputInterface $output, $k = null)
- {
- $origK = $k;
- foreach ($contents as $key => $value) {
- if ($k === null && !in_array($key, array('config', 'repositories'))) {
- continue;
- }
- $rawVal = isset($rawContents[$key]) ? $rawContents[$key] : null;
- if (is_array($value) && (!is_numeric(key($value)) || ($key === 'repositories' && null === $k))) {
- $k .= preg_replace('{^config\.}', '', $key . '.');
- $this->listConfiguration($value, $rawVal, $output, $k);
- if (substr_count($k, '.') > 1) {
- $k = str_split($k, strrpos($k, '.', -2));
- $k = $k[0] . '.';
- } else {
- $k = $origK;
- }
- continue;
- }
- if (is_array($value)) {
- $value = array_map(function ($val) {
- return is_array($val) ? json_encode($val) : $val;
- }, $value);
- $value = '['.implode(', ', $value).']';
- }
- if (is_bool($value)) {
- $value = var_export($value, true);
- }
- if (is_string($rawVal) && $rawVal != $value) {
- $this->getIO()->write('[<comment>' . $k . $key . '</comment>] <info>' . $rawVal . ' (' . $value . ')</info>');
- } else {
- $this->getIO()->write('[<comment>' . $k . $key . '</comment>] <info>' . $value . '</info>');
- }
- }
- }
- }
- <?php
- namespace Composer\Command;
- use Composer\Config;
- use Composer\Factory;
- use Composer\Installer;
- use Composer\Installer\ProjectInstaller;
- use Composer\Installer\InstallationManager;
- use Composer\IO\IOInterface;
- use Composer\Package\BasePackage;
- use Composer\DependencyResolver\Pool;
- use Composer\DependencyResolver\Operation\InstallOperation;
- use Composer\Package\Version\VersionSelector;
- use Composer\Repository\ComposerRepository;
- use Composer\Repository\CompositeRepository;
- use Composer\Repository\FilesystemRepository;
- use Composer\Repository\InstalledFilesystemRepository;
- use Composer\Script\ScriptEvents;
- use Symfony\Component\Console\Input\InputArgument;
- use Symfony\Component\Console\Input\InputInterface;
- use Symfony\Component\Console\Input\InputOption;
- use Symfony\Component\Console\Output\OutputInterface;
- use Symfony\Component\Finder\Finder;
- use Composer\Json\JsonFile;
- use Composer\Config\JsonConfigSource;
- use Composer\Util\Filesystem;
- use Composer\Util\RemoteFilesystem;
- use Composer\Package\Version\VersionParser;
- class CreateProjectCommand extends Command
- {
- protected function configure()
- {
- $this
- ->setName('create-project')
- ->setDescription('Create new project from a package into given directory.')
- ->setDefinition(array(
- new InputArgument('package', InputArgument::OPTIONAL, 'Package name to be installed'),
- new InputArgument('directory', InputArgument::OPTIONAL, 'Directory where the files should be created'),
- new InputArgument('version', InputArgument::OPTIONAL, 'Version, will default to latest'),
- new InputOption('stability', 's', InputOption::VALUE_REQUIRED, 'Minimum-stability allowed (unless a version is specified).'),
- new InputOption('prefer-source', null, InputOption::VALUE_NONE, 'Forces installation from package sources when possible, including VCS information.'),
- new InputOption('prefer-dist', null, InputOption::VALUE_NONE, 'Forces installation from package dist even for dev versions.'),
- new InputOption('repository-url', null, InputOption::VALUE_REQUIRED, 'Pick a different repository url to look for the package.'),
- new InputOption('dev', null, InputOption::VALUE_NONE, 'Enables installation of require-dev packages (enabled by default, only present for BC).'),
- new InputOption('no-dev', null, InputOption::VALUE_NONE, 'Disables installation of require-dev packages.'),
- new InputOption('no-plugins', null, InputOption::VALUE_NONE, 'Whether to disable plugins.'),
- new InputOption('no-custom-installers', null, InputOption::VALUE_NONE, 'DEPRECATED: Use no-plugins instead.'),
- new InputOption('no-scripts', null, InputOption::VALUE_NONE, 'Whether to prevent execution of all defined scripts in the root package.'),
- new InputOption('no-progress', null, InputOption::VALUE_NONE, 'Do not output download progress.'),
- new InputOption('keep-vcs', null, InputOption::VALUE_NONE, 'Whether to prevent deletion vcs folder.'),
- new InputOption('no-install', null, InputOption::VALUE_NONE, 'Whether to skip installation of the package dependencies.'),
- new InputOption('ignore-platform-reqs', null, InputOption::VALUE_NONE, 'Ignore platform requirements (php & ext- packages).'),
- ))
- ->setHelp(<<<EOT
- The <info>create-project</info> command creates a new project from a given
- package into a new directory. If executed without params and in a directory
- with a composer.json file it installs the packages for the current project.
- You can use this command to bootstrap new projects or setup a clean
- version-controlled installation for developers of your project.
- <info>php composer.phar create-project vendor/project target-directory [version]</info>
- You can also specify the version with the package name using = or : as separator.
- To install unstable packages, either specify the version you want, or use the
- --stability=dev (where dev can be one of RC, beta, alpha or dev).
- To setup a developer workable version you should create the project using the source
- controlled code by appending the <info>'--prefer-source'</info> flag.
- To install a package from another repository than the default one you
- can pass the <info>'--repository-url=http://myrepository.org'</info> flag.
- EOT
- )
- ;
- }
- protected function execute(InputInterface $input, OutputInterface $output)
- {
- $config = Factory::createConfig();
- $preferSource = false;
- $preferDist = false;
- $this->updatePreferredOptions($config, $input, $preferSource, $preferDist);
- if ($input->getOption('no-custom-installers')) {
- $this->getIO()->writeError('<warning>You are using the deprecated option "no-custom-installers". Use "no-plugins" instead.</warning>');
- $input->setOption('no-plugins', true);
- }
- return $this->installProject(
- $this->getIO(),
- $config,
- $input->getArgument('package'),
- $input->getArgument('directory'),
- $input->getArgument('version'),
- $input->getOption('stability'),
- $preferSource,
- $preferDist,
- !$input->getOption('no-dev'),
- $input->getOption('repository-url'),
- $input->getOption('no-plugins'),
- $input->getOption('no-scripts'),
- $input->getOption('keep-vcs'),
- $input->getOption('no-progress'),
- $input->getOption('no-install'),
- $input->getOption('ignore-platform-reqs'),
- $input
- );
- }
- public function installProject(IOInterface $io, Config $config, $packageName, $directory = null, $packageVersion = null, $stability = 'stable', $preferSource = false, $preferDist = false, $installDevPackages = false, $repositoryUrl = null, $disablePlugins = false, $noScripts = false, $keepVcs = false, $noProgress = false, $noInstall = false, $ignorePlatformReqs = false, InputInterface $input)
- {
- $oldCwd = getcwd();
- $io->loadConfiguration($config);
- if ($packageName !== null) {
- $installedFromVcs = $this->installRootPackage($io, $config, $packageName, $directory, $packageVersion, $stability, $preferSource, $preferDist, $installDevPackages, $repositoryUrl, $disablePlugins, $noScripts, $keepVcs, $noProgress);
- } else {
- $installedFromVcs = false;
- }
- $composer = Factory::create($io, null, $disablePlugins);
- $fs = new Filesystem();
- if ($noScripts === false) {
- $composer->getEventDispatcher()->dispatchScript(ScriptEvents::POST_ROOT_PACKAGE_INSTALL, $installDevPackages);
- }
- $rootPackageConfig = $composer->getConfig();
- $this->updatePreferredOptions($rootPackageConfig, $input, $preferSource, $preferDist);
- if ($noInstall === false) {
- $installer = Installer::create($io, $composer);
- $installer->setPreferSource($preferSource)
- ->setPreferDist($preferDist)
- ->setDevMode($installDevPackages)
- ->setRunScripts(!$noScripts)
- ->setIgnorePlatformRequirements($ignorePlatformReqs);
- if ($disablePlugins) {
- $installer->disablePlugins();
- }
- $status = $installer->run();
- if (0 !== $status) {
- return $status;
- }
- }
- $hasVcs = $installedFromVcs;
- if (!$keepVcs && $installedFromVcs
- && (
- !$io->isInteractive()
- || $io->askConfirmation('<info>Do you want to remove the existing VCS (.git, .svn..) history?</info> [<comment>Y,n</comment>]? ', true)
- )
- ) {
- $finder = new Finder();
- $finder->depth(0)->directories()->in(getcwd())->ignoreVCS(false)->ignoreDotFiles(false);
- foreach (array('.svn', '_svn', 'CVS', '_darcs', '.arch-params', '.monotone', '.bzr', '.git', '.hg') as $vcsName) {
- $finder->name($vcsName);
- }
- try {
- $dirs = iterator_to_array($finder);
- unset($finder);
- foreach ($dirs as $dir) {
- if (!$fs->removeDirectory($dir)) {
- throw new \RuntimeException('Could not remove '.$dir);
- }
- }
- } catch (\Exception $e) {
- $io->writeError('<error>An error occurred while removing the VCS metadata: '.$e->getMessage().'</error>');
- }
- $hasVcs = false;
- }
- if (!$hasVcs) {
- $package = $composer->getPackage();
- $configSource = new JsonConfigSource(new JsonFile('composer.json'));
- foreach (BasePackage::$supportedLinkTypes as $type => $meta) {
- foreach ($package->{'get'.$meta['method']}() as $link) {
- if ($link->getPrettyConstraint() === 'self.version') {
- $configSource->addLink($type, $link->getTarget(), $package->getPrettyVersion());
- }
- }
- }
- }
- if ($noScripts === false) {
- $composer->getEventDispatcher()->dispatchScript(ScriptEvents::POST_CREATE_PROJECT_CMD, $installDevPackages);
- }
- chdir($oldCwd);
- $vendorComposerDir = $composer->getConfig()->get('vendor-dir').'/composer';
- if (is_dir($vendorComposerDir) && $fs->isDirEmpty($vendorComposerDir)) {
- @rmdir($vendorComposerDir);
- $vendorDir = $composer->getConfig()->get('vendor-dir');
- if (is_dir($vendorDir) && $fs->isDirEmpty($vendorDir)) {
- @rmdir($vendorDir);
- }
- }
- return 0;
- }
- protected function installRootPackage(IOInterface $io, Config $config, $packageName, $directory = null, $packageVersion = null, $stability = 'stable', $preferSource = false, $preferDist = false, $installDevPackages = false, $repositoryUrl = null, $disablePlugins = false, $noScripts = false, $keepVcs = false, $noProgress = false)
- {
- if (null === $repositoryUrl) {
- $sourceRepo = new CompositeRepository(Factory::createDefaultRepositories($io, $config));
- } elseif ("json" === pathinfo($repositoryUrl, PATHINFO_EXTENSION) && file_exists($repositoryUrl)) {
- $json = new JsonFile($repositoryUrl, new RemoteFilesystem($io, $config));
- $data = $json->read();
- if (!empty($data['packages']) || !empty($data['includes']) || !empty($data['provider-includes'])) {
- $sourceRepo = new ComposerRepository(array('url' => 'file://' . strtr(realpath($repositoryUrl), '\\', '/')), $io, $config);
- } else {
- $sourceRepo = new FilesystemRepository($json);
- }
- } elseif (0 === strpos($repositoryUrl, 'http')) {
- $sourceRepo = new ComposerRepository(array('url' => $repositoryUrl), $io, $config);
- } else {
- throw new \InvalidArgumentException("Invalid repository url given. Has to be a .json file or an http url.");
- }
- $parser = new VersionParser();
- $requirements = $parser->parseNameVersionPairs(array($packageName));
- $name = strtolower($requirements[0]['name']);
- if (!$packageVersion && isset($requirements[0]['version'])) {
- $packageVersion = $requirements[0]['version'];
- }
- if (null === $stability) {
- if (preg_match('{^[^,\s]*?@('.implode('|', array_keys(BasePackage::$stabilities)).')$}i', $packageVersion, $match)) {
- $stability = $match[1];
- } else {
- $stability = VersionParser::parseStability($packageVersion);
- }
- }
- $stability = VersionParser::normalizeStability($stability);
- if (!isset(BasePackage::$stabilities[$stability])) {
- throw new \InvalidArgumentException('Invalid stability provided ('.$stability.'), must be one of: '.implode(', ', array_keys(BasePackage::$stabilities)));
- }
- $pool = new Pool($stability);
- $pool->addRepository($sourceRepo);
- $versionSelector = new VersionSelector($pool);
- $package = $versionSelector->findBestCandidate($name, $packageVersion);
- if (!$package) {
- throw new \InvalidArgumentException("Could not find package $name" . ($packageVersion ? " with version $packageVersion." : " with stability $stability."));
- }
- if (null === $directory) {
- $parts = explode("/", $name, 2);
- $directory = getcwd() . DIRECTORY_SEPARATOR . array_pop($parts);
- }
- $io->writeError('<info>Installing ' . $package->getName() . ' (' . VersionParser::formatVersion($package, false) . ')</info>');
- if ($disablePlugins) {
- $io->writeError('<info>Plugins have been disabled.</info>');
- }
- if (0 === strpos($package->getPrettyVersion(), 'dev-') && in_array($package->getSourceType(), array('git', 'hg'))) {
- $package->setSourceReference(substr($package->getPrettyVersion(), 4));
- }
- $dm = $this->createDownloadManager($io, $config);
- $dm->setPreferSource($preferSource)
- ->setPreferDist($preferDist)
- ->setOutputProgress(!$noProgress);
- $projectInstaller = new ProjectInstaller($directory, $dm);
- $im = $this->createInstallationManager();
- $im->addInstaller($projectInstaller);
- $im->install(new InstalledFilesystemRepository(new JsonFile('php://memory')), new InstallOperation($package));
- $im->notifyInstalls();
- $installedFromVcs = 'source' === $package->getInstallationSource();
- $io->writeError('<info>Created project in ' . $directory . '</info>');
- chdir($directory);
- putenv('COMPOSER_ROOT_VERSION='.$package->getPrettyVersion());
- return $installedFromVcs;
- }
- protected function createDownloadManager(IOInterface $io, Config $config)
- {
- $factory = new Factory();
- return $factory->createDownloadManager($io, $config);
- }
- protected function createInstallationManager()
- {
- return new InstallationManager();
- }
- protected function updatePreferredOptions(Config $config, InputInterface $input, &$preferSource, &$preferDist)
- {
- switch ($config->get('preferred-install')) {
- case 'source':
- $preferSource = true;
- $preferDist = false;
- break;
- case 'dist':
- $preferSource = false;
- $preferDist = true;
- break;
- case 'auto':
- default:
- break;
- }
- if ($input->getOption('prefer-source') || $input->getOption('prefer-dist')) {
- $preferSource = $input->getOption('prefer-source');
- $preferDist = $input->getOption('prefer-dist');
- }
- }
- }
- <?php
- namespace Composer\Command;
- use Composer\DependencyResolver\Pool;
- use Composer\Plugin\CommandEvent;
- use Composer\Plugin\PluginEvents;
- use Symfony\Component\Console\Input\InputInterface;
- use Symfony\Component\Console\Input\InputArgument;
- use Symfony\Component\Console\Input\InputOption;
- use Symfony\Component\Console\Output\OutputInterface;
- class DependsCommand extends Command
- {
- protected $linkTypes = array(
- 'require' => array('requires', 'requires'),
- 'require-dev' => array('devRequires', 'requires (dev)'),
- );
- protected function configure()
- {
- $this
- ->setName('depends')
- ->setDescription('Shows which packages depend on the given package')
- ->setDefinition(array(
- new InputArgument('package', InputArgument::REQUIRED, 'Package to inspect'),
- new InputOption('link-type', '', InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'Link types to show (require, require-dev)', array_keys($this->linkTypes)),
- ))
- ->setHelp(<<<EOT
- Displays detailed information about where a package is referenced.
- <info>php composer.phar depends composer/composer</info>
- EOT
- )
- ;
- }
- protected function execute(InputInterface $input, OutputInterface $output)
- {
- $composer = $this->getComposer();
- $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'depends', $input, $output);
- $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
- $repo = $composer->getRepositoryManager()->getLocalRepository();
- $needle = $input->getArgument('package');
- $pool = new Pool();
- $pool->addRepository($repo);
- $packages = $pool->whatProvides($needle);
- if (empty($packages)) {
- throw new \InvalidArgumentException('Could not find package "'.$needle.'" in your project.');
- }
- $linkTypes = $this->linkTypes;
- $types = array_map(function ($type) use ($linkTypes) {
- $type = rtrim($type, 's');
- if (!isset($linkTypes[$type])) {
- throw new \InvalidArgumentException('Unexpected link type: '.$type.', valid types: '.implode(', ', array_keys($linkTypes)));
- }
- return $type;
- }, $input->getOption('link-type'));
- $messages = array();
- $outputPackages = array();
- foreach ($repo->getPackages() as $package) {
- foreach ($types as $type) {
- foreach ($package->{'get'.$linkTypes[$type][0]}() as $link) {
- if ($link->getTarget() === $needle) {
- if (!isset($outputPackages[$package->getName()])) {
- $messages[] = '<info>'.$package->getPrettyName() . '</info> ' . $linkTypes[$type][1] . ' ' . $needle .' (<info>' . $link->getPrettyConstraint() . '</info>)';
- $outputPackages[$package->getName()] = true;
- }
- }
- }
- }
- }
- if ($messages) {
- sort($messages);
- $this->getIO()->write($messages);
- } else {
- $this->getIO()->writeError('<info>There is no installed package depending on "'.$needle.'".</info>');
- }
- }
- }
- <?php
- namespace Composer\Command;
- use Composer\Composer;
- use Composer\Factory;
- use Composer\Downloader\TransportException;
- use Composer\Plugin\CommandEvent;
- use Composer\Plugin\PluginEvents;
- use Composer\Util\ConfigValidator;
- use Composer\Util\ProcessExecutor;
- use Composer\Util\RemoteFilesystem;
- use Composer\Util\StreamContextFactory;
- use Symfony\Component\Console\Input\InputInterface;
- use Symfony\Component\Console\Output\OutputInterface;
- class DiagnoseCommand extends Command
- {
- protected $rfs;
- protected $process;
- protected $failures = 0;
- protected function configure()
- {
- $this
- ->setName('diagnose')
- ->setDescription('Diagnoses the system to identify common errors.')
- ->setHelp(<<<EOT
- The <info>diagnose</info> command checks common errors to help debugging problems.
- EOT
- )
- ;
- }
- protected function execute(InputInterface $input, OutputInterface $output)
- {
- $composer = $this->getComposer(false);
- if ($composer) {
- $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'diagnose', $input, $output);
- $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
- $this->getIO()->write('Checking composer.json: ', false);
- $this->outputResult($this->checkComposerSchema());
- }
- if ($composer) {
- $config = $composer->getConfig();
- } else {
- $config = Factory::createConfig();
- }
- $this->rfs = new RemoteFilesystem($this->getIO(), $config);
- $this->process = new ProcessExecutor($this->getIO());
- $this->getIO()->write('Checking platform settings: ', false);
- $this->outputResult($this->checkPlatform());
- $this->getIO()->write('Checking git settings: ', false);
- $this->outputResult($this->checkGit());
- $this->getIO()->write('Checking http connectivity: ', false);
- $this->outputResult($this->checkHttp());
- $opts = stream_context_get_options(StreamContextFactory::getContext('http://example.org'));
- if (!empty($opts['http']['proxy'])) {
- $this->getIO()->write('Checking HTTP proxy: ', false);
- $this->outputResult($this->checkHttpProxy());
- $this->getIO()->write('Checking HTTP proxy support for request_fulluri: ', false);
- $this->outputResult($this->checkHttpProxyFullUriRequestParam());
- $this->getIO()->write('Checking HTTPS proxy support for request_fulluri: ', false);
- $this->outputResult($this->checkHttpsProxyFullUriRequestParam());
- }
- if ($oauth = $config->get('github-oauth')) {
- foreach ($oauth as $domain => $token) {
- $this->getIO()->write('Checking '.$domain.' oauth access: ', false);
- $this->outputResult($this->checkGithubOauth($domain, $token));
- }
- } else {
- $this->getIO()->write('Checking github.com rate limit: ', false);
- $rate = $this->getGithubRateLimit('github.com');
- if (10 > $rate['remaining']) {
- $this->getIO()->write('<warning>WARNING</warning>');
- $this->getIO()->write(sprintf(
- '<comment>Github has a rate limit on their API. '
- . 'You currently have <options=bold>%u</options=bold> '
- . 'out of <options=bold>%u</options=bold> requests left.' . PHP_EOL
- . 'See https://developer.github.com/v3/#rate-limiting and also' . PHP_EOL
- . ' https://getcomposer.org/doc/articles/troubleshooting.md#api-rate-limit-and-oauth-tokens</comment>',
- $rate['remaining'],
- $rate['limit']
- ));
- } else {
- $this->getIO()->write('<info>OK</info>');
- }
- }
- $this->getIO()->write('Checking disk free space: ', false);
- $this->outputResult($this->checkDiskSpace($config));
- $this->getIO()->write('Checking composer version: ', false);
- $this->outputResult($this->checkVersion());
- return $this->failures;
- }
- private function checkComposerSchema()
- {
- $validator = new ConfigValidator($this->getIO());
- list($errors, $publishErrors, $warnings) = $validator->validate(Factory::getComposerFile());
- if ($errors || $publishErrors || $warnings) {
- $messages = array(
- 'error' => array_merge($errors, $publishErrors),
- 'warning' => $warnings,
- );
- $output = '';
- foreach ($messages as $style => $msgs) {
- foreach ($msgs as $msg) {
- $output .= '<' . $style . '>' . $msg . '</' . $style . '>' . PHP_EOL;
- }
- }
- return rtrim($output);
- }
- return true;
- }
- private function checkGit()
- {
- $this->process->execute('git config color.ui', $output);
- if (strtolower(trim($output)) === 'always') {
- return '<comment>Your git color.ui setting is set to always, this is known to create issues. Use "git config --global color.ui true" to set it correctly.</comment>';
- }
- return true;
- }
- private function checkHttp()
- {
- $protocol = extension_loaded('openssl') ? 'https' : 'http';
- try {
- $this->rfs->getContents('packagist.org', $protocol . '://packagist.org/packages.json', false);
- } catch (\Exception $e) {
- return $e;
- }
- return true;
- }
- private function checkHttpProxy()
- {
- $protocol = extension_loaded('openssl') ? 'https' : 'http';
- try {
- $json = json_decode($this->rfs->getContents('packagist.org', $protocol . '://packagist.org/packages.json', false), true);
- $hash = reset($json['provider-includes']);
- $hash = $hash['sha256'];
- $path = str_replace('%hash%', $hash, key($json['provider-includes']));
- $provider = $this->rfs->getContents('packagist.org', $protocol . '://packagist.org/'.$path, false);
- if (hash('sha256', $provider) !== $hash) {
- return 'It seems that your proxy is modifying http traffic on the fly';
- }
- } catch (\Exception $e) {
- return $e;
- }
- return true;
- }
- private function checkHttpProxyFullUriRequestParam()
- {
- $url = 'http://packagist.org/packages.json';
- try {
- $this->rfs->getContents('packagist.org', $url, false);
- } catch (TransportException $e) {
- try {
- $this->rfs->getContents('packagist.org', $url, false, array('http' => array('request_fulluri' => false)));
- } catch (TransportException $e) {
- return 'Unable to assess the situation, maybe packagist.org is down ('.$e->getMessage().')';
- }
- return 'It seems there is a problem with your proxy server, try setting the "HTTP_PROXY_REQUEST_FULLURI" and "HTTPS_PROXY_REQUEST_FULLURI" environment variables to "false"';
- }
- return true;
- }
- private function checkHttpsProxyFullUriRequestParam()
- {
- if (!extension_loaded('openssl')) {
- return 'You need the openssl extension installed for this check';
- }
- $url = 'https://api.github.com/repos/Seldaek/jsonlint/zipball/1.0.0';
- try {
- $this->rfs->getContents('github.com', $url, false);
- } catch (TransportException $e) {
- try {
- $this->rfs->getContents('github.com', $url, false, array('http' => array('request_fulluri' => false)));
- } catch (TransportException $e) {
- return 'Unable to assess the situation, maybe github is down ('.$e->getMessage().')';
- }
- return 'It seems there is a problem with your proxy server, try setting the "HTTPS_PROXY_REQUEST_FULLURI" environment variable to "false"';
- }
- return true;
- }
- private function checkGithubOauth($domain, $token)
- {
- $this->getIO()->setAuthentication($domain, $token, 'x-oauth-basic');
- try {
- $url = $domain === 'github.com' ? 'https://api.'.$domain.'/user/repos' : 'https://'.$domain.'/api/v3/user/repos';
- return $this->rfs->getContents($domain, $url, false, array(
- 'retry-auth-failure' => false
- )) ? true : 'Unexpected error';
- } catch (\Exception $e) {
- if ($e instanceof TransportException && $e->getCode() === 401) {
- return '<comment>The oauth token for '.$domain.' seems invalid, run "composer config --global --unset github-oauth.'.$domain.'" to remove it</comment>';
- }
- return $e;
- }
- }
- private function getGithubRateLimit($domain, $token = null)
- {
- if ($token) {
- $this->getIO()->setAuthentication($domain, $token, 'x-oauth-basic');
- }
- try {
- $url = $domain === 'github.com' ? 'https://api.'.$domain.'/rate_limit' : 'https://'.$domain.'/api/rate_limit';
- $json = $this->rfs->getContents($domain, $url, false, array('retry-auth-failure' => false));
- $data = json_decode($json, true);
- return $data['resources']['core'];
- } catch (\Exception $e) {
- if ($e instanceof TransportException && $e->getCode() === 401) {
- return '<comment>The oauth token for '.$domain.' seems invalid, run "composer config --global --unset github-oauth.'.$domain.'" to remove it</comment>';
- }
- return $e;
- }
- }
- private function checkDiskSpace($config)
- {
- $minSpaceFree = 1024*1024;
- if ((($df = @disk_free_space($dir = $config->get('home'))) !== false && $df < $minSpaceFree)
- || (($df = @disk_free_space($dir = $config->get('vendor-dir'))) !== false && $df < $minSpaceFree)
- ) {
- return '<error>The disk hosting '.$dir.' is full</error>';
- }
- return true;
- }
- private function checkVersion()
- {
- $protocol = extension_loaded('openssl') ? 'https' : 'http';
- $latest = trim($this->rfs->getContents('getcomposer.org', $protocol . '://getcomposer.org/version', false));
- if (Composer::VERSION !== $latest && Composer::VERSION !== '@package_version@') {
- return '<comment>You are not running the latest version</comment>';
- }
- return true;
- }
- private function outputResult($result)
- {
- if (true === $result) {
- $this->getIO()->write('<info>OK</info>');
- } else {
- $this->failures++;
- $this->getIO()->write('<error>FAIL</error>');
- if ($result instanceof \Exception) {
- $this->getIO()->write('['.get_class($result).'] '.$result->getMessage());
- } elseif ($result) {
- $this->getIO()->write(trim($result));
- }
- }
- }
- private function checkPlatform()
- {
- $output = '';
- $out = function ($msg, $style) use (&$output) {
- $output .= '<'.$style.'>'.$msg.'</'.$style.'>'.PHP_EOL;
- };
- $errors = array();
- $warnings = array();
- $iniPath = php_ini_loaded_file();
- $displayIniMessage = false;
- if ($iniPath) {
- $iniMessage = PHP_EOL.PHP_EOL.'The php.ini used by your command-line PHP is: ' . $iniPath;
- } else {
- $iniMessage = PHP_EOL.PHP_EOL.'A php.ini file does not exist. You will have to create one.';
- }
- $iniMessage .= PHP_EOL.'If you can not modify the ini file, you can also run `php -d option=value` to modify ini values on the fly. You can use -d multiple times.';
- if (!function_exists('json_decode')) {
- $errors['json'] = true;
- }
- if (!extension_loaded('Phar')) {
- $errors['phar'] = true;
- }
- if (!extension_loaded('filter')) {
- $errors['filter'] = true;
- }
- if (!extension_loaded('hash')) {
- $errors['hash'] = true;
- }
- if (!extension_loaded('ctype')) {
- $errors['ctype'] = true;
- }
- if (!ini_get('allow_url_fopen')) {
- $errors['allow_url_fopen'] = true;
- }
- if (extension_loaded('ionCube Loader') && ioncube_loader_iversion() < 40009) {
- $errors['ioncube'] = ioncube_loader_version();
- }
- if (version_compare(PHP_VERSION, '5.3.2', '<')) {
- $errors['php'] = PHP_VERSION;
- }
- if (!isset($errors['php']) && version_compare(PHP_VERSION, '5.3.4', '<')) {
- $warnings['php'] = PHP_VERSION;
- }
- if (!extension_loaded('openssl')) {
- $errors['openssl'] = true;
- }
- if (!defined('HHVM_VERSION') && !extension_loaded('apcu') && ini_get('apc.enable_cli')) {
- $warnings['apc_cli'] = true;
- }
- ob_start();
- phpinfo(INFO_GENERAL);
- $phpinfo = ob_get_clean();
- if (preg_match('{Configure Command(?: *</td><td class="v">| *=> *)(.*?)(?:</td>|$)}m', $phpinfo, $match)) {
- $configure = $match[1];
- if (false !== strpos($configure, '--enable-sigchild')) {
- $warnings['sigchild'] = true;
- }
- if (false !== strpos($configure, '--with-curlwrappers')) {
- $warnings['curlwrappers'] = true;
- }
- }
- if (ini_get('xdebug.profiler_enabled')) {
- $warnings['xdebug_profile'] = true;
- } elseif (extension_loaded('xdebug')) {
- $warnings['xdebug_loaded'] = true;
- }
- if (!empty($errors)) {
- foreach ($errors as $error => $current) {
- switch ($error) {
- case 'json':
- $text = PHP_EOL."The json extension is missing.".PHP_EOL;
- $text .= "Install it or recompile php without --disable-json";
- break;
- case 'phar':
- $text = PHP_EOL."The phar extension is missing.".PHP_EOL;
- $text .= "Install it or recompile php without --disable-phar";
- break;
- case 'filter':
- $text = PHP_EOL."The filter extension is missing.".PHP_EOL;
- $text .= "Install it or recompile php without --disable-filter";
- break;
- case 'hash':
- $text = PHP_EOL."The hash extension is missing.".PHP_EOL;
- $text .= "Install it or recompile php without --disable-hash";
- break;
- case 'ctype':
- $text = PHP_EOL."The ctype extension is missing.".PHP_EOL;
- $text .= "Install it or recompile php without --disable-ctype";
- break;
- case 'unicode':
- $text = PHP_EOL."The detect_unicode setting must be disabled.".PHP_EOL;
- $text .= "Add the following to the end of your `php.ini`:".PHP_EOL;
- $text .= " detect_unicode = Off";
- $displayIniMessage = true;
- break;
- case 'suhosin':
- $text = PHP_EOL."The suhosin.executor.include.whitelist setting is incorrect.".PHP_EOL;
- $text .= "Add the following to the end of your `php.ini` or suhosin.ini (Example path [for Debian]: /etc/php5/cli/conf.d/suhosin.ini):".PHP_EOL;
- $text .= " suhosin.executor.include.whitelist = phar ".$current;
- $displayIniMessage = true;
- break;
- case 'php':
- $text = PHP_EOL."Your PHP ({$current}) is too old, you must upgrade to PHP 5.3.2 or higher.";
- break;
- case 'allow_url_fopen':
- $text = PHP_EOL."The allow_url_fopen setting is incorrect.".PHP_EOL;
- $text .= "Add the following to the end of your `php.ini`:".PHP_EOL;
- $text .= " allow_url_fopen = On";
- $displayIniMessage = true;
- break;
- case 'ioncube':
- $text = PHP_EOL."Your ionCube Loader extension ($current) is incompatible with Phar files.".PHP_EOL;
- $text .= "Upgrade to ionCube 4.0.9 or higher or remove this line (path may be different) from your `php.ini` to disable it:".PHP_EOL;
- $text .= " zend_extension = /usr/lib/php5/20090626+lfs/ioncube_loader_lin_5.3.so";
- $displayIniMessage = true;
- break;
- case 'openssl':
- $text = PHP_EOL."The openssl extension is missing, which means that secure HTTPS transfers are impossible.".PHP_EOL;
- $text .= "If possible you should enable it or recompile php with --with-openssl";
- break;
- }
- $out($text, 'error');
- }
- $output .= PHP_EOL;
- }
- if (!empty($warnings)) {
- foreach ($warnings as $warning => $current) {
- switch ($warning) {
- case 'apc_cli':
- $text = "The apc.enable_cli setting is incorrect.".PHP_EOL;
- $text .= "Add the following to the end of your `php.ini`:".PHP_EOL;
- $text .= " apc.enable_cli = Off";
- $displayIniMessage = true;
- break;
- case 'sigchild':
- $text = "PHP was compiled with --enable-sigchild which can cause issues on some platforms.".PHP_EOL;
- $text .= "Recompile it without this flag if possible, see also:".PHP_EOL;
- $text .= " https://bugs.php.net/bug.php?id=22999";
- break;
- case 'curlwrappers':
- $text = "PHP was compiled with --with-curlwrappers which will cause issues with HTTP authentication and GitHub.".PHP_EOL;
- $text .= " Recompile it without this flag if possible";
- break;
- case 'php':
- $text = "Your PHP ({$current}) is quite old, upgrading to PHP 5.3.4 or higher is recommended.".PHP_EOL;
- $text .= " Composer works with 5.3.2+ for most people, but there might be edge case issues.";
- break;
- case 'xdebug_loaded':
- $text = "The xdebug extension is loaded, this can slow down Composer a little.".PHP_EOL;
- $text .= " Disabling it when using Composer is recommended.";
- break;
- case 'xdebug_profile':
- $text = "The xdebug.profiler_enabled setting is enabled, this can slow down Composer a lot.".PHP_EOL;
- $text .= "Add the following to the end of your `php.ini` to disable it:".PHP_EOL;
- $text .= " xdebug.profiler_enabled = 0";
- $displayIniMessage = true;
- break;
- }
- $out($text, 'comment');
- }
- }
- if ($displayIniMessage) {
- $out($iniMessage, 'comment');
- }
- return !$warnings && !$errors ? true : $output;
- }
- }
- <?php
- namespace Composer\Command;
- use Composer\Plugin\CommandEvent;
- use Composer\Plugin\PluginEvents;
- use Symfony\Component\Console\Input\InputInterface;
- use Symfony\Component\Console\Input\InputOption;
- use Symfony\Component\Console\Output\OutputInterface;
- class DumpAutoloadCommand extends Command
- {
- protected function configure()
- {
- $this
- ->setName('dump-autoload')
- ->setAliases(array('dumpautoload'))
- ->setDescription('Dumps the autoloader')
- ->setDefinition(array(
- new InputOption('optimize', 'o', InputOption::VALUE_NONE, 'Optimizes PSR0 and PSR4 packages to be loaded with classmaps too, good for production.'),
- new InputOption('no-dev', null, InputOption::VALUE_NONE, 'Disables autoload-dev rules.'),
- ))
- ->setHelp(<<<EOT
- <info>php composer.phar dump-autoload</info>
- EOT
- )
- ;
- }
- protected function execute(InputInterface $input, OutputInterface $output)
- {
- $composer = $this->getComposer();
- $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'dump-autoload', $input, $output);
- $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
- $installationManager = $composer->getInstallationManager();
- $localRepo = $composer->getRepositoryManager()->getLocalRepository();
- $package = $composer->getPackage();
- $config = $composer->getConfig();
- $optimize = $input->getOption('optimize') || $config->get('optimize-autoloader') || $config->get('classmap-authoritative');
- if ($optimize) {
- $this->getIO()->writeError('<info>Generating optimized autoload files</info>');
- } else {
- $this->getIO()->writeError('<info>Generating autoload files</info>');
- }
- $generator = $composer->getAutoloadGenerator();
- $generator->setDevMode(!$input->getOption('no-dev'));
- $generator->dump($config, $localRepo, $package, $installationManager, 'composer', $optimize);
- }
- }
- <?php
- namespace Composer\Command;
- use Composer\Factory;
- use Symfony\Component\Console\Input\InputInterface;
- use Symfony\Component\Console\Input\InputArgument;
- use Symfony\Component\Console\Input\StringInput;
- use Symfony\Component\Console\Output\OutputInterface;
- class GlobalCommand extends Command
- {
- protected function configure()
- {
- $this
- ->setName('global')
- ->setDescription('Allows running commands in the global composer dir ($COMPOSER_HOME).')
- ->setDefinition(array(
- new InputArgument('command-name', InputArgument::REQUIRED, ''),
- new InputArgument('args', InputArgument::IS_ARRAY | InputArgument::OPTIONAL, ''),
- ))
- ->setHelp(<<<EOT
- Use this command as a wrapper to run other Composer commands
- within the global context of COMPOSER_HOME.
- You can use this to install CLI utilities globally, all you need
- is to add the COMPOSER_HOME/vendor/bin dir to your PATH env var.
- COMPOSER_HOME is c:\Users\<user>\AppData\Roaming\Composer on Windows
- and /home/<user>/.composer on unix systems.
- Note: This path may vary depending on customizations to bin-dir in
- composer.json or the environmental variable COMPOSER_BIN_DIR.
- EOT
- )
- ;
- }
- public function run(InputInterface $input, OutputInterface $output)
- {
- $tokens = preg_split('{\s+}', $input->__toString());
- $args = array();
- foreach ($tokens as $token) {
- if ($token && $token[0] !== '-') {
- $args[] = $token;
- if (count($args) >= 2) {
- break;
- }
- }
- }
- if (count($args) < 2) {
- return parent::run($input, $output);
- }
- $config = Factory::createConfig();
- chdir($config->get('home'));
- $this->getIO()->writeError('<info>Changed current directory to '.$config->get('home').'</info>');
- $input = new StringInput(preg_replace('{\bg(?:l(?:o(?:b(?:a(?:l)?)?)?)?)?\b}', '', $input->__toString(), 1));
- return $this->getApplication()->run($input, $output);
- }
- }
- <?php
- namespace Composer\Command\Helper;
- use Symfony\Component\Console\Helper\DialogHelper as BaseDialogHelper;
- class DialogHelper extends BaseDialogHelper
- {
- public function getQuestion($question, $default = null, $sep = ':')
- {
- return $default !== null ?
- sprintf('<info>%s</info> [<comment>%s</comment>]%s ', $question, $default, $sep) :
- sprintf('<info>%s</info>%s ', $question, $sep);
- }
- }
- <?php
- namespace Composer\Command;
- use Composer\DependencyResolver\Pool;
- use Composer\Factory;
- use Composer\Package\CompletePackageInterface;
- use Composer\Repository\CompositeRepository;
- use Composer\Repository\RepositoryInterface;
- use Composer\Util\ProcessExecutor;
- use Symfony\Component\Console\Input\InputArgument;
- use Symfony\Component\Console\Input\InputOption;
- use Symfony\Component\Console\Input\InputInterface;
- use Symfony\Component\Console\Output\OutputInterface;
- class HomeCommand extends Command
- {
- protected function configure()
- {
- $this
- ->setName('browse')
- ->setAliases(array('home'))
- ->setDescription('Opens the package\'s repository URL or homepage in your browser.')
- ->setDefinition(array(
- new InputArgument('packages', InputArgument::IS_ARRAY | InputArgument::REQUIRED, 'Package(s) to browse to.'),
- new InputOption('homepage', 'H', InputOption::VALUE_NONE, 'Open the homepage instead of the repository URL.'),
- new InputOption('show', 's', InputOption::VALUE_NONE, 'Only show the homepage or repository URL.'),
- ))
- ->setHelp(<<<EOT
- The home command opens or shows a package's repository URL or
- homepage in your default browser.
- To open the homepage by default, use -H or --homepage.
- To show instead of open the repository or homepage URL, use -s or --show.
- EOT
- );
- }
- protected function execute(InputInterface $input, OutputInterface $output)
- {
- $repos = $this->initializeRepos();
- $return = 0;
- foreach ($input->getArgument('packages') as $packageName) {
- foreach ($repos as $repo) {
- $package = $this->getPackage($repo, $packageName);
- if ($package instanceof CompletePackageInterface) {
- break;
- }
- }
- $package = $this->getPackage($repo, $packageName);
- if (!$package instanceof CompletePackageInterface) {
- $return = 1;
- $this->getIO()->writeError('<warning>Package '.$packageName.' not found</warning>');
- continue;
- }
- $support = $package->getSupport();
- $url = isset($support['source']) ? $support['source'] : $package->getSourceUrl();
- if (!$url || $input->getOption('homepage')) {
- $url = $package->getHomepage();
- }
- if (!filter_var($url, FILTER_VALIDATE_URL)) {
- $return = 1;
- $this->getIO()->writeError('<warning>'.($input->getOption('homepage') ? 'Invalid or missing homepage' : 'Invalid or missing repository URL').' for '.$packageName.'</warning>');
- continue;
- }
- if ($input->getOption('show')) {
- $this->getIO()->write(sprintf('<info>%s</info>', $url));
- } else {
- $this->openBrowser($url);
- }
- }
- return $return;
- }
- protected function getPackage(RepositoryInterface $repos, $name)
- {
- $name = strtolower($name);
- $pool = new Pool('dev');
- $pool->addRepository($repos);
- $matches = $pool->whatProvides($name);
- foreach ($matches as $index => $package) {
- if ($package->getName() !== $name) {
- unset($matches[$index]);
- continue;
- }
- return $package;
- }
- }
- private function openBrowser($url)
- {
- $url = ProcessExecutor::escape($url);
- if (defined('PHP_WINDOWS_VERSION_MAJOR')) {
- return passthru('start "web" explorer "' . $url . '"');
- }
- passthru('which xdg-open', $linux);
- passthru('which open', $osx);
- if (0 === $linux) {
- passthru('xdg-open ' . $url);
- } elseif (0 === $osx) {
- passthru('open ' . $url);
- } else {
- $this->getIO()->writeError('no suitable browser opening command found, open yourself: ' . $url);
- }
- }
- private function initializeRepos()
- {
- $composer = $this->getComposer(false);
- if ($composer) {
- return array(
- $composer->getRepositoryManager()->getLocalRepository(),
- new CompositeRepository($composer->getRepositoryManager()->getRepositories())
- );
- }
- $defaultRepos = Factory::createDefaultRepositories($this->getIO());
- return array(new CompositeRepository($defaultRepos));
- }
- }
- <?php
- namespace Composer\Command;
- use Composer\DependencyResolver\Pool;
- use Composer\Json\JsonFile;
- use Composer\Factory;
- use Composer\Package\BasePackage;
- use Composer\Package\Version\VersionSelector;
- use Composer\Repository\CompositeRepository;
- use Composer\Repository\PlatformRepository;
- use Composer\Package\Version\VersionParser;
- use Composer\Util\ProcessExecutor;
- use Symfony\Component\Console\Input\InputInterface;
- use Symfony\Component\Console\Input\InputOption;
- use Symfony\Component\Console\Output\OutputInterface;
- use Symfony\Component\Process\Process;
- use Symfony\Component\Process\ExecutableFinder;
- class InitCommand extends Command
- {
- protected $repos;
- private $gitConfig;
- private $pool;
- public function parseAuthorString($author)
- {
- if (preg_match('/^(?P<name>[- \.,\p{L}\'’]+) <(?P<email>.+?)>$/u', $author, $match)) {
- if ($this->isValidEmail($match['email'])) {
- return array(
- 'name' => trim($match['name']),
- 'email' => $match['email']
- );
- }
- }
- throw new \InvalidArgumentException(
- 'Invalid author string. Must be in the format: '.
- 'John Smith <john@example.com>'
- );
- }
- protected function configure()
- {
- $this
- ->setName('init')
- ->setDescription('Creates a basic composer.json file in current directory.')
- ->setDefinition(array(
- new InputOption('name', null, InputOption::VALUE_REQUIRED, 'Name of the package'),
- new InputOption('description', null, InputOption::VALUE_REQUIRED, 'Description of package'),
- new InputOption('author', null, InputOption::VALUE_REQUIRED, 'Author name of package'),
- new InputOption('homepage', null, InputOption::VALUE_REQUIRED, 'Homepage of package'),
- new InputOption('require', null, InputOption::VALUE_IS_ARRAY | InputOption::VALUE_REQUIRED, 'Package to require with a version constraint, e.g. foo/bar:1.0.0 or foo/bar=1.0.0 or "foo/bar 1.0.0"'),
- new InputOption('require-dev', null, InputOption::VALUE_IS_ARRAY | InputOption::VALUE_REQUIRED, 'Package to require for development with a version constraint, e.g. foo/bar:1.0.0 or foo/bar=1.0.0 or "foo/bar 1.0.0"'),
- new InputOption('stability', 's', InputOption::VALUE_REQUIRED, 'Minimum stability (empty or one of: '.implode(', ', array_keys(BasePackage::$stabilities)).')'),
- new InputOption('license', 'l', InputOption::VALUE_REQUIRED, 'License of package'),
- ))
- ->setHelp(<<<EOT
- The <info>init</info> command creates a basic composer.json file
- in the current directory.
- <info>php composer.phar init</info>
- EOT
- )
- ;
- }
- protected function execute(InputInterface $input, OutputInterface $output)
- {
- $dialog = $this->getHelperSet()->get('dialog');
- $whitelist = array('name', 'description', 'author', 'homepage', 'require', 'require-dev', 'stability', 'license');
- $options = array_filter(array_intersect_key($input->getOptions(), array_flip($whitelist)));
- if (isset($options['author'])) {
- $options['authors'] = $this->formatAuthors($options['author']);
- unset($options['author']);
- }
- if (isset($options['stability'])) {
- $options['minimum-stability'] = $options['stability'];
- unset($options['stability']);
- }
- $options['require'] = isset($options['require']) ? $this->formatRequirements($options['require']) : new \stdClass;
- if (array() === $options['require']) {
- $options['require'] = new \stdClass;
- }
- if (isset($options['require-dev'])) {
- $options['require-dev'] = $this->formatRequirements($options['require-dev']);
- if (array() === $options['require-dev']) {
- $options['require-dev'] = new \stdClass;
- }
- }
- $file = new JsonFile('composer.json');
- $json = $file->encode($options);
- if ($input->isInteractive()) {
- $this->getIO()->writeError(array(
- '',
- $json,
- ''
- ));
- if (!$dialog->askConfirmation($output, $dialog->getQuestion('Do you confirm generation', 'yes', '?'), true)) {
- $this->getIO()->writeError('<error>Command aborted</error>');
- return 1;
- }
- }
- $file->write($options);
- if ($input->isInteractive() && is_dir('.git')) {
- $ignoreFile = realpath('.gitignore');
- if (false === $ignoreFile) {
- $ignoreFile = realpath('.') . '/.gitignore';
- }
- if (!$this->hasVendorIgnore($ignoreFile)) {
- $question = 'Would you like the <info>vendor</info> directory added to your <info>.gitignore</info> [<comment>yes</comment>]?';
- if ($dialog->askConfirmation($output, $question, true)) {
- $this->addVendorIgnore($ignoreFile);
- }
- }
- }
- }
- protected function interact(InputInterface $input, OutputInterface $output)
- {
- $git = $this->getGitConfig();
- $dialog = $this->getHelperSet()->get('dialog');
- $formatter = $this->getHelperSet()->get('formatter');
- $this->getIO()->writeError(array(
- '',
- $formatter->formatBlock('Welcome to the Composer config generator', 'bg=blue;fg=white', true),
- ''
- ));
- $this->getIO()->writeError(array(
- '',
- 'This command will guide you through creating your composer.json config.',
- '',
- ));
- $cwd = realpath(".");
- if (!$name = $input->getOption('name')) {
- $name = basename($cwd);
- $name = preg_replace('{(?:([a-z])([A-Z])|([A-Z])([A-Z][a-z]))}', '\\1\\3-\\2\\4', $name);
- $name = strtolower($name);
- if (isset($git['github.user'])) {
- $name = $git['github.user'] . '/' . $name;
- } elseif (!empty($_SERVER['USERNAME'])) {
- $name = $_SERVER['USERNAME'] . '/' . $name;
- } elseif (get_current_user()) {
- $name = get_current_user() . '/' . $name;
- } else {
- $name = $name . '/' . $name;
- }
- } else {
- if (!preg_match('{^[a-z0-9_.-]+/[a-z0-9_.-]+$}', $name)) {
- throw new \InvalidArgumentException(
- 'The package name '.$name.' is invalid, it should be lowercase and have a vendor name, a forward slash, and a package name, matching: [a-z0-9_.-]+/[a-z0-9_.-]+'
- );
- }
- }
- $name = $dialog->askAndValidate(
- $output,
- $dialog->getQuestion('Package name (<vendor>/<name>)', $name),
- function ($value) use ($name) {
- if (null === $value) {
- return $name;
- }
- if (!preg_match('{^[a-z0-9_.-]+/[a-z0-9_.-]+$}', $value)) {
- throw new \InvalidArgumentException(
- 'The package name '.$value.' is invalid, it should be lowercase and have a vendor name, a forward slash, and a package name, matching: [a-z0-9_.-]+/[a-z0-9_.-]+'
- );
- }
- return $value;
- }
- );
- $input->setOption('name', $name);
- $description = $input->getOption('description') ?: false;
- $description = $dialog->ask(
- $output,
- $dialog->getQuestion('Description', $description),
- $description
- );
- $input->setOption('description', $description);
- if (null === $author = $input->getOption('author')) {
- if (isset($git['user.name']) && isset($git['user.email'])) {
- $author = sprintf('%s <%s>', $git['user.name'], $git['user.email']);
- }
- }
- $self = $this;
- $author = $dialog->askAndValidate(
- $output,
- $dialog->getQuestion('Author', $author),
- function ($value) use ($self, $author) {
- $value = $value ?: $author;
- $author = $self->parseAuthorString($value);
- return sprintf('%s <%s>', $author['name'], $author['email']);
- }
- );
- $input->setOption('author', $author);
- $minimumStability = $input->getOption('stability') ?: '';
- $minimumStability = $dialog->askAndValidate(
- $output,
- $dialog->getQuestion('Minimum Stability', $minimumStability),
- function ($value) use ($self, $minimumStability) {
- if (null === $value) {
- return $minimumStability;
- }
- if (!isset(BasePackage::$stabilities[$value])) {
- throw new \InvalidArgumentException(
- 'Invalid minimum stability "'.$value.'". Must be empty or one of: '.
- implode(', ', array_keys(BasePackage::$stabilities))
- );
- }
- return $value;
- }
- );
- $input->setOption('stability', $minimumStability);
- $license = $input->getOption('license') ?: false;
- $license = $dialog->ask(
- $output,
- $dialog->getQuestion('License', $license),
- $license
- );
- $input->setOption('license', $license);
- $this->getIO()->writeError(array(
- '',
- 'Define your dependencies.',
- ''
- ));
- $requirements = array();
- if ($dialog->askConfirmation($output, $dialog->getQuestion('Would you like to define your dependencies (require) interactively', 'yes', '?'), true)) {
- $requirements = $this->determineRequirements($input, $output, $input->getOption('require'));
- }
- $input->setOption('require', $requirements);
- $devRequirements = array();
- if ($dialog->askConfirmation($output, $dialog->getQuestion('Would you like to define your dev dependencies (require-dev) interactively', 'yes', '?'), true)) {
- $devRequirements = $this->determineRequirements($input, $output, $input->getOption('require-dev'));
- }
- $input->setOption('require-dev', $devRequirements);
- }
- protected function findPackages($name)
- {
- return $this->getRepos()->search($name);
- }
- protected function getRepos()
- {
- if (!$this->repos) {
- $this->repos = new CompositeRepository(array_merge(
- array(new PlatformRepository),
- Factory::createDefaultRepositories($this->getIO())
- ));
- }
- return $this->repos;
- }
- protected function determineRequirements(InputInterface $input, OutputInterface $output, $requires = array())
- {
- $dialog = $this->getHelperSet()->get('dialog');
- $prompt = $dialog->getQuestion('Search for a package', false, ':');
- if ($requires) {
- $requires = $this->normalizeRequirements($requires);
- $result = array();
- foreach ($requires as $requirement) {
- if (!isset($requirement['version'])) {
- $version = $this->findBestVersionForPackage($input, $requirement['name']);
- $requirement['version'] = $version;
- $this->getIO()->writeError(sprintf(
- 'Using version <info>%s</info> for <info>%s</info>',
- $requirement['version'],
- $requirement['name']
- ));
- }
- $result[] = $requirement['name'] . ' ' . $requirement['version'];
- }
- return $result;
- }
- while (null !== $package = $dialog->ask($output, $prompt)) {
- $matches = $this->findPackages($package);
- if (count($matches)) {
- $exactMatch = null;
- $choices = array();
- foreach ($matches as $position => $foundPackage) {
- $choices[] = sprintf(' <info>%5s</info> %s', "[$position]", $foundPackage['name']);
- if ($foundPackage['name'] === $package) {
- $exactMatch = true;
- break;
- }
- }
- if (!$exactMatch) {
- $this->getIO()->writeError(array(
- '',
- sprintf('Found <info>%s</info> packages matching <info>%s</info>', count($matches), $package),
- ''
- ));
- $this->getIO()->writeError($choices);
- $this->getIO()->writeError('');
- $validator = function ($selection) use ($matches) {
- if ('' === $selection) {
- return false;
- }
- if (!is_numeric($selection) && preg_match('{^\s*(\S+)\s+(\S.*)\s*$}', $selection, $matches)) {
- return $matches[1].' '.$matches[2];
- }
- if (!isset($matches[(int) $selection])) {
- throw new \Exception('Not a valid selection');
- }
- $package = $matches[(int) $selection];
- return $package['name'];
- };
- $package = $dialog->askAndValidate($output, $dialog->getQuestion('Enter package # to add, or the complete package name if it is not listed', false, ':'), $validator, 3);
- }
- if (false !== $package && false === strpos($package, ' ')) {
- $validator = function ($input) {
- $input = trim($input);
- return $input ?: false;
- };
- $constraint = $dialog->askAndValidate(
- $output,
- $dialog->getQuestion('Enter the version constraint to require (or leave blank to use the latest version)', false, ':'),
- $validator,
- 3)
- ;
- if (false === $constraint) {
- $constraint = $this->findBestVersionForPackage($input, $package);
- $this->getIO()->writeError(sprintf(
- 'Using version <info>%s</info> for <info>%s</info>',
- $constraint,
- $package
- ));
- }
- $package .= ' '.$constraint;
- }
- if (false !== $package) {
- $requires[] = $package;
- }
- }
- }
- return $requires;
- }
- protected function formatAuthors($author)
- {
- return array($this->parseAuthorString($author));
- }
- protected function formatRequirements(array $requirements)
- {
- $requires = array();
- $requirements = $this->normalizeRequirements($requirements);
- foreach ($requirements as $requirement) {
- $requires[$requirement['name']] = $requirement['version'];
- }
- return $requires;
- }
- protected function getGitConfig()
- {
- if (null !== $this->gitConfig) {
- return $this->gitConfig;
- }
- $finder = new ExecutableFinder();
- $gitBin = $finder->find('git');
- $cmd = new Process(sprintf('%s config -l', ProcessExecutor::escape($gitBin)));
- $cmd->run();
- if ($cmd->isSuccessful()) {
- $this->gitConfig = array();
- preg_match_all('{^([^=]+)=(.*)$}m', $cmd->getOutput(), $matches, PREG_SET_ORDER);
- foreach ($matches as $match) {
- $this->gitConfig[$match[1]] = $match[2];
- }
- return $this->gitConfig;
- }
- return $this->gitConfig = array();
- }
- protected function hasVendorIgnore($ignoreFile, $vendor = 'vendor')
- {
- if (!file_exists($ignoreFile)) {
- return false;
- }
- $pattern = sprintf('{^/?%s(/\*?)?$}', preg_quote($vendor));
- $lines = file($ignoreFile, FILE_IGNORE_NEW_LINES);
- foreach ($lines as $line) {
- if (preg_match($pattern, $line)) {
- return true;
- }
- }
- return false;
- }
- protected function normalizeRequirements(array $requirements)
- {
- $parser = new VersionParser();
- return $parser->parseNameVersionPairs($requirements);
- }
- protected function addVendorIgnore($ignoreFile, $vendor = '/vendor/')
- {
- $contents = "";
- if (file_exists($ignoreFile)) {
- $contents = file_get_contents($ignoreFile);
- if ("\n" !== substr($contents, 0, -1)) {
- $contents .= "\n";
- }
- }
- file_put_contents($ignoreFile, $contents . $vendor. "\n");
- }
- protected function isValidEmail($email)
- {
- if (!function_exists('filter_var')) {
- return true;
- }
- if (version_compare(PHP_VERSION, '5.3.3', '<')) {
- return true;
- }
- return false !== filter_var($email, FILTER_VALIDATE_EMAIL);
- }
- private function getPool(InputInterface $input)
- {
- if (!$this->pool) {
- $this->pool = new Pool($this->getMinimumStability($input));
- $this->pool->addRepository($this->getRepos());
- }
- return $this->pool;
- }
- private function getMinimumStability(InputInterface $input)
- {
- if ($input->hasOption('stability')) {
- return $input->getOption('stability') ?: 'stable';
- }
- $file = Factory::getComposerFile();
- if (is_file($file) && is_readable($file) && is_array($composer = json_decode(file_get_contents($file), true))) {
- if (!empty($composer['minimum-stability'])) {
- return $composer['minimum-stability'];
- }
- }
- return 'stable';
- }
- private function findBestVersionForPackage(InputInterface $input, $name)
- {
- $versionSelector = new VersionSelector($this->getPool($input));
- $package = $versionSelector->findBestCandidate($name);
- if (!$package) {
- throw new \InvalidArgumentException(sprintf(
- 'Could not find package %s at any version for your minimum-stability (%s). Check the package spelling or your minimum-stability',
- $name,
- $this->getMinimumStability($input)
- ));
- }
- return $versionSelector->findRecommendedRequireVersion($package);
- }
- }
- <?php
- namespace Composer\Command;
- use Composer\Installer;
- use Composer\Plugin\CommandEvent;
- use Composer\Plugin\PluginEvents;
- use Symfony\Component\Console\Input\InputInterface;
- use Symfony\Component\Console\Input\InputOption;
- use Symfony\Component\Console\Input\InputArgument;
- use Symfony\Component\Console\Output\OutputInterface;
- class InstallCommand extends Command
- {
- protected function configure()
- {
- $this
- ->setName('install')
- ->setDescription('Installs the project dependencies from the composer.lock file if present, or falls back on the composer.json.')
- ->setDefinition(array(
- new InputOption('prefer-source', null, InputOption::VALUE_NONE, 'Forces installation from package sources when possible, including VCS information.'),
- new InputOption('prefer-dist', null, InputOption::VALUE_NONE, 'Forces installation from package dist even for dev versions.'),
- new InputOption('dry-run', null, InputOption::VALUE_NONE, 'Outputs the operations but will not execute anything (implicitly enables --verbose).'),
- new InputOption('dev', null, InputOption::VALUE_NONE, 'Enables installation of require-dev packages (enabled by default, only present for BC).'),
- new InputOption('no-dev', null, InputOption::VALUE_NONE, 'Disables installation of require-dev packages.'),
- new InputOption('no-plugins', null, InputOption::VALUE_NONE, 'Disables all plugins.'),
- new InputOption('no-custom-installers', null, InputOption::VALUE_NONE, 'DEPRECATED: Use no-plugins instead.'),
- new InputOption('no-autoloader', null, InputOption::VALUE_NONE, 'Skips autoloader generation'),
- new InputOption('no-scripts', null, InputOption::VALUE_NONE, 'Skips the execution of all scripts defined in composer.json file.'),
- new InputOption('no-progress', null, InputOption::VALUE_NONE, 'Do not output download progress.'),
- new InputOption('verbose', 'v|vv|vvv', InputOption::VALUE_NONE, 'Shows more details including new commits pulled in when updating packages.'),
- new InputOption('optimize-autoloader', 'o', InputOption::VALUE_NONE, 'Optimize autoloader during autoloader dump'),
- new InputOption('ignore-platform-reqs', null, InputOption::VALUE_NONE, 'Ignore platform requirements (php & ext- packages).'),
- new InputArgument('packages', InputArgument::IS_ARRAY | InputArgument::OPTIONAL, 'Should not be provided, use composer require instead to add a given package to composer.json.'),
- ))
- ->setHelp(<<<EOT
- The <info>install</info> command reads the composer.lock file from
- the current directory, processes it, and downloads and installs all the
- libraries and dependencies outlined in that file. If the file does not
- exist it will look for composer.json and do the same.
- <info>php composer.phar install</info>
- EOT
- )
- ;
- }
- protected function execute(InputInterface $input, OutputInterface $output)
- {
- if ($args = $input->getArgument('packages')) {
- $this->getIO()->writeError('<error>Invalid argument '.implode(' ', $args).'. Use "composer require '.implode(' ', $args).'" instead to add packages to your composer.json.</error>');
- return 1;
- }
- if ($input->getOption('no-custom-installers')) {
- $this->getIO()->writeError('<warning>You are using the deprecated option "no-custom-installers". Use "no-plugins" instead.</warning>');
- $input->setOption('no-plugins', true);
- }
- if ($input->getOption('dev')) {
- $this->getIO()->writeError('<warning>You are using the deprecated option "dev". Dev packages are installed by default now.</warning>');
- }
- $composer = $this->getComposer(true, $input->getOption('no-plugins'));
- $composer->getDownloadManager()->setOutputProgress(!$input->getOption('no-progress'));
- $io = $this->getIO();
- $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'install', $input, $output);
- $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
- $install = Installer::create($io, $composer);
- $preferSource = false;
- $preferDist = false;
- $config = $composer->getConfig();
- switch ($config->get('preferred-install')) {
- case 'source':
- $preferSource = true;
- break;
- case 'dist':
- $preferDist = true;
- break;
- case 'auto':
- default:
- break;
- }
- if ($input->getOption('prefer-source') || $input->getOption('prefer-dist')) {
- $preferSource = $input->getOption('prefer-source');
- $preferDist = $input->getOption('prefer-dist');
- }
- $optimize = $input->getOption('optimize-autoloader') || $config->get('optimize-autoloader') || $config->get('classmap-authoritative');
- $install
- ->setDryRun($input->getOption('dry-run'))
- ->setVerbose($input->getOption('verbose'))
- ->setPreferSource($preferSource)
- ->setPreferDist($preferDist)
- ->setDevMode(!$input->getOption('no-dev'))
- ->setDumpAutoloader(!$input->getOption('no-autoloader'))
- ->setRunScripts(!$input->getOption('no-scripts'))
- ->setOptimizeAutoloader($optimize)
- ->setIgnorePlatformRequirements($input->getOption('ignore-platform-reqs'))
- ;
- if ($input->getOption('no-plugins')) {
- $install->disablePlugins();
- }
- return $install->run();
- }
- }
- <?php
- namespace Composer\Command;
- use Composer\Json\JsonFile;
- use Composer\Package\Version\VersionParser;
- use Composer\Plugin\CommandEvent;
- use Composer\Plugin\PluginEvents;
- use Composer\Package\PackageInterface;
- use Composer\Repository\RepositoryInterface;
- use Symfony\Component\Console\Helper\Table;
- use Symfony\Component\Console\Helper\TableStyle;
- use Symfony\Component\Console\Input\InputInterface;
- use Symfony\Component\Console\Input\InputOption;
- use Symfony\Component\Console\Output\OutputInterface;
- class LicensesCommand extends Command
- {
- protected function configure()
- {
- $this
- ->setName('licenses')
- ->setDescription('Show information about licenses of dependencies')
- ->setDefinition(array(
- new InputOption('format', 'f', InputOption::VALUE_REQUIRED, 'Format of the output: text or json', 'text'),
- new InputOption('no-dev', null, InputOption::VALUE_NONE, 'Disables search in require-dev packages.'),
- ))
- ->setHelp(<<<EOT
- The license command displays detailed information about the licenses of
- the installed dependencies.
- EOT
- )
- ;
- }
- protected function execute(InputInterface $input, OutputInterface $output)
- {
- $composer = $this->getComposer();
- $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'licenses', $input, $output);
- $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
- $root = $composer->getPackage();
- $repo = $composer->getRepositoryManager()->getLocalRepository();
- $versionParser = new VersionParser;
- if ($input->getOption('no-dev')) {
- $packages = $this->filterRequiredPackages($repo, $root);
- } else {
- $packages = $this->appendPackages($repo->getPackages(), array());
- }
- ksort($packages);
- switch ($format = $input->getOption('format')) {
- case 'text':
- $this->getIO()->write('Name: <comment>'.$root->getPrettyName().'</comment>');
- $this->getIO()->write('Version: <comment>'.$versionParser->formatVersion($root).'</comment>');
- $this->getIO()->write('Licenses: <comment>'.(implode(', ', $root->getLicense()) ?: 'none').'</comment>');
- $this->getIO()->write('Dependencies:');
- $this->getIO()->write('');
- $table = new Table($output);
- $table->setStyle('compact');
- $table->getStyle()->setVerticalBorderChar('');
- $table->getStyle()->setCellRowContentFormat('%s ');
- $table->setHeaders(array('Name', 'Version', 'License'));
- foreach ($packages as $package) {
- $table->addRow(array(
- $package->getPrettyName(),
- $versionParser->formatVersion($package),
- implode(', ', $package->getLicense()) ?: 'none',
- ));
- }
- $table->render();
- break;
- case 'json':
- foreach ($packages as $package) {
- $dependencies[$package->getPrettyName()] = array(
- 'version' => $versionParser->formatVersion($package),
- 'license' => $package->getLicense(),
- );
- }
- $this->getIO()->write(JsonFile::encode(array(
- 'name' => $root->getPrettyName(),
- 'version' => $versionParser->formatVersion($root),
- 'license' => $root->getLicense(),
- 'dependencies' => $dependencies,
- )));
- break;
- default:
- throw new \RuntimeException(sprintf('Unsupported format "%s". See help for supported formats.', $format));
- }
- }
- private function filterRequiredPackages(RepositoryInterface $repo, PackageInterface $package, $bucket = array())
- {
- $requires = array_keys($package->getRequires());
- $packageListNames = array_keys($bucket);
- $packages = array_filter(
- $repo->getPackages(),
- function ($package) use ($requires, $packageListNames) {
- return in_array($package->getName(), $requires) && !in_array($package->getName(), $packageListNames);
- }
- );
- $bucket = $this->appendPackages($packages, $bucket);
- foreach ($packages as $package) {
- $bucket = $this->filterRequiredPackages($repo, $package, $bucket);
- }
- return $bucket;
- }
- public function appendPackages(array $packages, array $bucket)
- {
- foreach ($packages as $package) {
- $bucket[$package->getName()] = $package;
- }
- return $bucket;
- }
- }
- <?php
- namespace Composer\Command;
- use Composer\Config\JsonConfigSource;
- use Composer\Installer;
- use Composer\Plugin\CommandEvent;
- use Composer\Plugin\PluginEvents;
- use Composer\Json\JsonFile;
- use Composer\Factory;
- use Symfony\Component\Console\Input\InputInterface;
- use Symfony\Component\Console\Input\InputOption;
- use Symfony\Component\Console\Input\InputArgument;
- use Symfony\Component\Console\Output\OutputInterface;
- class RemoveCommand extends Command
- {
- protected function configure()
- {
- $this
- ->setName('remove')
- ->setDescription('Removes a package from the require or require-dev')
- ->setDefinition(array(
- new InputArgument('packages', InputArgument::IS_ARRAY, 'Packages that should be removed.'),
- new InputOption('dev', null, InputOption::VALUE_NONE, 'Removes a package from the require-dev section.'),
- new InputOption('no-progress', null, InputOption::VALUE_NONE, 'Do not output download progress.'),
- new InputOption('no-update', null, InputOption::VALUE_NONE, 'Disables the automatic update of the dependencies.'),
- new InputOption('update-no-dev', null, InputOption::VALUE_NONE, 'Run the dependency update with the --no-dev option.'),
- new InputOption('update-with-dependencies', null, InputOption::VALUE_NONE, 'Allows inherited dependencies to be updated with explicit dependencies.'),
- new InputOption('ignore-platform-reqs', null, InputOption::VALUE_NONE, 'Ignore platform requirements (php & ext- packages).'),
- ))
- ->setHelp(<<<EOT
- The <info>remove</info> command removes a package from the current
- list of installed packages
- <info>php composer.phar remove</info>
- EOT
- )
- ;
- }
- protected function execute(InputInterface $input, OutputInterface $output)
- {
- $packages = $input->getArgument('packages');
- $file = Factory::getComposerFile();
- $jsonFile = new JsonFile($file);
- $composer = $jsonFile->read();
- $composerBackup = file_get_contents($jsonFile->getPath());
- $json = new JsonConfigSource($jsonFile);
- $type = $input->getOption('dev') ? 'require-dev' : 'require';
- $altType = !$input->getOption('dev') ? 'require-dev' : 'require';
- foreach ($packages as $package) {
- if (isset($composer[$type][$package])) {
- $json->removeLink($type, $package);
- } elseif (isset($composer[$altType][$package])) {
- $this->getIO()->writeError('<warning>'.$package.' could not be found in '.$type.' but it is present in '.$altType.'</warning>');
- $dialog = $this->getHelperSet()->get('dialog');
- if ($this->getIO()->isInteractive()) {
- if ($dialog->askConfirmation($output, $dialog->getQuestion('Do you want to remove it from '.$altType, 'yes', '?'), true)) {
- $json->removeLink($altType, $package);
- }
- }
- } else {
- $this->getIO()->writeError('<warning>'.$package.' is not required in your composer.json and has not been removed</warning>');
- }
- }
- if ($input->getOption('no-update')) {
- return 0;
- }
- $composer = $this->getComposer();
- $composer->getDownloadManager()->setOutputProgress(!$input->getOption('no-progress'));
- $io = $this->getIO();
- $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'remove', $input, $output);
- $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
- $install = Installer::create($io, $composer);
- $updateDevMode = !$input->getOption('update-no-dev');
- $install
- ->setVerbose($input->getOption('verbose'))
- ->setDevMode($updateDevMode)
- ->setUpdate(true)
- ->setUpdateWhitelist($packages)
- ->setWhitelistDependencies($input->getOption('update-with-dependencies'))
- ->setIgnorePlatformRequirements($input->getOption('ignore-platform-reqs'))
- ;
- $status = $install->run();
- if ($status !== 0) {
- $this->getIO()->writeError("\n".'<error>Removal failed, reverting '.$file.' to its original content.</error>');
- file_put_contents($jsonFile->getPath(), $composerBackup);
- }
- return $status;
- }
- }
- <?php
- namespace Composer\Command;
- use Symfony\Component\Console\Input\InputInterface;
- use Symfony\Component\Console\Input\InputArgument;
- use Symfony\Component\Console\Input\InputOption;
- use Symfony\Component\Console\Output\OutputInterface;
- use Composer\Factory;
- use Composer\Installer;
- use Composer\Json\JsonFile;
- use Composer\Json\JsonManipulator;
- use Composer\Package\Version\VersionParser;
- use Composer\Plugin\CommandEvent;
- use Composer\Plugin\PluginEvents;
- use Composer\Repository\CompositeRepository;
- use Composer\Repository\PlatformRepository;
- class RequireCommand extends InitCommand
- {
- protected function configure()
- {
- $this
- ->setName('require')
- ->setDescription('Adds required packages to your composer.json and installs them')
- ->setDefinition(array(
- new InputArgument('packages', InputArgument::IS_ARRAY | InputArgument::OPTIONAL, 'Required package name optionally including a version constraint, e.g. foo/bar or foo/bar:1.0.0 or foo/bar=1.0.0 or "foo/bar 1.0.0"'),
- new InputOption('dev', null, InputOption::VALUE_NONE, 'Add requirement to require-dev.'),
- new InputOption('prefer-source', null, InputOption::VALUE_NONE, 'Forces installation from package sources when possible, including VCS information.'),
- new InputOption('prefer-dist', null, InputOption::VALUE_NONE, 'Forces installation from package dist even for dev versions.'),
- new InputOption('no-progress', null, InputOption::VALUE_NONE, 'Do not output download progress.'),
- new InputOption('no-update', null, InputOption::VALUE_NONE, 'Disables the automatic update of the dependencies.'),
- new InputOption('update-no-dev', null, InputOption::VALUE_NONE, 'Run the dependency update with the --no-dev option.'),
- new InputOption('update-with-dependencies', null, InputOption::VALUE_NONE, 'Allows inherited dependencies to be updated with explicit dependencies.'),
- new InputOption('ignore-platform-reqs', null, InputOption::VALUE_NONE, 'Ignore platform requirements (php & ext- packages).'),
- new InputOption('sort-packages', null, InputOption::VALUE_NONE, 'Sorts packages when adding/updating a new dependency'),
- ))
- ->setHelp(<<<EOT
- The require command adds required packages to your composer.json and installs them.
- If you do not specify a version constraint, composer will choose a suitable one based on the available package versions.
- If you do not want to install the new dependencies immediately you can call it with --no-update
- EOT
- )
- ;
- }
- protected function execute(InputInterface $input, OutputInterface $output)
- {
- $file = Factory::getComposerFile();
- $newlyCreated = !file_exists($file);
- if (!file_exists($file) && !file_put_contents($file, "{\n}\n")) {
- $this->getIO()->writeError('<error>'.$file.' could not be created.</error>');
- return 1;
- }
- if (!is_readable($file)) {
- $this->getIO()->writeError('<error>'.$file.' is not readable.</error>');
- return 1;
- }
- if (!is_writable($file)) {
- $this->getIO()->writeError('<error>'.$file.' is not writable.</error>');
- return 1;
- }
- $json = new JsonFile($file);
- $composerDefinition = $json->read();
- $composerBackup = file_get_contents($json->getPath());
- $composer = $this->getComposer();
- $repos = $composer->getRepositoryManager()->getRepositories();
- $this->repos = new CompositeRepository(array_merge(
- array(new PlatformRepository),
- $repos
- ));
- $requirements = $this->determineRequirements($input, $output, $input->getArgument('packages'));
- $requireKey = $input->getOption('dev') ? 'require-dev' : 'require';
- $removeKey = $input->getOption('dev') ? 'require' : 'require-dev';
- $baseRequirements = array_key_exists($requireKey, $composerDefinition) ? $composerDefinition[$requireKey] : array();
- $requirements = $this->formatRequirements($requirements);
- $versionParser = new VersionParser();
- foreach ($requirements as $constraint) {
- $versionParser->parseConstraints($constraint);
- }
- $sortPackages = $input->getOption('sort-packages');
- if (!$this->updateFileCleanly($json, $baseRequirements, $requirements, $requireKey, $removeKey, $sortPackages)) {
- foreach ($requirements as $package => $version) {
- $baseRequirements[$package] = $version;
- if (isset($composerDefinition[$removeKey][$package])) {
- unset($composerDefinition[$removeKey][$package]);
- }
- }
- $composerDefinition[$requireKey] = $baseRequirements;
- $json->write($composerDefinition);
- }
- $this->getIO()->writeError('<info>'.$file.' has been '.($newlyCreated ? 'created' : 'updated').'</info>');
- if ($input->getOption('no-update')) {
- return 0;
- }
- $updateDevMode = !$input->getOption('update-no-dev');
- $this->resetComposer();
- $composer = $this->getComposer();
- $composer->getDownloadManager()->setOutputProgress(!$input->getOption('no-progress'));
- $io = $this->getIO();
- $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'require', $input, $output);
- $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
- $install = Installer::create($io, $composer);
- $install
- ->setVerbose($input->getOption('verbose'))
- ->setPreferSource($input->getOption('prefer-source'))
- ->setPreferDist($input->getOption('prefer-dist'))
- ->setDevMode($updateDevMode)
- ->setUpdate(true)
- ->setUpdateWhitelist(array_keys($requirements))
- ->setWhitelistDependencies($input->getOption('update-with-dependencies'))
- ->setIgnorePlatformRequirements($input->getOption('ignore-platform-reqs'))
- ;
- $status = $install->run();
- if ($status !== 0) {
- if ($newlyCreated) {
- $this->getIO()->writeError("\n".'<error>Installation failed, deleting '.$file.'.</error>');
- unlink($json->getPath());
- } else {
- $this->getIO()->writeError("\n".'<error>Installation failed, reverting '.$file.' to its original content.</error>');
- file_put_contents($json->getPath(), $composerBackup);
- }
- }
- return $status;
- }
- private function updateFileCleanly($json, array $base, array $new, $requireKey, $removeKey, $sortPackages)
- {
- $contents = file_get_contents($json->getPath());
- $manipulator = new JsonManipulator($contents);
- foreach ($new as $package => $constraint) {
- if (!$manipulator->addLink($requireKey, $package, $constraint, $sortPackages)) {
- return false;
- }
- if (!$manipulator->removeSubNode($removeKey, $package)) {
- return false;
- }
- }
- file_put_contents($json->getPath(), $manipulator->getContents());
- return true;
- }
- protected function interact(InputInterface $input, OutputInterface $output)
- {
- return;
- }
- }
- <?php
- namespace Composer\Command;
- use Composer\Script\CommandEvent;
- use Composer\Script\ScriptEvents;
- use Symfony\Component\Console\Input\InputInterface;
- use Symfony\Component\Console\Input\InputOption;
- use Symfony\Component\Console\Input\InputArgument;
- use Symfony\Component\Console\Output\OutputInterface;
- class RunScriptCommand extends Command
- {
- protected $scriptEvents = array(
- ScriptEvents::PRE_INSTALL_CMD,
- ScriptEvents::POST_INSTALL_CMD,
- ScriptEvents::PRE_UPDATE_CMD,
- ScriptEvents::POST_UPDATE_CMD,
- ScriptEvents::PRE_STATUS_CMD,
- ScriptEvents::POST_STATUS_CMD,
- ScriptEvents::POST_ROOT_PACKAGE_INSTALL,
- ScriptEvents::POST_CREATE_PROJECT_CMD,
- ScriptEvents::PRE_ARCHIVE_CMD,
- ScriptEvents::POST_ARCHIVE_CMD,
- ScriptEvents::PRE_AUTOLOAD_DUMP,
- ScriptEvents::POST_AUTOLOAD_DUMP,
- );
- protected function configure()
- {
- $this
- ->setName('run-script')
- ->setDescription('Run the scripts defined in composer.json.')
- ->setDefinition(array(
- new InputArgument('script', InputArgument::OPTIONAL, 'Script name to run.'),
- new InputArgument('args', InputArgument::IS_ARRAY | InputArgument::OPTIONAL, ''),
- new InputOption('dev', null, InputOption::VALUE_NONE, 'Sets the dev mode.'),
- new InputOption('no-dev', null, InputOption::VALUE_NONE, 'Disables the dev mode.'),
- new InputOption('list', 'l', InputOption::VALUE_NONE, 'List scripts.'),
- ))
- ->setHelp(<<<EOT
- The <info>run-script</info> command runs scripts defined in composer.json:
- <info>php composer.phar run-script post-update-cmd</info>
- EOT
- )
- ;
- }
- protected function execute(InputInterface $input, OutputInterface $output)
- {
- if ($input->getOption('list')) {
- return $this->listScripts();
- } elseif (!$input->getArgument('script')) {
- throw new \RunTimeException('Missing required argument "script"');
- }
- $script = $input->getArgument('script');
- if (!in_array($script, $this->scriptEvents)) {
- if (defined('Composer\Script\ScriptEvents::'.str_replace('-', '_', strtoupper($script)))) {
- throw new \InvalidArgumentException(sprintf('Script "%s" cannot be run with this command', $script));
- }
- }
- $composer = $this->getComposer();
- $hasListeners = $composer->getEventDispatcher()->hasEventListeners(new CommandEvent($script, $composer, $this->getIO()));
- if (!$hasListeners) {
- throw new \InvalidArgumentException(sprintf('Script "%s" is not defined in this package', $script));
- }
- $binDir = $composer->getConfig()->get('bin-dir');
- if (is_dir($binDir)) {
- putenv('PATH='.realpath($binDir).PATH_SEPARATOR.getenv('PATH'));
- }
- $args = $input->getArgument('args');
- return $composer->getEventDispatcher()->dispatchScript($script, $input->getOption('dev') || !$input->getOption('no-dev'), $args);
- }
- protected function listScripts()
- {
- $scripts = $this->getComposer()->getPackage()->getScripts();
- if (!count($scripts)) {
- return 0;
- }
- $this->getIO()->writeError('<info>scripts:</info>');
- foreach ($scripts as $name => $script) {
- $this->getIO()->write(' ' . $name);
- }
- return 0;
- }
- }
- <?php
- namespace Composer\Command;
- use Symfony\Component\Console\Input\InputInterface;
- use Symfony\Component\Console\Input\InputOption;
- use Symfony\Component\Console\Input\InputArgument;
- use Symfony\Component\Console\Output\OutputInterface;
- class ScriptAliasCommand extends Command
- {
- private $script;
- public function __construct($script)
- {
- $this->script = $script;
- parent::__construct();
- }
- protected function configure()
- {
- $this
- ->setName($this->script)
- ->setDescription('Run the '.$this->script.' script as defined in composer.json.')
- ->setDefinition(array(
- new InputOption('dev', null, InputOption::VALUE_NONE, 'Sets the dev mode.'),
- new InputOption('no-dev', null, InputOption::VALUE_NONE, 'Disables the dev mode.'),
- new InputArgument('args', InputArgument::IS_ARRAY | InputArgument::OPTIONAL, ''),
- ))
- ->setHelp(<<<EOT
- The <info>run-script</info> command runs scripts defined in composer.json:
- <info>php composer.phar run-script post-update-cmd</info>
- EOT
- )
- ;
- }
- protected function execute(InputInterface $input, OutputInterface $output)
- {
- $composer = $this->getComposer();
- $binDir = $composer->getConfig()->get('bin-dir');
- if (is_dir($binDir)) {
- putenv('PATH='.realpath($binDir).PATH_SEPARATOR.getenv('PATH'));
- }
- $args = $input->getArguments();
- return $composer->getEventDispatcher()->dispatchScript($this->script, $input->getOption('dev') || !$input->getOption('no-dev'), $args['args']);
- }
- }
- <?php
- namespace Composer\Command;
- use Symfony\Component\Console\Input\InputInterface;
- use Symfony\Component\Console\Input\InputArgument;
- use Symfony\Component\Console\Input\InputOption;
- use Symfony\Component\Console\Output\OutputInterface;
- use Composer\Repository\CompositeRepository;
- use Composer\Repository\PlatformRepository;
- use Composer\Repository\RepositoryInterface;
- use Composer\Factory;
- use Composer\Plugin\CommandEvent;
- use Composer\Plugin\PluginEvents;
- class SearchCommand extends Command
- {
- protected $matches;
- protected $lowMatches = array();
- protected $tokens;
- protected $output;
- protected $onlyName;
- protected function configure()
- {
- $this
- ->setName('search')
- ->setDescription('Search for packages')
- ->setDefinition(array(
- new InputOption('only-name', 'N', InputOption::VALUE_NONE, 'Search only in name'),
- new InputArgument('tokens', InputArgument::IS_ARRAY | InputArgument::REQUIRED, 'tokens to search for'),
- ))
- ->setHelp(<<<EOT
- The search command searches for packages by its name
- <info>php composer.phar search symfony composer</info>
- EOT
- )
- ;
- }
- protected function execute(InputInterface $input, OutputInterface $output)
- {
- $platformRepo = new PlatformRepository;
- if ($composer = $this->getComposer(false)) {
- $localRepo = $composer->getRepositoryManager()->getLocalRepository();
- $installedRepo = new CompositeRepository(array($localRepo, $platformRepo));
- $repos = new CompositeRepository(array_merge(array($installedRepo), $composer->getRepositoryManager()->getRepositories()));
- } else {
- $defaultRepos = Factory::createDefaultRepositories($this->getIO());
- $this->getIO()->writeError('No composer.json found in the current directory, showing packages from ' . implode(', ', array_keys($defaultRepos)));
- $installedRepo = $platformRepo;
- $repos = new CompositeRepository(array_merge(array($installedRepo), $defaultRepos));
- }
- if ($composer) {
- $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'search', $input, $output);
- $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
- }
- $onlyName = $input->getOption('only-name');
- $flags = $onlyName ? RepositoryInterface::SEARCH_NAME : RepositoryInterface::SEARCH_FULLTEXT;
- $results = $repos->search(implode(' ', $input->getArgument('tokens')), $flags);
- foreach ($results as $result) {
- $this->getIO()->write($result['name'] . (isset($result['description']) ? ' '. $result['description'] : ''));
- }
- }
- }
- <?php
- namespace Composer\Command;
- use Composer\Composer;
- use Composer\Factory;
- use Composer\Util\Filesystem;
- use Composer\Util\RemoteFilesystem;
- use Composer\Downloader\FilesystemException;
- use Symfony\Component\Console\Input\InputInterface;
- use Symfony\Component\Console\Input\InputOption;
- use Symfony\Component\Console\Input\InputArgument;
- use Symfony\Component\Console\Output\OutputInterface;
- use Symfony\Component\Finder\Finder;
- class SelfUpdateCommand extends Command
- {
- const HOMEPAGE = 'getcomposer.org';
- const OLD_INSTALL_EXT = '-old.phar';
- protected function configure()
- {
- $this
- ->setName('self-update')
- ->setAliases(array('selfupdate'))
- ->setDescription('Updates composer.phar to the latest version.')
- ->setDefinition(array(
- new InputOption('rollback', 'r', InputOption::VALUE_NONE, 'Revert to an older installation of composer'),
- new InputOption('clean-backups', null, InputOption::VALUE_NONE, 'Delete old backups during an update. This makes the current version of composer the only backup available after the update'),
- new InputArgument('version', InputArgument::OPTIONAL, 'The version to update to'),
- new InputOption('no-progress', null, InputOption::VALUE_NONE, 'Do not output download progress.'),
- ))
- ->setHelp(<<<EOT
- The <info>self-update</info> command checks getcomposer.org for newer
- versions of composer and if found, installs the latest.
- <info>php composer.phar self-update</info>
- EOT
- )
- ;
- }
- protected function execute(InputInterface $input, OutputInterface $output)
- {
- $baseUrl = (extension_loaded('openssl') ? 'https' : 'http') . '://' . self::HOMEPAGE;
- $config = Factory::createConfig();
- $remoteFilesystem = new RemoteFilesystem($this->getIO(), $config);
- $cacheDir = $config->get('cache-dir');
- $rollbackDir = $config->get('home');
- $localFilename = realpath($_SERVER['argv'][0]) ?: $_SERVER['argv'][0];
- $tmpDir = is_writable(dirname($localFilename)) ? dirname($localFilename) : $cacheDir;
- if (!is_writable($tmpDir)) {
- throw new FilesystemException('Composer update failed: the "'.$tmpDir.'" directory used to download the temp file could not be written');
- }
- if (!is_writable($localFilename)) {
- throw new FilesystemException('Composer update failed: the "'.$localFilename.'" file could not be written');
- }
- if ($input->getOption('rollback')) {
- return $this->rollback($output, $rollbackDir, $localFilename);
- }
- $latestVersion = trim($remoteFilesystem->getContents(self::HOMEPAGE, $baseUrl. '/version', false));
- $updateVersion = $input->getArgument('version') ?: $latestVersion;
- if (preg_match('{^[0-9a-f]{40}$}', $updateVersion) && $updateVersion !== $latestVersion) {
- $this->getIO()->writeError('<error>You can not update to a specific SHA-1 as those phars are not available for download</error>');
- return 1;
- }
- if (Composer::VERSION === $updateVersion) {
- $this->getIO()->writeError('<info>You are already using composer version '.$updateVersion.'.</info>');
- return 0;
- }
- $tempFilename = $tmpDir . '/' . basename($localFilename, '.phar').'-temp.phar';
- $backupFile = sprintf(
- '%s/%s-%s%s',
- $rollbackDir,
- strtr(Composer::RELEASE_DATE, ' :', '_-'),
- preg_replace('{^([0-9a-f]{7})[0-9a-f]{33}$}', '$1', Composer::VERSION),
- self::OLD_INSTALL_EXT
- );
- $this->getIO()->writeError(sprintf("Updating to version <info>%s</info>.", $updateVersion));
- $remoteFilename = $baseUrl . (preg_match('{^[0-9a-f]{40}$}', $updateVersion) ? '/composer.phar' : "/download/{$updateVersion}/composer.phar");
- $remoteFilesystem->copy(self::HOMEPAGE, $remoteFilename, $tempFilename, !$input->getOption('no-progress'));
- if (!file_exists($tempFilename)) {
- $this->getIO()->writeError('<error>The download of the new composer version failed for an unexpected reason</error>');
- return 1;
- }
- if ($input->getOption('clean-backups')) {
- $finder = $this->getOldInstallationFinder($rollbackDir);
- $fs = new Filesystem;
- foreach ($finder as $file) {
- $file = (string) $file;
- $this->getIO()->writeError('<info>Removing: '.$file.'</info>');
- $fs->remove($file);
- }
- }
- if ($err = $this->setLocalPhar($localFilename, $tempFilename, $backupFile)) {
- $this->getIO()->writeError('<error>The file is corrupted ('.$err->getMessage().').</error>');
- $this->getIO()->writeError('<error>Please re-run the self-update command to try again.</error>');
- return 1;
- }
- if (file_exists($backupFile)) {
- $this->getIO()->writeError('Use <info>composer self-update --rollback</info> to return to version '.Composer::VERSION);
- } else {
- $this->getIO()->writeError('<warning>A backup of the current version could not be written to '.$backupFile.', no rollback possible</warning>');
- }
- }
- protected function rollback(OutputInterface $output, $rollbackDir, $localFilename)
- {
- $rollbackVersion = $this->getLastBackupVersion($rollbackDir);
- if (!$rollbackVersion) {
- throw new \UnexpectedValueException('Composer rollback failed: no installation to roll back to in "'.$rollbackDir.'"');
- }
- if (!is_writable($rollbackDir)) {
- throw new FilesystemException('Composer rollback failed: the "'.$rollbackDir.'" dir could not be written to');
- }
- $old = $rollbackDir . '/' . $rollbackVersion . self::OLD_INSTALL_EXT;
- if (!is_file($old)) {
- throw new FilesystemException('Composer rollback failed: "'.$old.'" could not be found');
- }
- if (!is_readable($old)) {
- throw new FilesystemException('Composer rollback failed: "'.$old.'" could not be read');
- }
- $oldFile = $rollbackDir . "/{$rollbackVersion}" . self::OLD_INSTALL_EXT;
- $this->getIO()->writeError(sprintf("Rolling back to version <info>%s</info>.", $rollbackVersion));
- if ($err = $this->setLocalPhar($localFilename, $oldFile)) {
- $this->getIO()->writeError('<error>The backup file was corrupted ('.$err->getMessage().') and has been removed.</error>');
- return 1;
- }
- return 0;
- }
- protected function setLocalPhar($localFilename, $newFilename, $backupTarget = null)
- {
- try {
- @chmod($newFilename, fileperms($localFilename));
- if (!ini_get('phar.readonly')) {
- $phar = new \Phar($newFilename);
- unset($phar);
- }
- if ($backupTarget && file_exists($localFilename)) {
- @copy($localFilename, $backupTarget);
- }
- rename($newFilename, $localFilename);
- } catch (\Exception $e) {
- if ($backupTarget) {
- @unlink($newFilename);
- }
- if (!$e instanceof \UnexpectedValueException && !$e instanceof \PharException) {
- throw $e;
- }
- return $e;
- }
- }
- protected function getLastBackupVersion($rollbackDir)
- {
- $finder = $this->getOldInstallationFinder($rollbackDir);
- $finder->sortByName();
- $files = iterator_to_array($finder);
- if (count($files)) {
- return basename(end($files), self::OLD_INSTALL_EXT);
- }
- return false;
- }
- protected function getOldInstallationFinder($rollbackDir)
- {
- $finder = Finder::create()
- ->depth(0)
- ->files()
- ->name('*' . self::OLD_INSTALL_EXT)
- ->in($rollbackDir);
- return $finder;
- }
- }
- <?php
- namespace Composer\Command;
- use Composer\DependencyResolver\Pool;
- use Composer\DependencyResolver\DefaultPolicy;
- use Composer\Factory;
- use Composer\Package\CompletePackageInterface;
- use Composer\Package\Version\VersionParser;
- use Composer\Plugin\CommandEvent;
- use Composer\Plugin\PluginEvents;
- use Symfony\Component\Console\Input\InputInterface;
- use Symfony\Component\Console\Input\InputArgument;
- use Symfony\Component\Console\Input\InputOption;
- use Symfony\Component\Console\Output\OutputInterface;
- use Composer\Repository\ArrayRepository;
- use Composer\Repository\CompositeRepository;
- use Composer\Repository\ComposerRepository;
- use Composer\Repository\PlatformRepository;
- use Composer\Repository\RepositoryInterface;
- class ShowCommand extends Command
- {
- protected $versionParser;
- protected function configure()
- {
- $this
- ->setName('show')
- ->setAliases(array('info'))
- ->setDescription('Show information about packages')
- ->setDefinition(array(
- new InputArgument('package', InputArgument::OPTIONAL, 'Package to inspect'),
- new InputArgument('version', InputArgument::OPTIONAL, 'Version or version constraint to inspect'),
- new InputOption('installed', 'i', InputOption::VALUE_NONE, 'List installed packages only'),
- new InputOption('platform', 'p', InputOption::VALUE_NONE, 'List platform packages only'),
- new InputOption('available', 'a', InputOption::VALUE_NONE, 'List available packages only'),
- new InputOption('self', 's', InputOption::VALUE_NONE, 'Show the root package information'),
- new InputOption('name-only', 'N', InputOption::VALUE_NONE, 'List package names only'),
- new InputOption('path', 'P', InputOption::VALUE_NONE, 'Show package paths'),
- ))
- ->setHelp(<<<EOT
- The show command displays detailed information about a package, or
- lists all packages available.
- EOT
- )
- ;
- }
- protected function execute(InputInterface $input, OutputInterface $output)
- {
- $this->versionParser = new VersionParser;
- $platformRepo = new PlatformRepository;
- $composer = $this->getComposer(false);
- if ($input->getOption('self')) {
- $package = $this->getComposer()->getPackage();
- $repos = $installedRepo = new ArrayRepository(array($package));
- } elseif ($input->getOption('platform')) {
- $repos = $installedRepo = $platformRepo;
- } elseif ($input->getOption('installed')) {
- $repos = $installedRepo = $this->getComposer()->getRepositoryManager()->getLocalRepository();
- } elseif ($input->getOption('available')) {
- $installedRepo = $platformRepo;
- if ($composer) {
- $repos = new CompositeRepository($composer->getRepositoryManager()->getRepositories());
- } else {
- $defaultRepos = Factory::createDefaultRepositories($this->getIO());
- $repos = new CompositeRepository($defaultRepos);
- $this->getIO()->writeError('No composer.json found in the current directory, showing available packages from ' . implode(', ', array_keys($defaultRepos)));
- }
- } elseif ($composer) {
- $localRepo = $composer->getRepositoryManager()->getLocalRepository();
- $installedRepo = new CompositeRepository(array($localRepo, $platformRepo));
- $repos = new CompositeRepository(array_merge(array($installedRepo), $composer->getRepositoryManager()->getRepositories()));
- } else {
- $defaultRepos = Factory::createDefaultRepositories($this->getIO());
- $this->getIO()->writeError('No composer.json found in the current directory, showing available packages from ' . implode(', ', array_keys($defaultRepos)));
- $installedRepo = $platformRepo;
- $repos = new CompositeRepository(array_merge(array($installedRepo), $defaultRepos));
- }
- if ($composer) {
- $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'show', $input, $output);
- $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
- }
- if ($input->getArgument('package') || !empty($package)) {
- $versions = array();
- if (empty($package)) {
- list($package, $versions) = $this->getPackage($installedRepo, $repos, $input->getArgument('package'), $input->getArgument('version'));
- if (!$package) {
- throw new \InvalidArgumentException('Package '.$input->getArgument('package').' not found');
- }
- } else {
- $versions = array($package->getPrettyVersion() => $package->getVersion());
- }
- $this->printMeta($input, $output, $package, $versions, $installedRepo, $repos);
- $this->printLinks($input, $output, $package, 'requires');
- $this->printLinks($input, $output, $package, 'devRequires', 'requires (dev)');
- if ($package->getSuggests()) {
- $this->getIO()->write("\n<info>suggests</info>");
- foreach ($package->getSuggests() as $suggested => $reason) {
- $this->getIO()->write($suggested . ' <comment>' . $reason . '</comment>');
- }
- }
- $this->printLinks($input, $output, $package, 'provides');
- $this->printLinks($input, $output, $package, 'conflicts');
- $this->printLinks($input, $output, $package, 'replaces');
- return;
- }
- $packages = array();
- if ($repos instanceof CompositeRepository) {
- $repos = $repos->getRepositories();
- } elseif (!is_array($repos)) {
- $repos = array($repos);
- }
- foreach ($repos as $repo) {
- if ($repo === $platformRepo) {
- $type = '<info>platform</info>:';
- } elseif (
- $repo === $installedRepo
- || ($installedRepo instanceof CompositeRepository && in_array($repo, $installedRepo->getRepositories(), true))
- ) {
- $type = '<info>installed</info>:';
- } else {
- $type = '<comment>available</comment>:';
- }
- if ($repo instanceof ComposerRepository && $repo->hasProviders()) {
- foreach ($repo->getProviderNames() as $name) {
- $packages[$type][$name] = $name;
- }
- } else {
- foreach ($repo->getPackages() as $package) {
- if (!isset($packages[$type][$package->getName()])
- || !is_object($packages[$type][$package->getName()])
- || version_compare($packages[$type][$package->getName()]->getVersion(), $package->getVersion(), '<')
- ) {
- $packages[$type][$package->getName()] = $package;
- }
- }
- }
- }
- $tree = !$input->getOption('platform') && !$input->getOption('installed') && !$input->getOption('available');
- $indent = $tree ? ' ' : '';
- foreach (array('<info>platform</info>:' => true, '<comment>available</comment>:' => false, '<info>installed</info>:' => true) as $type => $showVersion) {
- if (isset($packages[$type])) {
- if ($tree) {
- $this->getIO()->write($type);
- }
- ksort($packages[$type]);
- $nameLength = $versionLength = 0;
- foreach ($packages[$type] as $package) {
- if (is_object($package)) {
- $nameLength = max($nameLength, strlen($package->getPrettyName()));
- $versionLength = max($versionLength, strlen($this->versionParser->formatVersion($package)));
- } else {
- $nameLength = max($nameLength, $package);
- }
- }
- list($width) = $this->getApplication()->getTerminalDimensions();
- if (null === $width) {
-
- $width = PHP_INT_MAX;
- }
- if (defined('PHP_WINDOWS_VERSION_BUILD')) {
- $width--;
- }
- $writePath = !$input->getOption('name-only') && $input->getOption('path');
- $writeVersion = !$input->getOption('name-only') && !$input->getOption('path') && $showVersion && ($nameLength + $versionLength + 3 <= $width);
- $writeDescription = !$input->getOption('name-only') && !$input->getOption('path') && ($nameLength + ($showVersion ? $versionLength : 0) + 24 <= $width);
- foreach ($packages[$type] as $package) {
- if (is_object($package)) {
- $output->write($indent . str_pad($package->getPrettyName(), $nameLength, ' '), false);
- if ($writeVersion) {
- $output->write(' ' . str_pad($this->versionParser->formatVersion($package), $versionLength, ' '), false);
- }
- if ($writeDescription) {
- $description = strtok($package->getDescription(), "\r\n");
- $remaining = $width - $nameLength - $versionLength - 4;
- if (strlen($description) > $remaining) {
- $description = substr($description, 0, $remaining - 3) . '...';
- }
- $output->write(' ' . $description);
- }
- if ($writePath) {
- $path = strtok(realpath($composer->getInstallationManager()->getInstallPath($package)), "\r\n");
- $output->write(' ' . $path);
- }
- } else {
- $output->write($indent . $package);
- }
- $this->getIO()->write('');
- }
- if ($tree) {
- $this->getIO()->write('');
- }
- }
- }
- }
- protected function getPackage(RepositoryInterface $installedRepo, RepositoryInterface $repos, $name, $version = null)
- {
- $name = strtolower($name);
- $constraint = null;
- if ($version) {
- $constraint = $this->versionParser->parseConstraints($version);
- }
- $policy = new DefaultPolicy();
- $pool = new Pool('dev');
- $pool->addRepository($repos);
- $matchedPackage = null;
- $versions = array();
- $matches = $pool->whatProvides($name, $constraint);
- foreach ($matches as $index => $package) {
- if ($package->getName() !== $name) {
- unset($matches[$index]);
- continue;
- }
- if (null === $version && $installedRepo->hasPackage($package)) {
- $matchedPackage = $package;
- }
- $versions[$package->getPrettyVersion()] = $package->getVersion();
- $matches[$index] = $package->getId();
- }
- if (!$matchedPackage && $matches && $prefered = $policy->selectPreferedPackages($pool, array(), $matches)) {
- $matchedPackage = $pool->literalToPackage($prefered[0]);
- }
- return array($matchedPackage, $versions);
- }
- protected function printMeta(InputInterface $input, OutputInterface $output, CompletePackageInterface $package, array $versions, RepositoryInterface $installedRepo, RepositoryInterface $repos)
- {
- $this->getIO()->write('<info>name</info> : ' . $package->getPrettyName());
- $this->getIO()->write('<info>descrip.</info> : ' . $package->getDescription());
- $this->getIO()->write('<info>keywords</info> : ' . join(', ', $package->getKeywords() ?: array()));
- $this->printVersions($input, $output, $package, $versions, $installedRepo, $repos);
- $this->getIO()->write('<info>type</info> : ' . $package->getType());
- $this->getIO()->write('<info>license</info> : ' . implode(', ', $package->getLicense()));
- $this->getIO()->write('<info>source</info> : ' . sprintf('[%s] <comment>%s</comment> %s', $package->getSourceType(), $package->getSourceUrl(), $package->getSourceReference()));
- $this->getIO()->write('<info>dist</info> : ' . sprintf('[%s] <comment>%s</comment> %s', $package->getDistType(), $package->getDistUrl(), $package->getDistReference()));
- $this->getIO()->write('<info>names</info> : ' . implode(', ', $package->getNames()));
- if ($package->isAbandoned()) {
- $replacement = ($package->getReplacementPackage() !== null)
- ? ' The author suggests using the ' . $package->getReplacementPackage(). ' package instead.'
- : null;
- $this->getIO()->writeError(
- sprintf('<error>Attention: This package is abandoned and no longer maintained.%s</error>', $replacement)
- );
- }
- if ($package->getSupport()) {
- $this->getIO()->write("\n<info>support</info>");
- foreach ($package->getSupport() as $type => $value) {
- $this->getIO()->write('<comment>' . $type . '</comment> : '.$value);
- }
- }
- if ($package->getAutoload()) {
- $this->getIO()->write("\n<info>autoload</info>");
- foreach ($package->getAutoload() as $type => $autoloads) {
- $this->getIO()->write('<comment>' . $type . '</comment>');
- if ($type === 'psr-0') {
- foreach ($autoloads as $name => $path) {
- $this->getIO()->write(($name ?: '*') . ' => ' . (is_array($path) ? implode(', ', $path) : ($path ?: '.')));
- }
- } elseif ($type === 'psr-4') {
- foreach ($autoloads as $name => $path) {
- $this->getIO()->write(($name ?: '*') . ' => ' . (is_array($path) ? implode(', ', $path) : ($path ?: '.')));
- }
- } elseif ($type === 'classmap') {
- $this->getIO()->write(implode(', ', $autoloads));
- }
- }
- if ($package->getIncludePaths()) {
- $this->getIO()->write('<comment>include-path</comment>');
- $this->getIO()->write(implode(', ', $package->getIncludePaths()));
- }
- }
- }
- protected function printVersions(InputInterface $input, OutputInterface $output, CompletePackageInterface $package, array $versions, RepositoryInterface $installedRepo, RepositoryInterface $repos)
- {
- uasort($versions, 'version_compare');
- $versions = array_keys(array_reverse($versions));
- if ($installedRepo->hasPackage($package)) {
- $installedVersion = $package->getPrettyVersion();
- $key = array_search($installedVersion, $versions);
- if (false !== $key) {
- $versions[$key] = '<info>* ' . $installedVersion . '</info>';
- }
- }
- $versions = implode(', ', $versions);
- $this->getIO()->write('<info>versions</info> : ' . $versions);
- }
- protected function printLinks(InputInterface $input, OutputInterface $output, CompletePackageInterface $package, $linkType, $title = null)
- {
- $title = $title ?: $linkType;
- if ($links = $package->{'get'.ucfirst($linkType)}()) {
- $this->getIO()->write("\n<info>" . $title . "</info>");
- foreach ($links as $link) {
- $this->getIO()->write($link->getTarget() . ' <comment>' . $link->getPrettyConstraint() . '</comment>');
- }
- }
- }
- }
- <?php
- namespace Composer\Command;
- use Symfony\Component\Console\Input\InputInterface;
- use Symfony\Component\Console\Input\InputOption;
- use Symfony\Component\Console\Output\OutputInterface;
- use Composer\Downloader\ChangeReportInterface;
- use Composer\Plugin\CommandEvent;
- use Composer\Plugin\PluginEvents;
- use Composer\Script\ScriptEvents;
- class StatusCommand extends Command
- {
- protected function configure()
- {
- $this
- ->setName('status')
- ->setDescription('Show a list of locally modified packages')
- ->setDefinition(array(
- new InputOption('verbose', 'v|vv|vvv', InputOption::VALUE_NONE, 'Show modified files for each directory that contains changes.'),
- ))
- ->setHelp(<<<EOT
- The status command displays a list of dependencies that have
- been modified locally.
- EOT
- )
- ;
- }
- protected function execute(InputInterface $input, OutputInterface $output)
- {
- $composer = $this->getComposer();
- $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'status', $input, $output);
- $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
- $installedRepo = $composer->getRepositoryManager()->getLocalRepository();
- $dm = $composer->getDownloadManager();
- $im = $composer->getInstallationManager();
- $composer->getEventDispatcher()->dispatchScript(ScriptEvents::PRE_STATUS_CMD, true);
- $errors = array();
- foreach ($installedRepo->getPackages() as $package) {
- $downloader = $dm->getDownloaderForInstalledPackage($package);
- if ($downloader instanceof ChangeReportInterface) {
- $targetDir = $im->getInstallPath($package);
- if ($changes = $downloader->getLocalChanges($package, $targetDir)) {
- $errors[$targetDir] = $changes;
- }
- }
- }
- if (!$errors) {
- $this->getIO()->writeError('<info>No local changes</info>');
- } else {
- $this->getIO()->writeError('<error>You have changes in the following dependencies:</error>');
- }
- foreach ($errors as $path => $changes) {
- if ($input->getOption('verbose')) {
- $indentedChanges = implode("\n", array_map(function ($line) {
- return ' ' . ltrim($line);
- }, explode("\n", $changes)));
- $this->getIO()->write('<info>'.$path.'</info>:');
- $this->getIO()->write($indentedChanges);
- } else {
- $this->getIO()->write($path);
- }
- }
- if ($errors && !$input->getOption('verbose')) {
- $this->getIO()->writeError('Use --verbose (-v) to see modified files');
- }
- $composer->getEventDispatcher()->dispatchScript(ScriptEvents::POST_STATUS_CMD, true);
- return $errors ? 1 : 0;
- }
- }
- <?php
- namespace Composer\Command;
- use Composer\Installer;
- use Composer\Plugin\CommandEvent;
- use Composer\Plugin\PluginEvents;
- use Symfony\Component\Console\Input\InputInterface;
- use Symfony\Component\Console\Input\InputOption;
- use Symfony\Component\Console\Input\InputArgument;
- use Symfony\Component\Console\Output\OutputInterface;
- class UpdateCommand extends Command
- {
- protected function configure()
- {
- $this
- ->setName('update')
- ->setDescription('Updates your dependencies to the latest version according to composer.json, and updates the composer.lock file.')
- ->setDefinition(array(
- new InputArgument('packages', InputArgument::IS_ARRAY | InputArgument::OPTIONAL, 'Packages that should be updated, if not provided all packages are.'),
- new InputOption('prefer-source', null, InputOption::VALUE_NONE, 'Forces installation from package sources when possible, including VCS information.'),
- new InputOption('prefer-dist', null, InputOption::VALUE_NONE, 'Forces installation from package dist even for dev versions.'),
- new InputOption('dry-run', null, InputOption::VALUE_NONE, 'Outputs the operations but will not execute anything (implicitly enables --verbose).'),
- new InputOption('dev', null, InputOption::VALUE_NONE, 'Enables installation of require-dev packages (enabled by default, only present for BC).'),
- new InputOption('no-dev', null, InputOption::VALUE_NONE, 'Disables installation of require-dev packages.'),
- new InputOption('lock', null, InputOption::VALUE_NONE, 'Only updates the lock file hash to suppress warning about the lock file being out of date.'),
- new InputOption('no-plugins', null, InputOption::VALUE_NONE, 'Disables all plugins.'),
- new InputOption('no-custom-installers', null, InputOption::VALUE_NONE, 'DEPRECATED: Use no-plugins instead.'),
- new InputOption('no-autoloader', null, InputOption::VALUE_NONE, 'Skips autoloader generation'),
- new InputOption('no-scripts', null, InputOption::VALUE_NONE, 'Skips the execution of all scripts defined in composer.json file.'),
- new InputOption('no-progress', null, InputOption::VALUE_NONE, 'Do not output download progress.'),
- new InputOption('with-dependencies', null, InputOption::VALUE_NONE, 'Add also all dependencies of whitelisted packages to the whitelist.'),
- new InputOption('verbose', 'v|vv|vvv', InputOption::VALUE_NONE, 'Shows more details including new commits pulled in when updating packages.'),
- new InputOption('optimize-autoloader', 'o', InputOption::VALUE_NONE, 'Optimize autoloader during autoloader dump.'),
- new InputOption('ignore-platform-reqs', null, InputOption::VALUE_NONE, 'Ignore platform requirements (php & ext- packages).'),
- new InputOption('prefer-stable', null, InputOption::VALUE_NONE, 'Prefer stable versions of dependencies.'),
- new InputOption('prefer-lowest', null, InputOption::VALUE_NONE, 'Prefer lowest versions of dependencies.'),
- ))
- ->setHelp(<<<EOT
- The <info>update</info> command reads the composer.json file from the
- current directory, processes it, and updates, removes or installs all the
- dependencies.
- <info>php composer.phar update</info>
- To limit the update operation to a few packages, you can list the package(s)
- you want to update as such:
- <info>php composer.phar update vendor/package1 foo/mypackage [...]</info>
- You may also use an asterisk (*) pattern to limit the update operation to package(s)
- from a specific vendor:
- <info>php composer.phar update vendor/package1 foo/* [...]</info>
- EOT
- )
- ;
- }
- protected function execute(InputInterface $input, OutputInterface $output)
- {
- if ($input->getOption('no-custom-installers')) {
- $this->getIO()->writeError('<warning>You are using the deprecated option "no-custom-installers". Use "no-plugins" instead.</warning>');
- $input->setOption('no-plugins', true);
- }
- if ($input->getOption('dev')) {
- $this->getIO()->writeError('<warning>You are using the deprecated option "dev". Dev packages are installed by default now.</warning>');
- }
- $composer = $this->getComposer(true, $input->getOption('no-plugins'));
- $composer->getDownloadManager()->setOutputProgress(!$input->getOption('no-progress'));
- $io = $this->getIO();
- $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'update', $input, $output);
- $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
- $install = Installer::create($io, $composer);
- $preferSource = false;
- $preferDist = false;
- $config = $composer->getConfig();
- switch ($config->get('preferred-install')) {
- case 'source':
- $preferSource = true;
- break;
- case 'dist':
- $preferDist = true;
- break;
- case 'auto':
- default:
- break;
- }
- if ($input->getOption('prefer-source') || $input->getOption('prefer-dist')) {
- $preferSource = $input->getOption('prefer-source');
- $preferDist = $input->getOption('prefer-dist');
- }
- $optimize = $input->getOption('optimize-autoloader') || $config->get('optimize-autoloader') || $config->get('classmap-authoritative');
- $install
- ->setDryRun($input->getOption('dry-run'))
- ->setVerbose($input->getOption('verbose'))
- ->setPreferSource($preferSource)
- ->setPreferDist($preferDist)
- ->setDevMode(!$input->getOption('no-dev'))
- ->setDumpAutoloader(!$input->getOption('no-autoloader'))
- ->setRunScripts(!$input->getOption('no-scripts'))
- ->setOptimizeAutoloader($optimize)
- ->setUpdate(true)
- ->setUpdateWhitelist($input->getOption('lock') ? array('lock') : $input->getArgument('packages'))
- ->setWhitelistDependencies($input->getOption('with-dependencies'))
- ->setIgnorePlatformRequirements($input->getOption('ignore-platform-reqs'))
- ->setPreferStable($input->getOption('prefer-stable'))
- ->setPreferLowest($input->getOption('prefer-lowest'))
- ;
- if ($input->getOption('no-plugins')) {
- $install->disablePlugins();
- }
- return $install->run();
- }
- }
- <?php
- namespace Composer\Command;
- use Composer\Package\Loader\ValidatingArrayLoader;
- use Composer\Util\ConfigValidator;
- use Symfony\Component\Console\Input\InputArgument;
- use Symfony\Component\Console\Input\InputInterface;
- use Symfony\Component\Console\Input\InputOption;
- use Symfony\Component\Console\Output\OutputInterface;
- class ValidateCommand extends Command
- {
- protected function configure()
- {
- $this
- ->setName('validate')
- ->setDescription('Validates a composer.json')
- ->setDefinition(array(
- new InputOption('no-check-all', null, InputOption::VALUE_NONE, 'Do not make a complete validation'),
- new InputOption('no-check-publish', null, InputOption::VALUE_NONE, 'Do not check for publish errors'),
- new InputArgument('file', InputArgument::OPTIONAL, 'path to composer.json file', './composer.json')
- ))
- ->setHelp(<<<EOT
- The validate command validates a given composer.json
- EOT
- );
- }
- protected function execute(InputInterface $input, OutputInterface $output)
- {
- $file = $input->getArgument('file');
- if (!file_exists($file)) {
- $this->getIO()->writeError('<error>' . $file . ' not found.</error>');
- return 1;
- }
- if (!is_readable($file)) {
- $this->getIO()->writeError('<error>' . $file . ' is not readable.</error>');
- return 1;
- }
- $validator = new ConfigValidator($this->getIO());
- $checkAll = $input->getOption('no-check-all') ? 0 : ValidatingArrayLoader::CHECK_ALL;
- $checkPublish = !$input->getOption('no-check-publish');
- list($errors, $publishErrors, $warnings) = $validator->validate($file, $checkAll);
- if (!$errors && !$publishErrors && !$warnings) {
- $this->getIO()->write('<info>' . $file . ' is valid</info>');
- } elseif (!$errors && !$publishErrors) {
- $this->getIO()->writeError('<info>' . $file . ' is valid, but with a few warnings</info>');
- $this->getIO()->writeError('<warning>See http://getcomposer.org/doc/04-schema.md for details on the schema</warning>');
- } elseif (!$errors) {
- $this->getIO()->writeError('<info>' . $file . ' is valid for simple usage with composer but has</info>');
- $this->getIO()->writeError('<info>strict errors that make it unable to be published as a package:</info>');
- $this->getIO()->writeError('<warning>See http://getcomposer.org/doc/04-schema.md for details on the schema</warning>');
- } else {
- $this->getIO()->writeError('<error>' . $file . ' is invalid, the following errors/warnings were found:</error>');
- }
- $messages = array(
- 'error' => $errors,
- 'warning' => $warnings,
- );
- if ($checkPublish) {
- $messages['error'] = array_merge($messages['error'], $publishErrors);
- } else {
- $messages['warning'] = array_merge($messages['warning'], $publishErrors);
- }
- foreach ($messages as $style => $msgs) {
- foreach ($msgs as $msg) {
- $this->getIO()->writeError('<' . $style . '>' . $msg . '</' . $style . '>');
- }
- }
- return $errors || ($publishErrors && $checkPublish) ? 1 : 0;
- }
- }
- <?php
- namespace Composer;
- use Composer\Package\RootPackageInterface;
- use Composer\Package\Locker;
- use Composer\Repository\RepositoryManager;
- use Composer\Installer\InstallationManager;
- use Composer\Plugin\PluginManager;
- use Composer\Downloader\DownloadManager;
- use Composer\EventDispatcher\EventDispatcher;
- use Composer\Autoload\AutoloadGenerator;
- class Composer
- {
- const VERSION = 'f87039656850828dee6d536b4d5cdb72703e9fd3';
- const BRANCH_ALIAS_VERSION = '1.0-dev';
- const RELEASE_DATE = '2015-04-10 21:45:24';
- private $package;
- private $locker;
- private $repositoryManager;
- private $downloadManager;
- private $installationManager;
- private $pluginManager;
- private $config;
- private $eventDispatcher;
- private $autoloadGenerator;
- public function setPackage(RootPackageInterface $package)
- {
- $this->package = $package;
- }
- public function getPackage()
- {
- return $this->package;
- }
- public function setConfig(Config $config)
- {
- $this->config = $config;
- }
- public function getConfig()
- {
- return $this->config;
- }
- public function setLocker(Locker $locker)
- {
- $this->locker = $locker;
- }
- public function getLocker()
- {
- return $this->locker;
- }
- public function setRepositoryManager(RepositoryManager $manager)
- {
- $this->repositoryManager = $manager;
- }
- public function getRepositoryManager()
- {
- return $this->repositoryManager;
- }
- public function setDownloadManager(DownloadManager $manager)
- {
- $this->downloadManager = $manager;
- }
- public function getDownloadManager()
- {
- return $this->downloadManager;
- }
- public function setInstallationManager(InstallationManager $manager)
- {
- $this->installationManager = $manager;
- }
- public function getInstallationManager()
- {
- return $this->installationManager;
- }
- public function setPluginManager(PluginManager $manager)
- {
- $this->pluginManager = $manager;
- }
- public function getPluginManager()
- {
- return $this->pluginManager;
- }
- public function setEventDispatcher(EventDispatcher $eventDispatcher)
- {
- $this->eventDispatcher = $eventDispatcher;
- }
- public function getEventDispatcher()
- {
- return $this->eventDispatcher;
- }
- public function setAutoloadGenerator(AutoloadGenerator $autoloadGenerator)
- {
- $this->autoloadGenerator = $autoloadGenerator;
- }
- public function getAutoloadGenerator()
- {
- return $this->autoloadGenerator;
- }
- }
- <?php
- namespace Composer\Config;
- interface ConfigSourceInterface
- {
- public function addRepository($name, $config);
- public function removeRepository($name);
- public function addConfigSetting($name, $value);
- public function removeConfigSetting($name);
- public function addLink($type, $name, $value);
- public function removeLink($type, $name);
- public function getName();
- }
- <?php
- namespace Composer\Config;
- use Composer\Json\JsonFile;
- use Composer\Json\JsonManipulator;
- class JsonConfigSource implements ConfigSourceInterface
- {
- private $file;
- private $authConfig;
- public function __construct(JsonFile $file, $authConfig = false)
- {
- $this->file = $file;
- $this->authConfig = $authConfig;
- }
- public function getName()
- {
- return $this->file->getPath();
- }
- public function addRepository($name, $config)
- {
- $this->manipulateJson('addRepository', $name, $config, function (&$config, $repo, $repoConfig) {
- $config['repositories'][$repo] = $repoConfig;
- });
- }
- public function removeRepository($name)
- {
- $this->manipulateJson('removeRepository', $name, function (&$config, $repo) {
- unset($config['repositories'][$repo]);
- });
- }
- public function addConfigSetting($name, $value)
- {
- $this->manipulateJson('addConfigSetting', $name, $value, function (&$config, $key, $val) {
- if ($key === 'github-oauth' || $key === 'http-basic') {
- list($key, $host) = explode('.', $key, 2);
- if ($this->authConfig) {
- $config[$key][$host] = $val;
- } else {
- $config['config'][$key][$host] = $val;
- }
- } else {
- $config['config'][$key] = $val;
- }
- });
- }
- public function removeConfigSetting($name)
- {
- $this->manipulateJson('removeConfigSetting', $name, function (&$config, $key) {
- if ($key === 'github-oauth' || $key === 'http-basic') {
- list($key, $host) = explode('.', $key, 2);
- if ($this->authConfig) {
- unset($config[$key][$host]);
- } else {
- unset($config['config'][$key][$host]);
- }
- } else {
- unset($config['config'][$key]);
- }
- });
- }
- public function addLink($type, $name, $value)
- {
- $this->manipulateJson('addLink', $type, $name, $value, function (&$config, $type, $name, $value) {
- $config[$type][$name] = $value;
- });
- }
- public function removeLink($type, $name)
- {
- $this->manipulateJson('removeSubNode', $type, $name, function (&$config, $type, $name) {
- unset($config[$type][$name]);
- });
- }
- protected function manipulateJson($method, $args, $fallback)
- {
- $args = func_get_args();
- array_shift($args);
- $fallback = array_pop($args);
- if ($this->file->exists()) {
- $contents = file_get_contents($this->file->getPath());
- } elseif ($this->authConfig) {
- $contents = "{\n}\n";
- } else {
- $contents = "{\n \"config\": {\n }\n}\n";
- }
- $manipulator = new JsonManipulator($contents);
- $newFile = !$this->file->exists();
- if ($this->authConfig && $method === 'addConfigSetting') {
- $method = 'addSubNode';
- list($mainNode, $name) = explode('.', $args[0], 2);
- $args = array($mainNode, $name, $args[1]);
- } elseif ($this->authConfig && $method === 'removeConfigSetting') {
- $method = 'removeSubNode';
- list($mainNode, $name) = explode('.', $args[0], 2);
- $args = array($mainNode, $name);
- }
- if (call_user_func_array(array($manipulator, $method), $args)) {
- file_put_contents($this->file->getPath(), $manipulator->getContents());
- } else {
- $config = $this->file->read();
- $this->arrayUnshiftRef($args, $config);
- call_user_func_array($fallback, $args);
- $this->file->write($config);
- }
- if ($newFile) {
- @chmod($this->file->getPath(), 0600);
- }
- }
- private function arrayUnshiftRef(&$array, &$value)
- {
- $return = array_unshift($array, '');
- $array[0] = &$value;
- return $return;
- }
- }
- <?php
- namespace Composer;
- use Composer\Config\ConfigSourceInterface;
- class Config
- {
- const RELATIVE_PATHS = 1;
- public static $defaultConfig = array(
- 'process-timeout' => 300,
- 'use-include-path' => false,
- 'preferred-install' => 'auto',
- 'notify-on-install' => true,
- 'github-protocols' => array('git', 'https', 'ssh'),
- 'vendor-dir' => 'vendor',
- 'bin-dir' => '{$vendor-dir}/bin',
- 'cache-dir' => '{$home}/cache',
- 'cache-files-dir' => '{$cache-dir}/files',
- 'cache-repo-dir' => '{$cache-dir}/repo',
- 'cache-vcs-dir' => '{$cache-dir}/vcs',
- 'cache-ttl' => 15552000,
- 'cache-files-ttl' => null,
- 'cache-files-maxsize' => '300MiB',
- 'discard-changes' => false,
- 'autoloader-suffix' => null,
- 'optimize-autoloader' => false,
- 'classmap-authoritative' => false,
- 'prepend-autoloader' => true,
- 'github-domains' => array('github.com'),
- 'github-expose-hostname' => true,
- 'gitlab-domains' => array('gitlab.com'),
- 'store-auths' => 'prompt',
-
-
- );
- public static $defaultRepositories = array(
- 'packagist' => array(
- 'type' => 'composer',
- 'url' => 'https?://packagist.org',
- 'allow_ssl_downgrade' => true,
- )
- );
- private $config;
- private $baseDir;
- private $repositories;
- private $configSource;
- private $authConfigSource;
- private $useEnvironment;
- public function __construct($useEnvironment = true, $baseDir = null)
- {
- $this->config = static::$defaultConfig;
- $this->repositories = static::$defaultRepositories;
- $this->useEnvironment = (bool) $useEnvironment;
- $this->baseDir = $baseDir;
- }
- public function setConfigSource(ConfigSourceInterface $source)
- {
- $this->configSource = $source;
- }
- public function getConfigSource()
- {
- return $this->configSource;
- }
- public function setAuthConfigSource(ConfigSourceInterface $source)
- {
- $this->authConfigSource = $source;
- }
- public function getAuthConfigSource()
- {
- return $this->authConfigSource;
- }
- public function merge($config)
- {
- if (!empty($config['config']) && is_array($config['config'])) {
- foreach ($config['config'] as $key => $val) {
- if (in_array($key, array('github-oauth', 'http-basic')) && isset($this->config[$key])) {
- $this->config[$key] = array_merge($this->config[$key], $val);
- } else {
- $this->config[$key] = $val;
- }
- }
- }
- if (!empty($config['repositories']) && is_array($config['repositories'])) {
- $this->repositories = array_reverse($this->repositories, true);
- $newRepos = array_reverse($config['repositories'], true);
- foreach ($newRepos as $name => $repository) {
- if (false === $repository) {
- unset($this->repositories[$name]);
- continue;
- }
- if (is_array($repository) && 1 === count($repository) && false === current($repository)) {
- unset($this->repositories[key($repository)]);
- continue;
- }
- if (is_int($name)) {
- $this->repositories[] = $repository;
- } else {
- $this->repositories[$name] = $repository;
- }
- }
- $this->repositories = array_reverse($this->repositories, true);
- }
- }
- public function getRepositories()
- {
- return $this->repositories;
- }
- public function get($key, $flags = 0)
- {
- switch ($key) {
- case 'vendor-dir':
- case 'bin-dir':
- case 'process-timeout':
- case 'cache-dir':
- case 'cache-files-dir':
- case 'cache-repo-dir':
- case 'cache-vcs-dir':
- $env = 'COMPOSER_' . strtoupper(strtr($key, '-', '_'));
- $val = rtrim($this->process($this->getComposerEnv($env) ?: $this->config[$key], $flags), '/\\');
- $val = preg_replace('#^(\$HOME|~)(/|$)#', rtrim(getenv('HOME') ?: getenv('USERPROFILE'), '/\\') . '/', $val);
- if (substr($key, -4) !== '-dir') {
- return $val;
- }
- return ($flags & self::RELATIVE_PATHS == 1) ? $val : $this->realpath($val);
- case 'cache-ttl':
- return (int) $this->config[$key];
- case 'cache-files-maxsize':
- if (!preg_match('/^\s*([0-9.]+)\s*(?:([kmg])(?:i?b)?)?\s*$/i', $this->config[$key], $matches)) {
- throw new \RuntimeException(
- "Could not parse the value of 'cache-files-maxsize': {$this->config[$key]}"
- );
- }
- $size = $matches[1];
- if (isset($matches[2])) {
- switch (strtolower($matches[2])) {
- case 'g':
- $size *= 1024;
- case 'm':
- $size *= 1024;
- case 'k':
- $size *= 1024;
- break;
- }
- }
- return $size;
- case 'cache-files-ttl':
- if (isset($this->config[$key])) {
- return (int) $this->config[$key];
- }
- return (int) $this->config['cache-ttl'];
- case 'home':
- return rtrim($this->process($this->config[$key], $flags), '/\\');
- case 'discard-changes':
- if ($env = $this->getComposerEnv('COMPOSER_DISCARD_CHANGES')) {
- if (!in_array($env, array('stash', 'true', 'false', '1', '0'), true)) {
- throw new \RuntimeException(
- "Invalid value for COMPOSER_DISCARD_CHANGES: {$env}. Expected 1, 0, true, false or stash"
- );
- }
- if ('stash' === $env) {
- return 'stash';
- }
- return $env !== 'false' && (bool) $env;
- }
- if (!in_array($this->config[$key], array(true, false, 'stash'), true)) {
- throw new \RuntimeException(
- "Invalid value for 'discard-changes': {$this->config[$key]}. Expected true, false or stash"
- );
- }
- return $this->config[$key];
- case 'github-protocols':
- if (reset($this->config['github-protocols']) === 'http') {
- throw new \RuntimeException('The http protocol for github is not available anymore, update your config\'s github-protocols to use "https", "git" or "ssh"');
- }
- return $this->config[$key];
- default:
- if (!isset($this->config[$key])) {
- return null;
- }
- return $this->process($this->config[$key], $flags);
- }
- }
- public function all($flags = 0)
- {
- $all = array(
- 'repositories' => $this->getRepositories(),
- );
- foreach (array_keys($this->config) as $key) {
- $all['config'][$key] = $this->get($key, $flags);
- }
- return $all;
- }
- public function raw()
- {
- return array(
- 'repositories' => $this->getRepositories(),
- 'config' => $this->config,
- );
- }
- public function has($key)
- {
- return array_key_exists($key, $this->config);
- }
- private function process($value, $flags)
- {
- $config = $this;
- if (!is_string($value)) {
- return $value;
- }
- return preg_replace_callback('#\{\$(.+)\}#', function ($match) use ($config, $flags) {
- return $config->get($match[1], $flags);
- }, $value);
- }
- private function realpath($path)
- {
- if (substr($path, 0, 1) === '/' || substr($path, 1, 1) === ':') {
- return $path;
- }
- return $this->baseDir . '/' . $path;
- }
- private function getComposerEnv($var)
- {
- if ($this->useEnvironment) {
- return getenv($var);
- }
- return false;
- }
- }
- <?php
- namespace Composer\Console;
- use Symfony\Component\Console\Application as BaseApplication;
- use Symfony\Component\Console\Input\InputInterface;
- use Symfony\Component\Console\Input\InputOption;
- use Symfony\Component\Console\Output\ConsoleOutputInterface;
- use Symfony\Component\Console\Output\OutputInterface;
- use Symfony\Component\Console\Output\ConsoleOutput;
- use Symfony\Component\Console\Formatter\OutputFormatter;
- use Composer\Command;
- use Composer\Command\Helper\DialogHelper;
- use Composer\Composer;
- use Composer\Factory;
- use Composer\IO\IOInterface;
- use Composer\IO\ConsoleIO;
- use Composer\Json\JsonValidationException;
- use Composer\Util\ErrorHandler;
- class Application extends BaseApplication
- {
- protected $composer;
- protected $io;
- private static $logo = ' ______
- / ____/___ ____ ___ ____ ____ ________ _____
- / / / __ \/ __ `__ \/ __ \/ __ \/ ___/ _ \/ ___/
- / /___/ /_/ / / / / / / /_/ / /_/ (__ ) __/ /
- \____/\____/_/ /_/ /_/ .___/\____/____/\___/_/
- /_/
- ';
- public function __construct()
- {
- if (function_exists('ini_set') && extension_loaded('xdebug')) {
- ini_set('xdebug.show_exception_trace', false);
- ini_set('xdebug.scream', false);
- }
- if (function_exists('date_default_timezone_set') && function_exists('date_default_timezone_get')) {
- date_default_timezone_set(@date_default_timezone_get());
- }
- ErrorHandler::register();
- parent::__construct('Composer', Composer::VERSION);
- }
- public function run(InputInterface $input = null, OutputInterface $output = null)
- {
- if (null === $output) {
- $styles = Factory::createAdditionalStyles();
- $formatter = new OutputFormatter(null, $styles);
- $output = new ConsoleOutput(ConsoleOutput::VERBOSITY_NORMAL, null, $formatter);
- }
- return parent::run($input, $output);
- }
- public function doRun(InputInterface $input, OutputInterface $output)
- {
- $this->io = new ConsoleIO($input, $output, $this->getHelperSet());
- if (version_compare(PHP_VERSION, '5.3.2', '<')) {
- $this->getIO()->writeError('<warning>Composer only officially supports PHP 5.3.2 and above, you will most likely encounter problems with your PHP '.PHP_VERSION.', upgrading is strongly recommended.</warning>');
- }
- if (defined('COMPOSER_DEV_WARNING_TIME')) {
- $commandName = '';
- if ($name = $this->getCommandName($input)) {
- try {
- $commandName = $this->find($name)->getName();
- } catch (\InvalidArgumentException $e) {
- }
- }
- if ($commandName !== 'self-update' && $commandName !== 'selfupdate') {
- if (time() > COMPOSER_DEV_WARNING_TIME) {
- $this->getIO()->writeError(sprintf('<warning>Warning: This development build of composer is over 30 days old. It is recommended to update it by running "%s self-update" to get the latest version.</warning>', $_SERVER['PHP_SELF']));
- }
- }
- }
- if (getenv('COMPOSER_NO_INTERACTION')) {
- $input->setInteractive(false);
- }
- if ($newWorkDir = $this->getNewWorkingDir($input)) {
- $oldWorkingDir = getcwd();
- chdir($newWorkDir);
- if ($this->getIO()->isDebug() >= 4) {
- $this->getIO()->writeError('Changed CWD to ' . getcwd());
- }
- }
- $file = Factory::getComposerFile();
- if (is_file($file) && is_readable($file) && is_array($composer = json_decode(file_get_contents($file), true))) {
- if (isset($composer['scripts']) && is_array($composer['scripts'])) {
- foreach ($composer['scripts'] as $script => $dummy) {
- if (!defined('Composer\Script\ScriptEvents::'.str_replace('-', '_', strtoupper($script)))) {
- if ($this->has($script)) {
- $this->getIO()->writeError('<warning>A script named '.$script.' would override a native Composer function and has been skipped</warning>');
- } else {
- $this->add(new Command\ScriptAliasCommand($script));
- }
- }
- }
- }
- }
- if ($input->hasParameterOption('--profile')) {
- $startTime = microtime(true);
- $this->io->enableDebugging($startTime);
- }
- $result = parent::doRun($input, $output);
- if (isset($oldWorkingDir)) {
- chdir($oldWorkingDir);
- }
- if (isset($startTime)) {
- $this->getIO()->writeError('<info>Memory usage: '.round(memory_get_usage() / 1024 / 1024, 2).'MB (peak: '.round(memory_get_peak_usage() / 1024 / 1024, 2).'MB), time: '.round(microtime(true) - $startTime, 2).'s');
- }
- return $result;
- }
- private function getNewWorkingDir(InputInterface $input)
- {
- $workingDir = $input->getParameterOption(array('--working-dir', '-d'));
- if (false !== $workingDir && !is_dir($workingDir)) {
- throw new \RuntimeException('Invalid working directory specified.');
- }
- return $workingDir;
- }
- public function renderException($exception, $output)
- {
- try {
- $composer = $this->getComposer(false, true);
- if ($composer) {
- $config = $composer->getConfig();
- $minSpaceFree = 1024*1024;
- if ((($df = @disk_free_space($dir = $config->get('home'))) !== false && $df < $minSpaceFree)
- || (($df = @disk_free_space($dir = $config->get('vendor-dir'))) !== false && $df < $minSpaceFree)
- || (($df = @disk_free_space($dir = sys_get_temp_dir())) !== false && $df < $minSpaceFree)
- ) {
- $this->getIO()->writeError('<error>The disk hosting '.$dir.' is full, this may be the cause of the following exception</error>');
- }
- }
- } catch (\Exception $e) {
- }
- if (defined('PHP_WINDOWS_VERSION_BUILD') && false !== strpos($exception->getMessage(), 'The system cannot find the path specified')) {
- $this->getIO()->writeError('<error>The following exception may be caused by a stale entry in your cmd.exe AutoRun</error>');
- $this->getIO()->writeError('<error>Check https://getcomposer.org/doc/articles/troubleshooting.md#-the-system-cannot-find-the-path-specified-windows- for details</error>');
- }
- if (false !== strpos($exception->getMessage(), 'fork failed - Cannot allocate memory')) {
- $this->getIO()->writeError('<error>The following exception is caused by a lack of memory and not having swap configured</error>');
- $this->getIO()->writeError('<error>Check https://getcomposer.org/doc/articles/troubleshooting.md#proc-open-fork-failed-errors for details</error>');
- }
- if ($output instanceof ConsoleOutputInterface) {
- parent::renderException($exception, $output->getErrorOutput());
- } else {
- parent::renderException($exception, $output);
- }
- }
- public function getComposer($required = true, $disablePlugins = false)
- {
- if (null === $this->composer) {
- try {
- $this->composer = Factory::create($this->io, null, $disablePlugins);
- } catch (\InvalidArgumentException $e) {
- if ($required) {
- $this->io->writeError($e->getMessage());
- exit(1);
- }
- } catch (JsonValidationException $e) {
- $errors = ' - ' . implode(PHP_EOL . ' - ', $e->getErrors());
- $message = $e->getMessage() . ':' . PHP_EOL . $errors;
- throw new JsonValidationException($message);
- }
- }
- return $this->composer;
- }
- public function resetComposer()
- {
- $this->composer = null;
- }
- public function getIO()
- {
- return $this->io;
- }
- public function getHelp()
- {
- return self::$logo . parent::getHelp();
- }
- protected function getDefaultCommands()
- {
- $commands = parent::getDefaultCommands();
- $commands[] = new Command\AboutCommand();
- $commands[] = new Command\ConfigCommand();
- $commands[] = new Command\DependsCommand();
- $commands[] = new Command\InitCommand();
- $commands[] = new Command\InstallCommand();
- $commands[] = new Command\CreateProjectCommand();
- $commands[] = new Command\UpdateCommand();
- $commands[] = new Command\SearchCommand();
- $commands[] = new Command\ValidateCommand();
- $commands[] = new Command\ShowCommand();
- $commands[] = new Command\RequireCommand();
- $commands[] = new Command\DumpAutoloadCommand();
- $commands[] = new Command\StatusCommand();
- $commands[] = new Command\ArchiveCommand();
- $commands[] = new Command\DiagnoseCommand();
- $commands[] = new Command\RunScriptCommand();
- $commands[] = new Command\LicensesCommand();
- $commands[] = new Command\GlobalCommand();
- $commands[] = new Command\ClearCacheCommand();
- $commands[] = new Command\RemoveCommand();
- $commands[] = new Command\HomeCommand();
- if ('phar:' === substr(__FILE__, 0, 5)) {
- $commands[] = new Command\SelfUpdateCommand();
- }
- return $commands;
- }
- public function getLongVersion()
- {
- if (Composer::BRANCH_ALIAS_VERSION) {
- return sprintf(
- '<info>%s</info> version <comment>%s (%s)</comment> %s',
- $this->getName(),
- Composer::BRANCH_ALIAS_VERSION,
- $this->getVersion(),
- Composer::RELEASE_DATE
- );
- }
- return parent::getLongVersion() . ' ' . Composer::RELEASE_DATE;
- }
- protected function getDefaultInputDefinition()
- {
- $definition = parent::getDefaultInputDefinition();
- $definition->addOption(new InputOption('--profile', null, InputOption::VALUE_NONE, 'Display timing and memory usage information'));
- $definition->addOption(new InputOption('--working-dir', '-d', InputOption::VALUE_REQUIRED, 'If specified, use the given directory as working directory.'));
- return $definition;
- }
- protected function getDefaultHelperSet()
- {
- $helperSet = parent::getDefaultHelperSet();
- $helperSet->set(new DialogHelper());
- return $helperSet;
- }
- }
- <?php
- namespace Composer\Console;
- use Symfony\Component\Console\Formatter\OutputFormatter;
- class HtmlOutputFormatter extends OutputFormatter
- {
- private static $availableForegroundColors = array(
- 30 => 'black',
- 31 => 'red',
- 32 => 'green',
- 33 => 'yellow',
- 34 => 'blue',
- 35 => 'magenta',
- 36 => 'cyan',
- 37 => 'white'
- );
- private static $availableBackgroundColors = array(
- 40 => 'black',
- 41 => 'red',
- 42 => 'green',
- 43 => 'yellow',
- 44 => 'blue',
- 45 => 'magenta',
- 46 => 'cyan',
- 47 => 'white'
- );
- private static $availableOptions = array(
- 1 => 'bold',
- 4 => 'underscore',
-
-
- );
- public function __construct(array $styles = array())
- {
- parent::__construct(true, $styles);
- }
- public function format($message)
- {
- $formatted = parent::format($message);
- return preg_replace_callback("{\033\[([0-9;]+)m(.*?)\033\[0m}s", array($this, 'formatHtml'), $formatted);
- }
- private function formatHtml($matches)
- {
- $out = '<span style="';
- foreach (explode(';', $matches[1]) as $code) {
- if (isset(self::$availableForegroundColors[$code])) {
- $out .= 'color:'.self::$availableForegroundColors[$code].';';
- } elseif (isset(self::$availableBackgroundColors[$code])) {
- $out .= 'background-color:'.self::$availableBackgroundColors[$code].';';
- } elseif (isset(self::$availableOptions[$code])) {
- switch (self::$availableOptions[$code]) {
- case 'bold':
- $out .= 'font-weight:bold;';
- break;
- case 'underscore':
- $out .= 'text-decoration:underline;';
- break;
- }
- }
- }
- return $out.'">'.$matches[2].'</span>';
- }
- }
- <?php
- namespace Composer\DependencyResolver;
- class DebugSolver extends Solver
- {
- protected function printDecisionMap()
- {
- echo "\nDecisionMap: \n";
- foreach ($this->decisionMap as $packageId => $level) {
- if ($packageId === 0) {
- continue;
- }
- if ($level > 0) {
- echo ' +' . $this->pool->packageById($packageId)."\n";
- } elseif ($level < 0) {
- echo ' -' . $this->pool->packageById($packageId)."\n";
- } else {
- echo ' ?' . $this->pool->packageById($packageId)."\n";
- }
- }
- echo "\n";
- }
- protected function printDecisionQueue()
- {
- echo "DecisionQueue: \n";
- foreach ($this->decisionQueue as $i => $literal) {
- echo ' ' . $this->pool->literalToString($literal) . ' ' . $this->decisionQueueWhy[$i]." level ".$this->decisionMap[abs($literal)]."\n";
- }
- echo "\n";
- }
- protected function printWatches()
- {
- echo "\nWatches:\n";
- foreach ($this->watches as $literalId => $watch) {
- echo ' '.$this->literalFromId($literalId)."\n";
- $queue = array(array(' ', $watch));
- while (!empty($queue)) {
- list($indent, $watch) = array_pop($queue);
- echo $indent.$watch;
- if ($watch) {
- echo ' [id='.$watch->getId().',watch1='.$this->literalFromId($watch->watch1).',watch2='.$this->literalFromId($watch->watch2)."]";
- }
- echo "\n";
- if ($watch && ($watch->next1 == $watch || $watch->next2 == $watch)) {
- if ($watch->next1 == $watch) {
- echo $indent." 1 *RECURSION*";
- }
- if ($watch->next2 == $watch) {
- echo $indent." 2 *RECURSION*";
- }
- } elseif ($watch && ($watch->next1 || $watch->next2)) {
- $indent = str_replace(array('1', '2'), ' ', $indent);
- array_push($queue, array($indent.' 2 ', $watch->next2));
- array_push($queue, array($indent.' 1 ', $watch->next1));
- }
- }
- echo "\n";
- }
- }
- }
- <?php
- namespace Composer\DependencyResolver;
- class Decisions implements \Iterator, \Countable
- {
- const DECISION_LITERAL = 0;
- const DECISION_REASON = 1;
- protected $pool;
- protected $decisionMap;
- protected $decisionQueue = array();
- public function __construct($pool)
- {
- $this->pool = $pool;
- $this->decisionMap = array();
- }
- public function decide($literal, $level, $why)
- {
- $this->addDecision($literal, $level);
- $this->decisionQueue[] = array(
- self::DECISION_LITERAL => $literal,
- self::DECISION_REASON => $why,
- );
- }
- public function satisfy($literal)
- {
- $packageId = abs($literal);
- return (
- $literal > 0 && isset($this->decisionMap[$packageId]) && $this->decisionMap[$packageId] > 0 ||
- $literal < 0 && isset($this->decisionMap[$packageId]) && $this->decisionMap[$packageId] < 0
- );
- }
- public function conflict($literal)
- {
- $packageId = abs($literal);
- return (
- (isset($this->decisionMap[$packageId]) && $this->decisionMap[$packageId] > 0 && $literal < 0) ||
- (isset($this->decisionMap[$packageId]) && $this->decisionMap[$packageId] < 0 && $literal > 0)
- );
- }
- public function decided($literalOrPackageId)
- {
- return !empty($this->decisionMap[abs($literalOrPackageId)]);
- }
- public function undecided($literalOrPackageId)
- {
- return empty($this->decisionMap[abs($literalOrPackageId)]);
- }
- public function decidedInstall($literalOrPackageId)
- {
- $packageId = abs($literalOrPackageId);
- return isset($this->decisionMap[$packageId]) && $this->decisionMap[$packageId] > 0;
- }
- public function decisionLevel($literalOrPackageId)
- {
- $packageId = abs($literalOrPackageId);
- if (isset($this->decisionMap[$packageId])) {
- return abs($this->decisionMap[$packageId]);
- }
- return 0;
- }
- public function decisionRule($literalOrPackageId)
- {
- $packageId = abs($literalOrPackageId);
- foreach ($this->decisionQueue as $i => $decision) {
- if ($packageId === abs($decision[self::DECISION_LITERAL])) {
- return $decision[self::DECISION_REASON];
- }
- }
- return null;
- }
- public function atOffset($queueOffset)
- {
- return $this->decisionQueue[$queueOffset];
- }
- public function validOffset($queueOffset)
- {
- return $queueOffset >= 0 && $queueOffset < count($this->decisionQueue);
- }
- public function lastReason()
- {
- return $this->decisionQueue[count($this->decisionQueue) - 1][self::DECISION_REASON];
- }
- public function lastLiteral()
- {
- return $this->decisionQueue[count($this->decisionQueue) - 1][self::DECISION_LITERAL];
- }
- public function reset()
- {
- while ($decision = array_pop($this->decisionQueue)) {
- $this->decisionMap[abs($decision[self::DECISION_LITERAL])] = 0;
- }
- }
- public function resetToOffset($offset)
- {
- while (count($this->decisionQueue) > $offset + 1) {
- $decision = array_pop($this->decisionQueue);
- $this->decisionMap[abs($decision[self::DECISION_LITERAL])] = 0;
- }
- }
- public function revertLast()
- {
- $this->decisionMap[abs($this->lastLiteral())] = 0;
- array_pop($this->decisionQueue);
- }
- public function count()
- {
- return count($this->decisionQueue);
- }
- public function rewind()
- {
- end($this->decisionQueue);
- }
- public function current()
- {
- return current($this->decisionQueue);
- }
- public function key()
- {
- return key($this->decisionQueue);
- }
- public function next()
- {
- return prev($this->decisionQueue);
- }
- public function valid()
- {
- return false !== current($this->decisionQueue);
- }
- public function isEmpty()
- {
- return count($this->decisionQueue) === 0;
- }
- protected function addDecision($literal, $level)
- {
- $packageId = abs($literal);
- $previousDecision = isset($this->decisionMap[$packageId]) ? $this->decisionMap[$packageId] : null;
- if ($previousDecision != 0) {
- $literalString = $this->pool->literalToString($literal);
- $package = $this->pool->literalToPackage($literal);
- throw new SolverBugException(
- "Trying to decide $literalString on level $level, even though $package was previously decided as ".(int) $previousDecision."."
- );
- }
- if ($literal > 0) {
- $this->decisionMap[$packageId] = $level;
- } else {
- $this->decisionMap[$packageId] = -$level;
- }
- }
- }
- <?php
- namespace Composer\DependencyResolver;
- use Composer\Package\PackageInterface;
- use Composer\Package\AliasPackage;
- use Composer\Package\BasePackage;
- use Composer\Package\LinkConstraint\VersionConstraint;
- class DefaultPolicy implements PolicyInterface
- {
- private $preferStable;
- private $preferLowest;
- public function __construct($preferStable = false, $preferLowest = false)
- {
- $this->preferStable = $preferStable;
- $this->preferLowest = $preferLowest;
- }
- public function versionCompare(PackageInterface $a, PackageInterface $b, $operator)
- {
- if ($this->preferStable && ($stabA = $a->getStability()) !== ($stabB = $b->getStability())) {
- return BasePackage::$stabilities[$stabA] < BasePackage::$stabilities[$stabB];
- }
- $constraint = new VersionConstraint($operator, $b->getVersion());
- $version = new VersionConstraint('==', $a->getVersion());
- return $constraint->matchSpecific($version, true);
- }
- public function findUpdatePackages(Pool $pool, array $installedMap, PackageInterface $package, $mustMatchName = false)
- {
- $packages = array();
- foreach ($pool->whatProvides($package->getName(), null, $mustMatchName) as $candidate) {
- if ($candidate !== $package) {
- $packages[] = $candidate;
- }
- }
- return $packages;
- }
- public function getPriority(Pool $pool, PackageInterface $package)
- {
- return $pool->getPriority($package->getRepository());
- }
- public function selectPreferedPackages(Pool $pool, array $installedMap, array $literals, $requiredPackage = null)
- {
- $packages = $this->groupLiteralsByNamePreferInstalled($pool, $installedMap, $literals);
- foreach ($packages as &$literals) {
- $policy = $this;
- usort($literals, function ($a, $b) use ($policy, $pool, $installedMap, $requiredPackage) {
- return $policy->compareByPriorityPreferInstalled($pool, $installedMap, $pool->literalToPackage($a), $pool->literalToPackage($b), $requiredPackage, true);
- });
- }
- foreach ($packages as &$literals) {
- $literals = $this->pruneToBestVersion($pool, $literals);
- $literals = $this->pruneToHighestPriorityOrInstalled($pool, $installedMap, $literals);
- $literals = $this->pruneRemoteAliases($pool, $literals);
- }
- $selected = call_user_func_array('array_merge', $packages);
- usort($selected, function ($a, $b) use ($policy, $pool, $installedMap, $requiredPackage) {
- return $policy->compareByPriorityPreferInstalled($pool, $installedMap, $pool->literalToPackage($a), $pool->literalToPackage($b), $requiredPackage);
- });
- return $selected;
- }
- protected function groupLiteralsByNamePreferInstalled(Pool $pool, array $installedMap, $literals)
- {
- $packages = array();
- foreach ($literals as $literal) {
- $packageName = $pool->literalToPackage($literal)->getName();
- if (!isset($packages[$packageName])) {
- $packages[$packageName] = array();
- }
- if (isset($installedMap[abs($literal)])) {
- array_unshift($packages[$packageName], $literal);
- } else {
- $packages[$packageName][] = $literal;
- }
- }
- return $packages;
- }
- public function compareByPriorityPreferInstalled(Pool $pool, array $installedMap, PackageInterface $a, PackageInterface $b, $requiredPackage = null, $ignoreReplace = false)
- {
- if ($a->getRepository() === $b->getRepository()) {
- if ($a->getName() === $b->getName()) {
- $aAliased = $a instanceof AliasPackage;
- $bAliased = $b instanceof AliasPackage;
- if ($aAliased && !$bAliased) {
- return -1;
- }
- if (!$aAliased && $bAliased) {
- return 1;
- }
- }
- if (!$ignoreReplace) {
- if ($this->replaces($a, $b)) {
- return 1;
- }
- if ($this->replaces($b, $a)) {
- return -1;
- }
-
- if ($requiredPackage && false !== ($pos = strpos($requiredPackage, '/'))) {
- $requiredVendor = substr($requiredPackage, 0, $pos);
- $aIsSameVendor = substr($a->getName(), 0, $pos) === $requiredVendor;
- $bIsSameVendor = substr($b->getName(), 0, $pos) === $requiredVendor;
- if ($bIsSameVendor !== $aIsSameVendor) {
- return $aIsSameVendor ? -1 : 1;
- }
- }
- }
- if ($a->id === $b->id) {
- return 0;
- }
- return ($a->id < $b->id) ? -1 : 1;
- }
- if (isset($installedMap[$a->id])) {
- return -1;
- }
- if (isset($installedMap[$b->id])) {
- return 1;
- }
- return ($this->getPriority($pool, $a) > $this->getPriority($pool, $b)) ? -1 : 1;
- }
- protected function replaces(PackageInterface $source, PackageInterface $target)
- {
- foreach ($source->getReplaces() as $link) {
- if ($link->getTarget() === $target->getName()
- ) {
- return true;
- }
- }
- return false;
- }
- protected function pruneToBestVersion(Pool $pool, $literals)
- {
- $operator = $this->preferLowest ? '<' : '>';
- $bestLiterals = array($literals[0]);
- $bestPackage = $pool->literalToPackage($literals[0]);
- foreach ($literals as $i => $literal) {
- if (0 === $i) {
- continue;
- }
- $package = $pool->literalToPackage($literal);
- if ($this->versionCompare($package, $bestPackage, $operator)) {
- $bestPackage = $package;
- $bestLiterals = array($literal);
- } elseif ($this->versionCompare($package, $bestPackage, '==')) {
- $bestLiterals[] = $literal;
- }
- }
- return $bestLiterals;
- }
- protected function pruneToHighestPriorityOrInstalled(Pool $pool, array $installedMap, array $literals)
- {
- $selected = array();
- $priority = null;
- foreach ($literals as $literal) {
- $package = $pool->literalToPackage($literal);
- if (isset($installedMap[$package->id])) {
- $selected[] = $literal;
- continue;
- }
- if (null === $priority) {
- $priority = $this->getPriority($pool, $package);
- }
- if ($this->getPriority($pool, $package) != $priority) {
- break;
- }
- $selected[] = $literal;
- }
- return $selected;
- }
- protected function pruneRemoteAliases(Pool $pool, array $literals)
- {
- $hasLocalAlias = false;
- foreach ($literals as $literal) {
- $package = $pool->literalToPackage($literal);
- if ($package instanceof AliasPackage && $package->isRootPackageAlias()) {
- $hasLocalAlias = true;
- break;
- }
- }
- if (!$hasLocalAlias) {
- return $literals;
- }
- $selected = array();
- foreach ($literals as $literal) {
- $package = $pool->literalToPackage($literal);
- if ($package instanceof AliasPackage && $package->isRootPackageAlias()) {
- $selected[] = $literal;
- }
- }
- return $selected;
- }
- }
- <?php
- namespace Composer\DependencyResolver\Operation;
- use Composer\Package\PackageInterface;
- class InstallOperation extends SolverOperation
- {
- protected $package;
- public function __construct(PackageInterface $package, $reason = null)
- {
- parent::__construct($reason);
- $this->package = $package;
- }
- public function getPackage()
- {
- return $this->package;
- }
- public function getJobType()
- {
- return 'install';
- }
- public function __toString()
- {
- return 'Installing '.$this->package->getPrettyName().' ('.$this->formatVersion($this->package).')';
- }
- }
- <?php
- namespace Composer\DependencyResolver\Operation;
- use Composer\Package\AliasPackage;
- class MarkAliasInstalledOperation extends SolverOperation
- {
- protected $package;
- public function __construct(AliasPackage $package, $reason = null)
- {
- parent::__construct($reason);
- $this->package = $package;
- }
- public function getPackage()
- {
- return $this->package;
- }
- public function getJobType()
- {
- return 'markAliasInstalled';
- }
- public function __toString()
- {
- return 'Marking '.$this->package->getPrettyName().' ('.$this->formatVersion($this->package).') as installed, alias of '.$this->package->getAliasOf()->getPrettyName().' ('.$this->formatVersion($this->package->getAliasOf()).')';
- }
- }
- <?php
- namespace Composer\DependencyResolver\Operation;
- use Composer\Package\AliasPackage;
- class MarkAliasUninstalledOperation extends SolverOperation
- {
- protected $package;
- public function __construct(AliasPackage $package, $reason = null)
- {
- parent::__construct($reason);
- $this->package = $package;
- }
- public function getPackage()
- {
- return $this->package;
- }
- public function getJobType()
- {
- return 'markAliasUninstalled';
- }
- public function __toString()
- {
- return 'Marking '.$this->package->getPrettyName().' ('.$this->formatVersion($this->package).') as uninstalled, alias of '.$this->package->getAliasOf()->getPrettyName().' ('.$this->formatVersion($this->package->getAliasOf()).')';
- }
- }
- <?php
- namespace Composer\DependencyResolver\Operation;
- interface OperationInterface
- {
- public function getJobType();
- public function getReason();
- public function __toString();
- }
- <?php
- namespace Composer\DependencyResolver\Operation;
- use Composer\Package\Version\VersionParser;
- use Composer\Package\PackageInterface;
- abstract class SolverOperation implements OperationInterface
- {
- protected $reason;
- public function __construct($reason = null)
- {
- $this->reason = $reason;
- }
- public function getReason()
- {
- return $this->reason;
- }
- protected function formatVersion(PackageInterface $package)
- {
- return VersionParser::formatVersion($package);
- }
- }
- <?php
- namespace Composer\DependencyResolver\Operation;
- use Composer\Package\PackageInterface;
- class UninstallOperation extends SolverOperation
- {
- protected $package;
- public function __construct(PackageInterface $package, $reason = null)
- {
- parent::__construct($reason);
- $this->package = $package;
- }
- public function getPackage()
- {
- return $this->package;
- }
- public function getJobType()
- {
- return 'uninstall';
- }
- public function __toString()
- {
- return 'Uninstalling '.$this->package->getPrettyName().' ('.$this->formatVersion($this->package).')';
- }
- }
- <?php
- namespace Composer\DependencyResolver\Operation;
- use Composer\Package\PackageInterface;
- class UpdateOperation extends SolverOperation
- {
- protected $initialPackage;
- protected $targetPackage;
- public function __construct(PackageInterface $initial, PackageInterface $target, $reason = null)
- {
- parent::__construct($reason);
- $this->initialPackage = $initial;
- $this->targetPackage = $target;
- }
- public function getInitialPackage()
- {
- return $this->initialPackage;
- }
- public function getTargetPackage()
- {
- return $this->targetPackage;
- }
- public function getJobType()
- {
- return 'update';
- }
- public function __toString()
- {
- return 'Updating '.$this->initialPackage->getPrettyName().' ('.$this->formatVersion($this->initialPackage).') to '.
- $this->targetPackage->getPrettyName(). ' ('.$this->formatVersion($this->targetPackage).')';
- }
- }
- <?php
- namespace Composer\DependencyResolver;
- use Composer\Package\PackageInterface;
- interface PolicyInterface
- {
- public function versionCompare(PackageInterface $a, PackageInterface $b, $operator);
- public function findUpdatePackages(Pool $pool, array $installedMap, PackageInterface $package);
- public function selectPreferedPackages(Pool $pool, array $installedMap, array $literals);
- }
- <?php
- namespace Composer\DependencyResolver;
- use Composer\Package\BasePackage;
- use Composer\Package\AliasPackage;
- use Composer\Package\Version\VersionParser;
- use Composer\Package\LinkConstraint\LinkConstraintInterface;
- use Composer\Package\LinkConstraint\VersionConstraint;
- use Composer\Package\LinkConstraint\EmptyConstraint;
- use Composer\Repository\RepositoryInterface;
- use Composer\Repository\CompositeRepository;
- use Composer\Repository\ComposerRepository;
- use Composer\Repository\InstalledRepositoryInterface;
- use Composer\Repository\PlatformRepository;
- use Composer\Package\PackageInterface;
- class Pool
- {
- const MATCH_NAME = -1;
- const MATCH_NONE = 0;
- const MATCH = 1;
- const MATCH_PROVIDE = 2;
- const MATCH_REPLACE = 3;
- const MATCH_FILTERED = 4;
- protected $repositories = array();
- protected $providerRepos = array();
- protected $packages = array();
- protected $packageByName = array();
- protected $packageByExactName = array();
- protected $acceptableStabilities;
- protected $stabilityFlags;
- protected $versionParser;
- protected $providerCache = array();
- protected $filterRequires;
- protected $whitelist = null;
- protected $id = 1;
- public function __construct($minimumStability = 'stable', array $stabilityFlags = array(), array $filterRequires = array())
- {
- $stabilities = BasePackage::$stabilities;
- $this->versionParser = new VersionParser;
- $this->acceptableStabilities = array();
- foreach (BasePackage::$stabilities as $stability => $value) {
- if ($value <= BasePackage::$stabilities[$minimumStability]) {
- $this->acceptableStabilities[$stability] = $value;
- }
- }
- $this->stabilityFlags = $stabilityFlags;
- $this->filterRequires = $filterRequires;
- foreach ($filterRequires as $name => $constraint) {
- if (preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $name)) {
- unset($this->filterRequires[$name]);
- }
- }
- }
- public function setWhitelist($whitelist)
- {
- $this->whitelist = $whitelist;
- $this->providerCache = array();
- }
- public function addRepository(RepositoryInterface $repo, $rootAliases = array())
- {
- if ($repo instanceof CompositeRepository) {
- $repos = $repo->getRepositories();
- } else {
- $repos = array($repo);
- }
- foreach ($repos as $repo) {
- $this->repositories[] = $repo;
- $exempt = $repo instanceof PlatformRepository || $repo instanceof InstalledRepositoryInterface;
- if ($repo instanceof ComposerRepository && $repo->hasProviders()) {
- $this->providerRepos[] = $repo;
- $repo->setRootAliases($rootAliases);
- $repo->resetPackageIds();
- } else {
- foreach ($repo->getPackages() as $package) {
- $names = $package->getNames();
- $stability = $package->getStability();
- if ($exempt || $this->isPackageAcceptable($names, $stability)) {
- $package->setId($this->id++);
- $this->packages[] = $package;
- $this->packageByExactName[$package->getName()][$package->id] = $package;
- foreach ($names as $provided) {
- $this->packageByName[$provided][] = $package;
- }
- $name = $package->getName();
- if (isset($rootAliases[$name][$package->getVersion()])) {
- $alias = $rootAliases[$name][$package->getVersion()];
- if ($package instanceof AliasPackage) {
- $package = $package->getAliasOf();
- }
- $aliasPackage = new AliasPackage($package, $alias['alias_normalized'], $alias['alias']);
- $aliasPackage->setRootPackageAlias(true);
- $aliasPackage->setId($this->id++);
- $package->getRepository()->addPackage($aliasPackage);
- $this->packages[] = $aliasPackage;
- $this->packageByExactName[$aliasPackage->getName()][$aliasPackage->id] = $aliasPackage;
- foreach ($aliasPackage->getNames() as $name) {
- $this->packageByName[$name][] = $aliasPackage;
- }
- }
- }
- }
- }
- }
- }
- public function getPriority(RepositoryInterface $repo)
- {
- $priority = array_search($repo, $this->repositories, true);
- if (false === $priority) {
- throw new \RuntimeException("Could not determine repository priority. The repository was not registered in the pool.");
- }
- return -$priority;
- }
- public function packageById($id)
- {
- return $this->packages[$id - 1];
- }
- public function whatProvides($name, LinkConstraintInterface $constraint = null, $mustMatchName = false)
- {
- $key = ((int) $mustMatchName).$constraint;
- if (isset($this->providerCache[$name][$key])) {
- return $this->providerCache[$name][$key];
- }
- return $this->providerCache[$name][$key] = $this->computeWhatProvides($name, $constraint, $mustMatchName);
- }
- private function computeWhatProvides($name, $constraint, $mustMatchName = false)
- {
- $candidates = array();
- foreach ($this->providerRepos as $repo) {
- foreach ($repo->whatProvides($this, $name) as $candidate) {
- $candidates[] = $candidate;
- if ($candidate->id < 1) {
- $candidate->setId($this->id++);
- $this->packages[$this->id - 2] = $candidate;
- }
- }
- }
- if ($mustMatchName) {
- $candidates = array_filter($candidates, function ($candidate) use ($name) {
- return $candidate->getName() == $name;
- });
- if (isset($this->packageByExactName[$name])) {
- $candidates = array_merge($candidates, $this->packageByExactName[$name]);
- }
- } elseif (isset($this->packageByName[$name])) {
- $candidates = array_merge($candidates, $this->packageByName[$name]);
- }
- $matches = $provideMatches = array();
- $nameMatch = false;
- foreach ($candidates as $candidate) {
- $aliasOfCandidate = null;
-
- if ($candidate instanceof AliasPackage) {
- $aliasOfCandidate = $candidate->getAliasOf();
- }
- if ($this->whitelist !== null && (
- (!($candidate instanceof AliasPackage) && !isset($this->whitelist[$candidate->id])) ||
- ($candidate instanceof AliasPackage && !isset($this->whitelist[$aliasOfCandidate->id]))
- )) {
- continue;
- }
- switch ($this->match($candidate, $name, $constraint)) {
- case self::MATCH_NONE:
- break;
- case self::MATCH_NAME:
- $nameMatch = true;
- break;
- case self::MATCH:
- $nameMatch = true;
- $matches[] = $candidate;
- break;
- case self::MATCH_PROVIDE:
- $provideMatches[] = $candidate;
- break;
- case self::MATCH_REPLACE:
- $matches[] = $candidate;
- break;
- case self::MATCH_FILTERED:
- break;
- default:
- throw new \UnexpectedValueException('Unexpected match type');
- }
- }
- if ($nameMatch) {
- return $matches;
- }
- return array_merge($matches, $provideMatches);
- }
- public function literalToPackage($literal)
- {
- $packageId = abs($literal);
- return $this->packageById($packageId);
- }
- public function literalToString($literal)
- {
- return ($literal > 0 ? '+' : '-') . $this->literalToPackage($literal);
- }
- public function literalToPrettyString($literal, $installedMap)
- {
- $package = $this->literalToPackage($literal);
- if (isset($installedMap[$package->id])) {
- $prefix = ($literal > 0 ? 'keep' : 'remove');
- } else {
- $prefix = ($literal > 0 ? 'install' : 'don\'t install');
- }
- return $prefix.' '.$package->getPrettyString();
- }
- public function isPackageAcceptable($name, $stability)
- {
- foreach ((array) $name as $n) {
- if (!isset($this->stabilityFlags[$n]) && isset($this->acceptableStabilities[$stability])) {
- return true;
- }
- if (isset($this->stabilityFlags[$n]) && BasePackage::$stabilities[$stability] <= $this->stabilityFlags[$n]) {
- return true;
- }
- }
- return false;
- }
- private function match($candidate, $name, LinkConstraintInterface $constraint = null)
- {
- $candidateName = $candidate->getName();
- $candidateVersion = $candidate->getVersion();
- $isDev = $candidate->getStability() === 'dev';
- $isAlias = $candidate instanceof AliasPackage;
- if (!$isDev && !$isAlias && isset($this->filterRequires[$name])) {
- $requireFilter = $this->filterRequires[$name];
- } else {
- $requireFilter = new EmptyConstraint;
- }
- if ($candidateName === $name) {
- $pkgConstraint = new VersionConstraint('==', $candidateVersion);
- if ($constraint === null || $constraint->matches($pkgConstraint)) {
- return $requireFilter->matches($pkgConstraint) ? self::MATCH : self::MATCH_FILTERED;
- }
- return self::MATCH_NAME;
- }
- $provides = $candidate->getProvides();
- $replaces = $candidate->getReplaces();
- if (isset($replaces[0]) || isset($provides[0])) {
- foreach ($provides as $link) {
- if ($link->getTarget() === $name && ($constraint === null || $constraint->matches($link->getConstraint()))) {
- return $requireFilter->matches($link->getConstraint()) ? self::MATCH_PROVIDE : self::MATCH_FILTERED;
- }
- }
- foreach ($replaces as $link) {
- if ($link->getTarget() === $name && ($constraint === null || $constraint->matches($link->getConstraint()))) {
- return $requireFilter->matches($link->getConstraint()) ? self::MATCH_REPLACE : self::MATCH_FILTERED;
- }
- }
- return self::MATCH_NONE;
- }
- if (isset($provides[$name]) && ($constraint === null || $constraint->matches($provides[$name]->getConstraint()))) {
- return $requireFilter->matches($provides[$name]->getConstraint()) ? self::MATCH_PROVIDE : self::MATCH_FILTERED;
- }
- if (isset($replaces[$name]) && ($constraint === null || $constraint->matches($replaces[$name]->getConstraint()))) {
- return $requireFilter->matches($replaces[$name]->getConstraint()) ? self::MATCH_REPLACE : self::MATCH_FILTERED;
- }
- return self::MATCH_NONE;
- }
- }
- <?php
- namespace Composer\DependencyResolver;
- class Problem
- {
- protected $reasonSeen;
- protected $reasons = array();
- protected $section = 0;
- protected $pool;
- public function __construct(Pool $pool)
- {
- $this->pool = $pool;
- }
- public function addRule(Rule $rule)
- {
- $this->addReason($rule->getId(), array(
- 'rule' => $rule,
- 'job' => $rule->getJob(),
- ));
- }
- public function getReasons()
- {
- return $this->reasons;
- }
- public function getPrettyString(array $installedMap = array())
- {
- $reasons = call_user_func_array('array_merge', array_reverse($this->reasons));
- if (count($reasons) === 1) {
- reset($reasons);
- $reason = current($reasons);
- $rule = $reason['rule'];
- $job = $reason['job'];
- if (isset($job['constraint'])) {
- $packages = $this->pool->whatProvides($job['packageName'], $job['constraint']);
- } else {
- $packages = array();
- }
- if ($job && $job['cmd'] === 'install' && empty($packages)) {
- if ($job['packageName'] === 'php' || $job['packageName'] === 'php-64bit' || $job['packageName'] === 'hhvm') {
- $msg = "\n - This package requires ".$job['packageName'].$this->constraintToText($job['constraint']).' but ';
- if (defined('HHVM_VERSION')) {
- return $msg . 'your HHVM version does not satisfy that requirement.';
- } elseif ($job['packageName'] === 'hhvm') {
- return $msg . 'you are running this with PHP and not HHVM.';
- }
- return $msg . 'your PHP version does not satisfy that requirement.';
- }
- if (0 === stripos($job['packageName'], 'ext-')) {
- $ext = substr($job['packageName'], 4);
- $error = extension_loaded($ext) ? 'has the wrong version ('.(phpversion($ext) ?: '0').') installed' : 'is missing from your system';
- return "\n - The requested PHP extension ".$job['packageName'].$this->constraintToText($job['constraint']).' '.$error.'.';
- }
- if (0 === stripos($job['packageName'], 'lib-')) {
- if (strtolower($job['packageName']) === 'lib-icu') {
- $error = extension_loaded('intl') ? 'has the wrong version installed, try upgrading the intl extension.' : 'is missing from your system, make sure the intl extension is loaded.';
- return "\n - The requested linked library ".$job['packageName'].$this->constraintToText($job['constraint']).' '.$error;
- }
- return "\n - The requested linked library ".$job['packageName'].$this->constraintToText($job['constraint']).' has the wrong version installed or is missing from your system, make sure to load the extension providing it.';
- }
- if (!preg_match('{^[A-Za-z0-9_./-]+$}', $job['packageName'])) {
- $illegalChars = preg_replace('{[A-Za-z0-9_./-]+}', '', $job['packageName']);
- return "\n - The requested package ".$job['packageName'].' could not be found, it looks like its name is invalid, "'.$illegalChars.'" is not allowed in package names.';
- }
- if (!$this->pool->whatProvides($job['packageName'])) {
- return "\n - The requested package ".$job['packageName'].' could not be found in any version, there may be a typo in the package name.';
- }
- return "\n - The requested package ".$job['packageName'].$this->constraintToText($job['constraint']).' could not be found.';
- }
- }
- $messages = array();
- foreach ($reasons as $reason) {
- $rule = $reason['rule'];
- $job = $reason['job'];
- if ($job) {
- $messages[] = $this->jobToText($job);
- } elseif ($rule) {
- if ($rule instanceof Rule) {
- $messages[] = $rule->getPrettyString($this->pool, $installedMap);
- }
- }
- }
- return "\n - ".implode("\n - ", $messages);
- }
- protected function addReason($id, $reason)
- {
- if (!isset($this->reasonSeen[$id])) {
- $this->reasonSeen[$id] = true;
- $this->reasons[$this->section][] = $reason;
- }
- }
- public function nextSection()
- {
- $this->section++;
- }
- protected function jobToText($job)
- {
- switch ($job['cmd']) {
- case 'install':
- $packages = $this->pool->whatProvides($job['packageName'], $job['constraint']);
- if (!$packages) {
- return 'No package found to satisfy install request for '.$job['packageName'].$this->constraintToText($job['constraint']);
- }
- return 'Installation request for '.$job['packageName'].$this->constraintToText($job['constraint']).' -> satisfiable by '.$this->getPackageList($packages).'.';
- case 'update':
- return 'Update request for '.$job['packageName'].$this->constraintToText($job['constraint']).'.';
- case 'remove':
- return 'Removal request for '.$job['packageName'].$this->constraintToText($job['constraint']).'';
- }
- if (isset($job['constraint'])) {
- $packages = $this->pool->whatProvides($job['packageName'], $job['constraint']);
- } else {
- $packages = array();
- }
- return 'Job(cmd='.$job['cmd'].', target='.$job['packageName'].', packages=['.$this->getPackageList($packages).'])';
- }
- protected function getPackageList($packages)
- {
- $prepared = array();
- foreach ($packages as $package) {
- $prepared[$package->getName()]['name'] = $package->getPrettyName();
- $prepared[$package->getName()]['versions'][$package->getVersion()] = $package->getPrettyVersion();
- }
- foreach ($prepared as $name => $package) {
- $prepared[$name] = $package['name'].'['.implode(', ', $package['versions']).']';
- }
- return implode(', ', $prepared);
- }
- protected function constraintToText($constraint)
- {
- return ($constraint) ? ' '.$constraint->getPrettyString() : '';
- }
- }
- <?php
- namespace Composer\DependencyResolver;
- use Composer\Package\LinkConstraint\LinkConstraintInterface;
- class Request
- {
- protected $jobs;
- protected $pool;
- public function __construct(Pool $pool)
- {
- $this->pool = $pool;
- $this->jobs = array();
- }
- public function install($packageName, LinkConstraintInterface $constraint = null)
- {
- $this->addJob($packageName, 'install', $constraint);
- }
- public function update($packageName, LinkConstraintInterface $constraint = null)
- {
- $this->addJob($packageName, 'update', $constraint);
- }
- public function remove($packageName, LinkConstraintInterface $constraint = null)
- {
- $this->addJob($packageName, 'remove', $constraint);
- }
- public function fix($packageName, LinkConstraintInterface $constraint = null)
- {
- $this->addJob($packageName, 'install', $constraint, true);
- }
- protected function addJob($packageName, $cmd, LinkConstraintInterface $constraint = null, $fixed = false)
- {
- $packageName = strtolower($packageName);
- $this->jobs[] = array(
- 'cmd' => $cmd,
- 'packageName' => $packageName,
- 'constraint' => $constraint,
- 'fixed' => $fixed
- );
- }
- public function updateAll()
- {
- $this->jobs[] = array('cmd' => 'update-all');
- }
- public function getJobs()
- {
- return $this->jobs;
- }
- }
- <?php
- namespace Composer\DependencyResolver;
- class Rule
- {
- const RULE_INTERNAL_ALLOW_UPDATE = 1;
- const RULE_JOB_INSTALL = 2;
- const RULE_JOB_REMOVE = 3;
- const RULE_PACKAGE_CONFLICT = 6;
- const RULE_PACKAGE_REQUIRES = 7;
- const RULE_PACKAGE_OBSOLETES = 8;
- const RULE_INSTALLED_PACKAGE_OBSOLETES = 9;
- const RULE_PACKAGE_SAME_NAME = 10;
- const RULE_PACKAGE_IMPLICIT_OBSOLETES = 11;
- const RULE_LEARNED = 12;
- const RULE_PACKAGE_ALIAS = 13;
- public $literals;
- protected $disabled;
- protected $type;
- protected $id;
- protected $reason;
- protected $reasonData;
- protected $job;
- protected $ruleHash;
- public function __construct(array $literals, $reason, $reasonData, $job = null)
- {
- sort($literals);
- $this->literals = $literals;
- $this->reason = $reason;
- $this->reasonData = $reasonData;
- $this->disabled = false;
- $this->job = $job;
- $this->type = -1;
- $this->ruleHash = substr(md5(implode(',', $this->literals)), 0, 5);
- }
- public function getHash()
- {
- return $this->ruleHash;
- }
- public function setId($id)
- {
- $this->id = $id;
- }
- public function getId()
- {
- return $this->id;
- }
- public function getJob()
- {
- return $this->job;
- }
- public function getReason()
- {
- return $this->reason;
- }
- public function getReasonData()
- {
- return $this->reasonData;
- }
- public function getRequiredPackage()
- {
- if ($this->reason === self::RULE_JOB_INSTALL) {
- return $this->reasonData;
- }
- if ($this->reason === self::RULE_PACKAGE_REQUIRES) {
- return $this->reasonData->getTarget();
- }
- }
- public function equals(Rule $rule)
- {
- if ($this->ruleHash !== $rule->ruleHash) {
- return false;
- }
- if (count($this->literals) != count($rule->literals)) {
- return false;
- }
- for ($i = 0, $n = count($this->literals); $i < $n; $i++) {
- if ($this->literals[$i] !== $rule->literals[$i]) {
- return false;
- }
- }
- return true;
- }
- public function setType($type)
- {
- $this->type = $type;
- }
- public function getType()
- {
- return $this->type;
- }
- public function disable()
- {
- $this->disabled = true;
- }
- public function enable()
- {
- $this->disabled = false;
- }
- public function isDisabled()
- {
- return $this->disabled;
- }
- public function isEnabled()
- {
- return !$this->disabled;
- }
- public function getLiterals()
- {
- return $this->literals;
- }
- public function isAssertion()
- {
- return 1 === count($this->literals);
- }
- public function getPrettyString(Pool $pool, array $installedMap = array())
- {
- $ruleText = '';
- foreach ($this->literals as $i => $literal) {
- if ($i != 0) {
- $ruleText .= '|';
- }
- $ruleText .= $pool->literalToPrettyString($literal, $installedMap);
- }
- switch ($this->reason) {
- case self::RULE_INTERNAL_ALLOW_UPDATE:
- return $ruleText;
- case self::RULE_JOB_INSTALL:
- return "Install command rule ($ruleText)";
- case self::RULE_JOB_REMOVE:
- return "Remove command rule ($ruleText)";
- case self::RULE_PACKAGE_CONFLICT:
- $package1 = $pool->literalToPackage($this->literals[0]);
- $package2 = $pool->literalToPackage($this->literals[1]);
- return $package1->getPrettyString().' conflicts with '.$this->formatPackagesUnique($pool, array($package2)).'.';
- case self::RULE_PACKAGE_REQUIRES:
- $literals = $this->literals;
- $sourceLiteral = array_shift($literals);
- $sourcePackage = $pool->literalToPackage($sourceLiteral);
- $requires = array();
- foreach ($literals as $literal) {
- $requires[] = $pool->literalToPackage($literal);
- }
- $text = $this->reasonData->getPrettyString($sourcePackage);
- if ($requires) {
- $text .= ' -> satisfiable by ' . $this->formatPackagesUnique($pool, $requires) . '.';
- } else {
- $targetName = $this->reasonData->getTarget();
- if ($targetName === 'php' || $targetName === 'php-64bit' || $targetName === 'hhvm') {
- if (defined('HHVM_VERSION')) {
- $text .= ' -> your HHVM version does not satisfy that requirement.';
- } elseif ($targetName === 'hhvm') {
- $text .= ' -> you are running this with PHP and not HHVM.';
- } else {
- $text .= ' -> your PHP version does not satisfy that requirement.';
- }
- } elseif (0 === strpos($targetName, 'ext-')) {
- $ext = substr($targetName, 4);
- $error = extension_loaded($ext) ? 'has the wrong version ('.(phpversion($ext) ?: '0').') installed' : 'is missing from your system';
- $text .= ' -> the requested PHP extension '.$ext.' '.$error.'.';
- } elseif (0 === strpos($targetName, 'lib-')) {
- $lib = substr($targetName, 4);
- $text .= ' -> the requested linked library '.$lib.' has the wrong version installed or is missing from your system, make sure to have the extension providing it.';
- } else {
- $text .= ' -> no matching package found.';
- }
- }
- return $text;
- case self::RULE_PACKAGE_OBSOLETES:
- return $ruleText;
- case self::RULE_INSTALLED_PACKAGE_OBSOLETES:
- return $ruleText;
- case self::RULE_PACKAGE_SAME_NAME:
- return 'Can only install one of: ' . $this->formatPackagesUnique($pool, $this->literals) . '.';
- case self::RULE_PACKAGE_IMPLICIT_OBSOLETES:
- return $ruleText;
- case self::RULE_LEARNED:
- return 'Conclusion: '.$ruleText;
- case self::RULE_PACKAGE_ALIAS:
- return $ruleText;
- default:
- return '('.$ruleText.')';
- }
- }
- protected function formatPackagesUnique($pool, array $packages)
- {
- $prepared = array();
- foreach ($packages as $package) {
- if (!is_object($package)) {
- $package = $pool->literalToPackage($package);
- }
- $prepared[$package->getName()]['name'] = $package->getPrettyName();
- $prepared[$package->getName()]['versions'][$package->getVersion()] = $package->getPrettyVersion();
- }
- foreach ($prepared as $name => $package) {
- $prepared[$name] = $package['name'].'['.implode(', ', $package['versions']).']';
- }
- return implode(', ', $prepared);
- }
- public function __toString()
- {
- $result = ($this->isDisabled()) ? 'disabled(' : '(';
- foreach ($this->literals as $i => $literal) {
- if ($i != 0) {
- $result .= '|';
- }
- $result .= $literal;
- }
- $result .= ')';
- return $result;
- }
- }
- <?php
- namespace Composer\DependencyResolver;
- class RuleSet implements \IteratorAggregate, \Countable
- {
- const TYPE_PACKAGE = 0;
- const TYPE_JOB = 1;
- const TYPE_LEARNED = 4;
- public $ruleById;
- protected static $types = array(
- -1 => 'UNKNOWN',
- self::TYPE_PACKAGE => 'PACKAGE',
- self::TYPE_JOB => 'JOB',
- self::TYPE_LEARNED => 'LEARNED',
- );
- protected $rules;
- protected $nextRuleId;
- protected $rulesByHash;
- public function __construct()
- {
- $this->nextRuleId = 0;
- foreach ($this->getTypes() as $type) {
- $this->rules[$type] = array();
- }
- $this->rulesByHash = array();
- }
- public function add(Rule $rule, $type)
- {
- if (!isset(self::$types[$type])) {
- throw new \OutOfBoundsException('Unknown rule type: ' . $type);
- }
- if (!isset($this->rules[$type])) {
- $this->rules[$type] = array();
- }
- $this->rules[$type][] = $rule;
- $this->ruleById[$this->nextRuleId] = $rule;
- $rule->setType($type);
- $rule->setId($this->nextRuleId);
- $this->nextRuleId++;
- $hash = $rule->getHash();
- if (!isset($this->rulesByHash[$hash])) {
- $this->rulesByHash[$hash] = array($rule);
- } else {
- $this->rulesByHash[$hash][] = $rule;
- }
- }
- public function count()
- {
- return $this->nextRuleId;
- }
- public function ruleById($id)
- {
- return $this->ruleById[$id];
- }
- public function getRules()
- {
- return $this->rules;
- }
- public function getIterator()
- {
- return new RuleSetIterator($this->getRules());
- }
- public function getIteratorFor($types)
- {
- if (!is_array($types)) {
- $types = array($types);
- }
- $allRules = $this->getRules();
- $rules = array();
- foreach ($types as $type) {
- $rules[$type] = $allRules[$type];
- }
- return new RuleSetIterator($rules);
- }
- public function getIteratorWithout($types)
- {
- if (!is_array($types)) {
- $types = array($types);
- }
- $rules = $this->getRules();
- foreach ($types as $type) {
- unset($rules[$type]);
- }
- return new RuleSetIterator($rules);
- }
- public function getTypes()
- {
- $types = self::$types;
- unset($types[-1]);
- return array_keys($types);
- }
- public function containsEqual($rule)
- {
- if (isset($this->rulesByHash[$rule->getHash()])) {
- $potentialDuplicates = $this->rulesByHash[$rule->getHash()];
- foreach ($potentialDuplicates as $potentialDuplicate) {
- if ($rule->equals($potentialDuplicate)) {
- return true;
- }
- }
- }
- return false;
- }
- public function getPrettyString(Pool $pool = null)
- {
- $string = "\n";
- foreach ($this->rules as $type => $rules) {
- $string .= str_pad(self::$types[$type], 8, ' ') . ": ";
- foreach ($rules as $rule) {
- $string .= ($pool ? $rule->getPrettyString($pool) : $rule)."\n";
- }
- $string .= "\n\n";
- }
- return $string;
- }
- public function __toString()
- {
- return $this->getPrettyString(null);
- }
- }
- <?php
- namespace Composer\DependencyResolver;
- use Composer\Package\PackageInterface;
- use Composer\Package\AliasPackage;
- use Composer\Repository\PlatformRepository;
- class RuleSetGenerator
- {
- protected $policy;
- protected $pool;
- protected $rules;
- protected $jobs;
- protected $installedMap;
- protected $whitelistedMap;
- protected $addedMap;
- public function __construct(PolicyInterface $policy, Pool $pool)
- {
- $this->policy = $policy;
- $this->pool = $pool;
- }
- protected function createRequireRule(PackageInterface $package, array $providers, $reason, $reasonData = null)
- {
- $literals = array(-$package->id);
- foreach ($providers as $provider) {
- if ($provider === $package) {
- return null;
- }
- $literals[] = $provider->id;
- }
- return new Rule($literals, $reason, $reasonData);
- }
- protected function createInstallOneOfRule(array $packages, $reason, $job)
- {
- $literals = array();
- foreach ($packages as $package) {
- $literals[] = $package->id;
- }
- return new Rule($literals, $reason, $job['packageName'], $job);
- }
- protected function createRemoveRule(PackageInterface $package, $reason, $job)
- {
- return new Rule(array(-$package->id), $reason, $job['packageName'], $job);
- }
- protected function createConflictRule(PackageInterface $issuer, PackageInterface $provider, $reason, $reasonData = null)
- {
- if ($issuer === $provider) {
- return null;
- }
- return new Rule(array(-$issuer->id, -$provider->id), $reason, $reasonData);
- }
- private function addRule($type, Rule $newRule = null)
- {
- if (!$newRule || $this->rules->containsEqual($newRule)) {
- return;
- }
- $this->rules->add($newRule, $type);
- }
- protected function whitelistFromPackage(PackageInterface $package)
- {
- $workQueue = new \SplQueue;
- $workQueue->enqueue($package);
- while (!$workQueue->isEmpty()) {
- $package = $workQueue->dequeue();
- if (isset($this->whitelistedMap[$package->id])) {
- continue;
- }
- $this->whitelistedMap[$package->id] = true;
- foreach ($package->getRequires() as $link) {
- $possibleRequires = $this->pool->whatProvides($link->getTarget(), $link->getConstraint(), true);
- foreach ($possibleRequires as $require) {
- $workQueue->enqueue($require);
- }
- }
- $obsoleteProviders = $this->pool->whatProvides($package->getName(), null, true);
- foreach ($obsoleteProviders as $provider) {
- if ($provider === $package) {
- continue;
- }
- if (($package instanceof AliasPackage) && $package->getAliasOf() === $provider) {
- $workQueue->enqueue($provider);
- }
- }
- }
- }
- protected function addRulesForPackage(PackageInterface $package, $ignorePlatformReqs)
- {
- $workQueue = new \SplQueue;
- $workQueue->enqueue($package);
- while (!$workQueue->isEmpty()) {
- $package = $workQueue->dequeue();
- if (isset($this->addedMap[$package->id])) {
- continue;
- }
- $this->addedMap[$package->id] = true;
- foreach ($package->getRequires() as $link) {
- if ($ignorePlatformReqs && preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $link->getTarget())) {
- continue;
- }
- $possibleRequires = $this->pool->whatProvides($link->getTarget(), $link->getConstraint());
- $this->addRule(RuleSet::TYPE_PACKAGE, $rule = $this->createRequireRule($package, $possibleRequires, Rule::RULE_PACKAGE_REQUIRES, $link));
- foreach ($possibleRequires as $require) {
- $workQueue->enqueue($require);
- }
- }
- foreach ($package->getConflicts() as $link) {
- $possibleConflicts = $this->pool->whatProvides($link->getTarget(), $link->getConstraint());
- foreach ($possibleConflicts as $conflict) {
- $this->addRule(RuleSet::TYPE_PACKAGE, $this->createConflictRule($package, $conflict, Rule::RULE_PACKAGE_CONFLICT, $link));
- }
- }
- $isInstalled = (isset($this->installedMap[$package->id]));
- foreach ($package->getReplaces() as $link) {
- $obsoleteProviders = $this->pool->whatProvides($link->getTarget(), $link->getConstraint());
- foreach ($obsoleteProviders as $provider) {
- if ($provider === $package) {
- continue;
- }
- if (!$this->obsoleteImpossibleForAlias($package, $provider)) {
- $reason = ($isInstalled) ? Rule::RULE_INSTALLED_PACKAGE_OBSOLETES : Rule::RULE_PACKAGE_OBSOLETES;
- $this->addRule(RuleSet::TYPE_PACKAGE, $this->createConflictRule($package, $provider, $reason, $link));
- }
- }
- }
- $obsoleteProviders = $this->pool->whatProvides($package->getName(), null);
- foreach ($obsoleteProviders as $provider) {
- if ($provider === $package) {
- continue;
- }
- if (($package instanceof AliasPackage) && $package->getAliasOf() === $provider) {
- $this->addRule(RuleSet::TYPE_PACKAGE, $rule = $this->createRequireRule($package, array($provider), Rule::RULE_PACKAGE_ALIAS, $package));
- } elseif (!$this->obsoleteImpossibleForAlias($package, $provider)) {
- $reason = ($package->getName() == $provider->getName()) ? Rule::RULE_PACKAGE_SAME_NAME : Rule::RULE_PACKAGE_IMPLICIT_OBSOLETES;
- $this->addRule(RuleSet::TYPE_PACKAGE, $rule = $this->createConflictRule($package, $provider, $reason, $package));
- }
- }
- }
- }
- protected function obsoleteImpossibleForAlias($package, $provider)
- {
- $packageIsAlias = $package instanceof AliasPackage;
- $providerIsAlias = $provider instanceof AliasPackage;
- $impossible = (
- ($packageIsAlias && $package->getAliasOf() === $provider) ||
- ($providerIsAlias && $provider->getAliasOf() === $package) ||
- ($packageIsAlias && $providerIsAlias && $provider->getAliasOf() === $package->getAliasOf())
- );
- return $impossible;
- }
- protected function whitelistFromJobs()
- {
- foreach ($this->jobs as $job) {
- switch ($job['cmd']) {
- case 'install':
- $packages = $this->pool->whatProvides($job['packageName'], $job['constraint'], true);
- foreach ($packages as $package) {
- $this->whitelistFromPackage($package);
- }
- break;
- }
- }
- }
- protected function addRulesForJobs($ignorePlatformReqs)
- {
- foreach ($this->jobs as $job) {
- switch ($job['cmd']) {
- case 'install':
- if (!$job['fixed'] && $ignorePlatformReqs && preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $job['packageName'])) {
- continue;
- }
- $packages = $this->pool->whatProvides($job['packageName'], $job['constraint']);
- if ($packages) {
- foreach ($packages as $package) {
- if (!isset($this->installedMap[$package->id])) {
- $this->addRulesForPackage($package, $ignorePlatformReqs);
- }
- }
- $rule = $this->createInstallOneOfRule($packages, Rule::RULE_JOB_INSTALL, $job);
- $this->addRule(RuleSet::TYPE_JOB, $rule);
- }
- break;
- case 'remove':
-
- $packages = $this->pool->whatProvides($job['packageName'], $job['constraint']);
- foreach ($packages as $package) {
- $rule = $this->createRemoveRule($package, Rule::RULE_JOB_REMOVE, $job);
- $this->addRule(RuleSet::TYPE_JOB, $rule);
- }
- break;
- }
- }
- }
- public function getRulesFor($jobs, $installedMap, $ignorePlatformReqs = false)
- {
- $this->jobs = $jobs;
- $this->rules = new RuleSet;
- $this->installedMap = $installedMap;
- $this->whitelistedMap = array();
- foreach ($this->installedMap as $package) {
- $this->whitelistFromPackage($package);
- }
- $this->whitelistFromJobs();
- $this->pool->setWhitelist($this->whitelistedMap);
- $this->addedMap = array();
- foreach ($this->installedMap as $package) {
- $this->addRulesForPackage($package, $ignorePlatformReqs);
- }
- $this->addRulesForJobs($ignorePlatformReqs);
- return $this->rules;
- }
- }
- <?php
- namespace Composer\DependencyResolver;
- class RuleSetIterator implements \Iterator
- {
- protected $rules;
- protected $types;
- protected $currentOffset;
- protected $currentType;
- protected $currentTypeOffset;
- public function __construct(array $rules)
- {
- $this->rules = $rules;
- $this->types = array_keys($rules);
- sort($this->types);
- $this->rewind();
- }
- public function current()
- {
- return $this->rules[$this->currentType][$this->currentOffset];
- }
- public function key()
- {
- return $this->currentType;
- }
- public function next()
- {
- $this->currentOffset++;
- if (!isset($this->rules[$this->currentType])) {
- return;
- }
- if ($this->currentOffset >= sizeof($this->rules[$this->currentType])) {
- $this->currentOffset = 0;
- do {
- $this->currentTypeOffset++;
- if (!isset($this->types[$this->currentTypeOffset])) {
- $this->currentType = -1;
- break;
- }
- $this->currentType = $this->types[$this->currentTypeOffset];
- } while (isset($this->types[$this->currentTypeOffset]) && !sizeof($this->rules[$this->currentType]));
- }
- }
- public function rewind()
- {
- $this->currentOffset = 0;
- $this->currentTypeOffset = -1;
- $this->currentType = -1;
- do {
- $this->currentTypeOffset++;
- if (!isset($this->types[$this->currentTypeOffset])) {
- $this->currentType = -1;
- break;
- }
- $this->currentType = $this->types[$this->currentTypeOffset];
- } while (isset($this->types[$this->currentTypeOffset]) && !sizeof($this->rules[$this->currentType]));
- }
- public function valid()
- {
- return isset($this->rules[$this->currentType])
- && isset($this->rules[$this->currentType][$this->currentOffset]);
- }
- }
- <?php
- namespace Composer\DependencyResolver;
- class RuleWatchChain extends \SplDoublyLinkedList
- {
- protected $offset = 0;
- public function seek($offset)
- {
- $this->rewind();
- for ($i = 0; $i < $offset; $i++, $this->next());
- }
- public function remove()
- {
- $offset = $this->key();
- $this->offsetUnset($offset);
- $this->seek($offset);
- }
- }
- <?php
- namespace Composer\DependencyResolver;
- class RuleWatchGraph
- {
- protected $watchChains = array();
- public function insert(RuleWatchNode $node)
- {
- if ($node->getRule()->isAssertion()) {
- return;
- }
- foreach (array($node->watch1, $node->watch2) as $literal) {
- if (!isset($this->watchChains[$literal])) {
- $this->watchChains[$literal] = new RuleWatchChain;
- }
- $this->watchChains[$literal]->unshift($node);
- }
- }
- public function propagateLiteral($decidedLiteral, $level, $decisions)
- {
-
-
- $literal = -$decidedLiteral;
- if (!isset($this->watchChains[$literal])) {
- return null;
- }
- $chain = $this->watchChains[$literal];
- $chain->rewind();
- while ($chain->valid()) {
- $node = $chain->current();
- $otherWatch = $node->getOtherWatch($literal);
- if (!$node->getRule()->isDisabled() && !$decisions->satisfy($otherWatch)) {
- $ruleLiterals = $node->getRule()->literals;
- $alternativeLiterals = array_filter($ruleLiterals, function ($ruleLiteral) use ($literal, $otherWatch, $decisions) {
- return $literal !== $ruleLiteral &&
- $otherWatch !== $ruleLiteral &&
- !$decisions->conflict($ruleLiteral);
- });
- if ($alternativeLiterals) {
- reset($alternativeLiterals);
- $this->moveWatch($literal, current($alternativeLiterals), $node);
- continue;
- }
- if ($decisions->conflict($otherWatch)) {
- return $node->getRule();
- }
- $decisions->decide($otherWatch, $level, $node->getRule());
- }
- $chain->next();
- }
- return null;
- }
- protected function moveWatch($fromLiteral, $toLiteral, $node)
- {
- if (!isset($this->watchChains[$toLiteral])) {
- $this->watchChains[$toLiteral] = new RuleWatchChain;
- }
- $node->moveWatch($fromLiteral, $toLiteral);
- $this->watchChains[$fromLiteral]->remove();
- $this->watchChains[$toLiteral]->unshift($node);
- }
- }
- <?php
- namespace Composer\DependencyResolver;
- class RuleWatchNode
- {
- public $watch1;
- public $watch2;
- protected $rule;
- public function __construct($rule)
- {
- $this->rule = $rule;
- $literals = $rule->literals;
- $this->watch1 = count($literals) > 0 ? $literals[0] : 0;
- $this->watch2 = count($literals) > 1 ? $literals[1] : 0;
- }
- public function watch2OnHighest(Decisions $decisions)
- {
- $literals = $this->rule->literals;
- if (count($literals) < 3) {
- return;
- }
- $watchLevel = 0;
- foreach ($literals as $literal) {
- $level = $decisions->decisionLevel($literal);
- if ($level > $watchLevel) {
- $this->watch2 = $literal;
- $watchLevel = $level;
- }
- }
- }
- public function getRule()
- {
- return $this->rule;
- }
- public function getOtherWatch($literal)
- {
- if ($this->watch1 == $literal) {
- return $this->watch2;
- } else {
- return $this->watch1;
- }
- }
- public function moveWatch($from, $to)
- {
- if ($this->watch1 == $from) {
- $this->watch1 = $to;
- } else {
- $this->watch2 = $to;
- }
- }
- }
- <?php
- namespace Composer\DependencyResolver;
- use Composer\Repository\RepositoryInterface;
- use Composer\Repository\PlatformRepository;
- class Solver
- {
- const BRANCH_LITERALS = 0;
- const BRANCH_LEVEL = 1;
- protected $policy;
- protected $pool;
- protected $installed;
- protected $rules;
- protected $ruleSetGenerator;
- protected $updateAll;
- protected $addedMap = array();
- protected $updateMap = array();
- protected $watchGraph;
- protected $decisions;
- protected $installedMap;
- protected $propagateIndex;
- protected $branches = array();
- protected $problems = array();
- protected $learnedPool = array();
- protected $learnedWhy = array();
- public function __construct(PolicyInterface $policy, Pool $pool, RepositoryInterface $installed)
- {
- $this->policy = $policy;
- $this->pool = $pool;
- $this->installed = $installed;
- $this->ruleSetGenerator = new RuleSetGenerator($policy, $pool);
- }
- private function makeAssertionRuleDecisions()
- {
- $decisionStart = count($this->decisions) - 1;
- $rulesCount = count($this->rules);
- for ($ruleIndex = 0; $ruleIndex < $rulesCount; $ruleIndex++) {
- $rule = $this->rules->ruleById[$ruleIndex];
- if (!$rule->isAssertion() || $rule->isDisabled()) {
- continue;
- }
- $literals = $rule->literals;
- $literal = $literals[0];
- if (!$this->decisions->decided(abs($literal))) {
- $this->decisions->decide($literal, 1, $rule);
- continue;
- }
- if ($this->decisions->satisfy($literal)) {
- continue;
- }
- if (RuleSet::TYPE_LEARNED === $rule->getType()) {
- $rule->disable();
- continue;
- }
- $conflict = $this->decisions->decisionRule($literal);
- if ($conflict && RuleSet::TYPE_PACKAGE === $conflict->getType()) {
- $problem = new Problem($this->pool);
- $problem->addRule($rule);
- $problem->addRule($conflict);
- $this->disableProblem($rule);
- $this->problems[] = $problem;
- continue;
- }
- $problem = new Problem($this->pool);
- $problem->addRule($rule);
- $problem->addRule($conflict);
-
- foreach ($this->rules->getIteratorFor(RuleSet::TYPE_JOB) as $assertRule) {
- if ($assertRule->isDisabled() || !$assertRule->isAssertion()) {
- continue;
- }
- $assertRuleLiterals = $assertRule->literals;
- $assertRuleLiteral = $assertRuleLiterals[0];
- if (abs($literal) !== abs($assertRuleLiteral)) {
- continue;
- }
- $problem->addRule($assertRule);
- $this->disableProblem($assertRule);
- }
- $this->problems[] = $problem;
- $this->decisions->resetToOffset($decisionStart);
- $ruleIndex = -1;
- }
- }
- protected function setupInstalledMap()
- {
- $this->installedMap = array();
- foreach ($this->installed->getPackages() as $package) {
- $this->installedMap[$package->id] = $package;
- }
- }
- protected function checkForRootRequireProblems($ignorePlatformReqs)
- {
- foreach ($this->jobs as $job) {
- switch ($job['cmd']) {
- case 'update':
- $packages = $this->pool->whatProvides($job['packageName'], $job['constraint']);
- foreach ($packages as $package) {
- if (isset($this->installedMap[$package->id])) {
- $this->updateMap[$package->id] = true;
- }
- }
- break;
- case 'update-all':
- foreach ($this->installedMap as $package) {
- $this->updateMap[$package->id] = true;
- }
- break;
- case 'install':
- if ($ignorePlatformReqs && preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $job['packageName'])) {
- break;
- }
- if (!$this->pool->whatProvides($job['packageName'], $job['constraint'])) {
- $problem = new Problem($this->pool);
- $problem->addRule(new Rule(array(), null, null, $job));
- $this->problems[] = $problem;
- }
- break;
- }
- }
- }
- public function solve(Request $request, $ignorePlatformReqs = false)
- {
- $this->jobs = $request->getJobs();
- $this->setupInstalledMap();
- $this->rules = $this->ruleSetGenerator->getRulesFor($this->jobs, $this->installedMap, $ignorePlatformReqs);
- $this->checkForRootRequireProblems($ignorePlatformReqs);
- $this->decisions = new Decisions($this->pool);
- $this->watchGraph = new RuleWatchGraph;
- foreach ($this->rules as $rule) {
- $this->watchGraph->insert(new RuleWatchNode($rule));
- }
- $this->makeAssertionRuleDecisions();
- $this->runSat(true);
- foreach ($this->installedMap as $packageId => $void) {
- if ($this->decisions->undecided($packageId)) {
- $this->decisions->decide(-$packageId, 1, null);
- }
- }
- if ($this->problems) {
- throw new SolverProblemsException($this->problems, $this->installedMap);
- }
- $transaction = new Transaction($this->policy, $this->pool, $this->installedMap, $this->decisions);
- return $transaction->getOperations();
- }
- protected function literalFromId($id)
- {
- $package = $this->pool->packageById(abs($id));
- return new Literal($package, $id > 0);
- }
- protected function propagate($level)
- {
- while ($this->decisions->validOffset($this->propagateIndex)) {
- $decision = $this->decisions->atOffset($this->propagateIndex);
- $conflict = $this->watchGraph->propagateLiteral(
- $decision[Decisions::DECISION_LITERAL],
- $level,
- $this->decisions
- );
- $this->propagateIndex++;
- if ($conflict) {
- return $conflict;
- }
- }
- return null;
- }
- private function revert($level)
- {
- while (!$this->decisions->isEmpty()) {
- $literal = $this->decisions->lastLiteral();
- if ($this->decisions->undecided($literal)) {
- break;
- }
- $decisionLevel = $this->decisions->decisionLevel($literal);
- if ($decisionLevel <= $level) {
- break;
- }
- $this->decisions->revertLast();
- $this->propagateIndex = count($this->decisions);
- }
- while (!empty($this->branches) && $this->branches[count($this->branches) - 1][self::BRANCH_LEVEL] >= $level) {
- array_pop($this->branches);
- }
- }
- private function setPropagateLearn($level, $literal, $disableRules, Rule $rule)
- {
- $level++;
- $this->decisions->decide($literal, $level, $rule);
- while (true) {
- $rule = $this->propagate($level);
- if (!$rule) {
- break;
- }
- if ($level == 1) {
- return $this->analyzeUnsolvable($rule, $disableRules);
- }
- list($learnLiteral, $newLevel, $newRule, $why) = $this->analyze($level, $rule);
- if ($newLevel <= 0 || $newLevel >= $level) {
- throw new SolverBugException(
- "Trying to revert to invalid level ".(int) $newLevel." from level ".(int) $level."."
- );
- } elseif (!$newRule) {
- throw new SolverBugException(
- "No rule was learned from analyzing $rule at level $level."
- );
- }
- $level = $newLevel;
- $this->revert($level);
- $this->rules->add($newRule, RuleSet::TYPE_LEARNED);
- $this->learnedWhy[$newRule->getId()] = $why;
- $ruleNode = new RuleWatchNode($newRule);
- $ruleNode->watch2OnHighest($this->decisions);
- $this->watchGraph->insert($ruleNode);
- $this->decisions->decide($learnLiteral, $level, $newRule);
- }
- return $level;
- }
- private function selectAndInstall($level, array $decisionQueue, $disableRules, Rule $rule)
- {
- $literals = $this->policy->selectPreferedPackages($this->pool, $this->installedMap, $decisionQueue, $rule->getRequiredPackage());
- $selectedLiteral = array_shift($literals);
- if (count($literals)) {
- $this->branches[] = array($literals, $level);
- }
- return $this->setPropagateLearn($level, $selectedLiteral, $disableRules, $rule);
- }
- protected function analyze($level, $rule)
- {
- $analyzedRule = $rule;
- $ruleLevel = 1;
- $num = 0;
- $l1num = 0;
- $seen = array();
- $learnedLiterals = array(null);
- $decisionId = count($this->decisions);
- $this->learnedPool[] = array();
- while (true) {
- $this->learnedPool[count($this->learnedPool) - 1][] = $rule;
- foreach ($rule->literals as $literal) {
- if ($this->decisions->satisfy($literal)) {
- continue;
- }
- if (isset($seen[abs($literal)])) {
- continue;
- }
- $seen[abs($literal)] = true;
- $l = $this->decisions->decisionLevel($literal);
- if (1 === $l) {
- $l1num++;
- } elseif ($level === $l) {
- $num++;
- } else {
- $learnedLiterals[] = $literal;
- if ($l > $ruleLevel) {
- $ruleLevel = $l;
- }
- }
- }
- $l1retry = true;
- while ($l1retry) {
- $l1retry = false;
- if (!$num && !--$l1num) {
- break 2;
- }
- while (true) {
- if ($decisionId <= 0) {
- throw new SolverBugException(
- "Reached invalid decision id $decisionId while looking through $rule for a literal present in the analyzed rule $analyzedRule."
- );
- }
- $decisionId--;
- $decision = $this->decisions->atOffset($decisionId);
- $literal = $decision[Decisions::DECISION_LITERAL];
- if (isset($seen[abs($literal)])) {
- break;
- }
- }
- unset($seen[abs($literal)]);
- if ($num && 0 === --$num) {
- $learnedLiterals[0] = -abs($literal);
- if (!$l1num) {
- break 2;
- }
- foreach ($learnedLiterals as $i => $learnedLiteral) {
- if ($i !== 0) {
- unset($seen[abs($learnedLiteral)]);
- }
- }
- $l1num++;
- $l1retry = true;
- }
- }
- $decision = $this->decisions->atOffset($decisionId);
- $rule = $decision[Decisions::DECISION_REASON];
- }
- $why = count($this->learnedPool) - 1;
- if (!$learnedLiterals[0]) {
- throw new SolverBugException(
- "Did not find a learnable literal in analyzed rule $analyzedRule."
- );
- }
- $newRule = new Rule($learnedLiterals, Rule::RULE_LEARNED, $why);
- return array($learnedLiterals[0], $ruleLevel, $newRule, $why);
- }
- private function analyzeUnsolvableRule($problem, $conflictRule)
- {
- $why = $conflictRule->getId();
- if ($conflictRule->getType() == RuleSet::TYPE_LEARNED) {
- $learnedWhy = $this->learnedWhy[$why];
- $problemRules = $this->learnedPool[$learnedWhy];
- foreach ($problemRules as $problemRule) {
- $this->analyzeUnsolvableRule($problem, $problemRule);
- }
- return;
- }
- if ($conflictRule->getType() == RuleSet::TYPE_PACKAGE) {
- return;
- }
- $problem->nextSection();
- $problem->addRule($conflictRule);
- }
- private function analyzeUnsolvable($conflictRule, $disableRules)
- {
- $problem = new Problem($this->pool);
- $problem->addRule($conflictRule);
- $this->analyzeUnsolvableRule($problem, $conflictRule);
- $this->problems[] = $problem;
- $seen = array();
- $literals = $conflictRule->literals;
- foreach ($literals as $literal) {
- if ($this->decisions->satisfy($literal)) {
- continue;
- }
- $seen[abs($literal)] = true;
- }
- foreach ($this->decisions as $decision) {
- $literal = $decision[Decisions::DECISION_LITERAL];
- if (!isset($seen[abs($literal)])) {
- continue;
- }
- $why = $decision[Decisions::DECISION_REASON];
- $problem->addRule($why);
- $this->analyzeUnsolvableRule($problem, $why);
- $literals = $why->literals;
- foreach ($literals as $literal) {
- if ($this->decisions->satisfy($literal)) {
- continue;
- }
- $seen[abs($literal)] = true;
- }
- }
- if ($disableRules) {
- foreach ($this->problems[count($this->problems) - 1] as $reason) {
- $this->disableProblem($reason['rule']);
- }
- $this->resetSolver();
- return 1;
- }
- return 0;
- }
- private function disableProblem($why)
- {
- $job = $why->getJob();
- if (!$job) {
- $why->disable();
- return;
- }
- foreach ($this->rules as $rule) {
- if ($job === $rule->getJob()) {
- $rule->disable();
- }
- }
- }
- private function resetSolver()
- {
- $this->decisions->reset();
- $this->propagateIndex = 0;
- $this->branches = array();
- $this->enableDisableLearnedRules();
- $this->makeAssertionRuleDecisions();
- }
- private function enableDisableLearnedRules()
- {
- foreach ($this->rules->getIteratorFor(RuleSet::TYPE_LEARNED) as $rule) {
- $why = $this->learnedWhy[$rule->getId()];
- $problemRules = $this->learnedPool[$why];
- $foundDisabled = false;
- foreach ($problemRules as $problemRule) {
- if ($problemRule->isDisabled()) {
- $foundDisabled = true;
- break;
- }
- }
- if ($foundDisabled && $rule->isEnabled()) {
- $rule->disable();
- } elseif (!$foundDisabled && $rule->isDisabled()) {
- $rule->enable();
- }
- }
- }
- private function runSat($disableRules = true)
- {
- $this->propagateIndex = 0;
-
-
-
-
-
-
-
-
- $decisionQueue = array();
- $decisionSupplementQueue = array();
- $disableRules = array();
- $level = 1;
- $systemLevel = $level + 1;
- $installedPos = 0;
- while (true) {
- if (1 === $level) {
- $conflictRule = $this->propagate($level);
- if (null !== $conflictRule) {
- if ($this->analyzeUnsolvable($conflictRule, $disableRules)) {
- continue;
- }
- return;
- }
- }
- if ($level < $systemLevel) {
- $iterator = $this->rules->getIteratorFor(RuleSet::TYPE_JOB);
- foreach ($iterator as $rule) {
- if ($rule->isEnabled()) {
- $decisionQueue = array();
- $noneSatisfied = true;
- foreach ($rule->literals as $literal) {
- if ($this->decisions->satisfy($literal)) {
- $noneSatisfied = false;
- break;
- }
- if ($literal > 0 && $this->decisions->undecided($literal)) {
- $decisionQueue[] = $literal;
- }
- }
- if ($noneSatisfied && count($decisionQueue)) {
-
- if (count($this->installed) != count($this->updateMap)) {
- $prunedQueue = array();
- foreach ($decisionQueue as $literal) {
- if (isset($this->installedMap[abs($literal)])) {
- $prunedQueue[] = $literal;
- if (isset($this->updateMap[abs($literal)])) {
- $prunedQueue = $decisionQueue;
- break;
- }
- }
- }
- $decisionQueue = $prunedQueue;
- }
- }
- if ($noneSatisfied && count($decisionQueue)) {
- $oLevel = $level;
- $level = $this->selectAndInstall($level, $decisionQueue, $disableRules, $rule);
- if (0 === $level) {
- return;
- }
- if ($level <= $oLevel) {
- break;
- }
- }
- }
- }
- $systemLevel = $level + 1;
- $iterator->next();
- if ($iterator->valid()) {
- continue;
- }
- }
- if ($level < $systemLevel) {
- $systemLevel = $level;
- }
- for ($i = 0, $n = 0; $n < count($this->rules); $i++, $n++) {
- if ($i == count($this->rules)) {
- $i = 0;
- }
- $rule = $this->rules->ruleById[$i];
- $literals = $rule->literals;
- if ($rule->isDisabled()) {
- continue;
- }
- $decisionQueue = array();
-
-
-
-
-
- foreach ($literals as $literal) {
- if ($literal <= 0) {
- if (!$this->decisions->decidedInstall(abs($literal))) {
- continue 2;
- }
- } else {
- if ($this->decisions->decidedInstall(abs($literal))) {
- continue 2;
- }
- if ($this->decisions->undecided(abs($literal))) {
- $decisionQueue[] = $literal;
- }
- }
- }
- if (count($decisionQueue) < 2) {
- continue;
- }
- $oLevel = $level;
- $level = $this->selectAndInstall($level, $decisionQueue, $disableRules, $rule);
- if (0 === $level) {
- return;
- }
- $n = -1;
- }
- if ($level < $systemLevel) {
- continue;
- }
- if (count($this->branches)) {
- $lastLiteral = null;
- $lastLevel = null;
- $lastBranchIndex = 0;
- $lastBranchOffset = 0;
- $l = 0;
- for ($i = count($this->branches) - 1; $i >= 0; $i--) {
- list($literals, $l) = $this->branches[$i];
- foreach ($literals as $offset => $literal) {
- if ($literal && $literal > 0 && $this->decisions->decisionLevel($literal) > $l + 1) {
- $lastLiteral = $literal;
- $lastBranchIndex = $i;
- $lastBranchOffset = $offset;
- $lastLevel = $l;
- }
- }
- }
- if ($lastLiteral) {
- unset($this->branches[$lastBranchIndex][self::BRANCH_LITERALS][$lastBranchOffset]);
- $level = $lastLevel;
- $this->revert($level);
- $why = $this->decisions->lastReason();
- $oLevel = $level;
- $level = $this->setPropagateLearn($level, $lastLiteral, $disableRules, $why);
- if ($level == 0) {
- return;
- }
- continue;
- }
- }
- break;
- }
- }
- }
- <?php
- namespace Composer\DependencyResolver;
- class SolverBugException extends \RuntimeException
- {
- public function __construct($message)
- {
- parent::__construct(
- $message."\nThis exception was most likely caused by a bug in Composer.\n".
- "Please report the command you ran, the exact error you received, and your composer.json on https://github.com/composer/composer/issues - thank you!\n");
- }
- }
- <?php
- namespace Composer\DependencyResolver;
- class SolverProblemsException extends \RuntimeException
- {
- protected $problems;
- protected $installedMap;
- public function __construct(array $problems, array $installedMap)
- {
- $this->problems = $problems;
- $this->installedMap = $installedMap;
- parent::__construct($this->createMessage(), 2);
- }
- protected function createMessage()
- {
- $text = "\n";
- foreach ($this->problems as $i => $problem) {
- $text .= " Problem ".($i+1).$problem->getPrettyString($this->installedMap)."\n";
- }
- if (strpos($text, 'could not be found') || strpos($text, 'no matching package found')) {
- $text .= "\nPotential causes:\n - A typo in the package name\n - The package is not available in a stable-enough version according to your minimum-stability setting\n see <https://groups.google.com/d/topic/composer-dev/_g3ASeIFlrc/discussion> for more details.\n\nRead <http://getcomposer.org/doc/articles/troubleshooting.md> for further common problems.";
- }
- return $text;
- }
- public function getProblems()
- {
- return $this->problems;
- }
- }
- <?php
- namespace Composer\DependencyResolver;
- use Composer\Package\AliasPackage;
- class Transaction
- {
- protected $policy;
- protected $pool;
- protected $installedMap;
- protected $decisions;
- protected $transaction;
- public function __construct($policy, $pool, $installedMap, $decisions)
- {
- $this->policy = $policy;
- $this->pool = $pool;
- $this->installedMap = $installedMap;
- $this->decisions = $decisions;
- $this->transaction = array();
- }
- public function getOperations()
- {
- $installMeansUpdateMap = $this->findUpdates();
- $updateMap = array();
- $installMap = array();
- $uninstallMap = array();
- foreach ($this->decisions as $i => $decision) {
- $literal = $decision[Decisions::DECISION_LITERAL];
- $reason = $decision[Decisions::DECISION_REASON];
- $package = $this->pool->literalToPackage($literal);
- if (($literal > 0) == (isset($this->installedMap[$package->id]))) {
- continue;
- }
- if ($literal > 0) {
- if (isset($installMeansUpdateMap[abs($literal)]) && !$package instanceof AliasPackage) {
- $source = $installMeansUpdateMap[abs($literal)];
- $updateMap[$package->id] = array(
- 'package' => $package,
- 'source' => $source,
- 'reason' => $reason,
- );
- unset($installMeansUpdateMap[abs($literal)]);
- $ignoreRemove[$source->id] = true;
- } else {
- $installMap[$package->id] = array(
- 'package' => $package,
- 'reason' => $reason,
- );
- }
- }
- }
- foreach ($this->decisions as $i => $decision) {
- $literal = $decision[Decisions::DECISION_LITERAL];
- $reason = $decision[Decisions::DECISION_REASON];
- $package = $this->pool->literalToPackage($literal);
- if ($literal <= 0 &&
- isset($this->installedMap[$package->id]) &&
- !isset($ignoreRemove[$package->id])) {
- $uninstallMap[$package->id] = array(
- 'package' => $package,
- 'reason' => $reason,
- );
- }
- }
- $this->transactionFromMaps($installMap, $updateMap, $uninstallMap);
- return $this->transaction;
- }
- protected function transactionFromMaps($installMap, $updateMap, $uninstallMap)
- {
- $queue = array_map(function ($operation) {
- return $operation['package'];
- },
- $this->findRootPackages($installMap, $updateMap)
- );
- $visited = array();
- while (!empty($queue)) {
- $package = array_pop($queue);
- $packageId = $package->id;
- if (!isset($visited[$packageId])) {
- array_push($queue, $package);
- if ($package instanceof AliasPackage) {
- array_push($queue, $package->getAliasOf());
- } else {
- foreach ($package->getRequires() as $link) {
- $possibleRequires = $this->pool->whatProvides($link->getTarget(), $link->getConstraint());
- foreach ($possibleRequires as $require) {
- array_push($queue, $require);
- }
- }
- }
- $visited[$package->id] = true;
- } else {
- if (isset($installMap[$packageId])) {
- $this->install(
- $installMap[$packageId]['package'],
- $installMap[$packageId]['reason']
- );
- unset($installMap[$packageId]);
- }
- if (isset($updateMap[$packageId])) {
- $this->update(
- $updateMap[$packageId]['source'],
- $updateMap[$packageId]['package'],
- $updateMap[$packageId]['reason']
- );
- unset($updateMap[$packageId]);
- }
- }
- }
- foreach ($uninstallMap as $uninstall) {
- $this->uninstall($uninstall['package'], $uninstall['reason']);
- }
- }
- protected function findRootPackages($installMap, $updateMap)
- {
- $packages = $installMap + $updateMap;
- $roots = $packages;
- foreach ($packages as $packageId => $operation) {
- $package = $operation['package'];
- if (!isset($roots[$packageId])) {
- continue;
- }
- foreach ($package->getRequires() as $link) {
- $possibleRequires = $this->pool->whatProvides($link->getTarget(), $link->getConstraint());
- foreach ($possibleRequires as $require) {
- unset($roots[$require->id]);
- }
- }
- }
- return $roots;
- }
- protected function findUpdates()
- {
- $installMeansUpdateMap = array();
- foreach ($this->decisions as $i => $decision) {
- $literal = $decision[Decisions::DECISION_LITERAL];
- $package = $this->pool->literalToPackage($literal);
- if ($package instanceof AliasPackage) {
- continue;
- }
- if ($literal <= 0 && isset($this->installedMap[$package->id])) {
- $updates = $this->policy->findUpdatePackages($this->pool, $this->installedMap, $package);
- $literals = array($package->id);
- foreach ($updates as $update) {
- $literals[] = $update->id;
- }
- foreach ($literals as $updateLiteral) {
- if ($updateLiteral !== $literal) {
- $installMeansUpdateMap[abs($updateLiteral)] = $package;
- }
- }
- }
- }
- return $installMeansUpdateMap;
- }
- protected function install($package, $reason)
- {
- if ($package instanceof AliasPackage) {
- return $this->markAliasInstalled($package, $reason);
- }
- $this->transaction[] = new Operation\InstallOperation($package, $reason);
- }
- protected function update($from, $to, $reason)
- {
- $this->transaction[] = new Operation\UpdateOperation($from, $to, $reason);
- }
- protected function uninstall($package, $reason)
- {
- if ($package instanceof AliasPackage) {
- return $this->markAliasUninstalled($package, $reason);
- }
- $this->transaction[] = new Operation\UninstallOperation($package, $reason);
- }
- protected function markAliasInstalled($package, $reason)
- {
- $this->transaction[] = new Operation\MarkAliasInstalledOperation($package, $reason);
- }
- protected function markAliasUninstalled($package, $reason)
- {
- $this->transaction[] = new Operation\MarkAliasUninstalledOperation($package, $reason);
- }
- }
- <?php
- namespace Composer\Downloader;
- use Composer\Package\PackageInterface;
- use Symfony\Component\Finder\Finder;
- abstract class ArchiveDownloader extends FileDownloader
- {
- public function download(PackageInterface $package, $path)
- {
- $temporaryDir = $this->config->get('vendor-dir').'/composer/'.substr(md5(uniqid('', true)), 0, 8);
- $retries = 3;
- while ($retries--) {
- $fileName = parent::download($package, $path);
- if ($this->io->isVerbose()) {
- $this->io->writeError(' Extracting archive');
- }
- try {
- $this->filesystem->ensureDirectoryExists($temporaryDir);
- try {
- $this->extract($fileName, $temporaryDir);
- } catch (\Exception $e) {
- parent::clearCache($package, $path);
- throw $e;
- }
- $this->filesystem->unlink($fileName);
- $contentDir = $this->getFolderContent($temporaryDir);
- if (1 === count($contentDir) && is_dir(reset($contentDir))) {
- $contentDir = $this->getFolderContent((string) reset($contentDir));
- }
- foreach ($contentDir as $file) {
- $file = (string) $file;
- $this->filesystem->rename($file, $path . '/' . basename($file));
- }
- $this->filesystem->removeDirectory($temporaryDir);
- if ($this->filesystem->isDirEmpty($this->config->get('vendor-dir').'/composer/')) {
- $this->filesystem->removeDirectory($this->config->get('vendor-dir').'/composer/');
- }
- if ($this->filesystem->isDirEmpty($this->config->get('vendor-dir'))) {
- $this->filesystem->removeDirectory($this->config->get('vendor-dir'));
- }
- } catch (\Exception $e) {
- $this->filesystem->removeDirectory($path);
- $this->filesystem->removeDirectory($temporaryDir);
- if ($retries && $e instanceof \UnexpectedValueException && class_exists('ZipArchive') && $e->getCode() === \ZipArchive::ER_NOZIP) {
- $this->io->writeError(' Invalid zip file, retrying...');
- usleep(500000);
- continue;
- }
- throw $e;
- }
- break;
- }
- $this->io->writeError('');
- }
- protected function getFileName(PackageInterface $package, $path)
- {
- return rtrim($path.'/'.md5($path.spl_object_hash($package)).'.'.pathinfo(parse_url($package->getDistUrl(), PHP_URL_PATH), PATHINFO_EXTENSION), '.');
- }
- protected function processUrl(PackageInterface $package, $url)
- {
- if ($package->getDistReference() && strpos($url, 'github.com')) {
- if (preg_match('{^https?://(?:www\.)?github\.com/([^/]+)/([^/]+)/(zip|tar)ball/(.+)$}i', $url, $match)) {
- $url = 'https://api.github.com/repos/' . $match[1] . '/'. $match[2] . '/' . $match[3] . 'ball/' . $package->getDistReference();
- } elseif ($package->getDistReference() && preg_match('{^https?://(?:www\.)?github\.com/([^/]+)/([^/]+)/archive/.+\.(zip|tar)(?:\.gz)?$}i', $url, $match)) {
- $url = 'https://api.github.com/repos/' . $match[1] . '/'. $match[2] . '/' . $match[3] . 'ball/' . $package->getDistReference();
- } elseif ($package->getDistReference() && preg_match('{^https?://api\.github\.com/repos/([^/]+)/([^/]+)/(zip|tar)ball(?:/.+)?$}i', $url, $match)) {
- $url = 'https://api.github.com/repos/' . $match[1] . '/'. $match[2] . '/' . $match[3] . 'ball/' . $package->getDistReference();
- }
- }
- if (!extension_loaded('openssl') && (0 === strpos($url, 'https:') || 0 === strpos($url, 'http://github.com'))) {
- throw new \RuntimeException('You must enable the openssl extension to download files via https');
- }
- return parent::processUrl($package, $url);
- }
- abstract protected function extract($file, $path);
- private function getFolderContent($dir)
- {
- $finder = Finder::create()
- ->ignoreVCS(false)
- ->ignoreDotFiles(false)
- ->depth(0)
- ->in($dir);
- return iterator_to_array($finder);
- }
- }
- <?php
- namespace Composer\Downloader;
- use Composer\Package\PackageInterface;
- interface ChangeReportInterface
- {
- public function getLocalChanges(PackageInterface $package, $path);
- }
- <?php
- namespace Composer\Downloader;
- use Composer\Package\PackageInterface;
- interface DownloaderInterface
- {
- public function getInstallationSource();
- public function download(PackageInterface $package, $path);
- public function update(PackageInterface $initial, PackageInterface $target, $path);
- public function remove(PackageInterface $package, $path);
- public function setOutputProgress($outputProgress);
- }
- <?php
- namespace Composer\Downloader;
- use Composer\Package\PackageInterface;
- use Composer\IO\IOInterface;
- use Composer\Util\Filesystem;
- class DownloadManager
- {
- private $io;
- private $preferDist = false;
- private $preferSource = false;
- private $filesystem;
- private $downloaders = array();
- public function __construct(IOInterface $io, $preferSource = false, Filesystem $filesystem = null)
- {
- $this->io = $io;
- $this->preferSource = $preferSource;
- $this->filesystem = $filesystem ?: new Filesystem();
- }
- public function setPreferSource($preferSource)
- {
- $this->preferSource = $preferSource;
- return $this;
- }
- public function setPreferDist($preferDist)
- {
- $this->preferDist = $preferDist;
- return $this;
- }
- public function setOutputProgress($outputProgress)
- {
- foreach ($this->downloaders as $downloader) {
- $downloader->setOutputProgress($outputProgress);
- }
- return $this;
- }
- public function setDownloader($type, DownloaderInterface $downloader)
- {
- $type = strtolower($type);
- $this->downloaders[$type] = $downloader;
- return $this;
- }
- public function getDownloader($type)
- {
- $type = strtolower($type);
- if (!isset($this->downloaders[$type])) {
- throw new \InvalidArgumentException(sprintf('Unknown downloader type: %s. Available types: %s.', $type, implode(', ', array_keys($this->downloaders))));
- }
- return $this->downloaders[$type];
- }
- public function getDownloaderForInstalledPackage(PackageInterface $package)
- {
- $installationSource = $package->getInstallationSource();
- if ('metapackage' === $package->getType()) {
- return;
- }
- if ('dist' === $installationSource) {
- $downloader = $this->getDownloader($package->getDistType());
- } elseif ('source' === $installationSource) {
- $downloader = $this->getDownloader($package->getSourceType());
- } else {
- throw new \InvalidArgumentException(
- 'Package '.$package.' seems not been installed properly'
- );
- }
- if ($installationSource !== $downloader->getInstallationSource()) {
- throw new \LogicException(sprintf(
- 'Downloader "%s" is a %s type downloader and can not be used to download %s',
- get_class($downloader), $downloader->getInstallationSource(), $installationSource
- ));
- }
- return $downloader;
- }
- public function download(PackageInterface $package, $targetDir, $preferSource = null)
- {
- $preferSource = null !== $preferSource ? $preferSource : $this->preferSource;
- $sourceType = $package->getSourceType();
- $distType = $package->getDistType();
- $sources = array();
- if ($sourceType) {
- $sources[] = 'source';
- }
- if ($distType) {
- $sources[] = 'dist';
- }
- if (empty($sources)) {
- throw new \InvalidArgumentException('Package '.$package.' must have a source or dist specified');
- }
- if ((!$package->isDev() || $this->preferDist) && !$preferSource) {
- $sources = array_reverse($sources);
- }
- $this->filesystem->ensureDirectoryExists($targetDir);
- foreach ($sources as $i => $source) {
- if (isset($e)) {
- $this->io->writeError(' <warning>Now trying to download from ' . $source . '</warning>');
- }
- $package->setInstallationSource($source);
- try {
- $downloader = $this->getDownloaderForInstalledPackage($package);
- if ($downloader) {
- $downloader->download($package, $targetDir);
- }
- break;
- } catch (\RuntimeException $e) {
- if ($i === count($sources) - 1) {
- throw $e;
- }
- $this->io->writeError(
- ' <warning>Failed to download '.
- $package->getPrettyName().
- ' from ' . $source . ': '.
- $e->getMessage().'</warning>'
- );
- }
- }
- }
- public function update(PackageInterface $initial, PackageInterface $target, $targetDir)
- {
- $downloader = $this->getDownloaderForInstalledPackage($initial);
- if (!$downloader) {
- return;
- }
- $installationSource = $initial->getInstallationSource();
- if ('dist' === $installationSource) {
- $initialType = $initial->getDistType();
- $targetType = $target->getDistType();
- } else {
- $initialType = $initial->getSourceType();
- $targetType = $target->getSourceType();
- }
- if ($target->isDev() && 'dist' === $installationSource) {
- $downloader->remove($initial, $targetDir);
- $this->download($target, $targetDir);
- return;
- }
- if ($initialType === $targetType) {
- $target->setInstallationSource($installationSource);
- $downloader->update($initial, $target, $targetDir);
- } else {
- $downloader->remove($initial, $targetDir);
- $this->download($target, $targetDir, 'source' === $installationSource);
- }
- }
- public function remove(PackageInterface $package, $targetDir)
- {
- $downloader = $this->getDownloaderForInstalledPackage($package);
- if ($downloader) {
- $downloader->remove($package, $targetDir);
- }
- }
- }
- <?php
- namespace Composer\Downloader;
- use Composer\Config;
- use Composer\Cache;
- use Composer\IO\IOInterface;
- use Composer\Package\PackageInterface;
- use Composer\Package\Version\VersionParser;
- use Composer\Plugin\PluginEvents;
- use Composer\Plugin\PreFileDownloadEvent;
- use Composer\EventDispatcher\EventDispatcher;
- use Composer\Util\Filesystem;
- use Composer\Util\RemoteFilesystem;
- class FileDownloader implements DownloaderInterface
- {
- protected $io;
- protected $config;
- protected $rfs;
- protected $filesystem;
- protected $cache;
- protected $outputProgress = true;
- public function __construct(IOInterface $io, Config $config, EventDispatcher $eventDispatcher = null, Cache $cache = null, RemoteFilesystem $rfs = null, Filesystem $filesystem = null)
- {
- $this->io = $io;
- $this->config = $config;
- $this->eventDispatcher = $eventDispatcher;
- $this->rfs = $rfs ?: new RemoteFilesystem($io, $config);
- $this->filesystem = $filesystem ?: new Filesystem();
- $this->cache = $cache;
- if ($this->cache && $this->cache->gcIsNecessary()) {
- $this->cache->gc($config->get('cache-files-ttl'), $config->get('cache-files-maxsize'));
- }
- }
- public function getInstallationSource()
- {
- return 'dist';
- }
- public function download(PackageInterface $package, $path)
- {
- if (!$package->getDistUrl()) {
- throw new \InvalidArgumentException('The given package is missing url information');
- }
- $this->io->writeError(" - Installing <info>" . $package->getName() . "</info> (<comment>" . VersionParser::formatVersion($package) . "</comment>)");
- $urls = $package->getDistUrls();
- while ($url = array_shift($urls)) {
- try {
- return $this->doDownload($package, $path, $url);
- } catch (\Exception $e) {
- if ($this->io->isDebug()) {
- $this->io->writeError('');
- $this->io->writeError('Failed: ['.get_class($e).'] '.$e->getCode().': '.$e->getMessage());
- } elseif (count($urls)) {
- $this->io->writeError('');
- $this->io->writeError(' Failed, trying the next URL ('.$e->getCode().': '.$e->getMessage().')');
- }
- if (!count($urls)) {
- throw $e;
- }
- }
- }
- $this->io->writeError('');
- }
- protected function doDownload(PackageInterface $package, $path, $url)
- {
- $this->filesystem->emptyDirectory($path);
- $fileName = $this->getFileName($package, $path);
- $processedUrl = $this->processUrl($package, $url);
- $hostname = parse_url($processedUrl, PHP_URL_HOST);
- $preFileDownloadEvent = new PreFileDownloadEvent(PluginEvents::PRE_FILE_DOWNLOAD, $this->rfs, $processedUrl);
- if ($this->eventDispatcher) {
- $this->eventDispatcher->dispatch($preFileDownloadEvent->getName(), $preFileDownloadEvent);
- }
- $rfs = $preFileDownloadEvent->getRemoteFilesystem();
- try {
- $checksum = $package->getDistSha1Checksum();
- $cacheKey = $this->getCacheKey($package);
- if (!$this->cache || ($checksum && $checksum !== $this->cache->sha1($cacheKey)) || !$this->cache->copyTo($cacheKey, $fileName)) {
- if (!$this->outputProgress) {
- $this->io->writeError(' Downloading');
- }
- $retries = 3;
- while ($retries--) {
- try {
- $rfs->copy($hostname, $processedUrl, $fileName, $this->outputProgress, $package->getTransportOptions());
- break;
- } catch (TransportException $e) {
- if ((0 !== $e->getCode() && !in_array($e->getCode(),array(500, 502, 503, 504))) || !$retries) {
- throw $e;
- }
- if ($this->io->isVerbose()) {
- $this->io->writeError(' Download failed, retrying...');
- }
- usleep(500000);
- }
- }
- if ($this->cache) {
- $this->cache->copyFrom($cacheKey, $fileName);
- }
- } else {
- $this->io->writeError(' Loading from cache');
- }
- if (!file_exists($fileName)) {
- throw new \UnexpectedValueException($url.' could not be saved to '.$fileName.', make sure the'
- .' directory is writable and you have internet connectivity');
- }
- if ($checksum && hash_file('sha1', $fileName) !== $checksum) {
- throw new \UnexpectedValueException('The checksum verification of the file failed (downloaded from '.$url.')');
- }
- } catch (\Exception $e) {
- $this->filesystem->removeDirectory($path);
- $this->clearCache($package, $path);
- throw $e;
- }
- return $fileName;
- }
- public function setOutputProgress($outputProgress)
- {
- $this->outputProgress = $outputProgress;
- return $this;
- }
- protected function clearCache(PackageInterface $package, $path)
- {
- if ($this->cache) {
- $fileName = $this->getFileName($package, $path);
- $this->cache->remove($this->getCacheKey($package));
- }
- }
- public function update(PackageInterface $initial, PackageInterface $target, $path)
- {
- $this->remove($initial, $path);
- $this->download($target, $path);
- }
- public function remove(PackageInterface $package, $path)
- {
- $this->io->writeError(" - Removing <info>" . $package->getName() . "</info> (<comment>" . VersionParser::formatVersion($package) . "</comment>)");
- if (!$this->filesystem->removeDirectory($path)) {
- throw new \RuntimeException('Could not completely delete '.$path.', aborting.');
- }
- }
- protected function getFileName(PackageInterface $package, $path)
- {
- return $path.'/'.pathinfo(parse_url($package->getDistUrl(), PHP_URL_PATH), PATHINFO_BASENAME);
- }
- protected function processUrl(PackageInterface $package, $url)
- {
- if (!extension_loaded('openssl') && 0 === strpos($url, 'https:')) {
- throw new \RuntimeException('You must enable the openssl extension to download files via https');
- }
- return $url;
- }
- private function getCacheKey(PackageInterface $package)
- {
- if (preg_match('{^[a-f0-9]{40}$}', $package->getDistReference())) {
- return $package->getName().'/'.$package->getDistReference().'.'.$package->getDistType();
- }
- return $package->getName().'/'.$package->getVersion().'-'.$package->getDistReference().'.'.$package->getDistType();
- }
- }
- <?php
- namespace Composer\Downloader;
- class FilesystemException extends \Exception
- {
- public function __construct($message = null, $code = null, \Exception $previous = null)
- {
- parent::__construct("Filesystem exception: \n".$message, $code, $previous);
- }
- }
- <?php
- namespace Composer\Downloader;
- use Composer\Package\PackageInterface;
- use Composer\Util\GitHub;
- use Composer\Util\Git as GitUtil;
- use Composer\Util\ProcessExecutor;
- use Composer\IO\IOInterface;
- use Composer\Util\Filesystem;
- use Composer\Config;
- class GitDownloader extends VcsDownloader
- {
- private $hasStashedChanges = false;
- private $gitUtil;
- public function __construct(IOInterface $io, Config $config, ProcessExecutor $process = null, Filesystem $fs = null)
- {
- parent::__construct($io, $config, $process, $fs);
- $this->gitUtil = new GitUtil($this->io, $this->config, $this->process, $this->filesystem);
- }
- public function doDownload(PackageInterface $package, $path, $url)
- {
- GitUtil::cleanEnv();
- $path = $this->normalizePath($path);
- $ref = $package->getSourceReference();
- $flag = defined('PHP_WINDOWS_VERSION_MAJOR') ? '/D ' : '';
- $command = 'git clone --no-checkout %s %s && cd '.$flag.'%2$s && git remote add composer %1$s && git fetch composer';
- $this->io->writeError(" Cloning ".$ref);
- $commandCallable = function ($url) use ($ref, $path, $command) {
- return sprintf($command, ProcessExecutor::escape($url), ProcessExecutor::escape($path), ProcessExecutor::escape($ref));
- };
- $this->gitUtil->runCommand($commandCallable, $url, $path, true);
- if ($url !== $package->getSourceUrl()) {
- $url = $package->getSourceUrl();
- $this->process->execute(sprintf('git remote set-url origin %s', ProcessExecutor::escape($url)), $output, $path);
- }
- $this->setPushUrl($path, $url);
- if ($newRef = $this->updateToCommit($path, $ref, $package->getPrettyVersion(), $package->getReleaseDate())) {
- if ($package->getDistReference() === $package->getSourceReference()) {
- $package->setDistReference($newRef);
- }
- $package->setSourceReference($newRef);
- }
- }
- public function doUpdate(PackageInterface $initial, PackageInterface $target, $path, $url)
- {
- GitUtil::cleanEnv();
- $path = $this->normalizePath($path);
- if (!is_dir($path.'/.git')) {
- throw new \RuntimeException('The .git directory is missing from '.$path.', see http://getcomposer.org/commit-deps for more information');
- }
- $ref = $target->getSourceReference();
- $this->io->writeError(" Checking out ".$ref);
- $command = 'git remote set-url composer %s && git fetch composer && git fetch --tags composer';
- $commandCallable = function ($url) use ($command) {
- return sprintf($command, ProcessExecutor::escape ($url));
- };
- $this->gitUtil->runCommand($commandCallable, $url, $path);
- if ($newRef = $this->updateToCommit($path, $ref, $target->getPrettyVersion(), $target->getReleaseDate())) {
- if ($target->getDistReference() === $target->getSourceReference()) {
- $target->setDistReference($newRef);
- }
- $target->setSourceReference($newRef);
- }
- }
- public function getLocalChanges(PackageInterface $package, $path)
- {
- GitUtil::cleanEnv();
- $path = $this->normalizePath($path);
- if (!is_dir($path.'/.git')) {
- return;
- }
- $command = 'git status --porcelain --untracked-files=no';
- if (0 !== $this->process->execute($command, $output, $path)) {
- throw new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput());
- }
- return trim($output) ?: null;
- }
- protected function cleanChanges(PackageInterface $package, $path, $update)
- {
- GitUtil::cleanEnv();
- $path = $this->normalizePath($path);
- if (!$changes = $this->getLocalChanges($package, $path)) {
- return;
- }
- if (!$this->io->isInteractive()) {
- $discardChanges = $this->config->get('discard-changes');
- if (true === $discardChanges) {
- return $this->discardChanges($path);
- }
- if ('stash' === $discardChanges) {
- if (!$update) {
- return parent::cleanChanges($package, $path, $update);
- }
- return $this->stashChanges($path);
- }
- return parent::cleanChanges($package, $path, $update);
- }
- $changes = array_map(function ($elem) {
- return ' '.$elem;
- }, preg_split('{\s*\r?\n\s*}', $changes));
- $this->io->writeError(' <error>The package has modified files:</error>');
- $this->io->writeError(array_slice($changes, 0, 10));
- if (count($changes) > 10) {
- $this->io->writeError(' <info>'.count($changes) - 10 . ' more files modified, choose "v" to view the full list</info>');
- }
- while (true) {
- switch ($this->io->ask(' <info>Discard changes [y,n,v,'.($update ? 's,' : '').'?]?</info> ', '?')) {
- case 'y':
- $this->discardChanges($path);
- break 2;
- case 's':
- if (!$update) {
- goto help;
- }
- $this->stashChanges($path);
- break 2;
- case 'n':
- throw new \RuntimeException('Update aborted');
- case 'v':
- $this->io->writeError($changes);
- break;
- case '?':
- default:
- help:
- $this->io->writeError(array(
- ' y - discard changes and apply the '.($update ? 'update' : 'uninstall'),
- ' n - abort the '.($update ? 'update' : 'uninstall').' and let you manually clean things up',
- ' v - view modified files',
- ));
- if ($update) {
- $this->io->writeError(' s - stash changes and try to reapply them after the update');
- }
- $this->io->writeError(' ? - print help');
- break;
- }
- }
- }
- protected function reapplyChanges($path)
- {
- $path = $this->normalizePath($path);
- if ($this->hasStashedChanges) {
- $this->hasStashedChanges = false;
- $this->io->writeError(' <info>Re-applying stashed changes</info>');
- if (0 !== $this->process->execute('git stash pop', $output, $path)) {
- throw new \RuntimeException("Failed to apply stashed changes:\n\n".$this->process->getErrorOutput());
- }
- }
- }
- protected function updateToCommit($path, $reference, $branch, $date)
- {
- $template = 'git checkout %s && git reset --hard %1$s';
- $branch = preg_replace('{(?:^dev-|(?:\.x)?-dev$)}i', '', $branch);
- $branches = null;
- if (0 === $this->process->execute('git branch -r', $output, $path)) {
- $branches = $output;
- }
- $gitRef = $reference;
- if (!preg_match('{^[a-f0-9]{40}$}', $reference)
- && $branches
- && preg_match('{^\s+composer/'.preg_quote($reference).'$}m', $branches)
- ) {
- $command = sprintf('git checkout -B %s %s && git reset --hard %2$s', ProcessExecutor::escape($branch), ProcessExecutor::escape('composer/'.$reference));
- if (0 === $this->process->execute($command, $output, $path)) {
- return;
- }
- }
- if (preg_match('{^[a-f0-9]{40}$}', $reference)) {
- if (!preg_match('{^\s+composer/'.preg_quote($branch).'$}m', $branches) && preg_match('{^\s+composer/v'.preg_quote($branch).'$}m', $branches)) {
- $branch = 'v' . $branch;
- }
- $command = sprintf('git checkout %s', ProcessExecutor::escape($branch));
- $fallbackCommand = sprintf('git checkout -B %s %s', ProcessExecutor::escape($branch), ProcessExecutor::escape('composer/'.$branch));
- if (0 === $this->process->execute($command, $output, $path)
- || 0 === $this->process->execute($fallbackCommand, $output, $path)
- ) {
- $command = sprintf('git reset --hard %s', ProcessExecutor::escape($reference));
- if (0 === $this->process->execute($command, $output, $path)) {
- return;
- }
- }
- }
- $command = sprintf($template, ProcessExecutor::escape($gitRef));
- if (0 === $this->process->execute($command, $output, $path)) {
- return;
- }
- if (false !== strpos($this->process->getErrorOutput(), $reference)) {
- $this->io->writeError(' <warning>'.$reference.' is gone (history was rewritten?)</warning>');
- }
- throw new \RuntimeException('Failed to execute ' . GitUtil::sanitizeUrl($command) . "\n\n" . $this->process->getErrorOutput());
- }
- protected function setPushUrl($path, $url)
- {
- if (preg_match('{^(?:https?|git)://'.GitUtil::getGitHubDomainsRegex($this->config).'/([^/]+)/([^/]+?)(?:\.git)?$}', $url, $match)) {
- $protocols = $this->config->get('github-protocols');
- $pushUrl = 'git@'.$match[1].':'.$match[2].'/'.$match[3].'.git';
- if ($protocols[0] !== 'git') {
- $pushUrl = 'https://' . $match[1] . '/'.$match[2].'/'.$match[3].'.git';
- }
- $cmd = sprintf('git remote set-url --push origin %s', ProcessExecutor::escape($pushUrl));
- $this->process->execute($cmd, $ignoredOutput, $path);
- }
- }
- protected function getCommitLogs($fromReference, $toReference, $path)
- {
- $path = $this->normalizePath($path);
- $command = sprintf('git log %s..%s --pretty=format:"%%h - %%an: %%s"', $fromReference, $toReference);
- if (0 !== $this->process->execute($command, $output, $path)) {
- throw new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput());
- }
- return $output;
- }
- protected function discardChanges($path)
- {
- $path = $this->normalizePath($path);
- if (0 !== $this->process->execute('git reset --hard', $output, $path)) {
- throw new \RuntimeException("Could not reset changes\n\n:".$this->process->getErrorOutput());
- }
- }
- protected function stashChanges($path)
- {
- $path = $this->normalizePath($path);
- if (0 !== $this->process->execute('git stash', $output, $path)) {
- throw new \RuntimeException("Could not stash changes\n\n:".$this->process->getErrorOutput());
- }
- $this->hasStashedChanges = true;
- }
- protected function normalizePath($path)
- {
- if (defined('PHP_WINDOWS_VERSION_MAJOR') && strlen($path) > 0) {
- $basePath = $path;
- $removed = array();
- while (!is_dir($basePath) && $basePath !== '\\') {
- array_unshift($removed, basename($basePath));
- $basePath = dirname($basePath);
- }
- if ($basePath === '\\') {
- return $path;
- }
- $path = rtrim(realpath($basePath) . '/' . implode('/', $removed), '/');
- }
- return $path;
- }
- }
- <?php
- namespace Composer\Downloader;
- use Composer\Config;
- use Composer\Cache;
- use Composer\EventDispatcher\EventDispatcher;
- use Composer\Package\PackageInterface;
- use Composer\Util\ProcessExecutor;
- use Composer\IO\IOInterface;
- class GzipDownloader extends ArchiveDownloader
- {
- protected $process;
- public function __construct(IOInterface $io, Config $config, EventDispatcher $eventDispatcher = null, Cache $cache = null, ProcessExecutor $process = null)
- {
- $this->process = $process ?: new ProcessExecutor($io);
- parent::__construct($io, $config, $eventDispatcher, $cache);
- }
- protected function extract($file, $path)
- {
- $targetFilepath = $path . DIRECTORY_SEPARATOR . basename(substr($file, 0, -3));
- if (!defined('PHP_WINDOWS_VERSION_BUILD')) {
- $command = 'gzip -cd ' . ProcessExecutor::escape($file) . ' > ' . ProcessExecutor::escape($targetFilepath);
- if (0 === $this->process->execute($command, $ignoredOutput)) {
- return;
- }
- $processError = 'Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput();
- throw new \RuntimeException($processError);
- }
- $archiveFile = gzopen($file, 'rb');
- $targetFile = fopen($targetFilepath, 'wb');
- while ($string = gzread($archiveFile, 4096)) {
- fwrite($targetFile, $string, strlen($string));
- }
- gzclose($archiveFile);
- fclose($targetFile);
- }
- protected function getFileName(PackageInterface $package, $path)
- {
- return $path.'/'.pathinfo(parse_url($package->getDistUrl(), PHP_URL_PATH), PATHINFO_BASENAME);
- }
- }
- <?php
- namespace Composer\Downloader;
- use Composer\Package\PackageInterface;
- use Composer\Util\ProcessExecutor;
- class HgDownloader extends VcsDownloader
- {
- public function doDownload(PackageInterface $package, $path, $url)
- {
- $url = ProcessExecutor::escape($url);
- $ref = ProcessExecutor::escape($package->getSourceReference());
- $this->io->writeError(" Cloning ".$package->getSourceReference());
- $command = sprintf('hg clone %s %s', $url, ProcessExecutor::escape($path));
- if (0 !== $this->process->execute($command, $ignoredOutput)) {
- throw new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput());
- }
- $command = sprintf('hg up %s', $ref);
- if (0 !== $this->process->execute($command, $ignoredOutput, realpath($path))) {
- throw new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput());
- }
- }
- public function doUpdate(PackageInterface $initial, PackageInterface $target, $path, $url)
- {
- $url = ProcessExecutor::escape($url);
- $ref = ProcessExecutor::escape($target->getSourceReference());
- $this->io->writeError(" Updating to ".$target->getSourceReference());
- if (!is_dir($path.'/.hg')) {
- throw new \RuntimeException('The .hg directory is missing from '.$path.', see http://getcomposer.org/commit-deps for more information');
- }
- $command = sprintf('hg pull %s && hg up %s', $url, $ref);
- if (0 !== $this->process->execute($command, $ignoredOutput, realpath($path))) {
- throw new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput());
- }
- }
- public function getLocalChanges(PackageInterface $package, $path)
- {
- if (!is_dir($path.'/.hg')) {
- return;
- }
- $this->process->execute('hg st', $output, realpath($path));
- return trim($output) ?: null;
- }
- protected function getCommitLogs($fromReference, $toReference, $path)
- {
- $command = sprintf('hg log -r %s:%s --style compact', $fromReference, $toReference);
- if (0 !== $this->process->execute($command, $output, realpath($path))) {
- throw new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput());
- }
- return $output;
- }
- }
- <?php
- namespace Composer\Downloader;
- use Composer\Util\Filesystem;
- class PearPackageExtractor
- {
- private static $rolesWithoutPackageNamePrefix = array('php', 'script', 'www');
- private $filesystem;
- private $file;
- public function __construct($file)
- {
- if (!is_file($file)) {
- throw new \UnexpectedValueException('PEAR package file is not found at '.$file);
- }
- $this->filesystem = new Filesystem();
- $this->file = $file;
- }
- public function extractTo($target, array $roles = array('php' => '/', 'script' => '/bin'), $vars = array())
- {
- $extractionPath = $target.'/tarball';
- try {
- $archive = new \PharData($this->file);
- $archive->extractTo($extractionPath, null, true);
- if (!is_file($this->combine($extractionPath, '/package.xml'))) {
- throw new \RuntimeException('Invalid PEAR package. It must contain package.xml file.');
- }
- $fileCopyActions = $this->buildCopyActions($extractionPath, $roles, $vars);
- $this->copyFiles($fileCopyActions, $extractionPath, $target, $roles, $vars);
- $this->filesystem->removeDirectory($extractionPath);
- } catch (\Exception $exception) {
- throw new \UnexpectedValueException(sprintf('Failed to extract PEAR package %s to %s. Reason: %s', $this->file, $target, $exception->getMessage()), 0, $exception);
- }
- }
- private function copyFiles($files, $source, $target, $roles, $vars)
- {
- foreach ($files as $file) {
- $from = $this->combine($source, $file['from']);
- $to = $this->combine($target, $roles[$file['role']]);
- $to = $this->combine($to, $file['to']);
- $tasks = $file['tasks'];
- $this->copyFile($from, $to, $tasks, $vars);
- }
- }
- private function copyFile($from, $to, $tasks, $vars)
- {
- if (!is_file($from)) {
- throw new \RuntimeException('Invalid PEAR package. package.xml defines file that is not located inside tarball.');
- }
- $this->filesystem->ensureDirectoryExists(dirname($to));
- if (0 == count($tasks)) {
- $copied = copy($from, $to);
- } else {
- $content = file_get_contents($from);
- $replacements = array();
- foreach ($tasks as $task) {
- $pattern = $task['from'];
- $varName = $task['to'];
- if (isset($vars[$varName])) {
- if ($varName === 'php_bin' && false === strpos($to, '.bat')) {
- $replacements[$pattern] = preg_replace('{\.bat$}', '', $vars[$varName]);
- } else {
- $replacements[$pattern] = $vars[$varName];
- }
- }
- }
- $content = strtr($content, $replacements);
- $copied = file_put_contents($to, $content);
- }
- if (false === $copied) {
- throw new \RuntimeException(sprintf('Failed to copy %s to %s', $from, $to));
- }
- }
- private function buildCopyActions($source, array $roles, $vars)
- {
- $package = simplexml_load_file($this->combine($source, 'package.xml'));
- if (false === $package) {
- throw new \RuntimeException('Package definition file is not valid.');
- }
- $packageSchemaVersion = $package['version'];
- if ('1.0' == $packageSchemaVersion) {
- $children = $package->release->filelist->children();
- $packageName = (string) $package->name;
- $packageVersion = (string) $package->release->version;
- $sourceDir = $packageName . '-' . $packageVersion;
- $result = $this->buildSourceList10($children, $roles, $sourceDir, '', null, $packageName);
- } elseif ('2.0' == $packageSchemaVersion || '2.1' == $packageSchemaVersion) {
- $children = $package->contents->children();
- $packageName = (string) $package->name;
- $packageVersion = (string) $package->version->release;
- $sourceDir = $packageName . '-' . $packageVersion;
- $result = $this->buildSourceList20($children, $roles, $sourceDir, '', null, $packageName);
- $namespaces = $package->getNamespaces();
- $package->registerXPathNamespace('ns', $namespaces['']);
- $releaseNodes = $package->xpath('ns:phprelease');
- $this->applyRelease($result, $releaseNodes, $vars);
- } else {
- throw new \RuntimeException('Unsupported schema version of package definition file.');
- }
- return $result;
- }
- private function applyRelease(&$actions, $releaseNodes, $vars)
- {
- foreach ($releaseNodes as $releaseNode) {
- $requiredOs = $releaseNode->installconditions && $releaseNode->installconditions->os && $releaseNode->installconditions->os->name ? (string) $releaseNode->installconditions->os->name : '';
- if ($requiredOs && $vars['os'] != $requiredOs) {
- continue;
- }
- if ($releaseNode->filelist) {
- foreach ($releaseNode->filelist->children() as $action) {
- if ('install' == $action->getName()) {
- $name = (string) $action['name'];
- $as = (string) $action['as'];
- if (isset($actions[$name])) {
- $actions[$name]['to'] = $as;
- }
- } elseif ('ignore' == $action->getName()) {
- $name = (string) $action['name'];
- unset($actions[$name]);
- } else {
- }
- }
- }
- break;
- }
- }
- private function buildSourceList10($children, $targetRoles, $source, $target, $role, $packageName)
- {
- $result = array();
- foreach ($children as $child) {
- if ($child->getName() == 'dir') {
- $dirSource = $this->combine($source, (string) $child['name']);
- $dirTarget = $child['baseinstalldir'] ?: $target;
- $dirRole = $child['role'] ?: $role;
- $dirFiles = $this->buildSourceList10($child->children(), $targetRoles, $dirSource, $dirTarget, $dirRole, $packageName);
- $result = array_merge($result, $dirFiles);
- } elseif ($child->getName() == 'file') {
- $fileRole = (string) $child['role'] ?: $role;
- if (isset($targetRoles[$fileRole])) {
- $fileName = (string) ($child['name'] ?: $child[0]);
- $fileSource = $this->combine($source, $fileName);
- $fileTarget = $this->combine((string) $child['baseinstalldir'] ?: $target, $fileName);
- if (!in_array($fileRole, self::$rolesWithoutPackageNamePrefix)) {
- $fileTarget = $packageName . '/' . $fileTarget;
- }
- $result[(string) $child['name']] = array('from' => $fileSource, 'to' => $fileTarget, 'role' => $fileRole, 'tasks' => array());
- }
- }
- }
- return $result;
- }
- private function buildSourceList20($children, $targetRoles, $source, $target, $role, $packageName)
- {
- $result = array();
- foreach ($children as $child) {
- if ('dir' == $child->getName()) {
- $dirSource = $this->combine($source, $child['name']);
- $dirTarget = $child['baseinstalldir'] ?: $target;
- $dirRole = $child['role'] ?: $role;
- $dirFiles = $this->buildSourceList20($child->children(), $targetRoles, $dirSource, $dirTarget, $dirRole, $packageName);
- $result = array_merge($result, $dirFiles);
- } elseif ('file' == $child->getName()) {
- $fileRole = (string) $child['role'] ?: $role;
- if (isset($targetRoles[$fileRole])) {
- $fileSource = $this->combine($source, (string) $child['name']);
- $fileTarget = $this->combine((string) ($child['baseinstalldir'] ?: $target), (string) $child['name']);
- $fileTasks = array();
- foreach ($child->children('http://pear.php.net/dtd/tasks-1.0') as $taskNode) {
- if ('replace' == $taskNode->getName()) {
- $fileTasks[] = array('from' => (string) $taskNode->attributes()->from, 'to' => (string) $taskNode->attributes()->to);
- }
- }
- if (!in_array($fileRole, self::$rolesWithoutPackageNamePrefix)) {
- $fileTarget = $packageName . '/' . $fileTarget;
- }
- $result[(string) $child['name']] = array('from' => $fileSource, 'to' => $fileTarget, 'role' => $fileRole, 'tasks' => $fileTasks);
- }
- }
- }
- return $result;
- }
- private function combine($left, $right)
- {
- return rtrim($left, '/') . '/' . ltrim($right, '/');
- }
- }
- <?php
- namespace Composer\Downloader;
- use Composer\Package\PackageInterface;
- use Composer\Repository\VcsRepository;
- use Composer\Util\Perforce;
- class PerforceDownloader extends VcsDownloader
- {
- protected $perforce;
- public function doDownload(PackageInterface $package, $path, $url)
- {
- $ref = $package->getSourceReference();
- $label = $this->getLabelFromSourceReference($ref);
- $this->io->writeError(' Cloning ' . $ref);
- $this->initPerforce($package, $path, $url);
- $this->perforce->setStream($ref);
- $this->perforce->p4Login($this->io);
- $this->perforce->writeP4ClientSpec();
- $this->perforce->connectClient();
- $this->perforce->syncCodeBase($label);
- $this->perforce->cleanupClientSpec();
- }
- private function getLabelFromSourceReference($ref)
- {
- $pos = strpos($ref,'@');
- if (false !== $pos) {
- return substr($ref, $pos + 1);
- }
- return null;
- }
- public function initPerforce($package, $path, $url)
- {
- if (!empty($this->perforce)) {
- $this->perforce->initializePath($path);
- return;
- }
- $repository = $package->getRepository();
- $repoConfig = null;
- if ($repository instanceof VcsRepository) {
- $repoConfig = $this->getRepoConfig($repository);
- }
- $this->perforce = Perforce::create($repoConfig, $url, $path, $this->process, $this->io);
- }
- private function getRepoConfig(VcsRepository $repository)
- {
- return $repository->getRepoConfig();
- }
- public function doUpdate(PackageInterface $initial, PackageInterface $target, $path, $url)
- {
- $this->doDownload($target, $path, $url);
- }
- public function getLocalChanges(PackageInterface $package, $path)
- {
- $this->io->writeError('Perforce driver does not check for local changes before overriding', true);
- return;
- }
- protected function getCommitLogs($fromReference, $toReference, $path)
- {
- $commitLogs = $this->perforce->getCommitLogs($fromReference, $toReference);
- return $commitLogs;
- }
- public function setPerforce($perforce)
- {
- $this->perforce = $perforce;
- }
- }
- <?php
- namespace Composer\Downloader;
- class PharDownloader extends ArchiveDownloader
- {
- protected function extract($file, $path)
- {
- $archive = new \Phar($file);
- $archive->extractTo($path, null, true);
- }
- }
- <?php
- namespace Composer\Downloader;
- use Composer\Config;
- use Composer\Cache;
- use Composer\EventDispatcher\EventDispatcher;
- use Composer\Util\ProcessExecutor;
- use Composer\IO\IOInterface;
- use RarArchive;
- class RarDownloader extends ArchiveDownloader
- {
- protected $process;
- public function __construct(IOInterface $io, Config $config, EventDispatcher $eventDispatcher = null, Cache $cache = null, ProcessExecutor $process = null)
- {
- $this->process = $process ?: new ProcessExecutor($io);
- parent::__construct($io, $config, $eventDispatcher, $cache);
- }
- protected function extract($file, $path)
- {
- $processError = null;
- if (!defined('PHP_WINDOWS_VERSION_BUILD')) {
- $command = 'unrar x ' . ProcessExecutor::escape($file) . ' ' . ProcessExecutor::escape($path) . ' && chmod -R u+w ' . ProcessExecutor::escape($path);
- if (0 === $this->process->execute($command, $ignoredOutput)) {
- return;
- }
- $processError = 'Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput();
- }
- if (!class_exists('RarArchive')) {
- $iniPath = php_ini_loaded_file();
- if ($iniPath) {
- $iniMessage = 'The php.ini used by your command-line PHP is: ' . $iniPath;
- } else {
- $iniMessage = 'A php.ini file does not exist. You will have to create one.';
- }
- $error = "Could not decompress the archive, enable the PHP rar extension or install unrar.\n"
- . $iniMessage . "\n" . $processError;
- if (!defined('PHP_WINDOWS_VERSION_BUILD')) {
- $error = "Could not decompress the archive, enable the PHP rar extension.\n" . $iniMessage;
- }
- throw new \RuntimeException($error);
- }
- $rarArchive = RarArchive::open($file);
- if (false === $rarArchive) {
- throw new \UnexpectedValueException('Could not open RAR archive: ' . $file);
- }
- $entries = $rarArchive->getEntries();
- if (false === $entries) {
- throw new \RuntimeException('Could not retrieve RAR archive entries');
- }
- foreach ($entries as $entry) {
- if (false === $entry->extract($path)) {
- throw new \RuntimeException('Could not extract entry');
- }
- }
- $rarArchive->close();
- }
- }
- <?php
- namespace Composer\Downloader;
- use Composer\Package\PackageInterface;
- use Composer\Util\Svn as SvnUtil;
- class SvnDownloader extends VcsDownloader
- {
- public function doDownload(PackageInterface $package, $path, $url)
- {
- SvnUtil::cleanEnv();
- $ref = $package->getSourceReference();
- $this->io->writeError(" Checking out ".$package->getSourceReference());
- $this->execute($url, "svn co", sprintf("%s/%s", $url, $ref), null, $path);
- }
- public function doUpdate(PackageInterface $initial, PackageInterface $target, $path, $url)
- {
- SvnUtil::cleanEnv();
- $ref = $target->getSourceReference();
- if (!is_dir($path.'/.svn')) {
- throw new \RuntimeException('The .svn directory is missing from '.$path.', see http://getcomposer.org/commit-deps for more information');
- }
- $flags = "";
- if (0 === $this->process->execute('svn --version', $output)) {
- if (preg_match('{(\d+(?:\.\d+)+)}', $output, $match) && version_compare($match[1], '1.7.0', '>=')) {
- $flags .= ' --ignore-ancestry';
- }
- }
- $this->io->writeError(" Checking out " . $ref);
- $this->execute($url, "svn switch" . $flags, sprintf("%s/%s", $url, $ref), $path);
- }
- public function getLocalChanges(PackageInterface $package, $path)
- {
- if (!is_dir($path.'/.svn')) {
- return;
- }
- $this->process->execute('svn status --ignore-externals', $output, $path);
- return preg_match('{^ *[^X ] +}m', $output) ? $output : null;
- }
- protected function execute($baseUrl, $command, $url, $cwd = null, $path = null)
- {
- $util = new SvnUtil($baseUrl, $this->io, $this->config);
- try {
- return $util->execute($command, $url, $cwd, $path, $this->io->isVerbose());
- } catch (\RuntimeException $e) {
- throw new \RuntimeException(
- 'Package could not be downloaded, '.$e->getMessage()
- );
- }
- }
- protected function cleanChanges(PackageInterface $package, $path, $update)
- {
- if (!$changes = $this->getLocalChanges($package, $path)) {
- return;
- }
- if (!$this->io->isInteractive()) {
- if (true === $this->config->get('discard-changes')) {
- return $this->discardChanges($path);
- }
- return parent::cleanChanges($package, $path, $update);
- }
- $changes = array_map(function ($elem) {
- return ' '.$elem;
- }, preg_split('{\s*\r?\n\s*}', $changes));
- $this->io->writeError(' <error>The package has modified files:</error>');
- $this->io->writeError(array_slice($changes, 0, 10));
- if (count($changes) > 10) {
- $this->io->writeError(' <info>'.count($changes) - 10 . ' more files modified, choose "v" to view the full list</info>');
- }
- while (true) {
- switch ($this->io->ask(' <info>Discard changes [y,n,v,?]?</info> ', '?')) {
- case 'y':
- $this->discardChanges($path);
- break 2;
- case 'n':
- throw new \RuntimeException('Update aborted');
- case 'v':
- $this->io->writeError($changes);
- break;
- case '?':
- default:
- $this->io->writeError(array(
- ' y - discard changes and apply the '.($update ? 'update' : 'uninstall'),
- ' n - abort the '.($update ? 'update' : 'uninstall').' and let you manually clean things up',
- ' v - view modified files',
- ' ? - print help',
- ));
- break;
- }
- }
- }
- protected function getCommitLogs($fromReference, $toReference, $path)
- {
- if (preg_match('{.*@(\d+)$}', $fromReference) && preg_match('{.*@(\d+)$}', $toReference) ) {
- $fromRevision = preg_replace('{.*@(\d+)$}', '$1', $fromReference);
- $toRevision = preg_replace('{.*@(\d+)$}', '$1', $toReference);
- $command = sprintf('svn log -r%s:%s --incremental', $fromRevision, $toRevision);
- if (0 !== $this->process->execute($command, $output, $path)) {
- throw new \RuntimeException(
- 'Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput()
- );
- }
- } else {
- $output = "Could not retrieve changes between $fromReference and $toReference due to missing revision information";
- }
- return $output;
- }
- protected function discardChanges($path)
- {
- if (0 !== $this->process->execute('svn revert -R .', $output, $path)) {
- throw new \RuntimeException("Could not reset changes\n\n:".$this->process->getErrorOutput());
- }
- }
- }
- <?php
- namespace Composer\Downloader;
- class TarDownloader extends ArchiveDownloader
- {
- protected function extract($file, $path)
- {
- $archive = new \PharData($file);
- $archive->extractTo($path, null, true);
- }
- }
- <?php
- namespace Composer\Downloader;
- class TransportException extends \RuntimeException
- {
- protected $headers;
- protected $response;
- public function setHeaders($headers)
- {
- $this->headers = $headers;
- }
- public function getHeaders()
- {
- return $this->headers;
- }
- public function setResponse($response)
- {
- $this->response = $response;
- }
- public function getResponse()
- {
- return $this->response;
- }
- }
- <?php
- namespace Composer\Downloader;
- use Composer\Config;
- use Composer\Package\PackageInterface;
- use Composer\Package\Version\VersionParser;
- use Composer\Util\ProcessExecutor;
- use Composer\IO\IOInterface;
- use Composer\Util\Filesystem;
- abstract class VcsDownloader implements DownloaderInterface, ChangeReportInterface
- {
- protected $io;
- protected $config;
- protected $process;
- protected $filesystem;
- public function __construct(IOInterface $io, Config $config, ProcessExecutor $process = null, Filesystem $fs = null)
- {
- $this->io = $io;
- $this->config = $config;
- $this->process = $process ?: new ProcessExecutor($io);
- $this->filesystem = $fs ?: new Filesystem;
- }
- public function getInstallationSource()
- {
- return 'source';
- }
- public function download(PackageInterface $package, $path)
- {
- if (!$package->getSourceReference()) {
- throw new \InvalidArgumentException('Package '.$package->getPrettyName().' is missing reference information');
- }
- $this->io->writeError(" - Installing <info>" . $package->getName() . "</info> (<comment>" . VersionParser::formatVersion($package) . "</comment>)");
- $this->filesystem->emptyDirectory($path);
- $urls = $package->getSourceUrls();
- while ($url = array_shift($urls)) {
- try {
- if (Filesystem::isLocalPath($url)) {
- $url = realpath($url);
- }
- $this->doDownload($package, $path, $url);
- break;
- } catch (\Exception $e) {
- if ($this->io->isDebug()) {
- $this->io->writeError('Failed: ['.get_class($e).'] '.$e->getMessage());
- } elseif (count($urls)) {
- $this->io->writeError(' Failed, trying the next URL');
- }
- if (!count($urls)) {
- throw $e;
- }
- }
- }
- $this->io->writeError('');
- }
- public function update(PackageInterface $initial, PackageInterface $target, $path)
- {
- if (!$target->getSourceReference()) {
- throw new \InvalidArgumentException('Package '.$target->getPrettyName().' is missing reference information');
- }
- $name = $target->getName();
- if ($initial->getPrettyVersion() == $target->getPrettyVersion()) {
- if ($target->getSourceType() === 'svn') {
- $from = $initial->getSourceReference();
- $to = $target->getSourceReference();
- } else {
- $from = substr($initial->getSourceReference(), 0, 7);
- $to = substr($target->getSourceReference(), 0, 7);
- }
- $name .= ' '.$initial->getPrettyVersion();
- } else {
- $from = VersionParser::formatVersion($initial);
- $to = VersionParser::formatVersion($target);
- }
- $this->io->writeError(" - Updating <info>" . $name . "</info> (<comment>" . $from . "</comment> => <comment>" . $to . "</comment>)");
- $this->cleanChanges($initial, $path, true);
- $urls = $target->getSourceUrls();
- while ($url = array_shift($urls)) {
- try {
- if (Filesystem::isLocalPath($url)) {
- $url = realpath($url);
- }
- $this->doUpdate($initial, $target, $path, $url);
- break;
- } catch (\Exception $e) {
- if ($this->io->isDebug()) {
- $this->io->writeError('Failed: ['.get_class($e).'] '.$e->getMessage());
- } elseif (count($urls)) {
- $this->io->writeError(' Failed, trying the next URL');
- } else {
- $this->reapplyChanges($path);
- throw $e;
- }
- }
- }
- $this->reapplyChanges($path);
- if ($this->io->isVerbose()) {
- $message = 'Pulling in changes:';
- $logs = $this->getCommitLogs($initial->getSourceReference(), $target->getSourceReference(), $path);
- if (!trim($logs)) {
- $message = 'Rolling back changes:';
- $logs = $this->getCommitLogs($target->getSourceReference(), $initial->getSourceReference(), $path);
- }
- if (trim($logs)) {
- $logs = implode("\n", array_map(function ($line) {
- return ' ' . $line;
- }, explode("\n", $logs)));
- $this->io->writeError(' '.$message);
- $this->io->writeError($logs);
- }
- }
- $this->io->writeError('');
- }
- public function remove(PackageInterface $package, $path)
- {
- $this->io->writeError(" - Removing <info>" . $package->getName() . "</info> (<comment>" . $package->getPrettyVersion() . "</comment>)");
- $this->cleanChanges($package, $path, false);
- if (!$this->filesystem->removeDirectory($path)) {
- throw new \RuntimeException('Could not completely delete '.$path.', aborting.');
- }
- }
- public function setOutputProgress($outputProgress)
- {
- return $this;
- }
- protected function cleanChanges(PackageInterface $package, $path, $update)
- {
- if (null !== $this->getLocalChanges($package, $path)) {
- throw new \RuntimeException('Source directory ' . $path . ' has uncommitted changes.');
- }
- }
- protected function reapplyChanges($path)
- {
- }
- abstract protected function doDownload(PackageInterface $package, $path, $url);
- abstract protected function doUpdate(PackageInterface $initial, PackageInterface $target, $path, $url);
- abstract protected function getCommitLogs($fromReference, $toReference, $path);
- }
- <?php
- namespace Composer\Downloader;
- use Composer\Config;
- use Composer\Cache;
- use Composer\EventDispatcher\EventDispatcher;
- use Composer\Util\ProcessExecutor;
- use Composer\IO\IOInterface;
- use ZipArchive;
- class ZipDownloader extends ArchiveDownloader
- {
- protected $process;
- public function __construct(IOInterface $io, Config $config, EventDispatcher $eventDispatcher = null, Cache $cache = null, ProcessExecutor $process = null)
- {
- $this->process = $process ?: new ProcessExecutor($io);
- parent::__construct($io, $config, $eventDispatcher, $cache);
- }
- protected function extract($file, $path)
- {
- $processError = null;
- if (!defined('PHP_WINDOWS_VERSION_BUILD')) {
- $command = 'unzip '.ProcessExecutor::escape($file).' -d '.ProcessExecutor::escape($path) . ' && chmod -R u+w ' . ProcessExecutor::escape($path);
- try {
- if (0 === $this->process->execute($command, $ignoredOutput)) {
- return;
- }
- $processError = 'Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput();
- } catch (\Exception $e) {
- $processError = 'Failed to execute ' . $command . "\n\n" . $e->getMessage();
- }
- }
- if (!class_exists('ZipArchive')) {
- $iniPath = php_ini_loaded_file();
- if ($iniPath) {
- $iniMessage = 'The php.ini used by your command-line PHP is: ' . $iniPath;
- } else {
- $iniMessage = 'A php.ini file does not exist. You will have to create one.';
- }
- $error = "Could not decompress the archive, enable the PHP zip extension or install unzip.\n"
- . $iniMessage . "\n" . $processError;
- if (!defined('PHP_WINDOWS_VERSION_BUILD')) {
- $error = "Could not decompress the archive, enable the PHP zip extension.\n" . $iniMessage;
- }
- throw new \RuntimeException($error);
- }
- $zipArchive = new ZipArchive();
- if (true !== ($retval = $zipArchive->open($file))) {
- throw new \UnexpectedValueException($this->getErrorMessage($retval, $file), $retval);
- }
- if (true !== $zipArchive->extractTo($path)) {
- throw new \RuntimeException("There was an error extracting the ZIP file. Corrupt file?");
- }
- $zipArchive->close();
- }
- protected function getErrorMessage($retval, $file)
- {
- switch ($retval) {
- case ZipArchive::ER_EXISTS:
- return sprintf("File '%s' already exists.", $file);
- case ZipArchive::ER_INCONS:
- return sprintf("Zip archive '%s' is inconsistent.", $file);
- case ZipArchive::ER_INVAL:
- return sprintf("Invalid argument (%s)", $file);
- case ZipArchive::ER_MEMORY:
- return sprintf("Malloc failure (%s)", $file);
- case ZipArchive::ER_NOENT:
- return sprintf("No such zip file: '%s'", $file);
- case ZipArchive::ER_NOZIP:
- return sprintf("'%s' is not a zip archive.", $file);
- case ZipArchive::ER_OPEN:
- return sprintf("Can't open zip file: %s", $file);
- case ZipArchive::ER_READ:
- return sprintf("Zip read error (%s)", $file);
- case ZipArchive::ER_SEEK:
- return sprintf("Zip seek error (%s)", $file);
- default:
- return sprintf("'%s' is not a valid zip archive, got error code: %s", $file, $retval);
- }
- }
- }
- <?php
- namespace Composer\EventDispatcher;
- class Event
- {
- protected $name;
- protected $args;
- protected $flags;
- private $propagationStopped = false;
- public function __construct($name, array $args = array(), array $flags = array())
- {
- $this->name = $name;
- $this->args = $args;
- $this->flags = $flags;
- }
- public function getName()
- {
- return $this->name;
- }
- public function getArguments()
- {
- return $this->args;
- }
- public function getFlags()
- {
- return $this->flags;
- }
- public function isPropagationStopped()
- {
- return $this->propagationStopped;
- }
- public function stopPropagation()
- {
- $this->propagationStopped = true;
- }
- }
- <?php
- namespace Composer\EventDispatcher;
- use Composer\DependencyResolver\PolicyInterface;
- use Composer\DependencyResolver\Pool;
- use Composer\DependencyResolver\Request;
- use Composer\Installer\InstallerEvent;
- use Composer\IO\IOInterface;
- use Composer\Composer;
- use Composer\DependencyResolver\Operation\OperationInterface;
- use Composer\Repository\CompositeRepository;
- use Composer\Script;
- use Composer\Script\PackageEvent;
- use Composer\Util\ProcessExecutor;
- class EventDispatcher
- {
- protected $composer;
- protected $io;
- protected $loader;
- protected $process;
- protected $listeners;
- public function __construct(Composer $composer, IOInterface $io, ProcessExecutor $process = null)
- {
- $this->composer = $composer;
- $this->io = $io;
- $this->process = $process ?: new ProcessExecutor($io);
- }
- public function dispatch($eventName, Event $event = null)
- {
- if (null == $event) {
- $event = new Event($eventName);
- }
- return $this->doDispatch($event);
- }
- public function dispatchScript($eventName, $devMode = false, $additionalArgs = array(), $flags = array())
- {
- return $this->doDispatch(new Script\Event($eventName, $this->composer, $this->io, $devMode, $additionalArgs, $flags));
- }
- public function dispatchPackageEvent($eventName, $devMode, PolicyInterface $policy, Pool $pool, CompositeRepository $installedRepo, Request $request, array $operations, OperationInterface $operation)
- {
- return $this->doDispatch(new PackageEvent($eventName, $this->composer, $this->io, $devMode, $policy, $pool, $installedRepo, $request, $operations, $operation));
- }
- public function dispatchInstallerEvent($eventName, $devMode, PolicyInterface $policy, Pool $pool, CompositeRepository $installedRepo, Request $request, array $operations = array())
- {
- return $this->doDispatch(new InstallerEvent($eventName, $this->composer, $this->io, $devMode, $policy, $pool, $installedRepo, $request, $operations));
- }
- protected function doDispatch(Event $event)
- {
- $listeners = $this->getListeners($event);
- $return = 0;
- foreach ($listeners as $callable) {
- if (!is_string($callable) && is_callable($callable)) {
- $event = $this->checkListenerExpectedEvent($callable, $event);
- $return = false === call_user_func($callable, $event) ? 1 : 0;
- } elseif ($this->isPhpScript($callable)) {
- $className = substr($callable, 0, strpos($callable, '::'));
- $methodName = substr($callable, strpos($callable, '::') + 2);
- if (!class_exists($className)) {
- $this->io->writeError('<warning>Class '.$className.' is not autoloadable, can not call '.$event->getName().' script</warning>');
- continue;
- }
- if (!is_callable($callable)) {
- $this->io->writeError('<warning>Method '.$callable.' is not callable, can not call '.$event->getName().' script</warning>');
- continue;
- }
- try {
- $return = false === $this->executeEventPhpScript($className, $methodName, $event) ? 1 : 0;
- } catch (\Exception $e) {
- $message = "Script %s handling the %s event terminated with an exception";
- $this->io->writeError('<error>'.sprintf($message, $callable, $event->getName()).'</error>');
- throw $e;
- }
- } else {
- $args = implode(' ', array_map(array('Composer\Util\ProcessExecutor','escape'), $event->getArguments()));
- if (0 !== ($exitCode = $this->process->execute($callable . ($args === '' ? '' : ' '.$args)))) {
- $this->io->writeError(sprintf('<error>Script %s handling the %s event returned with an error</error>', $callable, $event->getName()));
- throw new \RuntimeException('Error Output: '.$this->process->getErrorOutput(), $exitCode);
- }
- }
- if ($event->isPropagationStopped()) {
- break;
- }
- }
- return $return;
- }
- protected function executeEventPhpScript($className, $methodName, Event $event)
- {
- $event = $this->checkListenerExpectedEvent(array($className, $methodName), $event);
- return $className::$methodName($event);
- }
- protected function checkListenerExpectedEvent($target, Event $event)
- {
- try {
- $reflected = new \ReflectionParameter($target, 0);
- } catch (\Exception $e) {
- return $event;
- }
- $typehint = $reflected->getClass();
- if (!$typehint instanceof \ReflectionClass) {
- return $event;
- }
- $expected = $typehint->getName();
- if (!$event instanceof $expected && $expected === 'Composer\Script\CommandEvent') {
- $event = new \Composer\Script\CommandEvent(
- $event->getName(), $event->getComposer(), $event->getIO(), $event->isDevMode(), $event->getArguments()
- );
- }
- if (!$event instanceof $expected && $expected === 'Composer\Script\PackageEvent') {
- $event = new \Composer\Script\PackageEvent(
- $event->getName(), $event->getComposer(), $event->getIO(), $event->isDevMode(),
- $event->getPolicy(), $event->getPool(), $event->getInstalledRepo(), $event->getRequest(),
- $event->getOperations(), $event->getOperation()
- );
- }
- if (!$event instanceof $expected && $expected === 'Composer\Script\Event') {
- $event = new \Composer\Script\Event(
- $event->getName(), $event->getComposer(), $event->getIO(), $event->isDevMode(),
- $event->getArguments(), $event->getFlags()
- );
- }
- return $event;
- }
- protected function addListener($eventName, $listener, $priority = 0)
- {
- $this->listeners[$eventName][$priority][] = $listener;
- }
- public function addSubscriber(EventSubscriberInterface $subscriber)
- {
- foreach ($subscriber->getSubscribedEvents() as $eventName => $params) {
- if (is_string($params)) {
- $this->addListener($eventName, array($subscriber, $params));
- } elseif (is_string($params[0])) {
- $this->addListener($eventName, array($subscriber, $params[0]), isset($params[1]) ? $params[1] : 0);
- } else {
- foreach ($params as $listener) {
- $this->addListener($eventName, array($subscriber, $listener[0]), isset($listener[1]) ? $listener[1] : 0);
- }
- }
- }
- }
- protected function getListeners(Event $event)
- {
- $scriptListeners = $this->getScriptListeners($event);
- if (!isset($this->listeners[$event->getName()][0])) {
- $this->listeners[$event->getName()][0] = array();
- }
- krsort($this->listeners[$event->getName()]);
- $listeners = $this->listeners;
- $listeners[$event->getName()][0] = array_merge($listeners[$event->getName()][0], $scriptListeners);
- return call_user_func_array('array_merge', $listeners[$event->getName()]);
- }
- public function hasEventListeners(Event $event)
- {
- $listeners = $this->getListeners($event);
- return count($listeners) > 0;
- }
- protected function getScriptListeners(Event $event)
- {
- $package = $this->composer->getPackage();
- $scripts = $package->getScripts();
- if (empty($scripts[$event->getName()])) {
- return array();
- }
- if ($this->loader) {
- $this->loader->unregister();
- }
- $generator = $this->composer->getAutoloadGenerator();
- $packages = $this->composer->getRepositoryManager()->getLocalRepository()->getCanonicalPackages();
- $packageMap = $generator->buildPackageMap($this->composer->getInstallationManager(), $package, $packages);
- $map = $generator->parseAutoloads($packageMap, $package);
- $this->loader = $generator->createLoader($map);
- $this->loader->register();
- return $scripts[$event->getName()];
- }
- protected function isPhpScript($callable)
- {
- return false === strpos($callable, ' ') && false !== strpos($callable, '::');
- }
- }
- <?php
- namespace Composer\EventDispatcher;
- interface EventSubscriberInterface
- {
- public static function getSubscribedEvents();
- }
- <?php
- namespace Composer;
- use Composer\Config\JsonConfigSource;
- use Composer\Json\JsonFile;
- use Composer\IO\IOInterface;
- use Composer\Package\Archiver;
- use Composer\Repository\RepositoryManager;
- use Composer\Repository\WritableRepositoryInterface;
- use Composer\Util\ProcessExecutor;
- use Composer\Util\RemoteFilesystem;
- use Symfony\Component\Console\Formatter\OutputFormatterStyle;
- use Composer\EventDispatcher\EventDispatcher;
- use Composer\Autoload\AutoloadGenerator;
- use Composer\Package\Version\VersionParser;
- class Factory
- {
- protected static function getHomeDir()
- {
- $home = getenv('COMPOSER_HOME');
- if (!$home) {
- if (defined('PHP_WINDOWS_VERSION_MAJOR')) {
- if (!getenv('APPDATA')) {
- throw new \RuntimeException('The APPDATA or COMPOSER_HOME environment variable must be set for composer to run correctly');
- }
- $home = strtr(getenv('APPDATA'), '\\', '/') . '/Composer';
- } else {
- if (!getenv('HOME')) {
- throw new \RuntimeException('The HOME or COMPOSER_HOME environment variable must be set for composer to run correctly');
- }
- $home = rtrim(getenv('HOME'), '/') . '/.composer';
- }
- }
- return $home;
- }
- protected static function getCacheDir($home)
- {
- $cacheDir = getenv('COMPOSER_CACHE_DIR');
- if (!$cacheDir) {
- if (defined('PHP_WINDOWS_VERSION_MAJOR')) {
- if ($cacheDir = getenv('LOCALAPPDATA')) {
- $cacheDir .= '/Composer';
- } else {
- $cacheDir = $home . '/cache';
- }
- $cacheDir = strtr($cacheDir, '\\', '/');
- } else {
- $cacheDir = $home.'/cache';
- }
- }
- return $cacheDir;
- }
- public static function createConfig(IOInterface $io = null, $cwd = null)
- {
- $cwd = $cwd ?: getcwd();
- $home = self::getHomeDir();
- $cacheDir = self::getCacheDir($home);
-
-
- foreach (array($home, $cacheDir) as $dir) {
- if (!file_exists($dir . '/.htaccess')) {
- if (!is_dir($dir)) {
- @mkdir($dir, 0777, true);
- }
- @file_put_contents($dir . '/.htaccess', 'Deny from all');
- }
- }
- $config = new Config(true, $cwd);
- $config->merge(array('config' => array('home' => $home, 'cache-dir' => $cacheDir)));
- $file = new JsonFile($home.'/config.json');
- if ($file->exists()) {
- if ($io && $io->isDebug()) {
- $io->writeError('Loading config file ' . $file->getPath());
- }
- $config->merge($file->read());
- }
- $config->setConfigSource(new JsonConfigSource($file));
- $file = new JsonFile($config->get('home').'/auth.json');
- if ($file->exists()) {
- if ($io && $io->isDebug()) {
- $io->writeError('Loading config file ' . $file->getPath());
- }
- $config->merge(array('config' => $file->read()));
- }
- $config->setAuthConfigSource(new JsonConfigSource($file, true));
- return $config;
- }
- public static function getComposerFile()
- {
- return trim(getenv('COMPOSER')) ?: './composer.json';
- }
- public static function createAdditionalStyles()
- {
- return array(
- 'highlight' => new OutputFormatterStyle('red'),
- 'warning' => new OutputFormatterStyle('black', 'yellow'),
- );
- }
- public static function createDefaultRepositories(IOInterface $io = null, Config $config = null, RepositoryManager $rm = null)
- {
- $repos = array();
- if (!$config) {
- $config = static::createConfig($io);
- }
- if (!$rm) {
- if (!$io) {
- throw new \InvalidArgumentException('This function requires either an IOInterface or a RepositoryManager');
- }
- $factory = new static;
- $rm = $factory->createRepositoryManager($io, $config);
- }
- foreach ($config->getRepositories() as $index => $repo) {
- if (is_string($repo)) {
- throw new \UnexpectedValueException('"repositories" should be an array of repository definitions, only a single repository was given');
- }
- if (!is_array($repo)) {
- throw new \UnexpectedValueException('Repository "'.$index.'" ('.json_encode($repo).') should be an array, '.gettype($repo).' given');
- }
- if (!isset($repo['type'])) {
- throw new \UnexpectedValueException('Repository "'.$index.'" ('.json_encode($repo).') must have a type defined');
- }
- $name = is_int($index) && isset($repo['url']) ? preg_replace('{^https?://}i', '', $repo['url']) : $index;
- while (isset($repos[$name])) {
- $name .= '2';
- }
- $repos[$name] = $rm->createRepository($repo['type'], $repo);
- }
- return $repos;
- }
- public function createComposer(IOInterface $io, $localConfig = null, $disablePlugins = false, $cwd = null, $fullLoad = true)
- {
- $cwd = $cwd ?: getcwd();
- if (null === $localConfig) {
- $localConfig = static::getComposerFile();
- }
- if (is_string($localConfig)) {
- $composerFile = $localConfig;
- $file = new JsonFile($localConfig, new RemoteFilesystem($io));
- if (!$file->exists()) {
- if ($localConfig === './composer.json' || $localConfig === 'composer.json') {
- $message = 'Composer could not find a composer.json file in '.$cwd;
- } else {
- $message = 'Composer could not find the config file: '.$localConfig;
- }
- $instructions = 'To initialize a project, please create a composer.json file as described in the http://getcomposer.org/ "Getting Started" section';
- throw new \InvalidArgumentException($message.PHP_EOL.$instructions);
- }
- $file->validateSchema(JsonFile::LAX_SCHEMA);
- $localConfig = $file->read();
- }
- $config = static::createConfig($io, $cwd);
- $config->merge($localConfig);
- if (isset($composerFile)) {
- if ($io && $io->isDebug()) {
- $io->writeError('Loading config file ' . $composerFile);
- }
- $localAuthFile = new JsonFile(dirname(realpath($composerFile)) . '/auth.json');
- if ($localAuthFile->exists()) {
- if ($io && $io->isDebug()) {
- $io->writeError('Loading config file ' . $localAuthFile->getPath());
- }
- $config->merge(array('config' => $localAuthFile->read()));
- $config->setAuthConfigSource(new JsonConfigSource($localAuthFile, true));
- }
- }
- $vendorDir = $config->get('vendor-dir');
- $binDir = $config->get('bin-dir');
- $composer = new Composer();
- $composer->setConfig($config);
- if ($fullLoad) {
- $io->loadConfiguration($config);
- ProcessExecutor::setTimeout((int) $config->get('process-timeout'));
- }
- $dispatcher = new EventDispatcher($composer, $io);
- $composer->setEventDispatcher($dispatcher);
- $rm = $this->createRepositoryManager($io, $config, $dispatcher);
- $composer->setRepositoryManager($rm);
- $this->addLocalRepository($rm, $vendorDir);
- $parser = new VersionParser;
- $loader = new Package\Loader\RootPackageLoader($rm, $config, $parser, new ProcessExecutor($io));
- $package = $loader->load($localConfig);
- $composer->setPackage($package);
- $im = $this->createInstallationManager();
- $composer->setInstallationManager($im);
- if ($fullLoad) {
- $dm = $this->createDownloadManager($io, $config, $dispatcher);
- $composer->setDownloadManager($dm);
- $generator = new AutoloadGenerator($dispatcher, $io);
- $composer->setAutoloadGenerator($generator);
- }
- $this->createDefaultInstallers($im, $composer, $io);
- if ($fullLoad) {
- $globalComposer = $this->createGlobalComposer($io, $config, $disablePlugins);
- $pm = $this->createPluginManager($io, $composer, $globalComposer);
- $composer->setPluginManager($pm);
- if (!$disablePlugins) {
- $pm->loadInstalledPlugins();
- }
-
- if ($rm->getLocalRepository()) {
- $this->purgePackages($rm->getLocalRepository(), $im);
- }
- }
- if ($fullLoad && isset($composerFile)) {
- $lockFile = "json" === pathinfo($composerFile, PATHINFO_EXTENSION)
- ? substr($composerFile, 0, -4).'lock'
- : $composerFile . '.lock';
- $locker = new Package\Locker($io, new JsonFile($lockFile, new RemoteFilesystem($io, $config)), $rm, $im, md5_file($composerFile));
- $composer->setLocker($locker);
- }
- return $composer;
- }
- protected function createRepositoryManager(IOInterface $io, Config $config, EventDispatcher $eventDispatcher = null)
- {
- $rm = new RepositoryManager($io, $config, $eventDispatcher);
- $rm->setRepositoryClass('composer', 'Composer\Repository\ComposerRepository');
- $rm->setRepositoryClass('vcs', 'Composer\Repository\VcsRepository');
- $rm->setRepositoryClass('package', 'Composer\Repository\PackageRepository');
- $rm->setRepositoryClass('pear', 'Composer\Repository\PearRepository');
- $rm->setRepositoryClass('git', 'Composer\Repository\VcsRepository');
- $rm->setRepositoryClass('gitlab', 'Composer\Repository\VcsRepository');
- $rm->setRepositoryClass('svn', 'Composer\Repository\VcsRepository');
- $rm->setRepositoryClass('perforce', 'Composer\Repository\VcsRepository');
- $rm->setRepositoryClass('hg', 'Composer\Repository\VcsRepository');
- $rm->setRepositoryClass('artifact', 'Composer\Repository\ArtifactRepository');
- return $rm;
- }
- protected function addLocalRepository(RepositoryManager $rm, $vendorDir)
- {
- $rm->setLocalRepository(new Repository\InstalledFilesystemRepository(new JsonFile($vendorDir.'/composer/installed.json')));
- }
- protected function createGlobalComposer(IOInterface $io, Config $config, $disablePlugins)
- {
- if (realpath($config->get('home')) === getcwd()) {
- return;
- }
- $composer = null;
- try {
- $composer = self::createComposer($io, $config->get('home') . '/composer.json', $disablePlugins, $config->get('home'), false);
- } catch (\Exception $e) {
- if ($io->isDebug()) {
- $io->writeError('Failed to initialize global composer: '.$e->getMessage());
- }
- }
- return $composer;
- }
- public function createDownloadManager(IOInterface $io, Config $config, EventDispatcher $eventDispatcher = null)
- {
- $cache = null;
- if ($config->get('cache-files-ttl') > 0) {
- $cache = new Cache($io, $config->get('cache-files-dir'), 'a-z0-9_./');
- }
- $dm = new Downloader\DownloadManager($io);
- switch ($config->get('preferred-install')) {
- case 'dist':
- $dm->setPreferDist(true);
- break;
- case 'source':
- $dm->setPreferSource(true);
- break;
- case 'auto':
- default:
- break;
- }
- $dm->setDownloader('git', new Downloader\GitDownloader($io, $config));
- $dm->setDownloader('svn', new Downloader\SvnDownloader($io, $config));
- $dm->setDownloader('hg', new Downloader\HgDownloader($io, $config));
- $dm->setDownloader('perforce', new Downloader\PerforceDownloader($io, $config));
- $dm->setDownloader('zip', new Downloader\ZipDownloader($io, $config, $eventDispatcher, $cache));
- $dm->setDownloader('rar', new Downloader\RarDownloader($io, $config, $eventDispatcher, $cache));
- $dm->setDownloader('tar', new Downloader\TarDownloader($io, $config, $eventDispatcher, $cache));
- $dm->setDownloader('gzip', new Downloader\GzipDownloader($io, $config, $eventDispatcher, $cache));
- $dm->setDownloader('phar', new Downloader\PharDownloader($io, $config, $eventDispatcher, $cache));
- $dm->setDownloader('file', new Downloader\FileDownloader($io, $config, $eventDispatcher, $cache));
- return $dm;
- }
- public function createArchiveManager(Config $config, Downloader\DownloadManager $dm = null)
- {
- if (null === $dm) {
- $io = new IO\NullIO();
- $io->loadConfiguration($config);
- $dm = $this->createDownloadManager($io, $config);
- }
- $am = new Archiver\ArchiveManager($dm);
- $am->addArchiver(new Archiver\PharArchiver);
- return $am;
- }
- protected function createPluginManager(IOInterface $io, Composer $composer, Composer $globalComposer = null)
- {
- return new Plugin\PluginManager($io, $composer, $globalComposer);
- }
- protected function createInstallationManager()
- {
- return new Installer\InstallationManager();
- }
- protected function createDefaultInstallers(Installer\InstallationManager $im, Composer $composer, IOInterface $io)
- {
- $im->addInstaller(new Installer\LibraryInstaller($io, $composer, null));
- $im->addInstaller(new Installer\PearInstaller($io, $composer, 'pear-library'));
- $im->addInstaller(new Installer\PluginInstaller($io, $composer));
- $im->addInstaller(new Installer\MetapackageInstaller($io));
- }
- protected function purgePackages(WritableRepositoryInterface $repo, Installer\InstallationManager $im)
- {
- foreach ($repo->getPackages() as $package) {
- if (!$im->isPackageInstalled($repo, $package)) {
- $repo->removePackage($package);
- }
- }
- }
- public static function create(IOInterface $io, $config = null, $disablePlugins = false)
- {
- $factory = new static();
- return $factory->createComposer($io, $config, $disablePlugins);
- }
- }
- <?php
- namespace Composer\Installer;
- use Composer\Package\PackageInterface;
- use Composer\Package\AliasPackage;
- use Composer\Repository\RepositoryInterface;
- use Composer\Repository\InstalledRepositoryInterface;
- use Composer\DependencyResolver\Operation\OperationInterface;
- use Composer\DependencyResolver\Operation\InstallOperation;
- use Composer\DependencyResolver\Operation\UpdateOperation;
- use Composer\DependencyResolver\Operation\UninstallOperation;
- use Composer\DependencyResolver\Operation\MarkAliasInstalledOperation;
- use Composer\DependencyResolver\Operation\MarkAliasUninstalledOperation;
- use Composer\Util\StreamContextFactory;
- class InstallationManager
- {
- private $installers = array();
- private $cache = array();
- private $notifiablePackages = array();
- public function reset()
- {
- $this->notifiablePackages = array();
- }
- public function addInstaller(InstallerInterface $installer)
- {
- array_unshift($this->installers, $installer);
- $this->cache = array();
- }
- public function removeInstaller(InstallerInterface $installer)
- {
- if (false !== ($key = array_search($installer, $this->installers, true))) {
- array_splice($this->installers, $key, 1);
- $this->cache = array();
- }
- }
- public function disablePlugins()
- {
- foreach ($this->installers as $i => $installer) {
- if (!$installer instanceof PluginInstaller) {
- continue;
- }
- unset($this->installers[$i]);
- }
- }
- public function getInstaller($type)
- {
- $type = strtolower($type);
- if (isset($this->cache[$type])) {
- return $this->cache[$type];
- }
- foreach ($this->installers as $installer) {
- if ($installer->supports($type)) {
- return $this->cache[$type] = $installer;
- }
- }
- throw new \InvalidArgumentException('Unknown installer type: '.$type);
- }
- public function isPackageInstalled(InstalledRepositoryInterface $repo, PackageInterface $package)
- {
- if ($package instanceof AliasPackage) {
- return $repo->hasPackage($package) && $this->isPackageInstalled($repo, $package->getAliasOf());
- }
- return $this->getInstaller($package->getType())->isInstalled($repo, $package);
- }
- public function execute(RepositoryInterface $repo, OperationInterface $operation)
- {
- $method = $operation->getJobType();
- $this->$method($repo, $operation);
- }
- public function install(RepositoryInterface $repo, InstallOperation $operation)
- {
- $package = $operation->getPackage();
- $installer = $this->getInstaller($package->getType());
- $installer->install($repo, $package);
- $this->markForNotification($package);
- }
- public function update(RepositoryInterface $repo, UpdateOperation $operation)
- {
- $initial = $operation->getInitialPackage();
- $target = $operation->getTargetPackage();
- $initialType = $initial->getType();
- $targetType = $target->getType();
- if ($initialType === $targetType) {
- $installer = $this->getInstaller($initialType);
- $installer->update($repo, $initial, $target);
- $this->markForNotification($target);
- } else {
- $this->getInstaller($initialType)->uninstall($repo, $initial);
- $this->getInstaller($targetType)->install($repo, $target);
- }
- }
- public function uninstall(RepositoryInterface $repo, UninstallOperation $operation)
- {
- $package = $operation->getPackage();
- $installer = $this->getInstaller($package->getType());
- $installer->uninstall($repo, $package);
- }
- public function markAliasInstalled(RepositoryInterface $repo, MarkAliasInstalledOperation $operation)
- {
- $package = $operation->getPackage();
- if (!$repo->hasPackage($package)) {
- $repo->addPackage(clone $package);
- }
- }
- public function markAliasUninstalled(RepositoryInterface $repo, MarkAliasUninstalledOperation $operation)
- {
- $package = $operation->getPackage();
- $repo->removePackage($package);
- }
- public function getInstallPath(PackageInterface $package)
- {
- $installer = $this->getInstaller($package->getType());
- return $installer->getInstallPath($package);
- }
- public function notifyInstalls()
- {
- foreach ($this->notifiablePackages as $repoUrl => $packages) {
- if (strpos($repoUrl, '%package%')) {
- foreach ($packages as $package) {
- $url = str_replace('%package%', $package->getPrettyName(), $repoUrl);
- $params = array(
- 'version' => $package->getPrettyVersion(),
- 'version_normalized' => $package->getVersion(),
- );
- $opts = array('http' =>
- array(
- 'method' => 'POST',
- 'header' => array('Content-type: application/x-www-form-urlencoded'),
- 'content' => http_build_query($params, '', '&'),
- 'timeout' => 3,
- )
- );
- $context = StreamContextFactory::getContext($url, $opts);
- @file_get_contents($url, false, $context);
- }
- continue;
- }
- $postData = array('downloads' => array());
- foreach ($packages as $package) {
- $postData['downloads'][] = array(
- 'name' => $package->getPrettyName(),
- 'version' => $package->getVersion(),
- );
- }
- $opts = array('http' =>
- array(
- 'method' => 'POST',
- 'header' => array('Content-Type: application/json'),
- 'content' => json_encode($postData),
- 'timeout' => 6,
- )
- );
- $context = StreamContextFactory::getContext($repoUrl, $opts);
- @file_get_contents($repoUrl, false, $context);
- }
- $this->reset();
- }
- private function markForNotification(PackageInterface $package)
- {
- if ($package->getNotificationUrl()) {
- $this->notifiablePackages[$package->getNotificationUrl()][$package->getName()] = $package;
- }
- }
- }
- <?php
- namespace Composer\Installer;
- use Composer\Composer;
- use Composer\DependencyResolver\PolicyInterface;
- use Composer\DependencyResolver\Operation\OperationInterface;
- use Composer\DependencyResolver\Pool;
- use Composer\DependencyResolver\Request;
- use Composer\EventDispatcher\Event;
- use Composer\IO\IOInterface;
- use Composer\Repository\CompositeRepository;
- class InstallerEvent extends Event
- {
- private $composer;
- private $io;
- private $devMode;
- private $policy;
- private $pool;
- private $installedRepo;
- private $request;
- private $operations;
- public function __construct($eventName, Composer $composer, IOInterface $io, $devMode, PolicyInterface $policy, Pool $pool, CompositeRepository $installedRepo, Request $request, array $operations = array())
- {
- parent::__construct($eventName);
- $this->composer = $composer;
- $this->io = $io;
- $this->devMode = $devMode;
- $this->policy = $policy;
- $this->pool = $pool;
- $this->installedRepo = $installedRepo;
- $this->request = $request;
- $this->operations = $operations;
- }
- public function getComposer()
- {
- return $this->composer;
- }
- public function getIO()
- {
- return $this->io;
- }
- public function isDevMode()
- {
- return $this->devMode;
- }
- public function getPolicy()
- {
- return $this->policy;
- }
- public function getPool()
- {
- return $this->pool;
- }
- public function getInstalledRepo()
- {
- return $this->installedRepo;
- }
- public function getRequest()
- {
- return $this->request;
- }
- public function getOperations()
- {
- return $this->operations;
- }
- }
- <?php
- namespace Composer\Installer;
- class InstallerEvents
- {
- const PRE_DEPENDENCIES_SOLVING = 'pre-dependencies-solving';
- const POST_DEPENDENCIES_SOLVING = 'post-dependencies-solving';
- }
- <?php
- namespace Composer\Installer;
- use Composer\Package\PackageInterface;
- use Composer\Repository\InstalledRepositoryInterface;
- interface InstallerInterface
- {
- public function supports($packageType);
- public function isInstalled(InstalledRepositoryInterface $repo, PackageInterface $package);
- public function install(InstalledRepositoryInterface $repo, PackageInterface $package);
- public function update(InstalledRepositoryInterface $repo, PackageInterface $initial, PackageInterface $target);
- public function uninstall(InstalledRepositoryInterface $repo, PackageInterface $package);
- public function getInstallPath(PackageInterface $package);
- }
- <?php
- namespace Composer\Installer;
- use Composer\Composer;
- use Composer\IO\IOInterface;
- use Composer\Repository\InstalledRepositoryInterface;
- use Composer\Package\PackageInterface;
- use Composer\Util\Filesystem;
- use Composer\Util\ProcessExecutor;
- class LibraryInstaller implements InstallerInterface
- {
- protected $composer;
- protected $vendorDir;
- protected $binDir;
- protected $downloadManager;
- protected $io;
- protected $type;
- protected $filesystem;
- public function __construct(IOInterface $io, Composer $composer, $type = 'library', Filesystem $filesystem = null)
- {
- $this->composer = $composer;
- $this->downloadManager = $composer->getDownloadManager();
- $this->io = $io;
- $this->type = $type;
- $this->filesystem = $filesystem ?: new Filesystem();
- $this->vendorDir = rtrim($composer->getConfig()->get('vendor-dir'), '/');
- $this->binDir = rtrim($composer->getConfig()->get('bin-dir'), '/');
- }
- public function supports($packageType)
- {
- return $packageType === $this->type || null === $this->type;
- }
- public function isInstalled(InstalledRepositoryInterface $repo, PackageInterface $package)
- {
- return $repo->hasPackage($package) && is_readable($this->getInstallPath($package));
- }
- public function install(InstalledRepositoryInterface $repo, PackageInterface $package)
- {
- $this->initializeVendorDir();
- $downloadPath = $this->getInstallPath($package);
- if (!is_readable($downloadPath) && $repo->hasPackage($package)) {
- $this->removeBinaries($package);
- }
- $this->installCode($package);
- $this->installBinaries($package);
- if (!$repo->hasPackage($package)) {
- $repo->addPackage(clone $package);
- }
- }
- public function update(InstalledRepositoryInterface $repo, PackageInterface $initial, PackageInterface $target)
- {
- if (!$repo->hasPackage($initial)) {
- throw new \InvalidArgumentException('Package is not installed: '.$initial);
- }
- $this->initializeVendorDir();
- $this->removeBinaries($initial);
- $this->updateCode($initial, $target);
- $this->installBinaries($target);
- $repo->removePackage($initial);
- if (!$repo->hasPackage($target)) {
- $repo->addPackage(clone $target);
- }
- }
- public function uninstall(InstalledRepositoryInterface $repo, PackageInterface $package)
- {
- if (!$repo->hasPackage($package)) {
- throw new \InvalidArgumentException('Package is not installed: '.$package);
- }
- $this->removeCode($package);
- $this->removeBinaries($package);
- $repo->removePackage($package);
- $downloadPath = $this->getPackageBasePath($package);
- if (strpos($package->getName(), '/')) {
- $packageVendorDir = dirname($downloadPath);
- if (is_dir($packageVendorDir) && $this->filesystem->isDirEmpty($packageVendorDir)) {
- @rmdir($packageVendorDir);
- }
- }
- }
- public function getInstallPath(PackageInterface $package)
- {
- $targetDir = $package->getTargetDir();
- return $this->getPackageBasePath($package) . ($targetDir ? '/'.$targetDir : '');
- }
- protected function getPackageBasePath(PackageInterface $package)
- {
- $this->initializeVendorDir();
- return ($this->vendorDir ? $this->vendorDir.'/' : '') . $package->getPrettyName();
- }
- protected function installCode(PackageInterface $package)
- {
- $downloadPath = $this->getInstallPath($package);
- $this->downloadManager->download($package, $downloadPath);
- }
- protected function updateCode(PackageInterface $initial, PackageInterface $target)
- {
- $initialDownloadPath = $this->getInstallPath($initial);
- $targetDownloadPath = $this->getInstallPath($target);
- if ($targetDownloadPath !== $initialDownloadPath) {
-
- if (substr($initialDownloadPath, 0, strlen($targetDownloadPath)) === $targetDownloadPath
- || substr($targetDownloadPath, 0, strlen($initialDownloadPath)) === $initialDownloadPath
- ) {
- $this->removeCode($initial);
- $this->installCode($target);
- return;
- }
- $this->filesystem->rename($initialDownloadPath, $targetDownloadPath);
- }
- $this->downloadManager->update($initial, $target, $targetDownloadPath);
- }
- protected function removeCode(PackageInterface $package)
- {
- $downloadPath = $this->getPackageBasePath($package);
- $this->downloadManager->remove($package, $downloadPath);
- }
- protected function getBinaries(PackageInterface $package)
- {
- return $package->getBinaries();
- }
- protected function installBinaries(PackageInterface $package)
- {
- $binaries = $this->getBinaries($package);
- if (!$binaries) {
- return;
- }
- foreach ($binaries as $bin) {
- $binPath = $this->getInstallPath($package).'/'.$bin;
- if (!file_exists($binPath)) {
- $this->io->writeError(' <warning>Skipped installation of bin '.$bin.' for package '.$package->getName().': file not found in package</warning>');
- continue;
- }
-
-
-
- $binPath = realpath($binPath);
- $this->initializeBinDir();
- $link = $this->binDir.'/'.basename($bin);
- if (file_exists($link)) {
- if (is_link($link)) {
-
-
- @chmod($link, 0777 & ~umask());
- }
- $this->io->writeError(' Skipped installation of bin '.$bin.' for package '.$package->getName().': name conflicts with an existing file');
- continue;
- }
- if (defined('PHP_WINDOWS_VERSION_BUILD')) {
- if ('.bat' !== substr($binPath, -4)) {
- file_put_contents($link, $this->generateUnixyProxyCode($binPath, $link));
- @chmod($link, 0777 & ~umask());
- $link .= '.bat';
- if (file_exists($link)) {
- $this->io->writeError(' Skipped installation of bin '.$bin.'.bat proxy for package '.$package->getName().': a .bat proxy was already installed');
- }
- }
- if (!file_exists($link)) {
- file_put_contents($link, $this->generateWindowsProxyCode($binPath, $link));
- }
- } else {
- $cwd = getcwd();
- try {
-
- $relativeBin = $this->filesystem->findShortestPath($link, $binPath);
- chdir(dirname($link));
- if (false === symlink($relativeBin, $link)) {
- throw new \ErrorException();
- }
- } catch (\ErrorException $e) {
- file_put_contents($link, $this->generateUnixyProxyCode($binPath, $link));
- }
- chdir($cwd);
- }
- @chmod($link, 0777 & ~umask());
- }
- }
- protected function removeBinaries(PackageInterface $package)
- {
- $binaries = $this->getBinaries($package);
- if (!$binaries) {
- return;
- }
- foreach ($binaries as $bin) {
- $link = $this->binDir.'/'.basename($bin);
- if (is_link($link) || file_exists($link)) {
- $this->filesystem->unlink($link);
- }
- if (file_exists($link.'.bat')) {
- $this->filesystem->unlink($link.'.bat');
- }
- }
- }
- protected function initializeVendorDir()
- {
- $this->filesystem->ensureDirectoryExists($this->vendorDir);
- $this->vendorDir = realpath($this->vendorDir);
- }
- protected function initializeBinDir()
- {
- $this->filesystem->ensureDirectoryExists($this->binDir);
- $this->binDir = realpath($this->binDir);
- }
- protected function generateWindowsProxyCode($bin, $link)
- {
- $binPath = $this->filesystem->findShortestPath($link, $bin);
- if ('.bat' === substr($bin, -4) || '.exe' === substr($bin, -4)) {
- $caller = 'call';
- } else {
- $handle = fopen($bin, 'r');
- $line = fgets($handle);
- fclose($handle);
- if (preg_match('{^#!/(?:usr/bin/env )?(?:[^/]+/)*(.+)$}m', $line, $match)) {
- $caller = trim($match[1]);
- } else {
- $caller = 'php';
- }
- }
- return "@ECHO OFF\r\n".
- "SET BIN_TARGET=%~dp0/".trim(ProcessExecutor::escape($binPath), '"')."\r\n".
- "{$caller} \"%BIN_TARGET%\" %*\r\n";
- }
- protected function generateUnixyProxyCode($bin, $link)
- {
- $binPath = $this->filesystem->findShortestPath($link, $bin);
- return "#!/usr/bin/env sh\n".
- 'SRC_DIR="`pwd`"'."\n".
- 'cd "`dirname "$0"`"'."\n".
- 'cd '.ProcessExecutor::escape(dirname($binPath))."\n".
- 'BIN_TARGET="`pwd`/'.basename($binPath)."\"\n".
- 'cd "$SRC_DIR"'."\n".
- '"$BIN_TARGET" "$@"'."\n";
- }
- }
- <?php
- namespace Composer\Installer;
- use Composer\Repository\InstalledRepositoryInterface;
- use Composer\Package\PackageInterface;
- class MetapackageInstaller implements InstallerInterface
- {
- public function supports($packageType)
- {
- return $packageType === 'metapackage';
- }
- public function isInstalled(InstalledRepositoryInterface $repo, PackageInterface $package)
- {
- return $repo->hasPackage($package);
- }
- public function install(InstalledRepositoryInterface $repo, PackageInterface $package)
- {
- $repo->addPackage(clone $package);
- }
- public function update(InstalledRepositoryInterface $repo, PackageInterface $initial, PackageInterface $target)
- {
- if (!$repo->hasPackage($initial)) {
- throw new \InvalidArgumentException('Package is not installed: '.$initial);
- }
- $repo->removePackage($initial);
- $repo->addPackage(clone $target);
- }
- public function uninstall(InstalledRepositoryInterface $repo, PackageInterface $package)
- {
- if (!$repo->hasPackage($package)) {
- throw new \InvalidArgumentException('Package is not installed: '.$package);
- }
- $repo->removePackage($package);
- }
- public function getInstallPath(PackageInterface $package)
- {
- return '';
- }
- }
- <?php
- namespace Composer\Installer;
- use Composer\Repository\InstalledRepositoryInterface;
- use Composer\Package\PackageInterface;
- class NoopInstaller implements InstallerInterface
- {
- public function supports($packageType)
- {
- return true;
- }
- public function isInstalled(InstalledRepositoryInterface $repo, PackageInterface $package)
- {
- return $repo->hasPackage($package);
- }
- public function install(InstalledRepositoryInterface $repo, PackageInterface $package)
- {
- if (!$repo->hasPackage($package)) {
- $repo->addPackage(clone $package);
- }
- }
- public function update(InstalledRepositoryInterface $repo, PackageInterface $initial, PackageInterface $target)
- {
- if (!$repo->hasPackage($initial)) {
- throw new \InvalidArgumentException('Package is not installed: '.$initial);
- }
- $repo->removePackage($initial);
- if (!$repo->hasPackage($target)) {
- $repo->addPackage(clone $target);
- }
- }
- public function uninstall(InstalledRepositoryInterface $repo, PackageInterface $package)
- {
- if (!$repo->hasPackage($package)) {
- throw new \InvalidArgumentException('Package is not installed: '.$package);
- }
- $repo->removePackage($package);
- }
- public function getInstallPath(PackageInterface $package)
- {
- $targetDir = $package->getTargetDir();
- return $package->getPrettyName() . ($targetDir ? '/'.$targetDir : '');
- }
- }
- <?php
- namespace Composer\Installer;
- use Composer\Composer;
- use Composer\IO\IOInterface;
- use Composer\DependencyResolver\Operation\OperationInterface;
- use Composer\DependencyResolver\PolicyInterface;
- use Composer\DependencyResolver\Pool;
- use Composer\DependencyResolver\Request;
- use Composer\EventDispatcher\Event;
- use Composer\Repository\CompositeRepository;
- class PackageEvent extends InstallerEvent
- {
- private $operation;
- public function __construct($eventName, Composer $composer, IOInterface $io, $devMode, PolicyInterface $policy, Pool $pool, CompositeRepository $installedRepo, Request $request, array $operations, OperationInterface $operation)
- {
- parent::__construct($eventName, $composer, $io, $devMode, $policy, $pool, $installedRepo, $request, $operations);
- $this->operation = $operation;
- }
- public function getOperation()
- {
- return $this->operation;
- }
- }
- <?php
- namespace Composer\Installer;
- class PackageEvents
- {
- const PRE_PACKAGE_INSTALL = 'pre-package-install';
- const POST_PACKAGE_INSTALL = 'post-package-install';
- const PRE_PACKAGE_UPDATE = 'pre-package-update';
- const POST_PACKAGE_UPDATE = 'post-package-update';
- const PRE_PACKAGE_UNINSTALL = 'pre-package-uninstall';
- const POST_PACKAGE_UNINSTALL = 'post-package-uninstall';
- }
- <?php
- namespace Composer\Installer;
- use Composer\IO\IOInterface;
- use Composer\Composer;
- use Composer\Downloader\PearPackageExtractor;
- use Composer\Repository\InstalledRepositoryInterface;
- use Composer\Package\PackageInterface;
- use Composer\Util\ProcessExecutor;
- class PearInstaller extends LibraryInstaller
- {
- public function __construct(IOInterface $io, Composer $composer, $type = 'pear-library')
- {
- parent::__construct($io, $composer, $type);
- }
- public function update(InstalledRepositoryInterface $repo, PackageInterface $initial, PackageInterface $target)
- {
- $this->uninstall($repo, $initial);
- $this->install($repo, $target);
- }
- protected function installCode(PackageInterface $package)
- {
- parent::installCode($package);
- parent::initializeBinDir();
- $isWindows = defined('PHP_WINDOWS_VERSION_BUILD');
- $php_bin = $this->binDir . ($isWindows ? '/composer-php.bat' : '/composer-php');
- if (!$isWindows) {
- $php_bin = '/usr/bin/env ' . $php_bin;
- }
- $installPath = $this->getInstallPath($package);
- $vars = array(
- 'os' => $isWindows ? 'windows' : 'linux',
- 'php_bin' => $php_bin,
- 'pear_php' => $installPath,
- 'php_dir' => $installPath,
- 'bin_dir' => $installPath . '/bin',
- 'data_dir' => $installPath . '/data',
- 'version' => $package->getPrettyVersion(),
- );
- $packageArchive = $this->getInstallPath($package).'/'.pathinfo($package->getDistUrl(), PATHINFO_BASENAME);
- $pearExtractor = new PearPackageExtractor($packageArchive);
- $pearExtractor->extractTo($this->getInstallPath($package), array('php' => '/', 'script' => '/bin', 'data' => '/data'), $vars);
- if ($this->io->isVerbose()) {
- $this->io->writeError(' Cleaning up');
- }
- $this->filesystem->unlink($packageArchive);
- }
- protected function getBinaries(PackageInterface $package)
- {
- $binariesPath = $this->getInstallPath($package) . '/bin/';
- $binaries = array();
- if (file_exists($binariesPath)) {
- foreach (new \FilesystemIterator($binariesPath, \FilesystemIterator::KEY_AS_FILENAME | \FilesystemIterator::CURRENT_AS_FILEINFO) as $fileName => $value) {
- if (!$value->isDir()) {
- $binaries[] = 'bin/'.$fileName;
- }
- }
- }
- return $binaries;
- }
- protected function initializeBinDir()
- {
- parent::initializeBinDir();
- file_put_contents($this->binDir.'/composer-php', $this->generateUnixyPhpProxyCode());
- @chmod($this->binDir.'/composer-php', 0777);
- file_put_contents($this->binDir.'/composer-php.bat', $this->generateWindowsPhpProxyCode());
- @chmod($this->binDir.'/composer-php.bat', 0777);
- }
- protected function generateWindowsProxyCode($bin, $link)
- {
- $binPath = $this->filesystem->findShortestPath($link, $bin);
- if ('.bat' === substr($bin, -4)) {
- $caller = 'call';
- } else {
- $handle = fopen($bin, 'r');
- $line = fgets($handle);
- fclose($handle);
- if (preg_match('{^#!/(?:usr/bin/env )?(?:[^/]+/)*(.+)$}m', $line, $match)) {
- $caller = trim($match[1]);
- } else {
- $caller = 'php';
- }
- if ($caller === 'php') {
- return "@echo off\r\n".
- "pushd .\r\n".
- "cd %~dp0\r\n".
- "set PHP_PROXY=%CD%\\composer-php.bat\r\n".
- "cd ".ProcessExecutor::escape(dirname($binPath))."\r\n".
- "set BIN_TARGET=%CD%\\".basename($binPath)."\r\n".
- "popd\r\n".
- "%PHP_PROXY% \"%BIN_TARGET%\" %*\r\n";
- }
- }
- return "@echo off\r\n".
- "pushd .\r\n".
- "cd %~dp0\r\n".
- "cd ".ProcessExecutor::escape(dirname($binPath))."\r\n".
- "set BIN_TARGET=%CD%\\".basename($binPath)."\r\n".
- "popd\r\n".
- $caller." \"%BIN_TARGET%\" %*\r\n";
- }
- private function generateWindowsPhpProxyCode()
- {
- $binToVendor = $this->filesystem->findShortestPath($this->binDir, $this->vendorDir, true);
- return
- "@echo off\r\n" .
- "setlocal enabledelayedexpansion\r\n" .
- "set BIN_DIR=%~dp0\r\n" .
- "set VENDOR_DIR=%BIN_DIR%\\".$binToVendor."\r\n" .
- "set DIRS=.\r\n" .
- "FOR /D %%V IN (%VENDOR_DIR%\\*) DO (\r\n" .
- " FOR /D %%P IN (%%V\\*) DO (\r\n" .
- " set DIRS=!DIRS!;%%~fP\r\n" .
- " )\r\n" .
- ")\r\n" .
- "php.exe -d include_path=!DIRS! %*\r\n";
- }
- private function generateUnixyPhpProxyCode()
- {
- $binToVendor = $this->filesystem->findShortestPath($this->binDir, $this->vendorDir, true);
- return
- "#!/usr/bin/env sh\n".
- "SRC_DIR=`pwd`\n".
- "BIN_DIR=`dirname $0`\n".
- "VENDOR_DIR=\$BIN_DIR/".escapeshellarg($binToVendor)."\n".
- "DIRS=\"\"\n".
- "for vendor in \$VENDOR_DIR/*; do\n".
- " if [ -d \"\$vendor\" ]; then\n".
- " for package in \$vendor/*; do\n".
- " if [ -d \"\$package\" ]; then\n".
- " DIRS=\"\${DIRS}:\${package}\"\n".
- " fi\n".
- " done\n".
- " fi\n".
- "done\n".
- "php -d include_path=\".\$DIRS\" $@\n";
- }
- }
- <?php
- namespace Composer\Installer;
- use Composer\Composer;
- use Composer\Package\Package;
- use Composer\IO\IOInterface;
- use Composer\Repository\InstalledRepositoryInterface;
- use Composer\Package\PackageInterface;
- class PluginInstaller extends LibraryInstaller
- {
- private $installationManager;
- private static $classCounter = 0;
- public function __construct(IOInterface $io, Composer $composer, $type = 'library')
- {
- parent::__construct($io, $composer, 'composer-plugin');
- $this->installationManager = $composer->getInstallationManager();
- }
- public function supports($packageType)
- {
- return $packageType === 'composer-plugin' || $packageType === 'composer-installer';
- }
- public function install(InstalledRepositoryInterface $repo, PackageInterface $package)
- {
- $extra = $package->getExtra();
- if (empty($extra['class'])) {
- throw new \UnexpectedValueException('Error while installing '.$package->getPrettyName().', composer-plugin packages should have a class defined in their extra key to be usable.');
- }
- parent::install($repo, $package);
- $this->composer->getPluginManager()->registerPackage($package, true);
- }
- public function update(InstalledRepositoryInterface $repo, PackageInterface $initial, PackageInterface $target)
- {
- $extra = $target->getExtra();
- if (empty($extra['class'])) {
- throw new \UnexpectedValueException('Error while installing '.$target->getPrettyName().', composer-plugin packages should have a class defined in their extra key to be usable.');
- }
- parent::update($repo, $initial, $target);
- $this->composer->getPluginManager()->registerPackage($target, true);
- }
- }
- <?php
- namespace Composer\Installer;
- use Composer\Package\PackageInterface;
- use Composer\Downloader\DownloadManager;
- use Composer\Repository\InstalledRepositoryInterface;
- use Composer\Util\Filesystem;
- class ProjectInstaller implements InstallerInterface
- {
- private $installPath;
- private $downloadManager;
- private $filesystem;
- public function __construct($installPath, DownloadManager $dm)
- {
- $this->installPath = rtrim(strtr($installPath, '\\', '/'), '/').'/';
- $this->downloadManager = $dm;
- $this->filesystem = new Filesystem;
- }
- public function supports($packageType)
- {
- return true;
- }
- public function isInstalled(InstalledRepositoryInterface $repo, PackageInterface $package)
- {
- return false;
- }
- public function install(InstalledRepositoryInterface $repo, PackageInterface $package)
- {
- $installPath = $this->installPath;
- if (file_exists($installPath) && !$this->filesystem->isDirEmpty($installPath)) {
- throw new \InvalidArgumentException("Project directory $installPath is not empty.");
- }
- if (!is_dir($installPath)) {
- mkdir($installPath, 0777, true);
- }
- $this->downloadManager->download($package, $installPath);
- }
- public function update(InstalledRepositoryInterface $repo, PackageInterface $initial, PackageInterface $target)
- {
- throw new \InvalidArgumentException("not supported");
- }
- public function uninstall(InstalledRepositoryInterface $repo, PackageInterface $package)
- {
- throw new \InvalidArgumentException("not supported");
- }
- public function getInstallPath(PackageInterface $package)
- {
- return $this->installPath;
- }
- }
- <?php
- namespace Composer;
- use Composer\Autoload\AutoloadGenerator;
- use Composer\DependencyResolver\DefaultPolicy;
- use Composer\DependencyResolver\Operation\UpdateOperation;
- use Composer\DependencyResolver\Operation\InstallOperation;
- use Composer\DependencyResolver\Operation\UninstallOperation;
- use Composer\DependencyResolver\Operation\OperationInterface;
- use Composer\DependencyResolver\Pool;
- use Composer\DependencyResolver\Request;
- use Composer\DependencyResolver\Rule;
- use Composer\DependencyResolver\Solver;
- use Composer\DependencyResolver\SolverProblemsException;
- use Composer\Downloader\DownloadManager;
- use Composer\EventDispatcher\EventDispatcher;
- use Composer\Installer\InstallationManager;
- use Composer\Installer\InstallerEvents;
- use Composer\Installer\NoopInstaller;
- use Composer\IO\IOInterface;
- use Composer\Json\JsonFile;
- use Composer\Package\AliasPackage;
- use Composer\Package\CompletePackage;
- use Composer\Package\Link;
- use Composer\Package\LinkConstraint\VersionConstraint;
- use Composer\Package\Locker;
- use Composer\Package\PackageInterface;
- use Composer\Package\RootPackageInterface;
- use Composer\Repository\CompositeRepository;
- use Composer\Repository\InstalledArrayRepository;
- use Composer\Repository\InstalledFilesystemRepository;
- use Composer\Repository\PlatformRepository;
- use Composer\Repository\RepositoryInterface;
- use Composer\Repository\RepositoryManager;
- use Composer\Script\ScriptEvents;
- class Installer
- {
- protected $io;
- protected $config;
- protected $package;
- protected $downloadManager;
- protected $repositoryManager;
- protected $locker;
- protected $installationManager;
- protected $eventDispatcher;
- protected $autoloadGenerator;
- protected $preferSource = false;
- protected $preferDist = false;
- protected $optimizeAutoloader = false;
- protected $devMode = false;
- protected $dryRun = false;
- protected $verbose = false;
- protected $update = false;
- protected $dumpAutoloader = true;
- protected $runScripts = true;
- protected $ignorePlatformReqs = false;
- protected $preferStable = false;
- protected $preferLowest = false;
- protected $updateWhitelist = null;
- protected $whitelistDependencies = false;
- protected $suggestedPackages;
- protected $additionalInstalledRepository;
- public function __construct(IOInterface $io, Config $config, RootPackageInterface $package, DownloadManager $downloadManager, RepositoryManager $repositoryManager, Locker $locker, InstallationManager $installationManager, EventDispatcher $eventDispatcher, AutoloadGenerator $autoloadGenerator)
- {
- $this->io = $io;
- $this->config = $config;
- $this->package = $package;
- $this->downloadManager = $downloadManager;
- $this->repositoryManager = $repositoryManager;
- $this->locker = $locker;
- $this->installationManager = $installationManager;
- $this->eventDispatcher = $eventDispatcher;
- $this->autoloadGenerator = $autoloadGenerator;
- }
- public function run()
- {
- gc_collect_cycles();
- gc_disable();
- if ($this->dryRun) {
- $this->verbose = true;
- $this->runScripts = false;
- $this->installationManager->addInstaller(new NoopInstaller);
- $this->mockLocalRepositories($this->repositoryManager);
- }
-
- $devRepo = new InstalledFilesystemRepository(new JsonFile($this->config->get('vendor-dir').'/composer/installed_dev.json'));
- if ($devRepo->getPackages()) {
- $this->io->writeError('<warning>BC Notice: Removing old dev packages to migrate to the new require-dev handling.</warning>');
- foreach ($devRepo->getPackages() as $package) {
- if ($this->installationManager->isPackageInstalled($devRepo, $package)) {
- $this->installationManager->uninstall($devRepo, new UninstallOperation($package));
- }
- }
- unlink($this->config->get('vendor-dir').'/composer/installed_dev.json');
- }
- unset($devRepo, $package);
- if ($this->runScripts) {
- $eventName = $this->update ? ScriptEvents::PRE_UPDATE_CMD : ScriptEvents::PRE_INSTALL_CMD;
- $this->eventDispatcher->dispatchScript($eventName, $this->devMode);
- }
- $this->downloadManager->setPreferSource($this->preferSource);
- $this->downloadManager->setPreferDist($this->preferDist);
-
-
- $installedRootPackage = clone $this->package;
- $installedRootPackage->setRequires(array());
- $installedRootPackage->setDevRequires(array());
- $localRepo = $this->repositoryManager->getLocalRepository();
- $platformRepo = new PlatformRepository();
- $repos = array(
- $localRepo,
- new InstalledArrayRepository(array($installedRootPackage)),
- $platformRepo,
- );
- $installedRepo = new CompositeRepository($repos);
- if ($this->additionalInstalledRepository) {
- $installedRepo->addRepository($this->additionalInstalledRepository);
- }
- $aliases = $this->getRootAliases();
- $this->aliasPlatformPackages($platformRepo, $aliases);
- try {
- $this->suggestedPackages = array();
- $res = $this->doInstall($localRepo, $installedRepo, $platformRepo, $aliases, $this->devMode);
- if ($res !== 0) {
- return $res;
- }
- } catch (\Exception $e) {
- $this->installationManager->notifyInstalls();
- throw $e;
- }
- $this->installationManager->notifyInstalls();
- if ($this->devMode) {
- foreach ($this->suggestedPackages as $suggestion) {
- $target = $suggestion['target'];
- foreach ($installedRepo->getPackages() as $package) {
- if (in_array($target, $package->getNames())) {
- continue 2;
- }
- }
- $this->io->writeError($suggestion['source'].' suggests installing '.$suggestion['target'].' ('.$suggestion['reason'].')');
- }
- }
- foreach ($localRepo->getPackages() as $package) {
- if (!$package instanceof CompletePackage || !$package->isAbandoned()) {
- continue;
- }
- $replacement = (is_string($package->getReplacementPackage()))
- ? 'Use ' . $package->getReplacementPackage() . ' instead'
- : 'No replacement was suggested';
- $this->io->writeError(
- sprintf(
- "<error>Package %s is abandoned, you should avoid using it. %s.</error>",
- $package->getPrettyName(),
- $replacement
- )
- );
- }
- if (!$this->dryRun) {
- if ($this->update || !$this->locker->isLocked()) {
- $localRepo->reload();
-
- $devPackages = ($this->devMode || !$this->package->getDevRequires()) ? array() : null;
- if ($this->devMode && $this->package->getDevRequires()) {
- $policy = $this->createPolicy();
- $pool = $this->createPool(true);
- $pool->addRepository($installedRepo, $aliases);
- $request = $this->createRequest($pool, $this->package, $platformRepo);
- $request->updateAll();
- foreach ($this->package->getRequires() as $link) {
- $request->install($link->getTarget(), $link->getConstraint());
- }
- $this->eventDispatcher->dispatchInstallerEvent(InstallerEvents::PRE_DEPENDENCIES_SOLVING, false, $policy, $pool, $installedRepo, $request);
- $solver = new Solver($policy, $pool, $installedRepo);
- $ops = $solver->solve($request, $this->ignorePlatformReqs);
- $this->eventDispatcher->dispatchInstallerEvent(InstallerEvents::POST_DEPENDENCIES_SOLVING, false, $policy, $pool, $installedRepo, $request, $ops);
- foreach ($ops as $op) {
- if ($op->getJobType() === 'uninstall') {
- $devPackages[] = $op->getPackage();
- }
- }
- }
- $platformReqs = $this->extractPlatformRequirements($this->package->getRequires());
- $platformDevReqs = $this->devMode ? $this->extractPlatformRequirements($this->package->getDevRequires()) : array();
- $updatedLock = $this->locker->setLockData(
- array_diff($localRepo->getCanonicalPackages(), (array) $devPackages),
- $devPackages,
- $platformReqs,
- $platformDevReqs,
- $aliases,
- $this->package->getMinimumStability(),
- $this->package->getStabilityFlags(),
- $this->preferStable || $this->package->getPreferStable(),
- $this->preferLowest
- );
- if ($updatedLock) {
- $this->io->writeError('<info>Writing lock file</info>');
- }
- }
- if ($this->dumpAutoloader) {
- if ($this->optimizeAutoloader) {
- $this->io->writeError('<info>Generating optimized autoload files</info>');
- } else {
- $this->io->writeError('<info>Generating autoload files</info>');
- }
- $this->autoloadGenerator->setDevMode($this->devMode);
- $this->autoloadGenerator->dump($this->config, $localRepo, $this->package, $this->installationManager, 'composer', $this->optimizeAutoloader);
- }
- if ($this->runScripts) {
- $eventName = $this->update ? ScriptEvents::POST_UPDATE_CMD : ScriptEvents::POST_INSTALL_CMD;
- $this->eventDispatcher->dispatchScript($eventName, $this->devMode);
- }
- $vendorDir = $this->config->get('vendor-dir');
- if (is_dir($vendorDir)) {
- touch($vendorDir);
- }
- }
- return 0;
- }
- protected function doInstall($localRepo, $installedRepo, $platformRepo, $aliases, $withDevReqs)
- {
- $lockedRepository = null;
- $repositories = null;
- $installFromLock = false;
- if (!$this->update && $this->locker->isLocked()) {
- $installFromLock = true;
- try {
- $lockedRepository = $this->locker->getLockedRepository($withDevReqs);
- } catch (\RuntimeException $e) {
- if ($this->package->getDevRequires()) {
- throw $e;
- }
- $lockedRepository = $this->locker->getLockedRepository();
- }
- }
- $this->whitelistUpdateDependencies(
- $localRepo,
- $withDevReqs,
- $this->package->getRequires(),
- $this->package->getDevRequires()
- );
- $this->io->writeError('<info>Loading composer repositories with package information</info>');
- $policy = $this->createPolicy();
- $pool = $this->createPool($withDevReqs, $lockedRepository);
- $pool->addRepository($installedRepo, $aliases);
- if ($installFromLock) {
- $pool->addRepository($lockedRepository, $aliases);
- }
- if (!$installFromLock) {
- $repositories = $this->repositoryManager->getRepositories();
- foreach ($repositories as $repository) {
- $pool->addRepository($repository, $aliases);
- }
- }
- $request = $this->createRequest($pool, $this->package, $platformRepo);
- if (!$installFromLock) {
- $removedUnstablePackages = array();
- foreach ($localRepo->getPackages() as $package) {
- if (
- !$pool->isPackageAcceptable($package->getNames(), $package->getStability())
- && $this->installationManager->isPackageInstalled($localRepo, $package)
- ) {
- $removedUnstablePackages[$package->getName()] = true;
- $request->remove($package->getName(), new VersionConstraint('=', $package->getVersion()));
- }
- }
- }
- if ($this->update) {
- $this->io->writeError('<info>Updating dependencies'.($withDevReqs ? ' (including require-dev)' : '').'</info>');
- $request->updateAll();
- if ($withDevReqs) {
- $links = array_merge($this->package->getRequires(), $this->package->getDevRequires());
- } else {
- $links = $this->package->getRequires();
- }
- foreach ($links as $link) {
- $request->install($link->getTarget(), $link->getConstraint());
- }
-
- if ($this->updateWhitelist) {
- if ($this->locker->isLocked()) {
- try {
- $currentPackages = $this->locker->getLockedRepository($withDevReqs)->getPackages();
- } catch (\RuntimeException $e) {
- $currentPackages = $this->locker->getLockedRepository()->getPackages();
- }
- } else {
- $currentPackages = $installedRepo->getPackages();
- }
- $candidates = array();
- foreach ($links as $link) {
- $candidates[$link->getTarget()] = true;
- }
- foreach ($localRepo->getPackages() as $package) {
- $candidates[$package->getName()] = true;
- }
- foreach ($candidates as $candidate => $dummy) {
- foreach ($currentPackages as $curPackage) {
- if ($curPackage->getName() === $candidate) {
- if (!$this->isUpdateable($curPackage) && !isset($removedUnstablePackages[$curPackage->getName()])) {
- $constraint = new VersionConstraint('=', $curPackage->getVersion());
- $request->install($curPackage->getName(), $constraint);
- }
- break;
- }
- }
- }
- }
- } elseif ($installFromLock) {
- $this->io->writeError('<info>Installing dependencies'.($withDevReqs ? ' (including require-dev)' : '').' from lock file</info>');
- if (!$this->locker->isFresh()) {
- $this->io->writeError('<warning>Warning: The lock file is not up to date with the latest changes in composer.json. You may be getting outdated dependencies. Run update to update them.</warning>');
- }
- foreach ($lockedRepository->getPackages() as $package) {
- $version = $package->getVersion();
- if (isset($aliases[$package->getName()][$version])) {
- $version = $aliases[$package->getName()][$version]['alias_normalized'];
- }
- $constraint = new VersionConstraint('=', $version);
- $constraint->setPrettyString($package->getPrettyVersion());
- $request->install($package->getName(), $constraint);
- }
- foreach ($this->locker->getPlatformRequirements($withDevReqs) as $link) {
- $request->install($link->getTarget(), $link->getConstraint());
- }
- } else {
- $this->io->writeError('<info>Installing dependencies'.($withDevReqs ? ' (including require-dev)' : '').'</info>');
- if ($withDevReqs) {
- $links = array_merge($this->package->getRequires(), $this->package->getDevRequires());
- } else {
- $links = $this->package->getRequires();
- }
- foreach ($links as $link) {
- $request->install($link->getTarget(), $link->getConstraint());
- }
- }
- $this->processDevPackages($localRepo, $pool, $policy, $repositories, $lockedRepository, $installFromLock, 'force-links');
- $this->eventDispatcher->dispatchInstallerEvent(InstallerEvents::PRE_DEPENDENCIES_SOLVING, $this->devMode, $policy, $pool, $installedRepo, $request);
- $solver = new Solver($policy, $pool, $installedRepo);
- try {
- $operations = $solver->solve($request, $this->ignorePlatformReqs);
- $this->eventDispatcher->dispatchInstallerEvent(InstallerEvents::POST_DEPENDENCIES_SOLVING, $this->devMode, $policy, $pool, $installedRepo, $request, $operations);
- } catch (SolverProblemsException $e) {
- $this->io->writeError('<error>Your requirements could not be resolved to an installable set of packages.</error>');
- $this->io->writeError($e->getMessage());
- return max(1, $e->getCode());
- }
- $operations = $this->processDevPackages($localRepo, $pool, $policy, $repositories, $lockedRepository, $installFromLock, 'force-updates', $operations);
- if (!$operations) {
- $this->io->writeError('Nothing to install or update');
- }
- $operations = $this->movePluginsToFront($operations);
- $operations = $this->moveUninstallsToFront($operations);
- foreach ($operations as $operation) {
- if ('install' === $operation->getJobType()) {
- foreach ($operation->getPackage()->getSuggests() as $target => $reason) {
- $this->suggestedPackages[] = array(
- 'source' => $operation->getPackage()->getPrettyName(),
- 'target' => $target,
- 'reason' => $reason,
- );
- }
- }
- if (!$installFromLock) {
- $package = null;
- if ('update' === $operation->getJobType()) {
- $package = $operation->getTargetPackage();
- } elseif ('install' === $operation->getJobType()) {
- $package = $operation->getPackage();
- }
- if ($package && $package->isDev()) {
- $references = $this->package->getReferences();
- if (isset($references[$package->getName()])) {
- $package->setSourceReference($references[$package->getName()]);
- $package->setDistReference($references[$package->getName()]);
- }
- }
- if ('update' === $operation->getJobType()
- && $operation->getTargetPackage()->isDev()
- && $operation->getTargetPackage()->getVersion() === $operation->getInitialPackage()->getVersion()
- && $operation->getTargetPackage()->getSourceReference() === $operation->getInitialPackage()->getSourceReference()
- ) {
- if ($this->io->isDebug()) {
- $this->io->writeError(' - Skipping update of '. $operation->getTargetPackage()->getPrettyName().' to the same reference-locked version');
- $this->io->writeError('');
- }
- continue;
- }
- }
- $event = 'Composer\Installer\PackageEvents::PRE_PACKAGE_'.strtoupper($operation->getJobType());
- if (defined($event) && $this->runScripts) {
- $this->eventDispatcher->dispatchPackageEvent(constant($event), $this->devMode, $policy, $pool, $installedRepo, $request, $operations, $operation);
- }
- if ($this->dryRun && false === strpos($operation->getJobType(), 'Alias')) {
- $this->io->writeError(' - ' . $operation);
- $this->io->writeError('');
- } elseif ($this->io->isDebug() && false !== strpos($operation->getJobType(), 'Alias')) {
- $this->io->writeError(' - ' . $operation);
- $this->io->writeError('');
- }
- $this->installationManager->execute($localRepo, $operation);
- if ($this->verbose && $this->io->isVeryVerbose() && in_array($operation->getJobType(), array('install', 'update'))) {
- $reason = $operation->getReason();
- if ($reason instanceof Rule) {
- switch ($reason->getReason()) {
- case Rule::RULE_JOB_INSTALL:
- $this->io->writeError(' REASON: Required by root: '.$reason->getPrettyString($pool));
- $this->io->writeError('');
- break;
- case Rule::RULE_PACKAGE_REQUIRES:
- $this->io->writeError(' REASON: '.$reason->getPrettyString($pool));
- $this->io->writeError('');
- break;
- }
- }
- }
- $event = 'Composer\Installer\PackageEvents::POST_PACKAGE_'.strtoupper($operation->getJobType());
- if (defined($event) && $this->runScripts) {
- $this->eventDispatcher->dispatchPackageEvent(constant($event), $this->devMode, $policy, $pool, $installedRepo, $request, $operations, $operation);
- }
- if (!$this->dryRun) {
- $localRepo->write();
- }
- }
- return 0;
- }
- private function movePluginsToFront(array $operations)
- {
- $installerOps = array();
- foreach ($operations as $idx => $op) {
- if ($op instanceof InstallOperation) {
- $package = $op->getPackage();
- } elseif ($op instanceof UpdateOperation) {
- $package = $op->getTargetPackage();
- } else {
- continue;
- }
- if ($package->getType() === 'composer-plugin' || $package->getType() === 'composer-installer') {
- $requires = array_keys($package->getRequires());
- foreach ($requires as $index => $req) {
- if ($req === 'composer-plugin-api' || preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $req)) {
- unset($requires[$index]);
- }
- }
- if (!count($requires)) {
- $installerOps[] = $op;
- unset($operations[$idx]);
- }
- }
- }
- return array_merge($installerOps, $operations);
- }
- private function moveUninstallsToFront(array $operations)
- {
- $uninstOps = array();
- foreach ($operations as $idx => $op) {
- if ($op instanceof UninstallOperation) {
- $uninstOps[] = $op;
- unset($operations[$idx]);
- }
- }
- return array_merge($uninstOps, $operations);
- }
- private function createPool($withDevReqs, RepositoryInterface $lockedRepository = null)
- {
- if (!$this->update && $this->locker->isLocked()) {
- $minimumStability = $this->locker->getMinimumStability();
- $stabilityFlags = $this->locker->getStabilityFlags();
- $requires = array();
- foreach ($lockedRepository->getPackages() as $package) {
- $constraint = new VersionConstraint('=', $package->getVersion());
- $constraint->setPrettyString($package->getPrettyVersion());
- $requires[$package->getName()] = $constraint;
- }
- } else {
- $minimumStability = $this->package->getMinimumStability();
- $stabilityFlags = $this->package->getStabilityFlags();
- $requires = $this->package->getRequires();
- if ($withDevReqs) {
- $requires = array_merge($requires, $this->package->getDevRequires());
- }
- }
- $rootConstraints = array();
- foreach ($requires as $req => $constraint) {
- if ($this->ignorePlatformReqs && preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $req)) {
- continue;
- }
- if ($constraint instanceof Link) {
- $rootConstraints[$req] = $constraint->getConstraint();
- } else {
- $rootConstraints[$req] = $constraint;
- }
- }
- return new Pool($minimumStability, $stabilityFlags, $rootConstraints);
- }
- private function createPolicy()
- {
- $preferStable = null;
- $preferLowest = null;
- if (!$this->update && $this->locker->isLocked()) {
- $preferStable = $this->locker->getPreferStable();
- $preferLowest = $this->locker->getPreferLowest();
- }
-
- if (null === $preferStable) {
- $preferStable = $this->preferStable || $this->package->getPreferStable();
- }
- if (null === $preferLowest) {
- $preferLowest = $this->preferLowest;
- }
- return new DefaultPolicy($preferStable, $preferLowest);
- }
- private function createRequest(Pool $pool, RootPackageInterface $rootPackage, PlatformRepository $platformRepo)
- {
- $request = new Request($pool);
- $constraint = new VersionConstraint('=', $rootPackage->getVersion());
- $constraint->setPrettyString($rootPackage->getPrettyVersion());
- $request->install($rootPackage->getName(), $constraint);
- $fixedPackages = $platformRepo->getPackages();
- if ($this->additionalInstalledRepository) {
- $additionalFixedPackages = $this->additionalInstalledRepository->getPackages();
- $fixedPackages = array_merge($fixedPackages, $additionalFixedPackages);
- }
-
- $provided = $rootPackage->getProvides();
- foreach ($fixedPackages as $package) {
- $constraint = new VersionConstraint('=', $package->getVersion());
- $constraint->setPrettyString($package->getPrettyVersion());
- if ($package->getRepository() !== $platformRepo
- || !isset($provided[$package->getName()])
- || !$provided[$package->getName()]->getConstraint()->matches($constraint)
- ) {
- $request->fix($package->getName(), $constraint);
- }
- }
- return $request;
- }
- private function processDevPackages($localRepo, $pool, $policy, $repositories, $lockedRepository, $installFromLock, $task, array $operations = null)
- {
- if ($task === 'force-updates' && null === $operations) {
- throw new \InvalidArgumentException('Missing operations argument');
- }
- if ($task === 'force-links') {
- $operations = array();
- }
- foreach ($localRepo->getCanonicalPackages() as $package) {
- if (!$package->isDev()) {
- continue;
- }
- foreach ($operations as $operation) {
- if (('update' === $operation->getJobType() && $operation->getInitialPackage()->equals($package))
- || ('uninstall' === $operation->getJobType() && $operation->getPackage()->equals($package))
- ) {
- continue 2;
- }
- }
- if ($installFromLock) {
- foreach ($lockedRepository->findPackages($package->getName()) as $lockedPackage) {
- if ($lockedPackage->isDev() && $lockedPackage->getVersion() === $package->getVersion()) {
- if ($task === 'force-links') {
- $package->setRequires($lockedPackage->getRequires());
- $package->setConflicts($lockedPackage->getConflicts());
- $package->setProvides($lockedPackage->getProvides());
- $package->setReplaces($lockedPackage->getReplaces());
- } elseif ($task === 'force-updates') {
- if (($lockedPackage->getSourceReference() && $lockedPackage->getSourceReference() !== $package->getSourceReference())
- || ($lockedPackage->getDistReference() && $lockedPackage->getDistReference() !== $package->getDistReference())
- ) {
- $operations[] = new UpdateOperation($package, $lockedPackage);
- }
- }
- break;
- }
- }
- } else {
- if ($this->update) {
- if ($this->updateWhitelist && !$this->isUpdateable($package)) {
- continue;
- }
- $matches = $pool->whatProvides($package->getName(), new VersionConstraint('=', $package->getVersion()));
- foreach ($matches as $index => $match) {
- if (!in_array($match->getRepository(), $repositories, true)) {
- unset($matches[$index]);
- continue;
- }
- if ($match->getName() !== $package->getName()) {
- unset($matches[$index]);
- continue;
- }
- $matches[$index] = $match->getId();
- }
- if ($matches && $matches = $policy->selectPreferedPackages($pool, array(), $matches)) {
- $newPackage = $pool->literalToPackage($matches[0]);
- if ($task === 'force-links' && $newPackage) {
- $package->setRequires($newPackage->getRequires());
- $package->setConflicts($newPackage->getConflicts());
- $package->setProvides($newPackage->getProvides());
- $package->setReplaces($newPackage->getReplaces());
- }
- if ($task === 'force-updates' && $newPackage && (
- (($newPackage->getSourceReference() && $newPackage->getSourceReference() !== $package->getSourceReference())
- || ($newPackage->getDistReference() && $newPackage->getDistReference() !== $package->getDistReference())
- )
- )) {
- $operations[] = new UpdateOperation($package, $newPackage);
- }
- }
- }
- if ($task === 'force-updates') {
- $references = $this->package->getReferences();
- if (isset($references[$package->getName()]) && $references[$package->getName()] !== $package->getSourceReference()) {
- $operations[] = new UpdateOperation($package, clone $package);
- }
- }
- }
- }
- return $operations;
- }
- private function getRootAliases()
- {
- if (!$this->update && $this->locker->isLocked()) {
- $aliases = $this->locker->getAliases();
- } else {
- $aliases = $this->package->getAliases();
- }
- $normalizedAliases = array();
- foreach ($aliases as $alias) {
- $normalizedAliases[$alias['package']][$alias['version']] = array(
- 'alias' => $alias['alias'],
- 'alias_normalized' => $alias['alias_normalized']
- );
- }
- return $normalizedAliases;
- }
- private function aliasPlatformPackages(PlatformRepository $platformRepo, $aliases)
- {
- foreach ($aliases as $package => $versions) {
- foreach ($versions as $version => $alias) {
- $packages = $platformRepo->findPackages($package, $version);
- foreach ($packages as $package) {
- $aliasPackage = new AliasPackage($package, $alias['alias_normalized'], $alias['alias']);
- $aliasPackage->setRootPackageAlias(true);
- $platformRepo->addPackage($aliasPackage);
- }
- }
- }
- }
- private function isUpdateable(PackageInterface $package)
- {
- if (!$this->updateWhitelist) {
- throw new \LogicException('isUpdateable should only be called when a whitelist is present');
- }
- foreach ($this->updateWhitelist as $whiteListedPattern => $void) {
- $patternRegexp = $this->packageNameToRegexp($whiteListedPattern);
- if (preg_match($patternRegexp, $package->getName())) {
- return true;
- }
- }
- return false;
- }
- private function packageNameToRegexp($whiteListedPattern)
- {
- $cleanedWhiteListedPattern = str_replace('\\*', '.*', preg_quote($whiteListedPattern));
- return "{^" . $cleanedWhiteListedPattern . "$}i";
- }
- private function extractPlatformRequirements($links)
- {
- $platformReqs = array();
- foreach ($links as $link) {
- if (preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $link->getTarget())) {
- $platformReqs[$link->getTarget()] = $link->getPrettyConstraint();
- }
- }
- return $platformReqs;
- }
- private function whitelistUpdateDependencies($localRepo, $devMode, array $rootRequires, array $rootDevRequires)
- {
- if (!$this->updateWhitelist) {
- return;
- }
- $requiredPackageNames = array();
- foreach (array_merge($rootRequires, $rootDevRequires) as $require) {
- $requiredPackageNames[] = $require->getTarget();
- }
- if ($devMode) {
- $rootRequires = array_merge($rootRequires, $rootDevRequires);
- }
- $skipPackages = array();
- foreach ($rootRequires as $require) {
- $skipPackages[$require->getTarget()] = true;
- }
- $pool = new Pool;
- $pool->addRepository($localRepo);
- $seen = array();
- $rootRequiredPackageNames = array_keys($rootRequires);
- foreach ($this->updateWhitelist as $packageName => $void) {
- $packageQueue = new \SplQueue;
- $depPackages = $pool->whatProvides($packageName);
- $nameMatchesRequiredPackage = in_array($packageName, $requiredPackageNames, true);
- if (!$nameMatchesRequiredPackage) {
- $whitelistPatternRegexp = $this->packageNameToRegexp($packageName);
- foreach ($rootRequiredPackageNames as $rootRequiredPackageName) {
- if (preg_match($whitelistPatternRegexp, $rootRequiredPackageName)) {
- $nameMatchesRequiredPackage = true;
- break;
- }
- }
- }
- if (count($depPackages) == 0 && !$nameMatchesRequiredPackage && !in_array($packageName, array('nothing', 'lock'))) {
- $this->io->writeError('<warning>Package "' . $packageName . '" listed for update is not installed. Ignoring.</warning>');
- }
- foreach ($depPackages as $depPackage) {
- $packageQueue->enqueue($depPackage);
- }
- while (!$packageQueue->isEmpty()) {
- $package = $packageQueue->dequeue();
- if (isset($seen[$package->getId()])) {
- continue;
- }
- $seen[$package->getId()] = true;
- $this->updateWhitelist[$package->getName()] = true;
- if (!$this->whitelistDependencies) {
- continue;
- }
- $requires = $package->getRequires();
- foreach ($requires as $require) {
- $requirePackages = $pool->whatProvides($require->getTarget());
- foreach ($requirePackages as $requirePackage) {
- if (isset($skipPackages[$requirePackage->getName()])) {
- continue;
- }
- $packageQueue->enqueue($requirePackage);
- }
- }
- }
- }
- }
- private function mockLocalRepositories(RepositoryManager $rm)
- {
- $packages = array();
- foreach ($rm->getLocalRepository()->getPackages() as $package) {
- $packages[(string) $package] = clone $package;
- }
- foreach ($packages as $key => $package) {
- if ($package instanceof AliasPackage) {
- $alias = (string) $package->getAliasOf();
- $packages[$key] = new AliasPackage($packages[$alias], $package->getVersion(), $package->getPrettyVersion());
- }
- }
- $rm->setLocalRepository(
- new InstalledArrayRepository($packages)
- );
- }
- public static function create(IOInterface $io, Composer $composer)
- {
- return new static(
- $io,
- $composer->getConfig(),
- $composer->getPackage(),
- $composer->getDownloadManager(),
- $composer->getRepositoryManager(),
- $composer->getLocker(),
- $composer->getInstallationManager(),
- $composer->getEventDispatcher(),
- $composer->getAutoloadGenerator()
- );
- }
- public function setAdditionalInstalledRepository(RepositoryInterface $additionalInstalledRepository)
- {
- $this->additionalInstalledRepository = $additionalInstalledRepository;
- return $this;
- }
- public function setDryRun($dryRun = true)
- {
- $this->dryRun = (boolean) $dryRun;
- return $this;
- }
- public function isDryRun()
- {
- return $this->dryRun;
- }
- public function setPreferSource($preferSource = true)
- {
- $this->preferSource = (boolean) $preferSource;
- return $this;
- }
- public function setPreferDist($preferDist = true)
- {
- $this->preferDist = (boolean) $preferDist;
- return $this;
- }
- public function setOptimizeAutoloader($optimizeAutoloader = false)
- {
- $this->optimizeAutoloader = (boolean) $optimizeAutoloader;
- return $this;
- }
- public function setUpdate($update = true)
- {
- $this->update = (boolean) $update;
- return $this;
- }
- public function setDevMode($devMode = true)
- {
- $this->devMode = (boolean) $devMode;
- return $this;
- }
- public function setDumpAutoloader($dumpAutoloader = true)
- {
- $this->dumpAutoloader = (boolean) $dumpAutoloader;
- return $this;
- }
- public function setRunScripts($runScripts = true)
- {
- $this->runScripts = (boolean) $runScripts;
- return $this;
- }
- public function setConfig(Config $config)
- {
- $this->config = $config;
- return $this;
- }
- public function setVerbose($verbose = true)
- {
- $this->verbose = (boolean) $verbose;
- return $this;
- }
- public function isVerbose()
- {
- return $this->verbose;
- }
- public function setIgnorePlatformRequirements($ignorePlatformReqs = false)
- {
- $this->ignorePlatformReqs = (boolean) $ignorePlatformReqs;
- return $this;
- }
- public function setUpdateWhitelist(array $packages)
- {
- $this->updateWhitelist = array_flip(array_map('strtolower', $packages));
- return $this;
- }
- public function setWhitelistDependencies($updateDependencies = true)
- {
- $this->whitelistDependencies = (boolean) $updateDependencies;
- return $this;
- }
- public function setPreferStable($preferStable = true)
- {
- $this->preferStable = (boolean) $preferStable;
- return $this;
- }
- public function setPreferLowest($preferLowest = true)
- {
- $this->preferLowest = (boolean) $preferLowest;
- return $this;
- }
- public function disablePlugins()
- {
- $this->installationManager->disablePlugins();
- return $this;
- }
- }
- <?php
- namespace Composer\IO;
- use Composer\Config;
- abstract class BaseIO implements IOInterface
- {
- protected $authentications = array();
- public function getAuthentications()
- {
- return $this->authentications;
- }
- public function hasAuthentication($repositoryName)
- {
- return isset($this->authentications[$repositoryName]);
- }
- public function getAuthentication($repositoryName)
- {
- if (isset($this->authentications[$repositoryName])) {
- return $this->authentications[$repositoryName];
- }
- return array('username' => null, 'password' => null);
- }
- public function setAuthentication($repositoryName, $username, $password = null)
- {
- $this->authentications[$repositoryName] = array('username' => $username, 'password' => $password);
- }
- public function loadConfiguration(Config $config)
- {
- if ($tokens = $config->get('github-oauth')) {
- foreach ($tokens as $domain => $token) {
- if (!preg_match('{^[a-z0-9]+$}', $token)) {
- throw new \UnexpectedValueException('Your github oauth token for '.$domain.' contains invalid characters: "'.$token.'"');
- }
- $this->setAuthentication($domain, $token, 'x-oauth-basic');
- }
- }
- if ($tokens = $config->get('gitlab-oauth')) {
- foreach ($tokens as $domain => $token) {
- $this->setAuthentication($domain, $token, 'oauth2');
- }
- }
- if ($creds = $config->get('http-basic')) {
- foreach ($creds as $domain => $cred) {
- $this->setAuthentication($domain, $cred['username'], $cred['password']);
- }
- }
- }
- }
- <?php
- namespace Composer\IO;
- use Symfony\Component\Console\Output\StreamOutput;
- use Symfony\Component\Console\Formatter\OutputFormatterInterface;
- use Symfony\Component\Console\Input\StringInput;
- use Symfony\Component\Console\Helper\HelperSet;
- class BufferIO extends ConsoleIO
- {
- public function __construct(
- $input = '',
- $verbosity = StreamOutput::VERBOSITY_NORMAL,
- OutputFormatterInterface $formatter = null
- ) {
- $input = new StringInput($input);
- $input->setInteractive(false);
- $output = new StreamOutput(fopen('php://memory', 'rw'), $verbosity, !empty($formatter), $formatter);
- parent::__construct($input, $output, new HelperSet(array()));
- }
- public function getOutput()
- {
- fseek($this->output->getStream(), 0);
- $output = stream_get_contents($this->output->getStream());
- $output = preg_replace_callback("{(?<=^|\n|\x08)(.+?)(\x08+)}", function ($matches) {
- $pre = strip_tags($matches[1]);
- if (strlen($pre) === strlen($matches[2])) {
- return '';
- }
- return rtrim($matches[1])."\n";
- }, $output);
- return $output;
- }
- }
- <?php
- namespace Composer\IO;
- use Symfony\Component\Console\Input\InputInterface;
- use Symfony\Component\Console\Output\ConsoleOutputInterface;
- use Symfony\Component\Console\Output\OutputInterface;
- use Symfony\Component\Console\Helper\HelperSet;
- use Symfony\Component\Process\ExecutableFinder;
- class ConsoleIO extends BaseIO
- {
- protected $input;
- protected $output;
- protected $helperSet;
- protected $lastMessage;
- protected $lastMessageErr;
- private $startTime;
- public function __construct(InputInterface $input, OutputInterface $output, HelperSet $helperSet)
- {
- $this->input = $input;
- $this->output = $output;
- $this->helperSet = $helperSet;
- }
- public function enableDebugging($startTime)
- {
- $this->startTime = $startTime;
- }
- public function isInteractive()
- {
- return $this->input->isInteractive();
- }
- public function isDecorated()
- {
- return $this->output->isDecorated();
- }
- public function isVerbose()
- {
- return $this->output->getVerbosity() >= OutputInterface::VERBOSITY_VERBOSE;
- }
- public function isVeryVerbose()
- {
- return $this->output->getVerbosity() >= 3;
- }
- public function isDebug()
- {
- return $this->output->getVerbosity() >= 4;
- }
- public function write($messages, $newline = true)
- {
- $this->doWrite($messages, $newline, false);
- }
- public function writeError($messages, $newline = true)
- {
- $this->doWrite($messages, $newline, true);
- }
- private function doWrite($messages, $newline, $stderr)
- {
- if (null !== $this->startTime) {
- $memoryUsage = memory_get_usage() / 1024 / 1024;
- $timeSpent = microtime(true) - $this->startTime;
- $messages = array_map(function ($message) use ($memoryUsage, $timeSpent) {
- return sprintf('[%.1fMB/%.2fs] %s', $memoryUsage, $timeSpent, $message);
- }, (array) $messages);
- }
- if (true === $stderr && $this->output instanceof ConsoleOutputInterface) {
- $this->output->getErrorOutput()->write($messages, $newline);
- $this->lastMessageErr = join($newline ? "\n" : '', (array) $messages);
- return;
- }
- $this->output->write($messages, $newline);
- $this->lastMessage = join($newline ? "\n" : '', (array) $messages);
- }
- public function overwrite($messages, $newline = true, $size = null)
- {
- $this->doOverwrite($messages, $newline, $size, false);
- }
- public function overwriteError($messages, $newline = true, $size = null)
- {
- $this->doOverwrite($messages, $newline, $size, true);
- }
- private function doOverwrite($messages, $newline, $size, $stderr)
- {
- if (true === $stderr && $this->output instanceof ConsoleOutputInterface) {
- $output = $this->output->getErrorOutput();
- } else {
- $output = $this->output;
- }
- if (!$output->isDecorated()) {
- if (!$messages) {
- return;
- }
- $this->doWrite($messages, count($messages) === 1 || $newline, $stderr);
- return;
- }
- $messages = join($newline ? "\n" : '', (array) $messages);
- if (!isset($size)) {
- $size = strlen(strip_tags($stderr ? $this->lastMessageErr : $this->lastMessage));
- }
- $this->doWrite(str_repeat("\x08", $size), false, $stderr);
- $this->doWrite($messages, false, $stderr);
- $fill = $size - strlen(strip_tags($messages));
- if ($fill > 0) {
- $this->doWrite(str_repeat(' ', $fill), false, $stderr);
- $this->doWrite(str_repeat("\x08", $fill), false, $stderr);
- }
- if ($newline) {
- $this->doWrite('', true, $stderr);
- }
- $this->lastMessage = $messages;
- }
- public function ask($question, $default = null)
- {
- $output = $this->output;
- if ($output instanceof ConsoleOutputInterface) {
- $output = $output->getErrorOutput();
- }
- $dialog = $this->helperSet->get('dialog');
- return $dialog->ask($output, $question, $default);
- }
- public function askConfirmation($question, $default = true)
- {
- $output = $this->output;
- if ($output instanceof ConsoleOutputInterface) {
- $output = $output->getErrorOutput();
- }
- $dialog = $this->helperSet->get('dialog');
- return $dialog->askConfirmation($output, $question, $default);
- }
- public function askAndValidate($question, $validator, $attempts = false, $default = null)
- {
- $output = $this->output;
- if ($output instanceof ConsoleOutputInterface) {
- $output = $output->getErrorOutput();
- }
- $dialog = $this->helperSet->get('dialog');
- return $dialog->askAndValidate($output, $question, $validator, $attempts, $default);
- }
- public function askAndHideAnswer($question)
- {
- if (defined('PHP_WINDOWS_VERSION_BUILD')) {
- $finder = new ExecutableFinder();
- if ($finder->find('bash') && $finder->find('stty')) {
- $this->writeError($question, false);
- $value = rtrim(shell_exec('bash -c "stty -echo; read -n0 discard; read -r mypassword; stty echo; echo $mypassword"'));
- $this->writeError('');
- return $value;
- }
- $exe = __DIR__.'\\hiddeninput.exe';
- if ('phar:' === substr(__FILE__, 0, 5)) {
- $tmpExe = sys_get_temp_dir().'/hiddeninput.exe';
-
- $source = fopen(__DIR__.'\\hiddeninput.exe', 'r');
- $target = fopen($tmpExe, 'w+');
- stream_copy_to_stream($source, $target);
- fclose($source);
- fclose($target);
- unset($source, $target);
- $exe = $tmpExe;
- }
- $this->writeError($question, false);
- $value = rtrim(shell_exec($exe));
- $this->writeError('');
- if (isset($tmpExe)) {
- unlink($tmpExe);
- }
- return $value;
- }
- if (file_exists('/usr/bin/env')) {
- $test = "/usr/bin/env %s -c 'echo OK' 2> /dev/null";
- foreach (array('bash', 'zsh', 'ksh', 'csh') as $sh) {
- if ('OK' === rtrim(shell_exec(sprintf($test, $sh)))) {
- $shell = $sh;
- break;
- }
- }
- if (isset($shell)) {
- $this->writeError($question, false);
- $readCmd = ($shell === 'csh') ? 'set mypassword = $<' : 'read -r mypassword';
- $command = sprintf("/usr/bin/env %s -c 'stty -echo; %s; stty echo; echo \$mypassword'", $shell, $readCmd);
- $value = rtrim(shell_exec($command));
- $this->writeError('');
- return $value;
- }
- }
- return $this->ask($question);
- }
- }
- <?php
- namespace Composer\IO;
- use Composer\Config;
- interface IOInterface
- {
- public function isInteractive();
- public function isVerbose();
- public function isVeryVerbose();
- public function isDebug();
- public function isDecorated();
- public function write($messages, $newline = true);
- public function writeError($messages, $newline = true);
- public function overwrite($messages, $newline = true, $size = null);
- public function overwriteError($messages, $newline = true, $size = null);
- public function ask($question, $default = null);
- public function askConfirmation($question, $default = true);
- public function askAndValidate($question, $validator, $attempts = false, $default = null);
- public function askAndHideAnswer($question);
- public function getAuthentications();
- public function hasAuthentication($repositoryName);
- public function getAuthentication($repositoryName);
- public function setAuthentication($repositoryName, $username, $password = null);
- public function loadConfiguration(Config $config);
- }
- <?php
- namespace Composer\IO;
- class NullIO extends BaseIO
- {
- public function isInteractive()
- {
- return false;
- }
- public function isVerbose()
- {
- return false;
- }
- public function isVeryVerbose()
- {
- return false;
- }
- public function isDebug()
- {
- return false;
- }
- public function isDecorated()
- {
- return false;
- }
- public function write($messages, $newline = true)
- {
- }
- public function writeError($messages, $newline = true)
- {
- }
- public function overwrite($messages, $newline = true, $size = 80)
- {
- }
- public function overwriteError($messages, $newline = true, $size = 80)
- {
- }
- public function ask($question, $default = null)
- {
- return $default;
- }
- public function askConfirmation($question, $default = true)
- {
- return $default;
- }
- public function askAndValidate($question, $validator, $attempts = false, $default = null)
- {
- return $default;
- }
- public function askAndHideAnswer($question)
- {
- return null;
- }
- }
- <?php
- namespace Composer\Json;
- use JsonSchema\Validator;
- use Seld\JsonLint\JsonParser;
- use Seld\JsonLint\ParsingException;
- use Composer\Util\RemoteFilesystem;
- use Composer\Downloader\TransportException;
- class JsonFile
- {
- const LAX_SCHEMA = 1;
- const STRICT_SCHEMA = 2;
- const JSON_UNESCAPED_SLASHES = 64;
- const JSON_PRETTY_PRINT = 128;
- const JSON_UNESCAPED_UNICODE = 256;
- private $path;
- private $rfs;
- public function __construct($path, RemoteFilesystem $rfs = null)
- {
- $this->path = $path;
- if (null === $rfs && preg_match('{^https?://}i', $path)) {
- throw new \InvalidArgumentException('http urls require a RemoteFilesystem instance to be passed');
- }
- $this->rfs = $rfs;
- }
- public function getPath()
- {
- return $this->path;
- }
- public function exists()
- {
- return is_file($this->path);
- }
- public function read()
- {
- try {
- if ($this->rfs) {
- $json = $this->rfs->getContents($this->path, $this->path, false);
- } else {
- $json = file_get_contents($this->path);
- }
- } catch (TransportException $e) {
- throw new \RuntimeException($e->getMessage(), 0, $e);
- } catch (\Exception $e) {
- throw new \RuntimeException('Could not read '.$this->path."\n\n".$e->getMessage());
- }
- return static::parseJson($json, $this->path);
- }
- public function write(array $hash, $options = 448)
- {
- $dir = dirname($this->path);
- if (!is_dir($dir)) {
- if (file_exists($dir)) {
- throw new \UnexpectedValueException(
- $dir.' exists and is not a directory.'
- );
- }
- if (!@mkdir($dir, 0777, true)) {
- throw new \UnexpectedValueException(
- $dir.' does not exist and could not be created.'
- );
- }
- }
- $retries = 3;
- while ($retries--) {
- try {
- file_put_contents($this->path, static::encode($hash, $options). ($options & self::JSON_PRETTY_PRINT ? "\n" : ''));
- break;
- } catch (\Exception $e) {
- if ($retries) {
- usleep(500000);
- continue;
- }
- throw $e;
- }
- }
- }
- public function validateSchema($schema = self::STRICT_SCHEMA)
- {
- $content = file_get_contents($this->path);
- $data = json_decode($content);
- if (null === $data && 'null' !== $content) {
- self::validateSyntax($content, $this->path);
- }
- $schemaFile = __DIR__ . '/../../../res/composer-schema.json';
- $schemaData = json_decode(file_get_contents($schemaFile));
- if ($schema === self::LAX_SCHEMA) {
- $schemaData->additionalProperties = true;
- $schemaData->required = array();
- }
- $validator = new Validator();
- $validator->check($data, $schemaData);
- if (!$validator->isValid()) {
- $errors = array();
- foreach ((array) $validator->getErrors() as $error) {
- $errors[] = ($error['property'] ? $error['property'].' : ' : '').$error['message'];
- }
- throw new JsonValidationException('"'.$this->path.'" does not match the expected JSON schema', $errors);
- }
- return true;
- }
- public static function encode($data, $options = 448)
- {
- if (version_compare(PHP_VERSION, '5.4', '>=')) {
- $json = json_encode($data, $options);
- if (PHP_VERSION_ID < 50428 || (PHP_VERSION_ID >= 50500 && PHP_VERSION_ID < 50512) || (defined('JSON_C_VERSION') && version_compare(phpversion('json'), '1.3.6', '<'))) {
- $json = preg_replace('/\[\s+\]/', '[]', $json);
- $json = preg_replace('/\{\s+\}/', '{}', $json);
- }
- return $json;
- }
- $json = json_encode($data);
- $prettyPrint = (bool) ($options & self::JSON_PRETTY_PRINT);
- $unescapeUnicode = (bool) ($options & self::JSON_UNESCAPED_UNICODE);
- $unescapeSlashes = (bool) ($options & self::JSON_UNESCAPED_SLASHES);
- if (!$prettyPrint && !$unescapeUnicode && !$unescapeSlashes) {
- return $json;
- }
- $result = JsonFormatter::format($json, $unescapeUnicode, $unescapeSlashes);
- return $result;
- }
- public static function parseJson($json, $file = null)
- {
- $data = json_decode($json, true);
- if (null === $data && JSON_ERROR_NONE !== json_last_error()) {
- self::validateSyntax($json, $file);
- }
- return $data;
- }
- protected static function validateSyntax($json, $file = null)
- {
- $parser = new JsonParser();
- $result = $parser->lint($json);
- if (null === $result) {
- if (defined('JSON_ERROR_UTF8') && JSON_ERROR_UTF8 === json_last_error()) {
- throw new \UnexpectedValueException('"'.$file.'" is not UTF-8, could not parse as JSON');
- }
- return true;
- }
- throw new ParsingException('"'.$file.'" does not contain valid JSON'."\n".$result->getMessage(), $result->getDetails());
- }
- }
- <?php
- namespace Composer\Json;
- class JsonFormatter
- {
- public static function format($json, $unescapeUnicode, $unescapeSlashes)
- {
- $result = '';
- $pos = 0;
- $strLen = strlen($json);
- $indentStr = ' ';
- $newLine = "\n";
- $outOfQuotes = true;
- $buffer = '';
- $noescape = true;
- for ($i = 0; $i < $strLen; $i++) {
- $char = substr($json, $i, 1);
- if ('"' === $char && $noescape) {
- $outOfQuotes = !$outOfQuotes;
- }
- if (!$outOfQuotes) {
- $buffer .= $char;
- $noescape = '\\' === $char ? !$noescape : true;
- continue;
- } elseif ('' !== $buffer) {
- if ($unescapeSlashes) {
- $buffer = str_replace('\\/', '/', $buffer);
- }
- if ($unescapeUnicode && function_exists('mb_convert_encoding')) {
- $buffer = preg_replace_callback('/(\\\\+)u([0-9a-f]{4})/i', function ($match) {
- $l = strlen($match[1]);
- if ($l % 2) {
- return str_repeat('\\', $l - 1) . mb_convert_encoding(
- pack('H*', $match[2]),
- 'UTF-8',
- 'UCS-2BE'
- );
- }
- return $match[0];
- }, $buffer);
- }
- $result .= $buffer.$char;
- $buffer = '';
- continue;
- }
- if (':' === $char) {
- $char .= ' ';
- } elseif (('}' === $char || ']' === $char)) {
- $pos--;
- $prevChar = substr($json, $i - 1, 1);
- if ('{' !== $prevChar && '[' !== $prevChar) {
-
- $result .= $newLine;
- for ($j = 0; $j < $pos; $j++) {
- $result .= $indentStr;
- }
- } else {
- $result = rtrim($result);
- }
- }
- $result .= $char;
-
- if (',' === $char || '{' === $char || '[' === $char) {
- $result .= $newLine;
- if ('{' === $char || '[' === $char) {
- $pos++;
- }
- for ($j = 0; $j < $pos; $j++) {
- $result .= $indentStr;
- }
- }
- }
- return $result;
- }
- }
- <?php
- namespace Composer\Json;
- class JsonManipulator
- {
- private static $RECURSE_BLOCKS;
- private static $RECURSE_ARRAYS;
- private static $JSON_VALUE;
- private static $JSON_STRING;
- private $contents;
- private $newline;
- private $indent;
- public function __construct($contents)
- {
- if (!self::$RECURSE_BLOCKS) {
- self::$RECURSE_BLOCKS = '(?:[^{}]*|\{(?:[^{}]*|\{(?:[^{}]*|\{(?:[^{}]*|\{[^{}]*\})*\})*\})*\})*';
- self::$RECURSE_ARRAYS = '(?:[^\]]*|\[(?:[^\]]*|\[(?:[^\]]*|\[(?:[^\]]*|\[[^\]]*\])*\])*\])*\]|'.self::$RECURSE_BLOCKS.')*';
- self::$JSON_STRING = '"(?:[^\0-\x09\x0a-\x1f\\\\"]+|\\\\["bfnrt/\\\\]|\\\\u[a-fA-F0-9]{4})*"';
- self::$JSON_VALUE = '(?:[0-9.]+|null|true|false|'.self::$JSON_STRING.'|\['.self::$RECURSE_ARRAYS.'\]|\{'.self::$RECURSE_BLOCKS.'\})';
- }
- $contents = trim($contents);
- if ($contents === '') {
- $contents = '{}';
- }
- if (!$this->pregMatch('#^\{(.*)\}$#s', $contents)) {
- throw new \InvalidArgumentException('The json file must be an object ({})');
- }
- $this->newline = false !== strpos($contents, "\r\n") ? "\r\n" : "\n";
- $this->contents = $contents === '{}' ? '{' . $this->newline . '}' : $contents;
- $this->detectIndenting();
- }
- public function getContents()
- {
- return $this->contents . $this->newline;
- }
- public function addLink($type, $package, $constraint, $sortPackages = false)
- {
- $decoded = JsonFile::parseJson($this->contents);
- if (!isset($decoded[$type])) {
- return $this->addMainKey($type, array($package => $constraint));
- }
- $regex = '{^(\s*\{\s*(?:'.self::$JSON_STRING.'\s*:\s*'.self::$JSON_VALUE.'\s*,\s*)*?)'.
- '('.preg_quote(JsonFile::encode($type)).'\s*:\s*)('.self::$JSON_VALUE.')(.*)}s';
- if (!$this->pregMatch($regex, $this->contents, $matches)) {
- return false;
- }
- $links = $matches[3];
- if (isset($decoded[$type][$package])) {
- $packageRegex = str_replace('/', '\\\\?/', preg_quote($package));
- $links = preg_replace('{"'.$packageRegex.'"(\s*:\s*)'.self::$JSON_STRING.'}i', addcslashes(JsonFile::encode($package).'${1}"'.$constraint.'"', '\\'), $links);
- } else {
- if ($this->pregMatch('#^\s*\{\s*\S+.*?(\s*\}\s*)$#s', $links, $match)) {
- $links = preg_replace(
- '{'.preg_quote($match[1]).'$}',
- addcslashes(',' . $this->newline . $this->indent . $this->indent . JsonFile::encode($package).': '.JsonFile::encode($constraint) . $match[1], '\\'),
- $links
- );
- } else {
- $links = '{' . $this->newline .
- $this->indent . $this->indent . JsonFile::encode($package).': '.JsonFile::encode($constraint) . $this->newline .
- $this->indent . '}';
- }
- }
- if (true === $sortPackages) {
- $requirements = json_decode($links, true);
- ksort($requirements);
- $links = $this->format($requirements);
- }
- $this->contents = $matches[1] . $matches[2] . $links . $matches[4];
- return true;
- }
- public function addRepository($name, $config)
- {
- return $this->addSubNode('repositories', $name, $config);
- }
- public function removeRepository($name)
- {
- return $this->removeSubNode('repositories', $name);
- }
- public function addConfigSetting($name, $value)
- {
- return $this->addSubNode('config', $name, $value);
- }
- public function removeConfigSetting($name)
- {
- return $this->removeSubNode('config', $name);
- }
- public function addSubNode($mainNode, $name, $value)
- {
- $decoded = JsonFile::parseJson($this->contents);
- if (!isset($decoded[$mainNode])) {
- $this->addMainKey($mainNode, array($name => $value));
- return true;
- }
- $subName = null;
- if (in_array($mainNode, array('config', 'repositories')) && false !== strpos($name, '.')) {
- list($name, $subName) = explode('.', $name, 2);
- }
- $nodeRegex = '{^(\s*\{\s*(?:'.self::$JSON_STRING.'\s*:\s*'.self::$JSON_VALUE.'\s*,\s*)*?)'.
- '('.preg_quote(JsonFile::encode($mainNode)).'\s*:\s*\{)('.self::$RECURSE_BLOCKS.')(\})(.*)}s';
- try {
- if (!$this->pregMatch($nodeRegex, $this->contents, $match)) {
- return false;
- }
- } catch (\RuntimeException $e) {
- if ($e->getCode() === PREG_BACKTRACK_LIMIT_ERROR) {
- return false;
- }
- throw $e;
- }
- $children = $match[3];
- if (!@json_decode('{'.$children.'}')) {
- return false;
- }
- $that = $this;
- if ($this->pregMatch('{("'.preg_quote($name).'"\s*:\s*)('.self::$JSON_VALUE.')(,?)}', $children, $matches)) {
- $children = preg_replace_callback('{("'.preg_quote($name).'"\s*:\s*)('.self::$JSON_VALUE.')(,?)}', function ($matches) use ($name, $subName, $value, $that) {
- if ($subName !== null) {
- $curVal = json_decode($matches[2], true);
- $curVal[$subName] = $value;
- $value = $curVal;
- }
- return $matches[1] . $that->format($value, 1) . $matches[3];
- }, $children);
- } elseif ($this->pregMatch('#[^\s](\s*)$#', $children, $match)) {
- if ($subName !== null) {
- $value = array($subName => $value);
- }
- $children = preg_replace(
- '#'.$match[1].'$#',
- addcslashes(',' . $this->newline . $this->indent . $this->indent . JsonFile::encode($name).': '.$this->format($value, 1) . $match[1], '\\'),
- $children
- );
- } else {
- if ($subName !== null) {
- $value = array($subName => $value);
- }
- $children = $this->newline . $this->indent . $this->indent . JsonFile::encode($name).': '.$this->format($value, 1) . $children;
- }
- $this->contents = preg_replace($nodeRegex, addcslashes('${1}${2}'.$children.'${4}${5}', '\\'), $this->contents);
- return true;
- }
- public function removeSubNode($mainNode, $name)
- {
- $decoded = JsonFile::parseJson($this->contents);
- if (empty($decoded[$mainNode])) {
- return true;
- }
- $nodeRegex = '{^(\s*\{\s*(?:'.self::$JSON_STRING.'\s*:\s*'.self::$JSON_VALUE.'\s*,\s*)*?)'.
- '('.preg_quote(JsonFile::encode($mainNode)).'\s*:\s*\{)('.self::$RECURSE_BLOCKS.')(\})(.*)}s';
- try {
- if (!$this->pregMatch($nodeRegex, $this->contents, $match)) {
- return false;
- }
- } catch (\RuntimeException $e) {
- if ($e->getCode() === PREG_BACKTRACK_LIMIT_ERROR) {
- return false;
- }
- throw $e;
- }
- $children = $match[3];
- if (!@json_decode('{'.$children.'}', true)) {
- return false;
- }
- $subName = null;
- if (in_array($mainNode, array('config', 'repositories')) && false !== strpos($name, '.')) {
- list($name, $subName) = explode('.', $name, 2);
- }
- if (!isset($decoded[$mainNode][$name]) || ($subName && !isset($decoded[$mainNode][$name][$subName]))) {
- return true;
- }
- if ($this->pregMatch('{"'.preg_quote($name).'"\s*:}i', $children)) {
- if (preg_match_all('{"'.preg_quote($name).'"\s*:\s*(?:'.self::$JSON_VALUE.')}', $children, $matches)) {
- $bestMatch = '';
- foreach ($matches[0] as $match) {
- if (strlen($bestMatch) < strlen($match)) {
- $bestMatch = $match;
- }
- }
- $childrenClean = preg_replace('{,\s*'.preg_quote($bestMatch).'}i', '', $children, -1, $count);
- if (1 !== $count) {
- $childrenClean = preg_replace('{'.preg_quote($bestMatch).'\s*,?\s*}i', '', $childrenClean, -1, $count);
- if (1 !== $count) {
- return false;
- }
- }
- }
- } else {
- $childrenClean = $children;
- }
- if (!trim($childrenClean)) {
- $this->contents = preg_replace($nodeRegex, '$1$2'.$this->newline.$this->indent.'$4$5', $this->contents);
- if ($subName !== null) {
- $curVal = json_decode('{'.$children.'}', true);
- unset($curVal[$name][$subName]);
- $this->addSubNode($mainNode, $name, $curVal[$name]);
- }
- return true;
- }
- $that = $this;
- $this->contents = preg_replace_callback($nodeRegex, function ($matches) use ($that, $name, $subName, $childrenClean) {
- if ($subName !== null) {
- $curVal = json_decode('{'.$matches[3].'}', true);
- unset($curVal[$name][$subName]);
- $childrenClean = substr($that->format($curVal, 0), 1, -1);
- }
- return $matches[1] . $matches[2] . $childrenClean . $matches[4] . $matches[5];
- }, $this->contents);
- return true;
- }
- public function addMainKey($key, $content)
- {
- $decoded = JsonFile::parseJson($this->contents);
- $content = $this->format($content);
- $regex = '{^(\s*\{\s*(?:'.self::$JSON_STRING.'\s*:\s*'.self::$JSON_VALUE.'\s*,\s*)*?)'.
- '('.preg_quote(JsonFile::encode($key)).'\s*:\s*'.self::$JSON_VALUE.')(.*)}s';
- if (isset($decoded[$key]) && $this->pregMatch($regex, $this->contents, $matches)) {
- if (!@json_decode('{'.$matches[2].'}')) {
- return false;
- }
- $this->contents = $matches[1] . JsonFile::encode($key).': '.$content . $matches[3];
- return true;
- }
- if ($this->pregMatch('#[^{\s](\s*)\}$#', $this->contents, $match)) {
- $this->contents = preg_replace(
- '#'.$match[1].'\}$#',
- addcslashes(',' . $this->newline . $this->indent . JsonFile::encode($key). ': '. $content . $this->newline . '}', '\\'),
- $this->contents
- );
- return true;
- }
- $this->contents = preg_replace(
- '#\}$#',
- addcslashes($this->indent . JsonFile::encode($key). ': '.$content . $this->newline . '}', '\\'),
- $this->contents
- );
- return true;
- }
- public function format($data, $depth = 0)
- {
- if (is_array($data)) {
- reset($data);
- if (is_numeric(key($data))) {
- foreach ($data as $key => $val) {
- $data[$key] = $this->format($val, $depth + 1);
- }
- return '['.implode(', ', $data).']';
- }
- $out = '{' . $this->newline;
- $elems = array();
- foreach ($data as $key => $val) {
- $elems[] = str_repeat($this->indent, $depth + 2) . JsonFile::encode($key). ': '.$this->format($val, $depth + 1);
- }
- return $out . implode(','.$this->newline, $elems) . $this->newline . str_repeat($this->indent, $depth + 1) . '}';
- }
- return JsonFile::encode($data);
- }
- protected function detectIndenting()
- {
- if ($this->pregMatch('{^(\s+)"}m', $this->contents, $match)) {
- $this->indent = $match[1];
- } else {
- $this->indent = ' ';
- }
- }
- protected function pregMatch($re, $str, &$matches = array())
- {
- $count = preg_match($re, $str, $matches);
- if ($count === false) {
- switch (preg_last_error()) {
- case PREG_NO_ERROR:
- throw new \RuntimeException('Failed to execute regex: PREG_NO_ERROR', PREG_NO_ERROR);
- case PREG_INTERNAL_ERROR:
- throw new \RuntimeException('Failed to execute regex: PREG_INTERNAL_ERROR', PREG_INTERNAL_ERROR);
- case PREG_BACKTRACK_LIMIT_ERROR:
- throw new \RuntimeException('Failed to execute regex: PREG_BACKTRACK_LIMIT_ERROR', PREG_BACKTRACK_LIMIT_ERROR);
- case PREG_RECURSION_LIMIT_ERROR:
- throw new \RuntimeException('Failed to execute regex: PREG_RECURSION_LIMIT_ERROR', PREG_RECURSION_LIMIT_ERROR);
- case PREG_BAD_UTF8_ERROR:
- throw new \RuntimeException('Failed to execute regex: PREG_BAD_UTF8_ERROR', PREG_BAD_UTF8_ERROR);
- case PREG_BAD_UTF8_OFFSET_ERROR:
- throw new \RuntimeException('Failed to execute regex: PREG_BAD_UTF8_OFFSET_ERROR', PREG_BAD_UTF8_OFFSET_ERROR);
- default:
- throw new \RuntimeException('Failed to execute regex: Unknown error');
- }
- }
- return $count;
- }
- }
- <?php
- namespace Composer\Json;
- use Exception;
- class JsonValidationException extends Exception
- {
- protected $errors;
- public function __construct($message, $errors = array(), Exception $previous = null)
- {
- $this->errors = $errors;
- parent::__construct($message, 0, $previous);
- }
- public function getErrors()
- {
- return $this->errors;
- }
- }
- <?php
- namespace Composer\Package;
- use Composer\Package\LinkConstraint\VersionConstraint;
- use Composer\Package\Version\VersionParser;
- class AliasPackage extends BasePackage implements CompletePackageInterface
- {
- protected $version;
- protected $prettyVersion;
- protected $dev;
- protected $aliasOf;
- protected $rootPackageAlias = false;
- protected $stability;
- protected $requires;
- protected $conflicts;
- protected $provides;
- protected $replaces;
- protected $recommends;
- protected $suggests;
- public function __construct(PackageInterface $aliasOf, $version, $prettyVersion)
- {
- parent::__construct($aliasOf->getName());
- $this->version = $version;
- $this->prettyVersion = $prettyVersion;
- $this->aliasOf = $aliasOf;
- $this->stability = VersionParser::parseStability($version);
- $this->dev = $this->stability === 'dev';
- foreach (array('requires', 'devRequires') as $type) {
- $links = $aliasOf->{'get'.ucfirst($type)}();
- foreach ($links as $index => $link) {
- if ('self.version' === $link->getPrettyConstraint()) {
- $links[$index] = new Link($link->getSource(), $link->getTarget(), new VersionConstraint('=', $this->version), $type, $prettyVersion);
- }
- }
- $this->$type = $links;
- }
- foreach (array('conflicts', 'provides', 'replaces') as $type) {
- $links = $aliasOf->{'get'.ucfirst($type)}();
- $newLinks = array();
- foreach ($links as $link) {
- if ('self.version' === $link->getPrettyConstraint()) {
- $newLinks[] = new Link($link->getSource(), $link->getTarget(), new VersionConstraint('=', $this->version), $type, $prettyVersion);
- }
- }
- $this->$type = array_merge($links, $newLinks);
- }
- }
- public function getAliasOf()
- {
- return $this->aliasOf;
- }
- public function getVersion()
- {
- return $this->version;
- }
- public function getStability()
- {
- return $this->stability;
- }
- public function getPrettyVersion()
- {
- return $this->prettyVersion;
- }
- public function isDev()
- {
- return $this->dev;
- }
- public function getRequires()
- {
- return $this->requires;
- }
- public function getConflicts()
- {
- return $this->conflicts;
- }
- public function getProvides()
- {
- return $this->provides;
- }
- public function getReplaces()
- {
- return $this->replaces;
- }
- public function getDevRequires()
- {
- return $this->devRequires;
- }
- public function setRootPackageAlias($value)
- {
- return $this->rootPackageAlias = $value;
- }
- public function isRootPackageAlias()
- {
- return $this->rootPackageAlias;
- }
- public function getType()
- {
- return $this->aliasOf->getType();
- }
- public function getTargetDir()
- {
- return $this->aliasOf->getTargetDir();
- }
- public function getExtra()
- {
- return $this->aliasOf->getExtra();
- }
- public function setInstallationSource($type)
- {
- $this->aliasOf->setInstallationSource($type);
- }
- public function getInstallationSource()
- {
- return $this->aliasOf->getInstallationSource();
- }
- public function getSourceType()
- {
- return $this->aliasOf->getSourceType();
- }
- public function getSourceUrl()
- {
- return $this->aliasOf->getSourceUrl();
- }
- public function getSourceUrls()
- {
- return $this->aliasOf->getSourceUrls();
- }
- public function getSourceReference()
- {
- return $this->aliasOf->getSourceReference();
- }
- public function setSourceReference($reference)
- {
- return $this->aliasOf->setSourceReference($reference);
- }
- public function setSourceMirrors($mirrors)
- {
- return $this->aliasOf->setSourceMirrors($mirrors);
- }
- public function getSourceMirrors()
- {
- return $this->aliasOf->getSourceMirrors();
- }
- public function getDistType()
- {
- return $this->aliasOf->getDistType();
- }
- public function getDistUrl()
- {
- return $this->aliasOf->getDistUrl();
- }
- public function getDistUrls()
- {
- return $this->aliasOf->getDistUrls();
- }
- public function getDistReference()
- {
- return $this->aliasOf->getDistReference();
- }
- public function setDistReference($reference)
- {
- return $this->aliasOf->setDistReference($reference);
- }
- public function getDistSha1Checksum()
- {
- return $this->aliasOf->getDistSha1Checksum();
- }
- public function setTransportOptions(array $options)
- {
- return $this->aliasOf->setTransportOptions($options);
- }
- public function getTransportOptions()
- {
- return $this->aliasOf->getTransportOptions();
- }
- public function setDistMirrors($mirrors)
- {
- return $this->aliasOf->setDistMirrors($mirrors);
- }
- public function getDistMirrors()
- {
- return $this->aliasOf->getDistMirrors();
- }
- public function getScripts()
- {
- return $this->aliasOf->getScripts();
- }
- public function getLicense()
- {
- return $this->aliasOf->getLicense();
- }
- public function getAutoload()
- {
- return $this->aliasOf->getAutoload();
- }
- public function getDevAutoload()
- {
- return $this->aliasOf->getDevAutoload();
- }
- public function getIncludePaths()
- {
- return $this->aliasOf->getIncludePaths();
- }
- public function getRepositories()
- {
- return $this->aliasOf->getRepositories();
- }
- public function getReleaseDate()
- {
- return $this->aliasOf->getReleaseDate();
- }
- public function getBinaries()
- {
- return $this->aliasOf->getBinaries();
- }
- public function getKeywords()
- {
- return $this->aliasOf->getKeywords();
- }
- public function getDescription()
- {
- return $this->aliasOf->getDescription();
- }
- public function getHomepage()
- {
- return $this->aliasOf->getHomepage();
- }
- public function getSuggests()
- {
- return $this->aliasOf->getSuggests();
- }
- public function getAuthors()
- {
- return $this->aliasOf->getAuthors();
- }
- public function getSupport()
- {
- return $this->aliasOf->getSupport();
- }
- public function getNotificationUrl()
- {
- return $this->aliasOf->getNotificationUrl();
- }
- public function getArchiveExcludes()
- {
- return $this->aliasOf->getArchiveExcludes();
- }
- public function isAbandoned()
- {
- return $this->aliasOf->isAbandoned();
- }
- public function getReplacementPackage()
- {
- return $this->aliasOf->getReplacementPackage();
- }
- public function __toString()
- {
- return parent::__toString().' (alias of '.$this->aliasOf->getVersion().')';
- }
- }
- <?php
- namespace Composer\Package\Archiver;
- use Composer\Util\Filesystem;
- use Symfony\Component\Finder;
- class ArchivableFilesFinder extends \FilterIterator
- {
- protected $finder;
- public function __construct($sources, array $excludes)
- {
- $fs = new Filesystem();
- $sources = $fs->normalizePath($sources);
- $filters = array(
- new HgExcludeFilter($sources),
- new GitExcludeFilter($sources),
- new ComposerExcludeFilter($sources, $excludes),
- );
- $this->finder = new Finder\Finder();
- $filter = function (\SplFileInfo $file) use ($sources, $filters, $fs) {
- if ($file->isLink() && strpos($file->getLinkTarget(), $sources) !== 0) {
- return false;
- }
- $relativePath = preg_replace(
- '#^'.preg_quote($sources, '#').'#',
- '',
- $fs->normalizePath($file->getRealPath())
- );
- $exclude = false;
- foreach ($filters as $filter) {
- $exclude = $filter->filter($relativePath, $exclude);
- }
- return !$exclude;
- };
- if (method_exists($filter, 'bindTo')) {
- $filter = $filter->bindTo(null);
- }
- $this->finder
- ->in($sources)
- ->filter($filter)
- ->ignoreVCS(true)
- ->ignoreDotFiles(false);
- parent::__construct($this->finder->getIterator());
- }
- public function accept()
- {
- return !$this->getInnerIterator()->current()->isDir();
- }
- }
- <?php
- namespace Composer\Package\Archiver;
- use Composer\Downloader\DownloadManager;
- use Composer\Package\PackageInterface;
- use Composer\Package\RootPackageInterface;
- use Composer\Util\Filesystem;
- use Composer\Json\JsonFile;
- class ArchiveManager
- {
- protected $downloadManager;
- protected $archivers = array();
- protected $overwriteFiles = true;
- public function __construct(DownloadManager $downloadManager)
- {
- $this->downloadManager = $downloadManager;
- }
- public function addArchiver(ArchiverInterface $archiver)
- {
- $this->archivers[] = $archiver;
- }
- public function setOverwriteFiles($overwriteFiles)
- {
- $this->overwriteFiles = $overwriteFiles;
- return $this;
- }
- public function getPackageFilename(PackageInterface $package)
- {
- $nameParts = array(preg_replace('#[^a-z0-9-_]#i', '-', $package->getName()));
- if (preg_match('{^[a-f0-9]{40}$}', $package->getDistReference())) {
- $nameParts = array_merge($nameParts, array($package->getDistReference(), $package->getDistType()));
- } else {
- $nameParts = array_merge($nameParts, array($package->getPrettyVersion(), $package->getDistReference()));
- }
- if ($package->getSourceReference()) {
- $nameParts[] = substr(sha1($package->getSourceReference()), 0, 6);
- }
- $name = implode('-', array_filter($nameParts, function ($p) {
- return !empty($p);
- }));
- return str_replace('/', '-', $name);
- }
- public function archive(PackageInterface $package, $format, $targetDir)
- {
- if (empty($format)) {
- throw new \InvalidArgumentException('Format must be specified');
- }
- $usableArchiver = null;
- foreach ($this->archivers as $archiver) {
- if ($archiver->supports($format, $package->getSourceType())) {
- $usableArchiver = $archiver;
- break;
- }
- }
- if (null === $usableArchiver) {
- throw new \RuntimeException(sprintf('No archiver found to support %s format', $format));
- }
- $filesystem = new Filesystem();
- $packageName = $this->getPackageFilename($package);
- $filesystem->ensureDirectoryExists($targetDir);
- $target = realpath($targetDir).'/'.$packageName.'.'.$format;
- $filesystem->ensureDirectoryExists(dirname($target));
- if (!$this->overwriteFiles && file_exists($target)) {
- return $target;
- }
- if ($package instanceof RootPackageInterface) {
- $sourcePath = realpath('.');
- } else {
- $sourcePath = sys_get_temp_dir().'/composer_archive'.uniqid();
- $filesystem->ensureDirectoryExists($sourcePath);
- $this->downloadManager->download($package, $sourcePath);
- if (file_exists($composerJsonPath = $sourcePath.'/composer.json')) {
- $jsonFile = new JsonFile($composerJsonPath);
- $jsonData = $jsonFile->read();
- if (!empty($jsonData['archive']['exclude'])) {
- $package->setArchiveExcludes($jsonData['archive']['exclude']);
- }
- }
- }
- $tempTarget = sys_get_temp_dir().'/composer_archive'.uniqid().'.'.$format;
- $filesystem->ensureDirectoryExists(dirname($tempTarget));
- $archivePath = $usableArchiver->archive($sourcePath, $tempTarget, $format, $package->getArchiveExcludes());
- rename($archivePath, $target);
- if (!$package instanceof RootPackageInterface) {
- $filesystem->removeDirectory($sourcePath);
- }
- $filesystem->remove($tempTarget);
- return $target;
- }
- }
- <?php
- namespace Composer\Package\Archiver;
- interface ArchiverInterface
- {
- public function archive($sources, $target, $format, array $excludes = array());
- public function supports($format, $sourceType);
- }
- <?php
- namespace Composer\Package\Archiver;
- use Symfony\Component\Finder;
- abstract class BaseExcludeFilter
- {
- protected $sourcePath;
- protected $excludePatterns;
- public function __construct($sourcePath)
- {
- $this->sourcePath = $sourcePath;
- $this->excludePatterns = array();
- }
- public function filter($relativePath, $exclude)
- {
- foreach ($this->excludePatterns as $patternData) {
- list($pattern, $negate, $stripLeadingSlash) = $patternData;
- if ($stripLeadingSlash) {
- $path = substr($relativePath, 1);
- } else {
- $path = $relativePath;
- }
- if (preg_match($pattern, $path)) {
- $exclude = !$negate;
- }
- }
- return $exclude;
- }
- protected function parseLines(array $lines, $lineParser)
- {
- return array_filter(
- array_map(
- function ($line) use ($lineParser) {
- $line = trim($line);
- if (!$line || 0 === strpos($line, '#')) {
- return;
- }
- return call_user_func($lineParser, $line);
- },
- $lines
- ),
- function ($pattern) {
- return $pattern !== null;
- }
- );
- }
- protected function generatePatterns($rules)
- {
- $patterns = array();
- foreach ($rules as $rule) {
- $patterns[] = $this->generatePattern($rule);
- }
- return $patterns;
- }
- protected function generatePattern($rule)
- {
- $negate = false;
- $pattern = '#';
- if (strlen($rule) && $rule[0] === '!') {
- $negate = true;
- $rule = substr($rule, 1);
- }
- if (strlen($rule) && $rule[0] === '/') {
- $pattern .= '^/';
- $rule = substr($rule, 1);
- } elseif (strlen($rule) - 1 === strpos($rule, '/')) {
- $pattern .= '/';
- $rule = substr($rule, 0, -1);
- } elseif (false === strpos($rule, '/')) {
- $pattern .= '/';
- }
- $pattern .= substr(Finder\Glob::toRegex($rule), 2, -2) . '(?=$|/)';
- return array($pattern . '#', $negate, false);
- }
- }
- <?php
- namespace Composer\Package\Archiver;
- class ComposerExcludeFilter extends BaseExcludeFilter
- {
- public function __construct($sourcePath, array $excludeRules)
- {
- parent::__construct($sourcePath);
- $this->excludePatterns = $this->generatePatterns($excludeRules);
- }
- }
- <?php
- namespace Composer\Package\Archiver;
- class GitExcludeFilter extends BaseExcludeFilter
- {
- public function __construct($sourcePath)
- {
- parent::__construct($sourcePath);
- if (file_exists($sourcePath.'/.gitignore')) {
- $this->excludePatterns = $this->parseLines(
- file($sourcePath.'/.gitignore'),
- array($this, 'parseGitIgnoreLine')
- );
- }
- if (file_exists($sourcePath.'/.gitattributes')) {
- $this->excludePatterns = array_merge(
- $this->excludePatterns,
- $this->parseLines(
- file($sourcePath.'/.gitattributes'),
- array($this, 'parseGitAttributesLine')
- ));
- }
- }
- public function parseGitIgnoreLine($line)
- {
- return $this->generatePattern($line);
- }
- public function parseGitAttributesLine($line)
- {
- $parts = preg_split('#\s+#', $line);
- if (count($parts) != 2) {
- return null;
- }
- if ($parts[1] === 'export-ignore') {
- return $this->generatePattern($parts[0]);
- }
- }
- }
- <?php
- namespace Composer\Package\Archiver;
- use Symfony\Component\Finder;
- class HgExcludeFilter extends BaseExcludeFilter
- {
- const HG_IGNORE_REGEX = 1;
- const HG_IGNORE_GLOB = 2;
- protected $patternMode;
- public function __construct($sourcePath)
- {
- parent::__construct($sourcePath);
- $this->patternMode = self::HG_IGNORE_REGEX;
- if (file_exists($sourcePath.'/.hgignore')) {
- $this->excludePatterns = $this->parseLines(
- file($sourcePath.'/.hgignore'),
- array($this, 'parseHgIgnoreLine')
- );
- }
- }
- public function parseHgIgnoreLine($line)
- {
- if (preg_match('#^syntax\s*:\s*(glob|regexp)$#', $line, $matches)) {
- if ($matches[1] === 'glob') {
- $this->patternMode = self::HG_IGNORE_GLOB;
- } else {
- $this->patternMode = self::HG_IGNORE_REGEX;
- }
- return null;
- }
- if ($this->patternMode == self::HG_IGNORE_GLOB) {
- return $this->patternFromGlob($line);
- } else {
- return $this->patternFromRegex($line);
- }
- }
- protected function patternFromGlob($line)
- {
- $pattern = '#'.substr(Finder\Glob::toRegex($line), 2, -1).'#';
- $pattern = str_replace('[^/]*', '.*', $pattern);
- return array($pattern, false, true);
- }
- public function patternFromRegex($line)
- {
- $pattern = '#'.preg_replace('/((?:\\\\\\\\)*)(\\\\?)#/', '\1\2\2\\#', $line).'#';
- return array($pattern, false, true);
- }
- }
- <?php
- namespace Composer\Package\Archiver;
- class PharArchiver implements ArchiverInterface
- {
- protected static $formats = array(
- 'zip' => \Phar::ZIP,
- 'tar' => \Phar::TAR,
- );
- public function archive($sources, $target, $format, array $excludes = array())
- {
- $sources = realpath($sources);
- if (file_exists($target)) {
- unlink($target);
- }
- try {
- $phar = new \PharData($target, null, null, static::$formats[$format]);
- $files = new ArchivableFilesFinder($sources, $excludes);
- $phar->buildFromIterator($files, $sources);
- return $target;
- } catch (\UnexpectedValueException $e) {
- $message = sprintf("Could not create archive '%s' from '%s': %s",
- $target,
- $sources,
- $e->getMessage()
- );
- throw new \RuntimeException($message, $e->getCode(), $e);
- }
- }
- public function supports($format, $sourceType)
- {
- return isset(static::$formats[$format]);
- }
- }
- <?php
- namespace Composer\Package;
- use Composer\Repository\RepositoryInterface;
- use Composer\Repository\PlatformRepository;
- abstract class BasePackage implements PackageInterface
- {
- public static $supportedLinkTypes = array(
- 'require' => array('description' => 'requires', 'method' => 'requires'),
- 'conflict' => array('description' => 'conflicts', 'method' => 'conflicts'),
- 'provide' => array('description' => 'provides', 'method' => 'provides'),
- 'replace' => array('description' => 'replaces', 'method' => 'replaces'),
- 'require-dev' => array('description' => 'requires (for development)', 'method' => 'devRequires'),
- );
- const STABILITY_STABLE = 0;
- const STABILITY_RC = 5;
- const STABILITY_BETA = 10;
- const STABILITY_ALPHA = 15;
- const STABILITY_DEV = 20;
- public static $stabilities = array(
- 'stable' => self::STABILITY_STABLE,
- 'RC' => self::STABILITY_RC,
- 'beta' => self::STABILITY_BETA,
- 'alpha' => self::STABILITY_ALPHA,
- 'dev' => self::STABILITY_DEV,
- );
- public $id;
- protected $name;
- protected $prettyName;
- protected $repository;
- protected $transportOptions;
- public function __construct($name)
- {
- $this->prettyName = $name;
- $this->name = strtolower($name);
- $this->id = -1;
- $this->transportOptions = array();
- }
- public function getName()
- {
- return $this->name;
- }
- public function getPrettyName()
- {
- return $this->prettyName;
- }
- public function getNames()
- {
- $names = array(
- $this->getName() => true,
- );
- foreach ($this->getProvides() as $link) {
- $names[$link->getTarget()] = true;
- }
- foreach ($this->getReplaces() as $link) {
- $names[$link->getTarget()] = true;
- }
- return array_keys($names);
- }
- public function setId($id)
- {
- $this->id = $id;
- }
- public function getId()
- {
- return $this->id;
- }
- public function setRepository(RepositoryInterface $repository)
- {
- if ($this->repository && $repository !== $this->repository) {
- throw new \LogicException('A package can only be added to one repository');
- }
- $this->repository = $repository;
- }
- public function getRepository()
- {
- return $this->repository;
- }
- public function getTransportOptions()
- {
- return $this->transportOptions;
- }
- public function setTransportOptions(array $options)
- {
- $this->transportOptions = $options;
- }
- public function isPlatform()
- {
- return $this->getRepository() instanceof PlatformRepository;
- }
- public function getUniqueName()
- {
- return $this->getName().'-'.$this->getVersion();
- }
- public function equals(PackageInterface $package)
- {
- $self = $this;
- if ($this instanceof AliasPackage) {
- $self = $this->getAliasOf();
- }
- if ($package instanceof AliasPackage) {
- $package = $package->getAliasOf();
- }
- return $package === $self;
- }
- public function __toString()
- {
- return $this->getUniqueName();
- }
- public function getPrettyString()
- {
- return $this->getPrettyName().' '.$this->getPrettyVersion();
- }
- public function __clone()
- {
- $this->repository = null;
- $this->id = -1;
- }
- }
- <?php
- namespace Composer\Package;
- class CompletePackage extends Package implements CompletePackageInterface
- {
- protected $repositories;
- protected $license = array();
- protected $keywords;
- protected $authors;
- protected $description;
- protected $homepage;
- protected $scripts = array();
- protected $support = array();
- protected $abandoned = false;
- public function setScripts(array $scripts)
- {
- $this->scripts = $scripts;
- }
- public function getScripts()
- {
- return $this->scripts;
- }
- public function setRepositories($repositories)
- {
- $this->repositories = $repositories;
- }
- public function getRepositories()
- {
- return $this->repositories;
- }
- public function setLicense(array $license)
- {
- $this->license = $license;
- }
- public function getLicense()
- {
- return $this->license;
- }
- public function setKeywords(array $keywords)
- {
- $this->keywords = $keywords;
- }
- public function getKeywords()
- {
- return $this->keywords;
- }
- public function setAuthors(array $authors)
- {
- $this->authors = $authors;
- }
- public function getAuthors()
- {
- return $this->authors;
- }
- public function setDescription($description)
- {
- $this->description = $description;
- }
- public function getDescription()
- {
- return $this->description;
- }
- public function setHomepage($homepage)
- {
- $this->homepage = $homepage;
- }
- public function getHomepage()
- {
- return $this->homepage;
- }
- public function setSupport(array $support)
- {
- $this->support = $support;
- }
- public function getSupport()
- {
- return $this->support;
- }
- public function isAbandoned()
- {
- return (boolean) $this->abandoned;
- }
- public function setAbandoned($abandoned)
- {
- $this->abandoned = $abandoned;
- }
- public function getReplacementPackage()
- {
- return is_string($this->abandoned) ? $this->abandoned : null;
- }
- }
- <?php
- namespace Composer\Package;
- interface CompletePackageInterface extends PackageInterface
- {
- public function getScripts();
- public function getRepositories();
- public function getLicense();
- public function getKeywords();
- public function getDescription();
- public function getHomepage();
- public function getAuthors();
- public function getSupport();
- public function isAbandoned();
- public function getReplacementPackage();
- }
- <?php
- namespace Composer\Package\Dumper;
- use Composer\Package\BasePackage;
- use Composer\Package\PackageInterface;
- use Composer\Package\CompletePackageInterface;
- use Composer\Package\RootPackageInterface;
- class ArrayDumper
- {
- public function dump(PackageInterface $package)
- {
- $keys = array(
- 'binaries' => 'bin',
- 'type',
- 'extra',
- 'installationSource' => 'installation-source',
- 'autoload',
- 'devAutoload' => 'autoload-dev',
- 'notificationUrl' => 'notification-url',
- 'includePaths' => 'include-path',
- );
- $data = array();
- $data['name'] = $package->getPrettyName();
- $data['version'] = $package->getPrettyVersion();
- $data['version_normalized'] = $package->getVersion();
- if ($package->getTargetDir()) {
- $data['target-dir'] = $package->getTargetDir();
- }
- if ($package->getSourceType()) {
- $data['source']['type'] = $package->getSourceType();
- $data['source']['url'] = $package->getSourceUrl();
- $data['source']['reference'] = $package->getSourceReference();
- if ($mirrors = $package->getSourceMirrors()) {
- $data['source']['mirrors'] = $mirrors;
- }
- }
- if ($package->getDistType()) {
- $data['dist']['type'] = $package->getDistType();
- $data['dist']['url'] = $package->getDistUrl();
- $data['dist']['reference'] = $package->getDistReference();
- $data['dist']['shasum'] = $package->getDistSha1Checksum();
- if ($mirrors = $package->getDistMirrors()) {
- $data['dist']['mirrors'] = $mirrors;
- }
- }
- if ($package->getArchiveExcludes()) {
- $data['archive']['exclude'] = $package->getArchiveExcludes();
- }
- foreach (BasePackage::$supportedLinkTypes as $type => $opts) {
- if ($links = $package->{'get'.ucfirst($opts['method'])}()) {
- foreach ($links as $link) {
- $data[$type][$link->getTarget()] = $link->getPrettyConstraint();
- }
- ksort($data[$type]);
- }
- }
- if ($packages = $package->getSuggests()) {
- ksort($packages);
- $data['suggest'] = $packages;
- }
- if ($package->getReleaseDate()) {
- $data['time'] = $package->getReleaseDate()->format('Y-m-d H:i:s');
- }
- $data = $this->dumpValues($package, $keys, $data);
- if ($package instanceof CompletePackageInterface) {
- $keys = array(
- 'scripts',
- 'license',
- 'authors',
- 'description',
- 'homepage',
- 'keywords',
- 'repositories',
- 'support',
- );
- $data = $this->dumpValues($package, $keys, $data);
- if (isset($data['keywords']) && is_array($data['keywords'])) {
- sort($data['keywords']);
- }
- if ($package->isAbandoned()) {
- $data['abandoned'] = $package->getReplacementPackage() ?: true;
- }
- }
- if ($package instanceof RootPackageInterface) {
- $minimumStability = $package->getMinimumStability();
- if ($minimumStability) {
- $data['minimum-stability'] = $minimumStability;
- }
- }
- if (count($package->getTransportOptions()) > 0) {
- $data['transport-options'] = $package->getTransportOptions();
- }
- return $data;
- }
- private function dumpValues(PackageInterface $package, array $keys, array $data)
- {
- foreach ($keys as $method => $key) {
- if (is_numeric($method)) {
- $method = $key;
- }
- $getter = 'get'.ucfirst($method);
- $value = $package->$getter();
- if (null !== $value && !(is_array($value) && 0 === count($value))) {
- $data[$key] = $value;
- }
- }
- return $data;
- }
- }
- <?php
- namespace Composer\Package;
- use Composer\Package\LinkConstraint\LinkConstraintInterface;
- class Link
- {
- protected $source;
- protected $target;
- protected $constraint;
- protected $description;
- protected $prettyConstraint;
- public function __construct($source, $target, LinkConstraintInterface $constraint = null, $description = 'relates to', $prettyConstraint = null)
- {
- $this->source = strtolower($source);
- $this->target = strtolower($target);
- $this->constraint = $constraint;
- $this->description = $description;
- $this->prettyConstraint = $prettyConstraint;
- }
- public function getSource()
- {
- return $this->source;
- }
- public function getTarget()
- {
- return $this->target;
- }
- public function getConstraint()
- {
- return $this->constraint;
- }
- public function getPrettyConstraint()
- {
- if (null === $this->prettyConstraint) {
- throw new \UnexpectedValueException(sprintf('Link %s has been misconfigured and had no prettyConstraint given.', $this));
- }
- return $this->prettyConstraint;
- }
- public function __toString()
- {
- return $this->source.' '.$this->description.' '.$this->target.' ('.$this->constraint.')';
- }
- public function getPrettyString(PackageInterface $sourcePackage)
- {
- return $sourcePackage->getPrettyString().' '.$this->description.' '.$this->target.' '.$this->constraint->getPrettyString().'';
- }
- }
- <?php
- namespace Composer\Package\LinkConstraint;
- class EmptyConstraint implements LinkConstraintInterface
- {
- protected $prettyString;
- public function matches(LinkConstraintInterface $provider)
- {
- return true;
- }
- public function setPrettyString($prettyString)
- {
- $this->prettyString = $prettyString;
- }
- public function getPrettyString()
- {
- if ($this->prettyString) {
- return $this->prettyString;
- }
- return $this->__toString();
- }
- public function __toString()
- {
- return '[]';
- }
- }
- <?php
- namespace Composer\Package\LinkConstraint;
- interface LinkConstraintInterface
- {
- public function matches(LinkConstraintInterface $provider);
- public function setPrettyString($prettyString);
- public function getPrettyString();
- public function __toString();
- }
- <?php
- namespace Composer\Package\LinkConstraint;
- class MultiConstraint implements LinkConstraintInterface
- {
- protected $constraints;
- protected $prettyString;
- protected $conjunctive;
- public function __construct(array $constraints, $conjunctive = true)
- {
- $this->constraints = $constraints;
- $this->conjunctive = $conjunctive;
- }
- public function matches(LinkConstraintInterface $provider)
- {
- if (false === $this->conjunctive) {
- foreach ($this->constraints as $constraint) {
- if ($constraint->matches($provider)) {
- return true;
- }
- }
- return false;
- }
- foreach ($this->constraints as $constraint) {
- if (!$constraint->matches($provider)) {
- return false;
- }
- }
- return true;
- }
- public function setPrettyString($prettyString)
- {
- $this->prettyString = $prettyString;
- }
- public function getPrettyString()
- {
- if ($this->prettyString) {
- return $this->prettyString;
- }
- return $this->__toString();
- }
- public function __toString()
- {
- $constraints = array();
- foreach ($this->constraints as $constraint) {
- $constraints[] = $constraint->__toString();
- }
- return '['.implode($this->conjunctive ? ' ' : ' || ', $constraints).']';
- }
- }
- <?php
- namespace Composer\Package\LinkConstraint;
- abstract class SpecificConstraint implements LinkConstraintInterface
- {
- protected $prettyString;
- public function matches(LinkConstraintInterface $provider)
- {
- if ($provider instanceof MultiConstraint) {
- return $provider->matches($this);
- } elseif ($provider instanceof $this) {
- return $this->matchSpecific($provider);
- }
- return true;
- }
- public function setPrettyString($prettyString)
- {
- $this->prettyString = $prettyString;
- }
- public function getPrettyString()
- {
- if ($this->prettyString) {
- return $this->prettyString;
- }
- return $this->__toString();
- }
-
-
- }
- <?php
- namespace Composer\Package\LinkConstraint;
- class VersionConstraint extends SpecificConstraint
- {
- private $operator;
- private $version;
- public function __construct($operator, $version)
- {
- if ('=' === $operator) {
- $operator = '==';
- }
- if ('<>' === $operator) {
- $operator = '!=';
- }
- $this->operator = $operator;
- $this->version = $version;
- }
- public function versionCompare($a, $b, $operator, $compareBranches = false)
- {
- $aIsBranch = 'dev-' === substr($a, 0, 4);
- $bIsBranch = 'dev-' === substr($b, 0, 4);
- if ($aIsBranch && $bIsBranch) {
- return $operator == '==' && $a === $b;
- }
- if (!$compareBranches && ($aIsBranch || $bIsBranch)) {
- return false;
- }
- return version_compare($a, $b, $operator);
- }
- public function matchSpecific(VersionConstraint $provider, $compareBranches = false)
- {
- static $cache = array();
- if (isset($cache[$this->operator][$this->version][$provider->operator][$provider->version][$compareBranches])) {
- return $cache[$this->operator][$this->version][$provider->operator][$provider->version][$compareBranches];
- }
- return $cache[$this->operator][$this->version][$provider->operator][$provider->version][$compareBranches] =
- $this->doMatchSpecific($provider, $compareBranches);
- }
- private function doMatchSpecific(VersionConstraint $provider, $compareBranches = false)
- {
- $noEqualOp = str_replace('=', '', $this->operator);
- $providerNoEqualOp = str_replace('=', '', $provider->operator);
- $isEqualOp = '==' === $this->operator;
- $isNonEqualOp = '!=' === $this->operator;
- $isProviderEqualOp = '==' === $provider->operator;
- $isProviderNonEqualOp = '!=' === $provider->operator;
-
- if ($isNonEqualOp || $isProviderNonEqualOp) {
- return !$isEqualOp && !$isProviderEqualOp
- || $this->versionCompare($provider->version, $this->version, '!=', $compareBranches);
- }
-
- if ($this->operator != '==' && $noEqualOp == $providerNoEqualOp) {
- return true;
- }
- if ($this->versionCompare($provider->version, $this->version, $this->operator, $compareBranches)) {
-
- if ($provider->version == $this->version && $provider->operator == $providerNoEqualOp && $this->operator != $noEqualOp) {
- return false;
- }
- return true;
- }
- return false;
- }
- public function __toString()
- {
- return $this->operator.' '.$this->version;
- }
- }
- <?php
- namespace Composer\Package\Loader;
- use Composer\Package;
- use Composer\Package\AliasPackage;
- use Composer\Package\RootAliasPackage;
- use Composer\Package\RootPackageInterface;
- use Composer\Package\Version\VersionParser;
- class ArrayLoader implements LoaderInterface
- {
- protected $versionParser;
- protected $loadOptions;
- public function __construct(VersionParser $parser = null, $loadOptions = false)
- {
- if (!$parser) {
- $parser = new VersionParser;
- }
- $this->versionParser = $parser;
- $this->loadOptions = $loadOptions;
- }
- public function load(array $config, $class = 'Composer\Package\CompletePackage')
- {
- if (!isset($config['name'])) {
- throw new \UnexpectedValueException('Unknown package has no name defined ('.json_encode($config).').');
- }
- if (!isset($config['version'])) {
- throw new \UnexpectedValueException('Package '.$config['name'].' has no version defined.');
- }
- if (isset($config['version_normalized'])) {
- $version = $config['version_normalized'];
- } else {
- $version = $this->versionParser->normalize($config['version']);
- }
- $package = new $class($config['name'], $version, $config['version']);
- $package->setType(isset($config['type']) ? strtolower($config['type']) : 'library');
- if (isset($config['target-dir'])) {
- $package->setTargetDir($config['target-dir']);
- }
- if (isset($config['extra']) && is_array($config['extra'])) {
- $package->setExtra($config['extra']);
- }
- if (isset($config['bin'])) {
- if (!is_array($config['bin'])) {
- throw new \UnexpectedValueException('Package '.$config['name'].'\'s bin key should be an array, '.gettype($config['bin']).' given.');
- }
- foreach ($config['bin'] as $key => $bin) {
- $config['bin'][$key] = ltrim($bin, '/');
- }
- $package->setBinaries($config['bin']);
- }
- if (isset($config['installation-source'])) {
- $package->setInstallationSource($config['installation-source']);
- }
- if (isset($config['source'])) {
- if (!isset($config['source']['type']) || !isset($config['source']['url']) || !isset($config['source']['reference'])) {
- throw new \UnexpectedValueException(sprintf(
- "Package %s's source key should be specified as {\"type\": ..., \"url\": ..., \"reference\": ...},\n%s given.",
- $config['name'],
- json_encode($config['source'])
- ));
- }
- $package->setSourceType($config['source']['type']);
- $package->setSourceUrl($config['source']['url']);
- $package->setSourceReference($config['source']['reference']);
- if (isset($config['source']['mirrors'])) {
- $package->setSourceMirrors($config['source']['mirrors']);
- }
- }
- if (isset($config['dist'])) {
- if (!isset($config['dist']['type'])
- || !isset($config['dist']['url'])) {
- throw new \UnexpectedValueException(sprintf(
- "Package %s's dist key should be specified as ".
- "{\"type\": ..., \"url\": ..., \"reference\": ..., \"shasum\": ...},\n%s given.",
- $config['name'],
- json_encode($config['dist'])
- ));
- }
- $package->setDistType($config['dist']['type']);
- $package->setDistUrl($config['dist']['url']);
- $package->setDistReference(isset($config['dist']['reference']) ? $config['dist']['reference'] : null);
- $package->setDistSha1Checksum(isset($config['dist']['shasum']) ? $config['dist']['shasum'] : null);
- if (isset($config['dist']['mirrors'])) {
- $package->setDistMirrors($config['dist']['mirrors']);
- }
- }
- foreach (Package\BasePackage::$supportedLinkTypes as $type => $opts) {
- if (isset($config[$type])) {
- $method = 'set'.ucfirst($opts['method']);
- $package->{$method}(
- $this->versionParser->parseLinks(
- $package->getName(),
- $package->getPrettyVersion(),
- $opts['description'],
- $config[$type]
- )
- );
- }
- }
- if (isset($config['suggest']) && is_array($config['suggest'])) {
- foreach ($config['suggest'] as $target => $reason) {
- if ('self.version' === trim($reason)) {
- $config['suggest'][$target] = $package->getPrettyVersion();
- }
- }
- $package->setSuggests($config['suggest']);
- }
- if (isset($config['autoload'])) {
- $package->setAutoload($config['autoload']);
- }
- if (isset($config['autoload-dev'])) {
- $package->setDevAutoload($config['autoload-dev']);
- }
- if (isset($config['include-path'])) {
- $package->setIncludePaths($config['include-path']);
- }
- if (!empty($config['time'])) {
- $time = ctype_digit($config['time']) ? '@'.$config['time'] : $config['time'];
- try {
- $date = new \DateTime($time, new \DateTimeZone('UTC'));
- $package->setReleaseDate($date);
- } catch (\Exception $e) {
- }
- }
- if (!empty($config['notification-url'])) {
- $package->setNotificationUrl($config['notification-url']);
- }
- if (!empty($config['archive']['exclude'])) {
- $package->setArchiveExcludes($config['archive']['exclude']);
- }
- if ($package instanceof Package\CompletePackageInterface) {
- if (isset($config['scripts']) && is_array($config['scripts'])) {
- foreach ($config['scripts'] as $event => $listeners) {
- $config['scripts'][$event] = (array) $listeners;
- }
- $package->setScripts($config['scripts']);
- }
- if (!empty($config['description']) && is_string($config['description'])) {
- $package->setDescription($config['description']);
- }
- if (!empty($config['homepage']) && is_string($config['homepage'])) {
- $package->setHomepage($config['homepage']);
- }
- if (!empty($config['keywords']) && is_array($config['keywords'])) {
- $package->setKeywords($config['keywords']);
- }
- if (!empty($config['license'])) {
- $package->setLicense(is_array($config['license']) ? $config['license'] : array($config['license']));
- }
- if (!empty($config['authors']) && is_array($config['authors'])) {
- $package->setAuthors($config['authors']);
- }
- if (isset($config['support'])) {
- $package->setSupport($config['support']);
- }
- if (isset($config['abandoned'])) {
- $package->setAbandoned($config['abandoned']);
- }
- }
- if ($aliasNormalized = $this->getBranchAlias($config)) {
- if ($package instanceof RootPackageInterface) {
- $package = new RootAliasPackage($package, $aliasNormalized, preg_replace('{(\.9{7})+}', '.x', $aliasNormalized));
- } else {
- $package = new AliasPackage($package, $aliasNormalized, preg_replace('{(\.9{7})+}', '.x', $aliasNormalized));
- }
- }
- if ($this->loadOptions && isset($config['transport-options'])) {
- $package->setTransportOptions($config['transport-options']);
- }
- return $package;
- }
- public function getBranchAlias(array $config)
- {
- if (('dev-' !== substr($config['version'], 0, 4) && '-dev' !== substr($config['version'], -4))
- || !isset($config['extra']['branch-alias'])
- || !is_array($config['extra']['branch-alias'])
- ) {
- return;
- }
- foreach ($config['extra']['branch-alias'] as $sourceBranch => $targetBranch) {
- if ('-dev' !== substr($targetBranch, -4)) {
- continue;
- }
- $validatedTargetBranch = $this->versionParser->normalizeBranch(substr($targetBranch, 0, -4));
- if ('-dev' !== substr($validatedTargetBranch, -4)) {
- continue;
- }
- if (strtolower($config['version']) !== strtolower($sourceBranch)) {
- continue;
- }
- if (($sourcePrefix = $this->versionParser->parseNumericAliasPrefix($sourceBranch))
- && ($targetPrefix = $this->versionParser->parseNumericAliasPrefix($targetBranch))
- && (stripos($targetPrefix, $sourcePrefix) !== 0)
- ) {
- continue;
- }
- return $validatedTargetBranch;
- }
- }
- }
- <?php
- namespace Composer\Package\Loader;
- class InvalidPackageException extends \Exception
- {
- private $errors;
- private $warnings;
- private $data;
- public function __construct(array $errors, array $warnings, array $data)
- {
- $this->errors = $errors;
- $this->warnings = $warnings;
- $this->data = $data;
- parent::__construct("Invalid package information: \n".implode("\n", array_merge($errors, $warnings)));
- }
- public function getData()
- {
- return $this->data;
- }
- public function getErrors()
- {
- return $this->errors;
- }
- public function getWarnings()
- {
- return $this->warnings;
- }
- }
- <?php
- namespace Composer\Package\Loader;
- use Composer\Json\JsonFile;
- class JsonLoader
- {
- private $loader;
- public function __construct(LoaderInterface $loader)
- {
- $this->loader = $loader;
- }
- public function load($json)
- {
- if ($json instanceof JsonFile) {
- $config = $json->read();
- } elseif (file_exists($json)) {
- $config = JsonFile::parseJson(file_get_contents($json), $json);
- } elseif (is_string($json)) {
- $config = JsonFile::parseJson($json);
- }
- return $this->loader->load($config);
- }
- }
- <?php
- namespace Composer\Package\Loader;
- interface LoaderInterface
- {
- public function load(array $package, $class = 'Composer\Package\CompletePackage');
- }
- <?php
- namespace Composer\Package\Loader;
- use Composer\Package\BasePackage;
- use Composer\Package\AliasPackage;
- use Composer\Config;
- use Composer\Factory;
- use Composer\Package\Version\VersionParser;
- use Composer\Repository\RepositoryManager;
- use Composer\Repository\Vcs\HgDriver;
- use Composer\IO\NullIO;
- use Composer\Util\ProcessExecutor;
- use Composer\Util\Git as GitUtil;
- use Composer\Util\Svn as SvnUtil;
- class RootPackageLoader extends ArrayLoader
- {
- private $manager;
- private $config;
- private $process;
- public function __construct(RepositoryManager $manager, Config $config, VersionParser $parser = null, ProcessExecutor $process = null)
- {
- $this->manager = $manager;
- $this->config = $config;
- $this->process = $process ?: new ProcessExecutor();
- parent::__construct($parser);
- }
- public function load(array $config, $class = 'Composer\Package\RootPackage')
- {
- if (!isset($config['name'])) {
- $config['name'] = '__root__';
- }
- if (!isset($config['version'])) {
- if (getenv('COMPOSER_ROOT_VERSION')) {
- $version = getenv('COMPOSER_ROOT_VERSION');
- } else {
- $version = $this->guessVersion($config);
- }
- if (!$version) {
- $version = '1.0.0';
- }
- $config['version'] = $version;
- }
- $realPackage = $package = parent::load($config, $class);
- if ($realPackage instanceof AliasPackage) {
- $realPackage = $package->getAliasOf();
- }
- if (isset($config['minimum-stability'])) {
- $realPackage->setMinimumStability(VersionParser::normalizeStability($config['minimum-stability']));
- }
- $aliases = array();
- $stabilityFlags = array();
- $references = array();
- foreach (array('require', 'require-dev') as $linkType) {
- if (isset($config[$linkType])) {
- $linkInfo = BasePackage::$supportedLinkTypes[$linkType];
- $method = 'get'.ucfirst($linkInfo['method']);
- $links = array();
- foreach ($realPackage->$method() as $link) {
- $links[$link->getTarget()] = $link->getConstraint()->getPrettyString();
- }
- $aliases = $this->extractAliases($links, $aliases);
- $stabilityFlags = $this->extractStabilityFlags($links, $stabilityFlags, $realPackage->getMinimumStability());
- $references = $this->extractReferences($links, $references);
- }
- }
- $realPackage->setAliases($aliases);
- $realPackage->setStabilityFlags($stabilityFlags);
- $realPackage->setReferences($references);
- if (isset($config['prefer-stable'])) {
- $realPackage->setPreferStable((bool) $config['prefer-stable']);
- }
- $repos = Factory::createDefaultRepositories(null, $this->config, $this->manager);
- foreach ($repos as $repo) {
- $this->manager->addRepository($repo);
- }
- $realPackage->setRepositories($this->config->getRepositories());
- return $package;
- }
- private function extractAliases(array $requires, array $aliases)
- {
- foreach ($requires as $reqName => $reqVersion) {
- if (preg_match('{^([^,\s#]+)(?:#[^ ]+)? +as +([^,\s]+)$}', $reqVersion, $match)) {
- $aliases[] = array(
- 'package' => strtolower($reqName),
- 'version' => $this->versionParser->normalize($match[1], $reqVersion),
- 'alias' => $match[2],
- 'alias_normalized' => $this->versionParser->normalize($match[2], $reqVersion),
- );
- }
- }
- return $aliases;
- }
- private function extractStabilityFlags(array $requires, array $stabilityFlags, $minimumStability)
- {
- $stabilities = BasePackage::$stabilities;
- $minimumStability = $stabilities[$minimumStability];
- foreach ($requires as $reqName => $reqVersion) {
- if (preg_match('{^[^@]*?@('.implode('|', array_keys($stabilities)).')$}i', $reqVersion, $match)) {
- $name = strtolower($reqName);
- $stability = $stabilities[VersionParser::normalizeStability($match[1])];
- if (isset($stabilityFlags[$name]) && $stabilityFlags[$name] > $stability) {
- continue;
- }
- $stabilityFlags[$name] = $stability;
- continue;
- }
-
- $reqVersion = preg_replace('{^([^,\s@]+) as .+$}', '$1', $reqVersion);
- if (preg_match('{^[^,\s@]+$}', $reqVersion) && 'stable' !== ($stabilityName = VersionParser::parseStability($reqVersion))) {
- $name = strtolower($reqName);
- $stability = $stabilities[$stabilityName];
- if ((isset($stabilityFlags[$name]) && $stabilityFlags[$name] > $stability) || ($minimumStability > $stability)) {
- continue;
- }
- $stabilityFlags[$name] = $stability;
- }
- }
- return $stabilityFlags;
- }
- private function extractReferences(array $requires, array $references)
- {
- foreach ($requires as $reqName => $reqVersion) {
- $reqVersion = preg_replace('{^([^,\s@]+) as .+$}', '$1', $reqVersion);
- if (preg_match('{^[^,\s@]+?#([a-f0-9]+)$}', $reqVersion, $match) && 'dev' === ($stabilityName = VersionParser::parseStability($reqVersion))) {
- $name = strtolower($reqName);
- $references[$name] = $match[1];
- }
- }
- return $references;
- }
- private function guessVersion(array $config)
- {
- if (function_exists('proc_open')) {
- $version = $this->guessGitVersion($config);
- if (null !== $version) {
- return $version;
- }
- $version = $this->guessHgVersion($config);
- if (null !== $version) {
- return $version;
- }
- return $this->guessSvnVersion($config);
- }
- }
- private function guessGitVersion(array $config)
- {
- GitUtil::cleanEnv();
- if (0 === $this->process->execute('git describe --exact-match --tags', $output)) {
- try {
- return $this->versionParser->normalize(trim($output));
- } catch (\Exception $e) {
- }
- }
- if (0 === $this->process->execute('git branch --no-color --no-abbrev -v', $output)) {
- $branches = array();
- $isFeatureBranch = false;
- $version = null;
- foreach ($this->process->splitLines($output) as $branch) {
- if ($branch && preg_match('{^(?:\* ) *(\(no branch\)|\(detached from \S+\)|\S+) *([a-f0-9]+) .*$}', $branch, $match)) {
- if ($match[1] === '(no branch)' || substr($match[1], 0, 10) === '(detached ') {
- $version = 'dev-'.$match[2];
- $isFeatureBranch = true;
- } else {
- $version = $this->versionParser->normalizeBranch($match[1]);
- $isFeatureBranch = 0 === strpos($version, 'dev-');
- if ('9999999-dev' === $version) {
- $version = 'dev-'.$match[1];
- }
- }
- }
- if ($branch && !preg_match('{^ *[^/]+/HEAD }', $branch)) {
- if (preg_match('{^(?:\* )? *(\S+) *([a-f0-9]+) .*$}', $branch, $match)) {
- $branches[] = $match[1];
- }
- }
- }
- if (!$isFeatureBranch) {
- return $version;
- }
- $version = $this->guessFeatureVersion($config, $version, $branches, 'git rev-list %candidate%..%branch%');
- return $version;
- }
- }
- private function guessHgVersion(array $config)
- {
- if (0 === $this->process->execute('hg branch', $output)) {
- $branch = trim($output);
- $version = $this->versionParser->normalizeBranch($branch);
- $isFeatureBranch = 0 === strpos($version, 'dev-');
- if ('9999999-dev' === $version) {
- $version = 'dev-'.$branch;
- }
- if (!$isFeatureBranch) {
- return $version;
- }
- $config = array('url' => getcwd());
- $driver = new HgDriver($config, new NullIO(), $this->config, $this->process);
- $branches = array_keys($driver->getBranches());
- $version = $this->guessFeatureVersion($config, $version, $branches, 'hg log -r "not ancestors(\'%candidate%\') and ancestors(\'%branch%\')" --template "{node}\\n"');
- return $version;
- }
- }
- private function guessFeatureVersion(array $config, $version, array $branches, $scmCmdline)
- {
-
- if ((isset($config['extra']['branch-alias']) && !isset($config['extra']['branch-alias'][$version]))
- || strpos(json_encode($config), '"self.version"')
- ) {
- $branch = preg_replace('{^dev-}', '', $version);
- $length = PHP_INT_MAX;
- $nonFeatureBranches = '';
- if (!empty($config['non-feature-branches'])) {
- $nonFeatureBranches = implode('|', $config['non-feature-branches']);
- }
- foreach ($branches as $candidate) {
- if ($candidate === $branch && preg_match('{^(' . $nonFeatureBranches . ')$}', $candidate)) {
- return $version;
- }
- if ($candidate === $branch || !preg_match('{^(master|trunk|default|develop|\d+\..+)$}', $candidate, $match)) {
- continue;
- }
- $cmdLine = str_replace(array('%candidate%', '%branch%'), array($candidate, $branch), $scmCmdline);
- if (0 !== $this->process->execute($cmdLine, $output)) {
- continue;
- }
- if (strlen($output) < $length) {
- $length = strlen($output);
- $version = $this->versionParser->normalizeBranch($candidate);
- if ('9999999-dev' === $version) {
- $version = 'dev-'.$match[1];
- }
- }
- }
- }
- return $version;
- }
- private function guessSvnVersion(array $config)
- {
- SvnUtil::cleanEnv();
- if (0 === $this->process->execute('svn info --xml', $output)) {
- $trunkPath = isset($config['trunk-path']) ? preg_quote($config['trunk-path'], '#') : 'trunk';
- $branchesPath = isset($config['branches-path']) ? preg_quote($config['branches-path'], '#') : 'branches';
- $tagsPath = isset($config['tags-path']) ? preg_quote($config['tags-path'], '#') : 'tags';
- $urlPattern = '#<url>.*/('.$trunkPath.'|('.$branchesPath.'|'. $tagsPath .')/(.*))</url>#';
- if (preg_match($urlPattern, $output, $matches)) {
- if (isset($matches[2]) && ($branchesPath === $matches[2] || $tagsPath === $matches[2])) {
- $version = $this->versionParser->normalizeBranch($matches[3]);
- if ('9999999-dev' === $version) {
- $version = 'dev-'.$matches[3];
- }
- return $version;
- }
- return $this->versionParser->normalize(trim($matches[1]));
- }
- }
- }
- }
- <?php
- namespace Composer\Package\Loader;
- use Composer\Package;
- use Composer\Package\BasePackage;
- use Composer\Package\LinkConstraint\VersionConstraint;
- use Composer\Package\Version\VersionParser;
- use Composer\Repository\PlatformRepository;
- class ValidatingArrayLoader implements LoaderInterface
- {
- const CHECK_ALL = 1;
- const CHECK_UNBOUND_CONSTRAINTS = 1;
- private $loader;
- private $versionParser;
- private $errors;
- private $warnings;
- private $config;
- private $strictName;
- private $flags;
- public function __construct(LoaderInterface $loader, $strictName = true, VersionParser $parser = null, $flags = 0)
- {
- $this->loader = $loader;
- $this->versionParser = $parser ?: new VersionParser();
- $this->strictName = $strictName;
- $this->flags = $flags;
- }
- public function load(array $config, $class = 'Composer\Package\CompletePackage')
- {
- $this->errors = array();
- $this->warnings = array();
- $this->config = $config;
- if ($this->strictName) {
- $this->validateRegex('name', '[A-Za-z0-9][A-Za-z0-9_.-]*/[A-Za-z0-9][A-Za-z0-9_.-]*', true);
- } else {
- $this->validateString('name', true);
- }
- if (!empty($this->config['version'])) {
- try {
- $this->versionParser->normalize($this->config['version']);
- } catch (\Exception $e) {
- $this->errors[] = 'version : invalid value ('.$this->config['version'].'): '.$e->getMessage();
- unset($this->config['version']);
- }
- }
- $this->validateRegex('type', '[A-Za-z0-9-]+');
- $this->validateString('target-dir');
- $this->validateArray('extra');
- $this->validateFlatArray('bin');
- $this->validateArray('scripts');
- $this->validateString('description');
- $this->validateUrl('homepage');
- $this->validateFlatArray('keywords', '[A-Za-z0-9 ._-]+');
- if (isset($this->config['license'])) {
- if (is_string($this->config['license'])) {
- $this->validateRegex('license', '[A-Za-z0-9+. ()-]+');
- } else {
- $this->validateFlatArray('license', '[A-Za-z0-9+. ()-]+');
- }
- }
- $this->validateString('time');
- if (!empty($this->config['time'])) {
- try {
- $date = new \DateTime($this->config['time'], new \DateTimeZone('UTC'));
- } catch (\Exception $e) {
- $this->errors[] = 'time : invalid value ('.$this->config['time'].'): '.$e->getMessage();
- unset($this->config['time']);
- }
- }
- if ($this->validateArray('authors') && !empty($this->config['authors'])) {
- foreach ($this->config['authors'] as $key => $author) {
- if (!is_array($author)) {
- $this->errors[] = 'authors.'.$key.' : should be an array, '.gettype($author).' given';
- unset($this->config['authors'][$key]);
- continue;
- }
- foreach (array('homepage', 'email', 'name', 'role') as $authorData) {
- if (isset($author[$authorData]) && !is_string($author[$authorData])) {
- $this->errors[] = 'authors.'.$key.'.'.$authorData.' : invalid value, must be a string';
- unset($this->config['authors'][$key][$authorData]);
- }
- }
- if (isset($author['homepage']) && !$this->filterUrl($author['homepage'])) {
- $this->warnings[] = 'authors.'.$key.'.homepage : invalid value ('.$author['homepage'].'), must be an http/https URL';
- unset($this->config['authors'][$key]['homepage']);
- }
- if (isset($author['email']) && !filter_var($author['email'], FILTER_VALIDATE_EMAIL)) {
- $this->warnings[] = 'authors.'.$key.'.email : invalid value ('.$author['email'].'), must be a valid email address';
- unset($this->config['authors'][$key]['email']);
- }
- if (empty($this->config['authors'][$key])) {
- unset($this->config['authors'][$key]);
- }
- }
- if (empty($this->config['authors'])) {
- unset($this->config['authors']);
- }
- }
- if ($this->validateArray('support') && !empty($this->config['support'])) {
- foreach (array('issues', 'forum', 'wiki', 'source', 'email', 'irc') as $key) {
- if (isset($this->config['support'][$key]) && !is_string($this->config['support'][$key])) {
- $this->errors[] = 'support.'.$key.' : invalid value, must be a string';
- unset($this->config['support'][$key]);
- }
- }
- if (isset($this->config['support']['email']) && !filter_var($this->config['support']['email'], FILTER_VALIDATE_EMAIL)) {
- $this->warnings[] = 'support.email : invalid value ('.$this->config['support']['email'].'), must be a valid email address';
- unset($this->config['support']['email']);
- }
- if (isset($this->config['support']['irc']) && !$this->filterUrl($this->config['support']['irc'], array('irc'))) {
- $this->warnings[] = 'support.irc : invalid value ('.$this->config['support']['irc'].'), must be a irc://<server>/<channel> URL';
- unset($this->config['support']['irc']);
- }
- foreach (array('issues', 'forum', 'wiki', 'source') as $key) {
- if (isset($this->config['support'][$key]) && !$this->filterUrl($this->config['support'][$key])) {
- $this->warnings[] = 'support.'.$key.' : invalid value ('.$this->config['support'][$key].'), must be an http/https URL';
- unset($this->config['support'][$key]);
- }
- }
- if (empty($this->config['support'])) {
- unset($this->config['support']);
- }
- }
- $unboundConstraint = new VersionConstraint('=', $this->versionParser->normalize('dev-master'));
- foreach (array_keys(BasePackage::$supportedLinkTypes) as $linkType) {
- if ($this->validateArray($linkType) && isset($this->config[$linkType])) {
- foreach ($this->config[$linkType] as $package => $constraint) {
- if (!preg_match('{^[A-Za-z0-9_./-]+$}', $package)) {
- $this->warnings[] = $linkType.'.'.$package.' : invalid key, package names must be strings containing only [A-Za-z0-9_./-]';
- }
- if (!is_string($constraint)) {
- $this->errors[] = $linkType.'.'.$package.' : invalid value, must be a string containing a version constraint';
- unset($this->config[$linkType][$package]);
- } elseif ('self.version' !== $constraint) {
- try {
- $linkConstraint = $this->versionParser->parseConstraints($constraint);
- } catch (\Exception $e) {
- $this->errors[] = $linkType.'.'.$package.' : invalid version constraint ('.$e->getMessage().')';
- unset($this->config[$linkType][$package]);
- continue;
- }
- if (
- ($this->flags & self::CHECK_UNBOUND_CONSTRAINTS)
- && 'require' === $linkType
- && $linkConstraint->matches($unboundConstraint)
- && !preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $package)
- ) {
- $this->warnings[] = $linkType.'.'.$package.' : unbound version constraints ('.$constraint.') should be avoided';
- }
- }
- }
- }
- }
- if ($this->validateArray('suggest') && !empty($this->config['suggest'])) {
- foreach ($this->config['suggest'] as $package => $description) {
- if (!is_string($description)) {
- $this->errors[] = 'suggest.'.$package.' : invalid value, must be a string describing why the package is suggested';
- unset($this->config['suggest'][$package]);
- }
- }
- }
- if ($this->validateString('minimum-stability') && !empty($this->config['minimum-stability'])) {
- if (!isset(BasePackage::$stabilities[$this->config['minimum-stability']])) {
- $this->errors[] = 'minimum-stability : invalid value ('.$this->config['minimum-stability'].'), must be one of '.implode(', ', array_keys(BasePackage::$stabilities));
- unset($this->config['minimum-stability']);
- }
- }
- if ($this->validateArray('autoload') && !empty($this->config['autoload'])) {
- $types = array('psr-0', 'psr-4', 'classmap', 'files');
- foreach ($this->config['autoload'] as $type => $typeConfig) {
- if (!in_array($type, $types)) {
- $this->errors[] = 'autoload : invalid value ('.$type.'), must be one of '.implode(', ', $types);
- unset($this->config['autoload'][$type]);
- }
- if ($type === 'psr-4') {
- foreach ($typeConfig as $namespace => $dirs) {
- if ($namespace !== '' && '\\' !== substr($namespace, -1)) {
- $this->errors[] = 'autoload.psr-4 : invalid value ('.$namespace.'), namespaces must end with a namespace separator, should be '.$namespace.'\\';
- }
- }
- }
- }
- }
- if (!empty($this->config['autoload']['psr-4']) && !empty($this->config['target-dir'])) {
- $this->errors[] = 'target-dir : this can not be used together with the autoload.psr-4 setting, remove target-dir to upgrade to psr-4';
-
- unset($this->config['autoload']['psr-4']);
- }
-
-
- $this->validateFlatArray('include-path');
- $this->validateArray('transport-options');
- if (isset($this->config['extra']['branch-alias'])) {
- if (!is_array($this->config['extra']['branch-alias'])) {
- $this->errors[] = 'extra.branch-alias : must be an array of versions => aliases';
- } else {
- foreach ($this->config['extra']['branch-alias'] as $sourceBranch => $targetBranch) {
- if ('-dev' !== substr($targetBranch, -4)) {
- $this->warnings[] = 'extra.branch-alias.'.$sourceBranch.' : the target branch ('.$targetBranch.') must end in -dev';
- unset($this->config['extra']['branch-alias'][$sourceBranch]);
- continue;
- }
- $validatedTargetBranch = $this->versionParser->normalizeBranch(substr($targetBranch, 0, -4));
- if ('-dev' !== substr($validatedTargetBranch, -4)) {
- $this->warnings[] = 'extra.branch-alias.'.$sourceBranch.' : the target branch ('.$targetBranch.') must be a parseable number like 2.0-dev';
- unset($this->config['extra']['branch-alias'][$sourceBranch]);
- continue;
- }
- if (($sourcePrefix = $this->versionParser->parseNumericAliasPrefix($sourceBranch))
- && ($targetPrefix = $this->versionParser->parseNumericAliasPrefix($targetBranch))
- && (stripos($targetPrefix, $sourcePrefix) !== 0)
- ) {
- $this->warnings[] = 'extra.branch-alias.'.$sourceBranch.' : the target branch ('.$targetBranch.') is not a valid numeric alias for this version';
- unset($this->config['extra']['branch-alias'][$sourceBranch]);
- }
- }
- }
- }
- if ($this->errors) {
- throw new InvalidPackageException($this->errors, $this->warnings, $config);
- }
- $package = $this->loader->load($this->config, $class);
- $this->config = null;
- return $package;
- }
- public function getWarnings()
- {
- return $this->warnings;
- }
- public function getErrors()
- {
- return $this->errors;
- }
- private function validateRegex($property, $regex, $mandatory = false)
- {
- if (!$this->validateString($property, $mandatory)) {
- return false;
- }
- if (!preg_match('{^'.$regex.'$}u', $this->config[$property])) {
- $message = $property.' : invalid value ('.$this->config[$property].'), must match '.$regex;
- if ($mandatory) {
- $this->errors[] = $message;
- } else {
- $this->warnings[] = $message;
- }
- unset($this->config[$property]);
- return false;
- }
- return true;
- }
- private function validateString($property, $mandatory = false)
- {
- if (isset($this->config[$property]) && !is_string($this->config[$property])) {
- $this->errors[] = $property.' : should be a string, '.gettype($this->config[$property]).' given';
- unset($this->config[$property]);
- return false;
- }
- if (!isset($this->config[$property]) || trim($this->config[$property]) === '') {
- if ($mandatory) {
- $this->errors[] = $property.' : must be present';
- }
- unset($this->config[$property]);
- return false;
- }
- return true;
- }
- private function validateArray($property, $mandatory = false)
- {
- if (isset($this->config[$property]) && !is_array($this->config[$property])) {
- $this->errors[] = $property.' : should be an array, '.gettype($this->config[$property]).' given';
- unset($this->config[$property]);
- return false;
- }
- if (!isset($this->config[$property]) || !count($this->config[$property])) {
- if ($mandatory) {
- $this->errors[] = $property.' : must be present and contain at least one element';
- }
- unset($this->config[$property]);
- return false;
- }
- return true;
- }
- private function validateFlatArray($property, $regex = null, $mandatory = false)
- {
- if (!$this->validateArray($property, $mandatory)) {
- return false;
- }
- $pass = true;
- foreach ($this->config[$property] as $key => $value) {
- if (!is_string($value) && !is_numeric($value)) {
- $this->errors[] = $property.'.'.$key.' : must be a string or int, '.gettype($value).' given';
- unset($this->config[$property][$key]);
- $pass = false;
- continue;
- }
- if ($regex && !preg_match('{^'.$regex.'$}u', $value)) {
- $this->warnings[] = $property.'.'.$key.' : invalid value ('.$value.'), must match '.$regex;
- unset($this->config[$property][$key]);
- $pass = false;
- }
- }
- return $pass;
- }
- private function validateUrl($property, $mandatory = false)
- {
- if (!$this->validateString($property, $mandatory)) {
- return false;
- }
- if (!$this->filterUrl($this->config[$property])) {
- $this->warnings[] = $property.' : invalid value ('.$this->config[$property].'), must be an http/https URL';
- unset($this->config[$property]);
- return false;
- }
- return true;
- }
- private function filterUrl($value, array $schemes = array('http', 'https'))
- {
- if ($value === '') {
- return true;
- }
- $bits = parse_url($value);
- if (empty($bits['scheme']) || empty($bits['host'])) {
- return false;
- }
- if (!in_array($bits['scheme'], $schemes, true)) {
- return false;
- }
- return true;
- }
- }
- <?php
- namespace Composer\Package;
- use Composer\Json\JsonFile;
- use Composer\Installer\InstallationManager;
- use Composer\Repository\RepositoryManager;
- use Composer\Util\ProcessExecutor;
- use Composer\Repository\ArrayRepository;
- use Composer\Package\Dumper\ArrayDumper;
- use Composer\Package\Loader\ArrayLoader;
- use Composer\Package\Version\VersionParser;
- use Composer\Util\Git as GitUtil;
- use Composer\IO\IOInterface;
- class Locker
- {
- private $lockFile;
- private $repositoryManager;
- private $installationManager;
- private $hash;
- private $loader;
- private $dumper;
- private $process;
- private $lockDataCache;
- public function __construct(IOInterface $io, JsonFile $lockFile, RepositoryManager $repositoryManager, InstallationManager $installationManager, $hash)
- {
- $this->lockFile = $lockFile;
- $this->repositoryManager = $repositoryManager;
- $this->installationManager = $installationManager;
- $this->hash = $hash;
- $this->loader = new ArrayLoader(null, true);
- $this->dumper = new ArrayDumper();
- $this->process = new ProcessExecutor($io);
- }
- public function isLocked()
- {
- if (!$this->lockFile->exists()) {
- return false;
- }
- $data = $this->getLockData();
- return isset($data['packages']);
- }
- public function isFresh()
- {
- $lock = $this->lockFile->read();
- return $this->hash === $lock['hash'];
- }
- public function getLockedRepository($withDevReqs = false)
- {
- $lockData = $this->getLockData();
- $packages = new ArrayRepository();
- $lockedPackages = $lockData['packages'];
- if ($withDevReqs) {
- if (isset($lockData['packages-dev'])) {
- $lockedPackages = array_merge($lockedPackages, $lockData['packages-dev']);
- } else {
- throw new \RuntimeException('The lock file does not contain require-dev information, run install with the --no-dev option or run update to install those packages.');
- }
- }
- if (empty($lockedPackages)) {
- return $packages;
- }
- if (isset($lockedPackages[0]['name'])) {
- foreach ($lockedPackages as $info) {
- $packages->addPackage($this->loader->load($info));
- }
- return $packages;
- }
- throw new \RuntimeException('Your composer.lock was created before 2012-09-15, and is not supported anymore. Run "composer update" to generate a new one.');
- }
- public function getPlatformRequirements($withDevReqs = false)
- {
- $lockData = $this->getLockData();
- $versionParser = new VersionParser();
- $requirements = array();
- if (!empty($lockData['platform'])) {
- $requirements = $versionParser->parseLinks(
- '__ROOT__',
- '1.0.0',
- 'requires',
- isset($lockData['platform']) ? $lockData['platform'] : array()
- );
- }
- if ($withDevReqs && !empty($lockData['platform-dev'])) {
- $devRequirements = $versionParser->parseLinks(
- '__ROOT__',
- '1.0.0',
- 'requires',
- isset($lockData['platform-dev']) ? $lockData['platform-dev'] : array()
- );
- $requirements = array_merge($requirements, $devRequirements);
- }
- return $requirements;
- }
- public function getMinimumStability()
- {
- $lockData = $this->getLockData();
- return isset($lockData['minimum-stability']) ? $lockData['minimum-stability'] : 'stable';
- }
- public function getStabilityFlags()
- {
- $lockData = $this->getLockData();
- return isset($lockData['stability-flags']) ? $lockData['stability-flags'] : array();
- }
- public function getPreferStable()
- {
- $lockData = $this->getLockData();
-
- return isset($lockData['prefer-stable']) ? $lockData['prefer-stable'] : null;
- }
- public function getPreferLowest()
- {
- $lockData = $this->getLockData();
-
- return isset($lockData['prefer-lowest']) ? $lockData['prefer-lowest'] : null;
- }
- public function getAliases()
- {
- $lockData = $this->getLockData();
- return isset($lockData['aliases']) ? $lockData['aliases'] : array();
- }
- public function getLockData()
- {
- if (null !== $this->lockDataCache) {
- return $this->lockDataCache;
- }
- if (!$this->lockFile->exists()) {
- throw new \LogicException('No lockfile found. Unable to read locked packages');
- }
- return $this->lockDataCache = $this->lockFile->read();
- }
- public function setLockData(array $packages, $devPackages, array $platformReqs, $platformDevReqs, array $aliases, $minimumStability, array $stabilityFlags, $preferStable, $preferLowest)
- {
- $lock = array(
- '_readme' => array('This file locks the dependencies of your project to a known state',
- 'Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file',
- 'This file is @gener'.'ated automatically'),
- 'hash' => $this->hash,
- 'packages' => null,
- 'packages-dev' => null,
- 'aliases' => array(),
- 'minimum-stability' => $minimumStability,
- 'stability-flags' => $stabilityFlags,
- 'prefer-stable' => $preferStable,
- 'prefer-lowest' => $preferLowest,
- );
- foreach ($aliases as $package => $versions) {
- foreach ($versions as $version => $alias) {
- $lock['aliases'][] = array(
- 'alias' => $alias['alias'],
- 'alias_normalized' => $alias['alias_normalized'],
- 'version' => $version,
- 'package' => $package,
- );
- }
- }
- $lock['packages'] = $this->lockPackages($packages);
- if (null !== $devPackages) {
- $lock['packages-dev'] = $this->lockPackages($devPackages);
- }
- $lock['platform'] = $platformReqs;
- $lock['platform-dev'] = $platformDevReqs;
- if (empty($lock['packages']) && empty($lock['packages-dev']) && empty($lock['platform']) && empty($lock['platform-dev'])) {
- if ($this->lockFile->exists()) {
- unlink($this->lockFile->getPath());
- }
- return false;
- }
- if (!$this->isLocked() || $lock !== $this->getLockData()) {
- $this->lockFile->write($lock);
- $this->lockDataCache = null;
- return true;
- }
- return false;
- }
- private function lockPackages(array $packages)
- {
- $locked = array();
- foreach ($packages as $package) {
- if ($package instanceof AliasPackage) {
- continue;
- }
- $name = $package->getPrettyName();
- $version = $package->getPrettyVersion();
- if (!$name || !$version) {
- throw new \LogicException(sprintf(
- 'Package "%s" has no version or name and can not be locked', $package
- ));
- }
- $spec = $this->dumper->dump($package);
- unset($spec['version_normalized']);
- $time = isset($spec['time']) ? $spec['time'] : null;
- unset($spec['time']);
- if ($package->isDev() && $package->getInstallationSource() === 'source') {
- $time = $this->getPackageTime($package) ?: $time;
- }
- if (null !== $time) {
- $spec['time'] = $time;
- }
- unset($spec['installation-source']);
- $locked[] = $spec;
- }
- usort($locked, function ($a, $b) {
- $comparison = strcmp($a['name'], $b['name']);
- if (0 !== $comparison) {
- return $comparison;
- }
- return strcmp($a['version'], $b['version']);
- });
- return $locked;
- }
- private function getPackageTime(PackageInterface $package)
- {
- if (!function_exists('proc_open')) {
- return null;
- }
- $path = realpath($this->installationManager->getInstallPath($package));
- $sourceType = $package->getSourceType();
- $datetime = null;
- if ($path && in_array($sourceType, array('git', 'hg'))) {
- $sourceRef = $package->getSourceReference() ?: $package->getDistReference();
- switch ($sourceType) {
- case 'git':
- GitUtil::cleanEnv();
- if (0 === $this->process->execute('git log -n1 --pretty=%ct '.ProcessExecutor::escape($sourceRef), $output, $path) && preg_match('{^\s*\d+\s*$}', $output)) {
- $datetime = new \DateTime('@'.trim($output), new \DateTimeZone('UTC'));
- }
- break;
- case 'hg':
- if (0 === $this->process->execute('hg log --template "{date|hgdate}" -r '.ProcessExecutor::escape($sourceRef), $output, $path) && preg_match('{^\s*(\d+)\s*}', $output, $match)) {
- $datetime = new \DateTime('@'.$match[1], new \DateTimeZone('UTC'));
- }
- break;
- }
- }
- return $datetime ? $datetime->format('Y-m-d H:i:s') : null;
- }
- }
- <?php
- namespace Composer\Package;
- use Composer\Package\Version\VersionParser;
- use Composer\Util\ComposerMirror;
- class Package extends BasePackage
- {
- protected $type;
- protected $targetDir;
- protected $installationSource;
- protected $sourceType;
- protected $sourceUrl;
- protected $sourceReference;
- protected $sourceMirrors;
- protected $distType;
- protected $distUrl;
- protected $distReference;
- protected $distSha1Checksum;
- protected $distMirrors;
- protected $version;
- protected $prettyVersion;
- protected $releaseDate;
- protected $extra = array();
- protected $binaries = array();
- protected $dev;
- protected $stability;
- protected $notificationUrl;
- protected $requires = array();
- protected $conflicts = array();
- protected $provides = array();
- protected $replaces = array();
- protected $devRequires = array();
- protected $suggests = array();
- protected $autoload = array();
- protected $devAutoload = array();
- protected $includePaths = array();
- protected $archiveExcludes = array();
- public function __construct($name, $version, $prettyVersion)
- {
- parent::__construct($name);
- $this->version = $version;
- $this->prettyVersion = $prettyVersion;
- $this->stability = VersionParser::parseStability($version);
- $this->dev = $this->stability === 'dev';
- }
- public function isDev()
- {
- return $this->dev;
- }
- public function setType($type)
- {
- $this->type = $type;
- }
- public function getType()
- {
- return $this->type ?: 'library';
- }
- public function getStability()
- {
- return $this->stability;
- }
- public function setTargetDir($targetDir)
- {
- $this->targetDir = $targetDir;
- }
- public function getTargetDir()
- {
- if (null === $this->targetDir) {
- return;
- }
- return ltrim(preg_replace('{ (?:^|[\\\\/]+) \.\.? (?:[\\\\/]+|$) (?:\.\.? (?:[\\\\/]+|$) )*}x', '/', $this->targetDir), '/');
- }
- public function setExtra(array $extra)
- {
- $this->extra = $extra;
- }
- public function getExtra()
- {
- return $this->extra;
- }
- public function setBinaries(array $binaries)
- {
- $this->binaries = $binaries;
- }
- public function getBinaries()
- {
- return $this->binaries;
- }
- public function setInstallationSource($type)
- {
- $this->installationSource = $type;
- }
- public function getInstallationSource()
- {
- return $this->installationSource;
- }
- public function setSourceType($type)
- {
- $this->sourceType = $type;
- }
- public function getSourceType()
- {
- return $this->sourceType;
- }
- public function setSourceUrl($url)
- {
- $this->sourceUrl = $url;
- }
- public function getSourceUrl()
- {
- return $this->sourceUrl;
- }
- public function setSourceReference($reference)
- {
- $this->sourceReference = $reference;
- }
- public function getSourceReference()
- {
- return $this->sourceReference;
- }
- public function setSourceMirrors($mirrors)
- {
- $this->sourceMirrors = $mirrors;
- }
- public function getSourceMirrors()
- {
- return $this->sourceMirrors;
- }
- public function getSourceUrls()
- {
- return $this->getUrls($this->sourceUrl, $this->sourceMirrors, $this->sourceReference, $this->sourceType, 'source');
- }
- public function setDistType($type)
- {
- $this->distType = $type;
- }
- public function getDistType()
- {
- return $this->distType;
- }
- public function setDistUrl($url)
- {
- $this->distUrl = $url;
- }
- public function getDistUrl()
- {
- return $this->distUrl;
- }
- public function setDistReference($reference)
- {
- $this->distReference = $reference;
- }
- public function getDistReference()
- {
- return $this->distReference;
- }
- public function setDistSha1Checksum($sha1checksum)
- {
- $this->distSha1Checksum = $sha1checksum;
- }
- public function getDistSha1Checksum()
- {
- return $this->distSha1Checksum;
- }
- public function setDistMirrors($mirrors)
- {
- $this->distMirrors = $mirrors;
- }
- public function getDistMirrors()
- {
- return $this->distMirrors;
- }
- public function getDistUrls()
- {
- return $this->getUrls($this->distUrl, $this->distMirrors, $this->distReference, $this->distType, 'dist');
- }
- public function getVersion()
- {
- return $this->version;
- }
- public function getPrettyVersion()
- {
- return $this->prettyVersion;
- }
- public function setReleaseDate(\DateTime $releaseDate)
- {
- $this->releaseDate = $releaseDate;
- }
- public function getReleaseDate()
- {
- return $this->releaseDate;
- }
- public function setRequires(array $requires)
- {
- $this->requires = $requires;
- }
- public function getRequires()
- {
- return $this->requires;
- }
- public function setConflicts(array $conflicts)
- {
- $this->conflicts = $conflicts;
- }
- public function getConflicts()
- {
- return $this->conflicts;
- }
- public function setProvides(array $provides)
- {
- $this->provides = $provides;
- }
- public function getProvides()
- {
- return $this->provides;
- }
- public function setReplaces(array $replaces)
- {
- $this->replaces = $replaces;
- }
- public function getReplaces()
- {
- return $this->replaces;
- }
- public function setDevRequires(array $devRequires)
- {
- $this->devRequires = $devRequires;
- }
- public function getDevRequires()
- {
- return $this->devRequires;
- }
- public function setSuggests(array $suggests)
- {
- $this->suggests = $suggests;
- }
- public function getSuggests()
- {
- return $this->suggests;
- }
- public function setAutoload(array $autoload)
- {
- $this->autoload = $autoload;
- }
- public function getAutoload()
- {
- return $this->autoload;
- }
- public function setDevAutoload(array $devAutoload)
- {
- $this->devAutoload = $devAutoload;
- }
- public function getDevAutoload()
- {
- return $this->devAutoload;
- }
- public function setIncludePaths(array $includePaths)
- {
- $this->includePaths = $includePaths;
- }
- public function getIncludePaths()
- {
- return $this->includePaths;
- }
- public function setNotificationUrl($notificationUrl)
- {
- $this->notificationUrl = $notificationUrl;
- }
- public function getNotificationUrl()
- {
- return $this->notificationUrl;
- }
- public function setArchiveExcludes(array $excludes)
- {
- $this->archiveExcludes = $excludes;
- }
- public function getArchiveExcludes()
- {
- return $this->archiveExcludes;
- }
- public function replaceVersion($version, $prettyVersion)
- {
- $this->version = $version;
- $this->prettyVersion = $prettyVersion;
- $this->stability = VersionParser::parseStability($version);
- $this->dev = $this->stability === 'dev';
- }
- protected function getUrls($url, $mirrors, $ref, $type, $urlType)
- {
- if (!$url) {
- return array();
- }
- $urls = array($url);
- if ($mirrors) {
- foreach ($mirrors as $mirror) {
- if ($urlType === 'dist') {
- $mirrorUrl = ComposerMirror::processUrl($mirror['url'], $this->name, $this->version, $ref, $type);
- } elseif ($urlType === 'source' && $type === 'git') {
- $mirrorUrl = ComposerMirror::processGitUrl($mirror['url'], $this->name, $url, $type);
- } elseif ($urlType === 'source' && $type === 'hg') {
- $mirrorUrl = ComposerMirror::processHgUrl($mirror['url'], $this->name, $url, $type);
- }
- if (!in_array($mirrorUrl, $urls)) {
- $func = $mirror['preferred'] ? 'array_unshift' : 'array_push';
- $func($urls, $mirrorUrl);
- }
- }
- }
- return $urls;
- }
- }
- <?php
- namespace Composer\Package;
- use Composer\Repository\RepositoryInterface;
- interface PackageInterface
- {
- public function getName();
- public function getPrettyName();
- public function getNames();
- public function setId($id);
- public function getId();
- public function isDev();
- public function getType();
- public function getTargetDir();
- public function getExtra();
- public function setInstallationSource($type);
- public function getInstallationSource();
- public function getSourceType();
- public function getSourceUrl();
- public function getSourceUrls();
- public function getSourceReference();
- public function getSourceMirrors();
- public function getDistType();
- public function getDistUrl();
- public function getDistUrls();
- public function getDistReference();
- public function getDistSha1Checksum();
- public function getDistMirrors();
- public function getVersion();
- public function getPrettyVersion();
- public function getReleaseDate();
- public function getStability();
- public function getRequires();
- public function getConflicts();
- public function getProvides();
- public function getReplaces();
- public function getDevRequires();
- public function getSuggests();
- public function getAutoload();
- public function getDevAutoload();
- public function getIncludePaths();
- public function setRepository(RepositoryInterface $repository);
- public function getRepository();
- public function getBinaries();
- public function getUniqueName();
- public function getNotificationUrl();
- public function __toString();
- public function getPrettyString();
- public function getArchiveExcludes();
- public function getTransportOptions();
- }
- <?php
- namespace Composer\Package;
- class RootAliasPackage extends AliasPackage implements RootPackageInterface
- {
- public function __construct(RootPackageInterface $aliasOf, $version, $prettyVersion)
- {
- parent::__construct($aliasOf, $version, $prettyVersion);
- }
- public function getAliases()
- {
- return $this->aliasOf->getAliases();
- }
- public function getMinimumStability()
- {
- return $this->aliasOf->getMinimumStability();
- }
- public function getStabilityFlags()
- {
- return $this->aliasOf->getStabilityFlags();
- }
- public function getReferences()
- {
- return $this->aliasOf->getReferences();
- }
- public function getPreferStable()
- {
- return $this->aliasOf->getPreferStable();
- }
- public function setRequires(array $require)
- {
- return $this->aliasOf->setRequires($require);
- }
- public function setDevRequires(array $devRequire)
- {
- return $this->aliasOf->setDevRequires($devRequire);
- }
- public function __clone()
- {
- parent::__clone();
- $this->aliasOf = clone $this->aliasOf;
- }
- }
- <?php
- namespace Composer\Package;
- class RootPackage extends CompletePackage implements RootPackageInterface
- {
- protected $minimumStability = 'stable';
- protected $preferStable = false;
- protected $stabilityFlags = array();
- protected $references = array();
- protected $aliases = array();
- public function setMinimumStability($minimumStability)
- {
- $this->minimumStability = $minimumStability;
- }
- public function getMinimumStability()
- {
- return $this->minimumStability;
- }
- public function setStabilityFlags(array $stabilityFlags)
- {
- $this->stabilityFlags = $stabilityFlags;
- }
- public function getStabilityFlags()
- {
- return $this->stabilityFlags;
- }
- public function setPreferStable($preferStable)
- {
- $this->preferStable = $preferStable;
- }
- public function getPreferStable()
- {
- return $this->preferStable;
- }
- public function setReferences(array $references)
- {
- $this->references = $references;
- }
- public function getReferences()
- {
- return $this->references;
- }
- public function setAliases(array $aliases)
- {
- $this->aliases = $aliases;
- }
- public function getAliases()
- {
- return $this->aliases;
- }
- }
- <?php
- namespace Composer\Package;
- interface RootPackageInterface extends CompletePackageInterface
- {
- public function getAliases();
- public function getMinimumStability();
- public function getStabilityFlags();
- public function getReferences();
- public function getPreferStable();
- public function setRequires(array $requires);
- public function setDevRequires(array $devRequires);
- }
- <?php
- namespace Composer\Package\Version;
- use Composer\Package\BasePackage;
- use Composer\Package\PackageInterface;
- use Composer\Package\Link;
- use Composer\Package\LinkConstraint\EmptyConstraint;
- use Composer\Package\LinkConstraint\MultiConstraint;
- use Composer\Package\LinkConstraint\VersionConstraint;
- class VersionParser
- {
- private static $modifierRegex = '[._-]?(?:(stable|beta|b|RC|alpha|a|patch|pl|p)(?:[.-]?(\d+))?)?([.-]?dev)?';
- public static function parseStability($version)
- {
- $version = preg_replace('{#.+$}i', '', $version);
- if ('dev-' === substr($version, 0, 4) || '-dev' === substr($version, -4)) {
- return 'dev';
- }
- preg_match('{'.self::$modifierRegex.'$}i', strtolower($version), $match);
- if (!empty($match[3])) {
- return 'dev';
- }
- if (!empty($match[1])) {
- if ('beta' === $match[1] || 'b' === $match[1]) {
- return 'beta';
- }
- if ('alpha' === $match[1] || 'a' === $match[1]) {
- return 'alpha';
- }
- if ('rc' === $match[1]) {
- return 'RC';
- }
- }
- return 'stable';
- }
- public static function normalizeStability($stability)
- {
- $stability = strtolower($stability);
- return $stability === 'rc' ? 'RC' : $stability;
- }
- public static function formatVersion(PackageInterface $package, $truncate = true)
- {
- if (!$package->isDev() || !in_array($package->getSourceType(), array('hg', 'git'))) {
- return $package->getPrettyVersion();
- }
- if ($truncate && strlen($package->getSourceReference()) === 40) {
- return $package->getPrettyVersion() . ' ' . substr($package->getSourceReference(), 0, 7);
- }
- return $package->getPrettyVersion() . ' ' . $package->getSourceReference();
- }
- public function normalize($version, $fullVersion = null)
- {
- $version = trim($version);
- if (null === $fullVersion) {
- $fullVersion = $version;
- }
- if (preg_match('{^([^,\s]+) +as +([^,\s]+)$}', $version, $match)) {
- $version = $match[1];
- }
- if (preg_match('{^([^,\s+]+)\+[^\s]+$}', $version, $match)) {
- $version = $match[1];
- }
- if (preg_match('{^(?:dev-)?(?:master|trunk|default)$}i', $version)) {
- return '9999999-dev';
- }
- if ('dev-' === strtolower(substr($version, 0, 4))) {
- return 'dev-'.substr($version, 4);
- }
- if (preg_match('{^v?(\d{1,3})(\.\d+)?(\.\d+)?(\.\d+)?'.self::$modifierRegex.'$}i', $version, $matches)) {
- $version = $matches[1]
- .(!empty($matches[2]) ? $matches[2] : '.0')
- .(!empty($matches[3]) ? $matches[3] : '.0')
- .(!empty($matches[4]) ? $matches[4] : '.0');
- $index = 5;
- } elseif (preg_match('{^v?(\d{4}(?:[.:-]?\d{2}){1,6}(?:[.:-]?\d{1,3})?)'.self::$modifierRegex.'$}i', $version, $matches)) {
- $version = preg_replace('{\D}', '-', $matches[1]);
- $index = 2;
- } elseif (preg_match('{^v?(\d{4,})(\.\d+)?(\.\d+)?(\.\d+)?'.self::$modifierRegex.'$}i', $version, $matches)) {
- $version = $matches[1]
- .(!empty($matches[2]) ? $matches[2] : '.0')
- .(!empty($matches[3]) ? $matches[3] : '.0')
- .(!empty($matches[4]) ? $matches[4] : '.0');
- $index = 5;
- }
- if (isset($index)) {
- if (!empty($matches[$index])) {
- if ('stable' === $matches[$index]) {
- return $version;
- }
- $version .= '-' . $this->expandStability($matches[$index]) . (!empty($matches[$index+1]) ? $matches[$index+1] : '');
- }
- if (!empty($matches[$index+2])) {
- $version .= '-dev';
- }
- return $version;
- }
- if (preg_match('{(.*?)[.-]?dev$}i', $version, $match)) {
- try {
- return $this->normalizeBranch($match[1]);
- } catch (\Exception $e) {
- }
- }
- $extraMessage = '';
- if (preg_match('{ +as +'.preg_quote($version).'$}', $fullVersion)) {
- $extraMessage = ' in "'.$fullVersion.'", the alias must be an exact version';
- } elseif (preg_match('{^'.preg_quote($version).' +as +}', $fullVersion)) {
- $extraMessage = ' in "'.$fullVersion.'", the alias source must be an exact version, if it is a branch name you should prefix it with dev-';
- }
- throw new \UnexpectedValueException('Invalid version string "'.$version.'"'.$extraMessage);
- }
- public function parseNumericAliasPrefix($branch)
- {
- if (preg_match('/^(?P<version>(\d+\\.)*\d+)(?:\.x)?-dev$/i', $branch, $matches)) {
- return $matches['version'].".";
- }
- return false;
- }
- public function normalizeBranch($name)
- {
- $name = trim($name);
- if (in_array($name, array('master', 'trunk', 'default'))) {
- return $this->normalize($name);
- }
- if (preg_match('#^v?(\d+)(\.(?:\d+|[xX*]))?(\.(?:\d+|[xX*]))?(\.(?:\d+|[xX*]))?$#i', $name, $matches)) {
- $version = '';
- for ($i = 1; $i < 5; $i++) {
- $version .= isset($matches[$i]) ? str_replace(array('*', 'X'), 'x', $matches[$i]) : '.x';
- }
- return str_replace('x', '9999999', $version).'-dev';
- }
- return 'dev-'.$name;
- }
- public function parseLinks($source, $sourceVersion, $description, $links)
- {
- $res = array();
- foreach ($links as $target => $constraint) {
- if ('self.version' === $constraint) {
- $parsedConstraint = $this->parseConstraints($sourceVersion);
- } else {
- $parsedConstraint = $this->parseConstraints($constraint);
- }
- $res[strtolower($target)] = new Link($source, $target, $parsedConstraint, $description, $constraint);
- }
- return $res;
- }
- public function parseConstraints($constraints)
- {
- $prettyConstraint = $constraints;
- if (preg_match('{^([^,\s]*?)@('.implode('|', array_keys(BasePackage::$stabilities)).')$}i', $constraints, $match)) {
- $constraints = empty($match[1]) ? '*' : $match[1];
- }
- if (preg_match('{^(dev-[^,\s@]+?|[^,\s@]+?\.x-dev)#.+$}i', $constraints, $match)) {
- $constraints = $match[1];
- }
- $orConstraints = preg_split('{\s*\|\|?\s*}', trim($constraints));
- $orGroups = array();
- foreach ($orConstraints as $constraints) {
- $andConstraints = preg_split('{(?<!^|as|[=>< ,]) *(?<!-)[, ](?!-) *(?!,|as|$)}', $constraints);
- if (count($andConstraints) > 1) {
- $constraintObjects = array();
- foreach ($andConstraints as $constraint) {
- $constraintObjects = array_merge($constraintObjects, $this->parseConstraint($constraint));
- }
- } else {
- $constraintObjects = $this->parseConstraint($andConstraints[0]);
- }
- if (1 === count($constraintObjects)) {
- $constraint = $constraintObjects[0];
- } else {
- $constraint = new MultiConstraint($constraintObjects);
- }
- $orGroups[] = $constraint;
- }
- if (1 === count($orGroups)) {
- $constraint = $orGroups[0];
- } else {
- $constraint = new MultiConstraint($orGroups, false);
- }
- $constraint->setPrettyString($prettyConstraint);
- return $constraint;
- }
- private function parseConstraint($constraint)
- {
- if (preg_match('{^([^,\s]+?)@('.implode('|', array_keys(BasePackage::$stabilities)).')$}i', $constraint, $match)) {
- $constraint = $match[1];
- if ($match[2] !== 'stable') {
- $stabilityModifier = $match[2];
- }
- }
- if (preg_match('{^[xX*](\.[xX*])*$}i', $constraint)) {
- return array(new EmptyConstraint);
- }
- $versionRegex = '(\d+)(?:\.(\d+))?(?:\.(\d+))?(?:\.(\d+))?'.self::$modifierRegex;
-
-
-
-
- if (preg_match('{^~>?'.$versionRegex.'$}i', $constraint, $matches)) {
- if (substr($constraint, 0, 2) === '~>') {
- throw new \UnexpectedValueException(
- 'Could not parse version constraint '.$constraint.': '.
- 'Invalid operator "~>", you probably meant to use the "~" operator'
- );
- }
- if (isset($matches[4]) && '' !== $matches[4]) {
- $position = 4;
- } elseif (isset($matches[3]) && '' !== $matches[3]) {
- $position = 3;
- } elseif (isset($matches[2]) && '' !== $matches[2]) {
- $position = 2;
- } else {
- $position = 1;
- }
- $stabilitySuffix = '';
- if (!empty($matches[5])) {
- $stabilitySuffix .= '-' . $this->expandStability($matches[5]) . (!empty($matches[6]) ? $matches[6] : '');
- }
- if (!empty($matches[7])) {
- $stabilitySuffix .= '-dev';
- }
- if (!$stabilitySuffix) {
- $stabilitySuffix = "-dev";
- }
- $lowVersion = $this->manipulateVersionString($matches, $position, 0) . $stabilitySuffix;
- $lowerBound = new VersionConstraint('>=', $lowVersion);
-
- $highPosition = max(1, $position - 1);
- $highVersion = $this->manipulateVersionString($matches, $highPosition, 1) . '-dev';
- $upperBound = new VersionConstraint('<', $highVersion);
- return array(
- $lowerBound,
- $upperBound
- );
- }
- if (preg_match('{^\^'.$versionRegex.'($)}i', $constraint, $matches)) {
- if ('0' !== $matches[1] || '' === $matches[2]) {
- $position = 1;
- } elseif ('0' !== $matches[2] || '' === $matches[3]) {
- $position = 2;
- } else {
- $position = 3;
- }
- $stabilitySuffix = '';
- if (empty($matches[5]) && empty($matches[7])) {
- $stabilitySuffix .= '-dev';
- }
- $lowVersion = $this->normalize(substr($constraint . $stabilitySuffix, 1));
- $lowerBound = new VersionConstraint('>=', $lowVersion);
-
- $highVersion = $this->manipulateVersionString($matches, $position, 1) . '-dev';
- $upperBound = new VersionConstraint('<', $highVersion);
- return array(
- $lowerBound,
- $upperBound
- );
- }
- if (preg_match('{^(\d+)(?:\.(\d+))?(?:\.(\d+))?\.[xX*]$}', $constraint, $matches)) {
- if (isset($matches[3]) && '' !== $matches[3]) {
- $position = 3;
- } elseif (isset($matches[2]) && '' !== $matches[2]) {
- $position = 2;
- } else {
- $position = 1;
- }
- $lowVersion = $this->manipulateVersionString($matches, $position) . "-dev";
- $highVersion = $this->manipulateVersionString($matches, $position, 1) . "-dev";
- if ($lowVersion === "0.0.0.0-dev") {
- return array(new VersionConstraint('<', $highVersion));
- }
- return array(
- new VersionConstraint('>=', $lowVersion),
- new VersionConstraint('<', $highVersion),
- );
- }
- if (preg_match('{^(?P<from>'.$versionRegex.') +- +(?P<to>'.$versionRegex.')($)}i', $constraint, $matches)) {
- $lowStabilitySuffix = '';
- if (empty($matches[6]) && empty($matches[8])) {
- $lowStabilitySuffix = '-dev';
- }
- $lowVersion = $this->normalize($matches['from']);
- $lowerBound = new VersionConstraint('>=', $lowVersion . $lowStabilitySuffix);
- $highVersion = $matches[10];
- if ((!empty($matches[11]) && !empty($matches[12])) || !empty($matches[14]) || !empty($matches[16])) {
- $highVersion = $this->normalize($matches['to']);
- $upperBound = new VersionConstraint('<=', $highVersion);
- } else {
- $highMatch = array('', $matches[10], $matches[11], $matches[12], $matches[13]);
- $highVersion = $this->manipulateVersionString($highMatch, empty($matches[11]) ? 1 : 2, 1) . '-dev';
- $upperBound = new VersionConstraint('<', $highVersion);
- }
- return array(
- $lowerBound,
- $upperBound
- );
- }
- if (preg_match('{^(<>|!=|>=?|<=?|==?)?\s*(.*)}', $constraint, $matches)) {
- try {
- $version = $this->normalize($matches[2]);
- if (!empty($stabilityModifier) && $this->parseStability($version) === 'stable') {
- $version .= '-' . $stabilityModifier;
- } elseif ('<' === $matches[1]) {
- if (!preg_match('/-' . self::$modifierRegex . '$/', strtolower($matches[2]))) {
- $version .= '-dev';
- }
- }
- return array(new VersionConstraint($matches[1] ?: '=', $version));
- } catch (\Exception $e) {
- }
- }
- $message = 'Could not parse version constraint '.$constraint;
- if (isset($e)) {
- $message .= ': '. $e->getMessage();
- }
- throw new \UnexpectedValueException($message);
- }
- private function manipulateVersionString($matches, $position, $increment = 0, $pad = '0')
- {
- for ($i = 4; $i > 0; $i--) {
- if ($i > $position) {
- $matches[$i] = $pad;
- } elseif ($i == $position && $increment) {
- $matches[$i] += $increment;
- if ($matches[$i] < 0) {
- $matches[$i] = $pad;
- $position--;
- if ($i == 1) {
- return;
- }
- }
- }
- }
- return $matches[1] . '.' . $matches[2] . '.' . $matches[3] . '.' . $matches[4];
- }
- private function expandStability($stability)
- {
- $stability = strtolower($stability);
- switch ($stability) {
- case 'a':
- return 'alpha';
- case 'b':
- return 'beta';
- case 'p':
- case 'pl':
- return 'patch';
- case 'rc':
- return 'RC';
- default:
- return $stability;
- }
- }
- public function parseNameVersionPairs(array $pairs)
- {
- $pairs = array_values($pairs);
- $result = array();
- for ($i = 0, $count = count($pairs); $i < $count; $i++) {
- $pair = preg_replace('{^([^=: ]+)[=: ](.*)$}', '$1 $2', trim($pairs[$i]));
- if (false === strpos($pair, ' ') && isset($pairs[$i+1]) && false === strpos($pairs[$i+1], '/')) {
- $pair .= ' '.$pairs[$i+1];
- $i++;
- }
- if (strpos($pair, ' ')) {
- list($name, $version) = explode(" ", $pair, 2);
- $result[] = array('name' => $name, 'version' => $version);
- } else {
- $result[] = array('name' => $pair);
- }
- }
- return $result;
- }
- }
- <?php
- namespace Composer\Package\Version;
- use Composer\DependencyResolver\Pool;
- use Composer\Package\PackageInterface;
- use Composer\Package\Loader\ArrayLoader;
- use Composer\Package\Dumper\ArrayDumper;
- class VersionSelector
- {
- private $pool;
- private $parser;
- public function __construct(Pool $pool)
- {
- $this->pool = $pool;
- }
- public function findBestCandidate($packageName, $targetPackageVersion = null)
- {
- $constraint = $targetPackageVersion ? $this->getParser()->parseConstraints($targetPackageVersion) : null;
- $candidates = $this->pool->whatProvides($packageName, $constraint, true);
- if (!$candidates) {
- return false;
- }
- $package = reset($candidates);
- foreach ($candidates as $candidate) {
- if (version_compare($package->getVersion(), $candidate->getVersion(), '<')) {
- $package = $candidate;
- }
- }
- return $package;
- }
- public function findRecommendedRequireVersion(PackageInterface $package)
- {
- $version = $package->getVersion();
- if (!$package->isDev()) {
- return $this->transformVersion($version, $package->getPrettyVersion(), $package->getStability());
- }
- $loader = new ArrayLoader($this->getParser());
- $dumper = new ArrayDumper();
- $extra = $loader->getBranchAlias($dumper->dump($package));
- if ($extra) {
- $extra = preg_replace('{^(\d+\.\d+\.\d+)(\.9999999)-dev$}', '$1.0', $extra, -1, $count);
- if ($count) {
- $extra = str_replace('.9999999', '.0', $extra);
- return $this->transformVersion($extra, $extra, 'dev');
- }
- }
- return $package->getPrettyVersion();
- }
- private function transformVersion($version, $prettyVersion, $stability)
- {
-
- $semanticVersionParts = explode('.', $version);
- $op = '~';
- if (count($semanticVersionParts) == 4 && preg_match('{^0\D?}', $semanticVersionParts[3])) {
- if ($semanticVersionParts[0] === '0') {
- if ($semanticVersionParts[1] === '0') {
- $semanticVersionParts[3] = '*';
- } else {
- $semanticVersionParts[2] = '*';
- unset($semanticVersionParts[3]);
- }
- $op = '';
- } else {
- unset($semanticVersionParts[2], $semanticVersionParts[3]);
- }
- $version = implode('.', $semanticVersionParts);
- } else {
- return $prettyVersion;
- }
- if ($stability != 'stable') {
- $version .= '@'.$stability;
- }
- return $op.$version;
- }
- private function getParser()
- {
- if ($this->parser === null) {
- $this->parser = new VersionParser();
- }
- return $this->parser;
- }
- }
- <?php
- namespace Composer\Plugin;
- use Composer\EventDispatcher\Event;
- use Symfony\Component\Console\Input\InputInterface;
- use Symfony\Component\Console\Output\OutputInterface;
- class CommandEvent extends Event
- {
- private $commandName;
- private $input;
- private $output;
- public function __construct($name, $commandName, $input, $output, array $args = array(), array $flags = array())
- {
- parent::__construct($name, $args, $flags);
- $this->commandName = $commandName;
- $this->input = $input;
- $this->output = $output;
- }
- public function getInput()
- {
- return $this->input;
- }
- public function getOutput()
- {
- return $this->output;
- }
- public function getCommandName()
- {
- return $this->commandName;
- }
- }
- <?php
- namespace Composer\Plugin;
- class PluginEvents
- {
- const COMMAND = 'command';
- const PRE_FILE_DOWNLOAD = 'pre-file-download';
- }
- <?php
- namespace Composer\Plugin;
- use Composer\Composer;
- use Composer\IO\IOInterface;
- interface PluginInterface
- {
- const PLUGIN_API_VERSION = '1.0.0';
- public function activate(Composer $composer, IOInterface $io);
- }
- <?php
- namespace Composer\Plugin;
- use Composer\Composer;
- use Composer\EventDispatcher\EventSubscriberInterface;
- use Composer\IO\IOInterface;
- use Composer\Package\Package;
- use Composer\Package\Version\VersionParser;
- use Composer\Repository\RepositoryInterface;
- use Composer\Package\AliasPackage;
- use Composer\Package\PackageInterface;
- use Composer\Package\Link;
- use Composer\Package\LinkConstraint\VersionConstraint;
- use Composer\DependencyResolver\Pool;
- class PluginManager
- {
- protected $composer;
- protected $io;
- protected $globalComposer;
- protected $versionParser;
- protected $plugins = array();
- protected $registeredPlugins = array();
- private static $classCounter = 0;
- public function __construct(IOInterface $io, Composer $composer, Composer $globalComposer = null)
- {
- $this->io = $io;
- $this->composer = $composer;
- $this->globalComposer = $globalComposer;
- $this->versionParser = new VersionParser();
- }
- public function loadInstalledPlugins()
- {
- $repo = $this->composer->getRepositoryManager()->getLocalRepository();
- $globalRepo = $this->globalComposer ? $this->globalComposer->getRepositoryManager()->getLocalRepository() : null;
- if ($repo) {
- $this->loadRepository($repo);
- }
- if ($globalRepo) {
- $this->loadRepository($globalRepo);
- }
- }
- public function addPlugin(PluginInterface $plugin)
- {
- if ($this->io->isDebug()) {
- $this->io->writeError('Loading plugin '.get_class($plugin));
- }
- $this->plugins[] = $plugin;
- $plugin->activate($this->composer, $this->io);
- if ($plugin instanceof EventSubscriberInterface) {
- $this->composer->getEventDispatcher()->addSubscriber($plugin);
- }
- }
- public function getPlugins()
- {
- return $this->plugins;
- }
- public function loadRepository(RepositoryInterface $repo)
- {
- foreach ($repo->getPackages() as $package) {
- if ($package instanceof AliasPackage) {
- continue;
- }
- if ('composer-plugin' === $package->getType()) {
- $requiresComposer = null;
- foreach ($package->getRequires() as $link) {
- if ($link->getTarget() == 'composer-plugin-api') {
- $requiresComposer = $link->getConstraint();
- }
- }
- if (!$requiresComposer) {
- throw new \RuntimeException("Plugin ".$package->getName()." is missing a require statement for a version of the composer-plugin-api package.");
- }
- if (!$requiresComposer->matches(new VersionConstraint('==', $this->versionParser->normalize(PluginInterface::PLUGIN_API_VERSION)))) {
- $this->io->writeError("<warning>The plugin ".$package->getName()." requires a version of composer-plugin-api that does not match your composer installation. You may need to run composer update with the '--no-plugins' option.</warning>");
- }
- $this->registerPackage($package);
- }
- if ('composer-installer' === $package->getType()) {
- $this->registerPackage($package);
- }
- }
- }
- protected function collectDependencies(Pool $pool, array $collected, PackageInterface $package)
- {
- $requires = array_merge(
- $package->getRequires(),
- $package->getDevRequires()
- );
- foreach ($requires as $requireLink) {
- $requiredPackage = $this->lookupInstalledPackage($pool, $requireLink);
- if ($requiredPackage && !isset($collected[$requiredPackage->getName()])) {
- $collected[$requiredPackage->getName()] = $requiredPackage;
- $collected = $this->collectDependencies($pool, $collected, $requiredPackage);
- }
- }
- return $collected;
- }
- protected function lookupInstalledPackage(Pool $pool, Link $link)
- {
- $packages = $pool->whatProvides($link->getTarget(), $link->getConstraint());
- return (!empty($packages)) ? $packages[0] : null;
- }
- public function registerPackage(PackageInterface $package, $failOnMissingClasses = false)
- {
- $oldInstallerPlugin = ($package->getType() === 'composer-installer');
- if (in_array($package->getName(), $this->registeredPlugins)) {
- return;
- }
- $extra = $package->getExtra();
- if (empty($extra['class'])) {
- throw new \UnexpectedValueException('Error while installing '.$package->getPrettyName().', composer-plugin packages should have a class defined in their extra key to be usable.');
- }
- $classes = is_array($extra['class']) ? $extra['class'] : array($extra['class']);
- $localRepo = $this->composer->getRepositoryManager()->getLocalRepository();
- $globalRepo = $this->globalComposer ? $this->globalComposer->getRepositoryManager()->getLocalRepository() : null;
- $pool = new Pool('dev');
- $pool->addRepository($localRepo);
- if ($globalRepo) {
- $pool->addRepository($globalRepo);
- }
- $autoloadPackages = array($package->getName() => $package);
- $autoloadPackages = $this->collectDependencies($pool, $autoloadPackages, $package);
- $generator = $this->composer->getAutoloadGenerator();
- $autoloads = array();
- foreach ($autoloadPackages as $autoloadPackage) {
- $downloadPath = $this->getInstallPath($autoloadPackage, ($globalRepo && $globalRepo->hasPackage($autoloadPackage)));
- $autoloads[] = array($autoloadPackage, $downloadPath);
- }
- $map = $generator->parseAutoloads($autoloads, new Package('dummy', '1.0.0.0', '1.0.0'));
- $classLoader = $generator->createLoader($map);
- $classLoader->register();
- foreach ($classes as $class) {
- if (class_exists($class, false)) {
- $code = file_get_contents($classLoader->findFile($class));
- $code = preg_replace('{^(\s*)class\s+(\S+)}mi', '$1class $2_composer_tmp'.self::$classCounter, $code);
- eval('?>'.$code);
- $class .= '_composer_tmp'.self::$classCounter;
- self::$classCounter++;
- }
- if ($oldInstallerPlugin) {
- $installer = new $class($this->io, $this->composer);
- $this->composer->getInstallationManager()->addInstaller($installer);
- } elseif (class_exists($class)) {
- $plugin = new $class();
- $this->addPlugin($plugin);
- $this->registeredPlugins[] = $package->getName();
- } elseif ($failOnMissingClasses) {
- throw new \UnexpectedValueException('Plugin '.$package->getName().' could not be initialized, class not found: '.$class);
- }
- }
- }
- public function getInstallPath(PackageInterface $package, $global = false)
- {
- if (!$global) {
- return $this->composer->getInstallationManager()->getInstallPath($package);
- }
- return $this->globalComposer->getInstallationManager()->getInstallPath($package);
- }
- }
- <?php
- namespace Composer\Plugin;
- use Composer\EventDispatcher\Event;
- use Composer\Util\RemoteFilesystem;
- class PreFileDownloadEvent extends Event
- {
- private $rfs;
- private $processedUrl;
- public function __construct($name, RemoteFilesystem $rfs, $processedUrl)
- {
- parent::__construct($name);
- $this->rfs = $rfs;
- $this->processedUrl = $processedUrl;
- }
- public function getRemoteFilesystem()
- {
- return $this->rfs;
- }
- public function setRemoteFilesystem(RemoteFilesystem $rfs)
- {
- $this->rfs = $rfs;
- }
- public function getProcessedUrl()
- {
- return $this->processedUrl;
- }
- }
- <?php
- namespace Composer\Repository;
- use Composer\Package\AliasPackage;
- use Composer\Package\PackageInterface;
- use Composer\Package\CompletePackageInterface;
- use Composer\Package\Version\VersionParser;
- class ArrayRepository implements RepositoryInterface
- {
- protected $packages;
- public function __construct(array $packages = array())
- {
- foreach ($packages as $package) {
- $this->addPackage($package);
- }
- }
- public function findPackage($name, $version)
- {
- $versionParser = new VersionParser();
- $version = $versionParser->normalize($version);
- $name = strtolower($name);
- foreach ($this->getPackages() as $package) {
- if ($name === $package->getName() && $version === $package->getVersion()) {
- return $package;
- }
- }
- }
- public function findPackages($name, $version = null)
- {
- $name = strtolower($name);
- if (null !== $version) {
- $versionParser = new VersionParser();
- $version = $versionParser->normalize($version);
- }
- $packages = array();
- foreach ($this->getPackages() as $package) {
- if ($package->getName() === $name && (null === $version || $version === $package->getVersion())) {
- $packages[] = $package;
- }
- }
- return $packages;
- }
- public function search($query, $mode = 0)
- {
- $regex = '{(?:'.implode('|', preg_split('{\s+}', $query)).')}i';
- $matches = array();
- foreach ($this->getPackages() as $package) {
- $name = $package->getName();
- if (isset($matches[$name])) {
- continue;
- }
- if (preg_match($regex, $name)
- || ($mode === self::SEARCH_FULLTEXT && $package instanceof CompletePackageInterface && preg_match($regex, implode(' ', (array) $package->getKeywords()) . ' ' . $package->getDescription()))
- ) {
- $matches[$name] = array(
- 'name' => $package->getPrettyName(),
- 'description' => $package->getDescription(),
- );
- }
- }
- return array_values($matches);
- }
- public function hasPackage(PackageInterface $package)
- {
- $packageId = $package->getUniqueName();
- foreach ($this->getPackages() as $repoPackage) {
- if ($packageId === $repoPackage->getUniqueName()) {
- return true;
- }
- }
- return false;
- }
- public function addPackage(PackageInterface $package)
- {
- if (null === $this->packages) {
- $this->initialize();
- }
- $package->setRepository($this);
- $this->packages[] = $package;
- if ($package instanceof AliasPackage) {
- $aliasedPackage = $package->getAliasOf();
- if (null === $aliasedPackage->getRepository()) {
- $this->addPackage($aliasedPackage);
- }
- }
- }
- protected function createAliasPackage(PackageInterface $package, $alias, $prettyAlias)
- {
- return new AliasPackage($package instanceof AliasPackage ? $package->getAliasOf() : $package, $alias, $prettyAlias);
- }
- public function removePackage(PackageInterface $package)
- {
- $packageId = $package->getUniqueName();
- foreach ($this->getPackages() as $key => $repoPackage) {
- if ($packageId === $repoPackage->getUniqueName()) {
- array_splice($this->packages, $key, 1);
- return;
- }
- }
- }
- public function getPackages()
- {
- if (null === $this->packages) {
- $this->initialize();
- }
- return $this->packages;
- }
- public function count()
- {
- return count($this->packages);
- }
- protected function initialize()
- {
- $this->packages = array();
- }
- }
- <?php
- namespace Composer\Repository;
- use Composer\IO\IOInterface;
- use Composer\Json\JsonFile;
- use Composer\Package\Loader\ArrayLoader;
- class ArtifactRepository extends ArrayRepository
- {
- protected $loader;
- protected $lookup;
- public function __construct(array $repoConfig, IOInterface $io)
- {
- if (!extension_loaded('zip')) {
- throw new \RuntimeException('The artifact repository requires PHP\'s zip extension');
- }
- $this->loader = new ArrayLoader();
- $this->lookup = $repoConfig['url'];
- $this->io = $io;
- }
- protected function initialize()
- {
- parent::initialize();
- $this->scanDirectory($this->lookup);
- }
- private function scanDirectory($path)
- {
- $io = $this->io;
- $directory = new \RecursiveDirectoryIterator($path);
- $iterator = new \RecursiveIteratorIterator($directory);
- $regex = new \RegexIterator($iterator, '/^.+\.(zip|phar)$/i');
- foreach ($regex as $file) {
- if (!$file->isFile()) {
- continue;
- }
- $package = $this->getComposerInformation($file);
- if (!$package) {
- if ($io->isVerbose()) {
- $io->writeError("File <comment>{$file->getBasename()}</comment> doesn't seem to hold a package");
- }
- continue;
- }
- if ($io->isVerbose()) {
- $template = 'Found package <info>%s</info> (<comment>%s</comment>) in file <info>%s</info>';
- $io->writeError(sprintf($template, $package->getName(), $package->getPrettyVersion(), $file->getBasename()));
- }
- $this->addPackage($package);
- }
- }
- private function locateFile(\ZipArchive $zip, $filename)
- {
- $indexOfShortestMatch = false;
- $lengthOfShortestMatch = -1;
- for ($i = 0; $i < $zip->numFiles; $i++) {
- $stat = $zip->statIndex($i);
- if (strcmp(basename($stat['name']), $filename) === 0) {
- $directoryName = dirname($stat['name']);
- if ($directoryName == '.') {
-
- return $i;
- }
- if (strpos($directoryName, '\\') !== false ||
- strpos($directoryName, '/') !== false) {
- continue;
- }
- $length = strlen($stat['name']);
- if ($indexOfShortestMatch == false || $length < $lengthOfShortestMatch) {
- $contents = $zip->getFromIndex($i);
- if ($contents !== false) {
- $indexOfShortestMatch = $i;
- $lengthOfShortestMatch = $length;
- }
- }
- }
- }
- return $indexOfShortestMatch;
- }
- private function getComposerInformation(\SplFileInfo $file)
- {
- $zip = new \ZipArchive();
- $zip->open($file->getPathname());
- if (0 == $zip->numFiles) {
- return false;
- }
- $foundFileIndex = $this->locateFile($zip, 'composer.json');
- if (false === $foundFileIndex) {
- return false;
- }
- $configurationFileName = $zip->getNameIndex($foundFileIndex);
- $composerFile = "zip://{$file->getPathname()}#$configurationFileName";
- $json = file_get_contents($composerFile);
- $package = JsonFile::parseJson($json, $composerFile);
- $package['dist'] = array(
- 'type' => 'zip',
- 'url' => $file->getPathname(),
- 'shasum' => sha1_file($file->getRealPath())
- );
- $package = $this->loader->load($package);
- return $package;
- }
- }
- <?php
- namespace Composer\Repository;
- use Composer\Package\Loader\ArrayLoader;
- use Composer\Package\Package;
- use Composer\Package\PackageInterface;
- use Composer\Package\AliasPackage;
- use Composer\Package\Version\VersionParser;
- use Composer\DependencyResolver\Pool;
- use Composer\Json\JsonFile;
- use Composer\Cache;
- use Composer\Config;
- use Composer\IO\IOInterface;
- use Composer\Util\RemoteFilesystem;
- use Composer\Plugin\PluginEvents;
- use Composer\Plugin\PreFileDownloadEvent;
- use Composer\EventDispatcher\EventDispatcher;
- class ComposerRepository extends ArrayRepository
- {
- protected $config;
- protected $options;
- protected $url;
- protected $baseUrl;
- protected $io;
- protected $rfs;
- protected $cache;
- protected $notifyUrl;
- protected $searchUrl;
- protected $hasProviders = false;
- protected $providersUrl;
- protected $lazyProvidersUrl;
- protected $providerListing;
- protected $providers = array();
- protected $providersByUid = array();
- protected $loader;
- protected $rootAliases;
- protected $allowSslDowngrade = false;
- protected $eventDispatcher;
- protected $sourceMirrors;
- protected $distMirrors;
- private $degradedMode = false;
- private $rootData;
- public function __construct(array $repoConfig, IOInterface $io, Config $config, EventDispatcher $eventDispatcher = null)
- {
- if (!preg_match('{^[\w.]+\??://}', $repoConfig['url'])) {
- $repoConfig['url'] = 'http://'.$repoConfig['url'];
- }
- $repoConfig['url'] = rtrim($repoConfig['url'], '/');
- if ('https?' === substr($repoConfig['url'], 0, 6)) {
- $repoConfig['url'] = (extension_loaded('openssl') ? 'https' : 'http') . substr($repoConfig['url'], 6);
- }
- $urlBits = parse_url($repoConfig['url']);
- if ($urlBits === false || empty($urlBits['scheme'])) {
- throw new \UnexpectedValueException('Invalid url given for Composer repository: '.$repoConfig['url']);
- }
- if (!isset($repoConfig['options'])) {
- $repoConfig['options'] = array();
- }
- if (isset($repoConfig['allow_ssl_downgrade']) && true === $repoConfig['allow_ssl_downgrade']) {
- $this->allowSslDowngrade = true;
- }
- $this->config = $config;
- $this->options = $repoConfig['options'];
- $this->url = $repoConfig['url'];
- $this->baseUrl = rtrim(preg_replace('{^(.*)(?:/[^/\\]+.json)?(?:[?#].*)?$}', '$1', $this->url), '/');
- $this->io = $io;
- $this->cache = new Cache($io, $config->get('cache-repo-dir').'/'.preg_replace('{[^a-z0-9.]}i', '-', $this->url), 'a-z0-9.$');
- $this->loader = new ArrayLoader();
- $this->rfs = new RemoteFilesystem($this->io, $this->config, $this->options);
- $this->eventDispatcher = $eventDispatcher;
- }
- public function setRootAliases(array $rootAliases)
- {
- $this->rootAliases = $rootAliases;
- }
- public function findPackage($name, $version)
- {
- if (!$this->hasProviders()) {
- return parent::findPackage($name, $version);
- }
- $versionParser = new VersionParser();
- $version = $versionParser->normalize($version);
- $name = strtolower($name);
- foreach ($this->getProviderNames() as $providerName) {
- if ($name === $providerName) {
- $packages = $this->whatProvides(new Pool('dev'), $providerName);
- foreach ($packages as $package) {
- if ($name == $package->getName() && $version === $package->getVersion()) {
- return $package;
- }
- }
- }
- }
- }
- public function findPackages($name, $version = null)
- {
- if (!$this->hasProviders()) {
- return parent::findPackages($name, $version);
- }
- $name = strtolower($name);
- if (null !== $version) {
- $versionParser = new VersionParser();
- $version = $versionParser->normalize($version);
- }
- $packages = array();
- foreach ($this->getProviderNames() as $providerName) {
- if ($name === $providerName) {
- $packages = $this->whatProvides(new Pool('dev'), $providerName);
- foreach ($packages as $package) {
- if ($name == $package->getName() && (null === $version || $version === $package->getVersion())) {
- $packages[] = $package;
- }
- }
- }
- }
- return $packages;
- }
- public function getPackages()
- {
- if ($this->hasProviders()) {
- throw new \LogicException('Composer repositories that have providers can not load the complete list of packages, use getProviderNames instead.');
- }
- return parent::getPackages();
- }
- public function search($query, $mode = 0)
- {
- $this->loadRootServerFile();
- if ($this->searchUrl && $mode === self::SEARCH_FULLTEXT) {
- $url = str_replace('%query%', $query, $this->searchUrl);
- $hostname = parse_url($url, PHP_URL_HOST) ?: $url;
- $json = $this->rfs->getContents($hostname, $url, false);
- $results = JsonFile::parseJson($json, $url);
- return $results['results'];
- }
- if ($this->hasProviders()) {
- $results = array();
- $regex = '{(?:'.implode('|', preg_split('{\s+}', $query)).')}i';
- foreach ($this->getProviderNames() as $name) {
- if (preg_match($regex, $name)) {
- $results[] = array('name' => $name);
- }
- }
- return $results;
- }
- return parent::search($query, $mode);
- }
- public function getProviderNames()
- {
- $this->loadRootServerFile();
- if (null === $this->providerListing) {
- $this->loadProviderListings($this->loadRootServerFile());
- }
- if ($this->lazyProvidersUrl) {
- return array();
- }
- if ($this->providersUrl) {
- return array_keys($this->providerListing);
- }
- $providers = array();
- foreach (array_keys($this->providerListing) as $provider) {
- $providers[] = substr($provider, 2, -5);
- }
- return $providers;
- }
- protected function configurePackageTransportOptions(PackageInterface $package)
- {
- foreach ($package->getDistUrls() as $url) {
- if (strpos($url, $this->baseUrl) === 0) {
- $package->setTransportOptions($this->options);
- return;
- }
- }
- }
- public function hasProviders()
- {
- $this->loadRootServerFile();
- return $this->hasProviders;
- }
- public function resetPackageIds()
- {
- foreach ($this->providersByUid as $package) {
- if ($package instanceof AliasPackage) {
- $package->getAliasOf()->setId(-1);
- }
- $package->setId(-1);
- }
- }
- public function whatProvides(Pool $pool, $name)
- {
- if (isset($this->providers[$name])) {
- return $this->providers[$name];
- }
- if (preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $name) || '__root__' === $name) {
- return array();
- }
- if (null === $this->providerListing) {
- $this->loadProviderListings($this->loadRootServerFile());
- }
- if ($this->lazyProvidersUrl && !isset($this->providerListing[$name])) {
- $hash = null;
- $url = str_replace('%package%', $name, $this->lazyProvidersUrl);
- $cacheKey = false;
- } elseif ($this->providersUrl) {
- if (!isset($this->providerListing[$name])) {
- return array();
- }
- $hash = $this->providerListing[$name]['sha256'];
- $url = str_replace(array('%package%', '%hash%'), array($name, $hash), $this->providersUrl);
- $cacheKey = 'provider-'.strtr($name, '/', '$').'.json';
- } else {
- $url = 'p/'.$name.'.json';
- if (!isset($this->providerListing[$url])) {
- return array();
- }
- $hash = $this->providerListing[$url]['sha256'];
- $cacheKey = null;
- }
- if ($cacheKey && $this->cache->sha256($cacheKey) === $hash) {
- $packages = json_decode($this->cache->read($cacheKey), true);
- } else {
- $packages = $this->fetchFile($url, $cacheKey, $hash);
- }
- $this->providers[$name] = array();
- foreach ($packages['packages'] as $versions) {
- foreach ($versions as $version) {
- if (isset($this->providersByUid[$version['uid']])) {
- if (!isset($this->providers[$name][$version['uid']])) {
- if ($this->providersByUid[$version['uid']] instanceof AliasPackage) {
- $this->providers[$name][$version['uid']] = $this->providersByUid[$version['uid']]->getAliasOf();
- $this->providers[$name][$version['uid'].'-alias'] = $this->providersByUid[$version['uid']];
- } else {
- $this->providers[$name][$version['uid']] = $this->providersByUid[$version['uid']];
- }
- if (isset($this->providersByUid[$version['uid'].'-root'])) {
- $this->providers[$name][$version['uid'].'-root'] = $this->providersByUid[$version['uid'].'-root'];
- }
- }
- } else {
- if (!$pool->isPackageAcceptable(strtolower($version['name']), VersionParser::parseStability($version['version']))) {
- continue;
- }
- $package = $this->createPackage($version, 'Composer\Package\Package');
- $package->setRepository($this);
- if ($package instanceof AliasPackage) {
- $aliased = $package->getAliasOf();
- $aliased->setRepository($this);
- $this->providers[$name][$version['uid']] = $aliased;
- $this->providers[$name][$version['uid'].'-alias'] = $package;
- $this->providersByUid[$version['uid']] = $package;
- } else {
- $this->providers[$name][$version['uid']] = $package;
- $this->providersByUid[$version['uid']] = $package;
- }
- unset($rootAliasData);
- if (isset($this->rootAliases[$package->getName()][$package->getVersion()])) {
- $rootAliasData = $this->rootAliases[$package->getName()][$package->getVersion()];
- } elseif ($package instanceof AliasPackage && isset($this->rootAliases[$package->getName()][$package->getAliasOf()->getVersion()])) {
- $rootAliasData = $this->rootAliases[$package->getName()][$package->getAliasOf()->getVersion()];
- }
- if (isset($rootAliasData)) {
- $alias = $this->createAliasPackage($package, $rootAliasData['alias_normalized'], $rootAliasData['alias']);
- $alias->setRepository($this);
- $this->providers[$name][$version['uid'].'-root'] = $alias;
- $this->providersByUid[$version['uid'].'-root'] = $alias;
- }
- }
- }
- }
- return $this->providers[$name];
- }
- protected function initialize()
- {
- parent::initialize();
- $repoData = $this->loadDataFromServer();
- foreach ($repoData as $package) {
- $this->addPackage($this->createPackage($package, 'Composer\Package\CompletePackage'));
- }
- }
- public function addPackage(PackageInterface $package)
- {
- parent::addPackage($package);
- $this->configurePackageTransportOptions($package);
- }
- protected function loadRootServerFile()
- {
- if (null !== $this->rootData) {
- return $this->rootData;
- }
- if (!extension_loaded('openssl') && 'https' === substr($this->url, 0, 5)) {
- throw new \RuntimeException('You must enable the openssl extension in your php.ini to load information from '.$this->url);
- }
- $jsonUrlParts = parse_url($this->url);
- if (isset($jsonUrlParts['path']) && false !== strpos($jsonUrlParts['path'], '.json')) {
- $jsonUrl = $this->url;
- } else {
- $jsonUrl = $this->url . '/packages.json';
- }
- $data = $this->fetchFile($jsonUrl, 'packages.json');
- if (!empty($data['notify-batch'])) {
- $this->notifyUrl = $this->canonicalizeUrl($data['notify-batch']);
- } elseif (!empty($data['notify_batch'])) {
- $this->notifyUrl = $this->canonicalizeUrl($data['notify_batch']);
- } elseif (!empty($data['notify'])) {
- $this->notifyUrl = $this->canonicalizeUrl($data['notify']);
- }
- if (!empty($data['search'])) {
- $this->searchUrl = $this->canonicalizeUrl($data['search']);
- }
- if (!empty($data['mirrors'])) {
- foreach ($data['mirrors'] as $mirror) {
- if (!empty($mirror['git-url'])) {
- $this->sourceMirrors['git'][] = array('url' => $mirror['git-url'], 'preferred' => !empty($mirror['preferred']));
- }
- if (!empty($mirror['hg-url'])) {
- $this->sourceMirrors['hg'][] = array('url' => $mirror['hg-url'], 'preferred' => !empty($mirror['preferred']));
- }
- if (!empty($mirror['dist-url'])) {
- $this->distMirrors[] = array('url' => $mirror['dist-url'], 'preferred' => !empty($mirror['preferred']));
- }
- }
- }
- if (!empty($data['warning'])) {
- $this->io->writeError('<warning>Warning from '.$this->url.': '.$data['warning'].'</warning>');
- }
- if (!empty($data['providers-lazy-url'])) {
- $this->lazyProvidersUrl = $this->canonicalizeUrl($data['providers-lazy-url']);
- $this->hasProviders = true;
- }
- if ($this->allowSslDowngrade) {
- $this->url = str_replace('https://', 'http://', $this->url);
- }
- if (!empty($data['providers-url'])) {
- $this->providersUrl = $this->canonicalizeUrl($data['providers-url']);
- $this->hasProviders = true;
- }
- if (!empty($data['providers']) || !empty($data['providers-includes'])) {
- $this->hasProviders = true;
- }
- return $this->rootData = $data;
- }
- protected function canonicalizeUrl($url)
- {
- if ('/' === $url[0]) {
- return preg_replace('{(https?://[^/]+).*}i', '$1' . $url, $this->url);
- }
- return $url;
- }
- protected function loadDataFromServer()
- {
- $data = $this->loadRootServerFile();
- return $this->loadIncludes($data);
- }
- protected function loadProviderListings($data)
- {
- if (isset($data['providers'])) {
- if (!is_array($this->providerListing)) {
- $this->providerListing = array();
- }
- $this->providerListing = array_merge($this->providerListing, $data['providers']);
- }
- if ($this->providersUrl && isset($data['provider-includes'])) {
- $includes = $data['provider-includes'];
- foreach ($includes as $include => $metadata) {
- $url = $this->baseUrl . '/' . str_replace('%hash%', $metadata['sha256'], $include);
- $cacheKey = str_replace(array('%hash%','$'), '', $include);
- if ($this->cache->sha256($cacheKey) === $metadata['sha256']) {
- $includedData = json_decode($this->cache->read($cacheKey), true);
- } else {
- $includedData = $this->fetchFile($url, $cacheKey, $metadata['sha256']);
- }
- $this->loadProviderListings($includedData);
- }
- } elseif (isset($data['providers-includes'])) {
- $includes = $data['providers-includes'];
- foreach ($includes as $include => $metadata) {
- if ($this->cache->sha256($include) === $metadata['sha256']) {
- $includedData = json_decode($this->cache->read($include), true);
- } else {
- $includedData = $this->fetchFile($include, null, $metadata['sha256']);
- }
- $this->loadProviderListings($includedData);
- }
- }
- }
- protected function loadIncludes($data)
- {
- $packages = array();
- if (!isset($data['packages']) && !isset($data['includes'])) {
- foreach ($data as $pkg) {
- foreach ($pkg['versions'] as $metadata) {
- $packages[] = $metadata;
- }
- }
- return $packages;
- }
- if (isset($data['packages'])) {
- foreach ($data['packages'] as $package => $versions) {
- foreach ($versions as $version => $metadata) {
- $packages[] = $metadata;
- }
- }
- }
- if (isset($data['includes'])) {
- foreach ($data['includes'] as $include => $metadata) {
- if ($this->cache->sha1($include) === $metadata['sha1']) {
- $includedData = json_decode($this->cache->read($include), true);
- } else {
- $includedData = $this->fetchFile($include);
- }
- $packages = array_merge($packages, $this->loadIncludes($includedData));
- }
- }
- return $packages;
- }
- protected function createPackage(array $data, $class)
- {
- try {
- if (!isset($data['notification-url'])) {
- $data['notification-url'] = $this->notifyUrl;
- }
- $package = $this->loader->load($data, 'Composer\Package\CompletePackage');
- if (isset($this->sourceMirrors[$package->getSourceType()])) {
- $package->setSourceMirrors($this->sourceMirrors[$package->getSourceType()]);
- }
- $package->setDistMirrors($this->distMirrors);
- $this->configurePackageTransportOptions($package);
- return $package;
- } catch (\Exception $e) {
- throw new \RuntimeException('Could not load package '.(isset($data['name']) ? $data['name'] : json_encode($data)).' in '.$this->url.': ['.get_class($e).'] '.$e->getMessage(), 0, $e);
- }
- }
- protected function fetchFile($filename, $cacheKey = null, $sha256 = null)
- {
- if (null === $cacheKey) {
- $cacheKey = $filename;
- $filename = $this->baseUrl.'/'.$filename;
- }
- $retries = 3;
- while ($retries--) {
- try {
- $preFileDownloadEvent = new PreFileDownloadEvent(PluginEvents::PRE_FILE_DOWNLOAD, $this->rfs, $filename);
- if ($this->eventDispatcher) {
- $this->eventDispatcher->dispatch($preFileDownloadEvent->getName(), $preFileDownloadEvent);
- }
- $hostname = parse_url($filename, PHP_URL_HOST) ?: $filename;
- $json = $preFileDownloadEvent->getRemoteFilesystem()->getContents($hostname, $filename, false);
- if ($sha256 && $sha256 !== hash('sha256', $json)) {
- if ($retries) {
- usleep(100000);
- continue;
- }
- throw new RepositorySecurityException('The contents of '.$filename.' do not match its signature. This should indicate a man-in-the-middle attack. Try running composer again and report this if you think it is a mistake.');
- }
- $data = JsonFile::parseJson($json, $filename);
- if ($cacheKey) {
- $this->cache->write($cacheKey, $json);
- }
- break;
- } catch (\Exception $e) {
- if ($retries) {
- usleep(100000);
- continue;
- }
- if ($e instanceof RepositorySecurityException) {
- throw $e;
- }
- if ($cacheKey && ($contents = $this->cache->read($cacheKey))) {
- if (!$this->degradedMode) {
- $this->io->writeError('<warning>'.$e->getMessage().'</warning>');
- $this->io->writeError('<warning>'.$this->url.' could not be fully loaded, package information was loaded from the local cache and may be out of date</warning>');
- }
- $this->degradedMode = true;
- $data = JsonFile::parseJson($contents, $this->cache->getRoot().$cacheKey);
- break;
- }
- throw $e;
- }
- }
- return $data;
- }
- }
- <?php
- namespace Composer\Repository;
- use Composer\Package\PackageInterface;
- class CompositeRepository implements RepositoryInterface
- {
- private $repositories;
- public function __construct(array $repositories)
- {
- $this->repositories = array();
- foreach ($repositories as $repo) {
- $this->addRepository($repo);
- }
- }
- public function getRepositories()
- {
- return $this->repositories;
- }
- public function hasPackage(PackageInterface $package)
- {
- foreach ($this->repositories as $repository) {
- if ($repository->hasPackage($package)) {
- return true;
- }
- }
- return false;
- }
- public function findPackage($name, $version)
- {
- foreach ($this->repositories as $repository) {
- $package = $repository->findPackage($name, $version);
- if (null !== $package) {
- return $package;
- }
- }
- return null;
- }
- public function findPackages($name, $version = null)
- {
- $packages = array();
- foreach ($this->repositories as $repository) {
- $packages[] = $repository->findPackages($name, $version);
- }
- return $packages ? call_user_func_array('array_merge', $packages) : array();
- }
- public function search($query, $mode = 0)
- {
- $matches = array();
- foreach ($this->repositories as $repository) {
- $matches[] = $repository->search($query, $mode);
- }
- return $matches ? call_user_func_array('array_merge', $matches) : array();
- }
- public function filterPackages($callback, $class = 'Composer\Package\Package')
- {
- foreach ($this->repositories as $repository) {
- if (false === $repository->filterPackages($callback, $class)) {
- return false;
- }
- }
- return true;
- }
- public function getPackages()
- {
- $packages = array();
- foreach ($this->repositories as $repository) {
- $packages[] = $repository->getPackages();
- }
- return $packages ? call_user_func_array('array_merge', $packages) : array();
- }
- public function removePackage(PackageInterface $package)
- {
- foreach ($this->repositories as $repository) {
- $repository->removePackage($package);
- }
- }
- public function count()
- {
- $total = 0;
- foreach ($this->repositories as $repository) {
- $total += $repository->count();
- }
- return $total;
- }
- public function addRepository(RepositoryInterface $repository)
- {
- if ($repository instanceof self) {
- foreach ($repository->getRepositories() as $repo) {
- $this->addRepository($repo);
- }
- } else {
- $this->repositories[] = $repository;
- }
- }
- }
- <?php
- namespace Composer\Repository;
- use Composer\Json\JsonFile;
- use Composer\Package\Loader\ArrayLoader;
- use Composer\Package\Dumper\ArrayDumper;
- class FilesystemRepository extends WritableArrayRepository
- {
- private $file;
- public function __construct(JsonFile $repositoryFile)
- {
- $this->file = $repositoryFile;
- }
- protected function initialize()
- {
- parent::initialize();
- if (!$this->file->exists()) {
- return;
- }
- try {
- $packages = $this->file->read();
- if (!is_array($packages)) {
- throw new \UnexpectedValueException('Could not parse package list from the repository');
- }
- } catch (\Exception $e) {
- throw new InvalidRepositoryException('Invalid repository data in '.$this->file->getPath().', packages could not be loaded: ['.get_class($e).'] '.$e->getMessage());
- }
- $loader = new ArrayLoader(null, true);
- foreach ($packages as $packageData) {
- $package = $loader->load($packageData);
- $this->addPackage($package);
- }
- }
- public function reload()
- {
- $this->packages = null;
- $this->initialize();
- }
- public function write()
- {
- $data = array();
- $dumper = new ArrayDumper();
- foreach ($this->getCanonicalPackages() as $package) {
- $data[] = $dumper->dump($package);
- }
- $this->file->write($data);
- }
- }
- <?php
- namespace Composer\Repository;
- class InstalledArrayRepository extends WritableArrayRepository implements InstalledRepositoryInterface
- {
- }
- <?php
- namespace Composer\Repository;
- class InstalledFilesystemRepository extends FilesystemRepository implements InstalledRepositoryInterface
- {
- }
- <?php
- namespace Composer\Repository;
- interface InstalledRepositoryInterface extends WritableRepositoryInterface
- {
- }
- <?php
- namespace Composer\Repository;
- class InvalidRepositoryException extends \Exception
- {
- }
- <?php
- namespace Composer\Repository;
- use Composer\Package\Loader\ArrayLoader;
- use Composer\Package\Loader\ValidatingArrayLoader;
- class PackageRepository extends ArrayRepository
- {
- private $config;
- public function __construct(array $config)
- {
- $this->config = $config['package'];
- if (!is_numeric(key($this->config))) {
- $this->config = array($this->config);
- }
- }
- protected function initialize()
- {
- parent::initialize();
- $loader = new ValidatingArrayLoader(new ArrayLoader, false);
- foreach ($this->config as $package) {
- try {
- $package = $loader->load($package);
- } catch (\Exception $e) {
- throw new InvalidRepositoryException('A repository of type "package" contains an invalid package definition: '.$e->getMessage()."\n\nInvalid package definition:\n".json_encode($package));
- }
- $this->addPackage($package);
- }
- }
- }
- <?php
- namespace Composer\Repository\Pear;
- use Composer\Util\RemoteFilesystem;
- abstract class BaseChannelReader
- {
- const CHANNEL_NS = 'http://pear.php.net/channel-1.0';
- const ALL_CATEGORIES_NS = 'http://pear.php.net/dtd/rest.allcategories';
- const CATEGORY_PACKAGES_INFO_NS = 'http://pear.php.net/dtd/rest.categorypackageinfo';
- const ALL_PACKAGES_NS = 'http://pear.php.net/dtd/rest.allpackages';
- const ALL_RELEASES_NS = 'http://pear.php.net/dtd/rest.allreleases';
- const PACKAGE_INFO_NS = 'http://pear.php.net/dtd/rest.package';
- private $rfs;
- protected function __construct(RemoteFilesystem $rfs)
- {
- $this->rfs = $rfs;
- }
- protected function requestContent($origin, $path)
- {
- $url = rtrim($origin, '/') . '/' . ltrim($path, '/');
- $content = $this->rfs->getContents($origin, $url, false);
- if (!$content) {
- throw new \UnexpectedValueException('The PEAR channel at ' . $url . ' did not respond.');
- }
- return $content;
- }
- protected function requestXml($origin, $path)
- {
- $xml = simplexml_load_string($this->requestContent($origin, $path), "SimpleXMLElement", LIBXML_NOERROR);
- if (false == $xml) {
- $url = rtrim($origin, '/') . '/' . ltrim($path, '/');
- throw new \UnexpectedValueException(sprintf('The PEAR channel at ' . $origin . ' is broken. (Invalid XML at file `%s`)', $path));
- }
- return $xml;
- }
- }
- <?php
- namespace Composer\Repository\Pear;
- class ChannelInfo
- {
- private $name;
- private $alias;
- private $packages;
- public function __construct($name, $alias, array $packages)
- {
- $this->name = $name;
- $this->alias = $alias;
- $this->packages = $packages;
- }
- public function getName()
- {
- return $this->name;
- }
- public function getAlias()
- {
- return $this->alias;
- }
- public function getPackages()
- {
- return $this->packages;
- }
- }
- <?php
- namespace Composer\Repository\Pear;
- use Composer\Util\RemoteFilesystem;
- class ChannelReader extends BaseChannelReader
- {
- private $readerMap;
- public function __construct(RemoteFilesystem $rfs)
- {
- parent::__construct($rfs);
- $rest10reader = new ChannelRest10Reader($rfs);
- $rest11reader = new ChannelRest11Reader($rfs);
- $this->readerMap = array(
- 'REST1.3' => $rest11reader,
- 'REST1.2' => $rest11reader,
- 'REST1.1' => $rest11reader,
- 'REST1.0' => $rest10reader,
- );
- }
- public function read($url)
- {
- $xml = $this->requestXml($url, "/channel.xml");
- $channelName = (string) $xml->name;
- $channelSummary = (string) $xml->summary;
- $channelAlias = (string) $xml->suggestedalias;
- $supportedVersions = array_keys($this->readerMap);
- $selectedRestVersion = $this->selectRestVersion($xml, $supportedVersions);
- if (!$selectedRestVersion) {
- throw new \UnexpectedValueException(sprintf('PEAR repository %s does not supports any of %s protocols.', $url, implode(', ', $supportedVersions)));
- }
- $reader = $this->readerMap[$selectedRestVersion['version']];
- $packageDefinitions = $reader->read($selectedRestVersion['baseUrl']);
- return new ChannelInfo($channelName, $channelAlias, $packageDefinitions);
- }
- private function selectRestVersion($channelXml, $supportedVersions)
- {
- $channelXml->registerXPathNamespace('ns', self::CHANNEL_NS);
- foreach ($supportedVersions as $version) {
- $xpathTest = "ns:servers/ns:primary/ns:rest/ns:baseurl[@type='{$version}']";
- $testResult = $channelXml->xpath($xpathTest);
- if (count($testResult) > 0) {
- return array('version' => $version, 'baseUrl' => (string) $testResult[0]);
- }
- }
- return null;
- }
- }
- <?php
- namespace Composer\Repository\Pear;
- use Composer\Downloader\TransportException;
- class ChannelRest10Reader extends BaseChannelReader
- {
- private $dependencyReader;
- public function __construct($rfs)
- {
- parent::__construct($rfs);
- $this->dependencyReader = new PackageDependencyParser();
- }
- public function read($baseUrl)
- {
- return $this->readPackages($baseUrl);
- }
- private function readPackages($baseUrl)
- {
- $result = array();
- $xmlPath = '/p/packages.xml';
- $xml = $this->requestXml($baseUrl, $xmlPath);
- $xml->registerXPathNamespace('ns', self::ALL_PACKAGES_NS);
- foreach ($xml->xpath('ns:p') as $node) {
- $packageName = (string) $node;
- $packageInfo = $this->readPackage($baseUrl, $packageName);
- $result[] = $packageInfo;
- }
- return $result;
- }
- private function readPackage($baseUrl, $packageName)
- {
- $xmlPath = '/p/' . strtolower($packageName) . '/info.xml';
- $xml = $this->requestXml($baseUrl, $xmlPath);
- $xml->registerXPathNamespace('ns', self::PACKAGE_INFO_NS);
- $channelName = (string) $xml->c;
- $packageName = (string) $xml->n;
- $license = (string) $xml->l;
- $shortDescription = (string) $xml->s;
- $description = (string) $xml->d;
- return new PackageInfo(
- $channelName,
- $packageName,
- $license,
- $shortDescription,
- $description,
- $this->readPackageReleases($baseUrl, $packageName)
- );
- }
- private function readPackageReleases($baseUrl, $packageName)
- {
- $result = array();
- try {
- $xmlPath = '/r/' . strtolower($packageName) . '/allreleases.xml';
- $xml = $this->requestXml($baseUrl, $xmlPath);
- $xml->registerXPathNamespace('ns', self::ALL_RELEASES_NS);
- foreach ($xml->xpath('ns:r') as $node) {
- $releaseVersion = (string) $node->v;
- $releaseStability = (string) $node->s;
- try {
- $result[$releaseVersion] = new ReleaseInfo(
- $releaseStability,
- $this->readPackageReleaseDependencies($baseUrl, $packageName, $releaseVersion)
- );
- } catch (TransportException $exception) {
- if ($exception->getCode() != 404) {
- throw $exception;
- }
- }
- }
- } catch (TransportException $exception) {
- if ($exception->getCode() != 404) {
- throw $exception;
- }
- }
- return $result;
- }
- private function readPackageReleaseDependencies($baseUrl, $packageName, $version)
- {
- $dependencyReader = new PackageDependencyParser();
- $depthPath = '/r/' . strtolower($packageName) . '/deps.' . $version . '.txt';
- $content = $this->requestContent($baseUrl, $depthPath);
- $dependencyArray = unserialize($content);
- $result = $dependencyReader->buildDependencyInfo($dependencyArray);
- return $result;
- }
- }
- <?php
- namespace Composer\Repository\Pear;
- class ChannelRest11Reader extends BaseChannelReader
- {
- private $dependencyReader;
- public function __construct($rfs)
- {
- parent::__construct($rfs);
- $this->dependencyReader = new PackageDependencyParser();
- }
- public function read($baseUrl)
- {
- return $this->readChannelPackages($baseUrl);
- }
- private function readChannelPackages($baseUrl)
- {
- $result = array();
- $xml = $this->requestXml($baseUrl, "/c/categories.xml");
- $xml->registerXPathNamespace('ns', self::ALL_CATEGORIES_NS);
- foreach ($xml->xpath('ns:c') as $node) {
- $categoryName = (string) $node;
- $categoryPackages = $this->readCategoryPackages($baseUrl, $categoryName);
- $result = array_merge($result, $categoryPackages);
- }
- return $result;
- }
- private function readCategoryPackages($baseUrl, $categoryName)
- {
- $result = array();
- $categoryPath = '/c/'.urlencode($categoryName).'/packagesinfo.xml';
- $xml = $this->requestXml($baseUrl, $categoryPath);
- $xml->registerXPathNamespace('ns', self::CATEGORY_PACKAGES_INFO_NS);
- foreach ($xml->xpath('ns:pi') as $node) {
- $packageInfo = $this->parsePackage($node);
- $result[] = $packageInfo;
- }
- return $result;
- }
- private function parsePackage($packageInfo)
- {
- $packageInfo->registerXPathNamespace('ns', self::CATEGORY_PACKAGES_INFO_NS);
- $channelName = (string) $packageInfo->p->c;
- $packageName = (string) $packageInfo->p->n;
- $license = (string) $packageInfo->p->l;
- $shortDescription = (string) $packageInfo->p->s;
- $description = (string) $packageInfo->p->d;
- $dependencies = array();
- foreach ($packageInfo->xpath('ns:deps') as $node) {
- $dependencyVersion = (string) $node->v;
- $dependencyArray = unserialize((string) $node->d);
- $dependencyInfo = $this->dependencyReader->buildDependencyInfo($dependencyArray);
- $dependencies[$dependencyVersion] = $dependencyInfo;
- }
- $releases = array();
- $releasesInfo = $packageInfo->xpath('ns:a/ns:r');
- if ($releasesInfo) {
- foreach ($releasesInfo as $node) {
- $releaseVersion = (string) $node->v;
- $releaseStability = (string) $node->s;
- $releases[$releaseVersion] = new ReleaseInfo(
- $releaseStability,
- isset($dependencies[$releaseVersion]) ? $dependencies[$releaseVersion] : new DependencyInfo(array(), array())
- );
- }
- }
- return new PackageInfo(
- $channelName,
- $packageName,
- $license,
- $shortDescription,
- $description,
- $releases
- );
- }
- }
- <?php
- namespace Composer\Repository\Pear;
- class DependencyConstraint
- {
- private $type;
- private $constraint;
- private $channelName;
- private $packageName;
- public function __construct($type, $constraint, $channelName, $packageName)
- {
- $this->type = $type;
- $this->constraint = $constraint;
- $this->channelName = $channelName;
- $this->packageName = $packageName;
- }
- public function getChannelName()
- {
- return $this->channelName;
- }
- public function getConstraint()
- {
- return $this->constraint;
- }
- public function getPackageName()
- {
- return $this->packageName;
- }
- public function getType()
- {
- return $this->type;
- }
- }
- <?php
- namespace Composer\Repository\Pear;
- class DependencyInfo
- {
- private $requires;
- private $optionals;
- public function __construct($requires, $optionals)
- {
- $this->requires = $requires;
- $this->optionals = $optionals;
- }
- public function getRequires()
- {
- return $this->requires;
- }
- public function getOptionals()
- {
- return $this->optionals;
- }
- }
- <?php
- namespace Composer\Repository\Pear;
- class PackageDependencyParser
- {
- public function buildDependencyInfo($depArray)
- {
- if (!is_array($depArray)) {
- return new DependencyInfo(array(), array());
- }
- if (!$this->isHash($depArray)) {
- return new DependencyInfo($this->buildDependency10Info($depArray), array());
- }
- return $this->buildDependency20Info($depArray);
- }
- private function buildDependency10Info($depArray)
- {
- static $dep10toOperatorMap = array('has' => '==', 'eq' => '==', 'ge' => '>=', 'gt' => '>', 'le' => '<=', 'lt' => '<', 'not' => '!=');
- $result = array();
- foreach ($depArray as $depItem) {
- if (empty($depItem['rel']) || !array_key_exists($depItem['rel'], $dep10toOperatorMap)) {
- continue;
- }
- $depType = !empty($depItem['optional']) && 'yes' == $depItem['optional']
- ? 'optional'
- : 'required';
- $depType = 'not' == $depItem['rel']
- ? 'conflicts'
- : $depType;
- $depVersion = !empty($depItem['version']) ? $this->parseVersion($depItem['version']) : '*';
- $depVersionConstraint = ('has' == $depItem['rel'] || 'not' == $depItem['rel']) && '*' == $depVersion
- ? '*'
- : $dep10toOperatorMap[$depItem['rel']] . $depVersion;
- switch ($depItem['type']) {
- case 'php':
- $depChannelName = 'php';
- $depPackageName = '';
- break;
- case 'pkg':
- $depChannelName = !empty($depItem['channel']) ? $depItem['channel'] : 'pear.php.net';
- $depPackageName = $depItem['name'];
- break;
- case 'ext':
- $depChannelName = 'ext';
- $depPackageName = $depItem['name'];
- break;
- case 'os':
- case 'sapi':
- $depChannelName = '';
- $depPackageName = '';
- break;
- default:
- $depChannelName = '';
- $depPackageName = '';
- break;
- }
- if ('' != $depChannelName) {
- $result[] = new DependencyConstraint(
- $depType,
- $depVersionConstraint,
- $depChannelName,
- $depPackageName
- );
- }
- }
- return $result;
- }
- private function buildDependency20Info($depArray)
- {
- $result = array();
- $optionals = array();
- $defaultOptionals = array();
- foreach ($depArray as $depType => $depTypeGroup) {
- if (!is_array($depTypeGroup)) {
- continue;
- }
- if ('required' == $depType || 'optional' == $depType) {
- foreach ($depTypeGroup as $depItemType => $depItem) {
- switch ($depItemType) {
- case 'php':
- $result[] = new DependencyConstraint(
- $depType,
- $this->parse20VersionConstraint($depItem),
- 'php',
- ''
- );
- break;
- case 'package':
- $deps = $this->buildDepPackageConstraints($depItem, $depType);
- $result = array_merge($result, $deps);
- break;
- case 'extension':
- $deps = $this->buildDepExtensionConstraints($depItem, $depType);
- $result = array_merge($result, $deps);
- break;
- case 'subpackage':
- $deps = $this->buildDepPackageConstraints($depItem, 'replaces');
- $defaultOptionals += $deps;
- break;
- case 'os':
- case 'pearinstaller':
- break;
- default:
- break;
- }
- }
- } elseif ('group' == $depType) {
- if ($this->isHash($depTypeGroup)) {
- $depTypeGroup = array($depTypeGroup);
- }
- foreach ($depTypeGroup as $depItem) {
- $groupName = $depItem['attribs']['name'];
- if (!isset($optionals[$groupName])) {
- $optionals[$groupName] = array();
- }
- if (isset($depItem['subpackage'])) {
- $optionals[$groupName] += $this->buildDepPackageConstraints($depItem['subpackage'], 'replaces');
- } else {
- $result += $this->buildDepPackageConstraints($depItem['package'], 'optional');
- }
- }
- }
- }
- if (count($defaultOptionals) > 0) {
- $optionals['*'] = $defaultOptionals;
- }
- return new DependencyInfo($result, $optionals);
- }
- private function buildDepExtensionConstraints($depItem, $depType)
- {
- if ($this->isHash($depItem)) {
- $depItem = array($depItem);
- }
- $result = array();
- foreach ($depItem as $subDepItem) {
- $depChannelName = 'ext';
- $depPackageName = $subDepItem['name'];
- $depVersionConstraint = $this->parse20VersionConstraint($subDepItem);
- $result[] = new DependencyConstraint(
- $depType,
- $depVersionConstraint,
- $depChannelName,
- $depPackageName
- );
- }
- return $result;
- }
- private function buildDepPackageConstraints($depItem, $depType)
- {
- if ($this->isHash($depItem)) {
- $depItem = array($depItem);
- }
- $result = array();
- foreach ($depItem as $subDepItem) {
- $depChannelName = $subDepItem['channel'];
- $depPackageName = $subDepItem['name'];
- $depVersionConstraint = $this->parse20VersionConstraint($subDepItem);
- if (isset($subDepItem['conflicts'])) {
- $depType = 'conflicts';
- }
- $result[] = new DependencyConstraint(
- $depType,
- $depVersionConstraint,
- $depChannelName,
- $depPackageName
- );
- }
- return $result;
- }
- private function parse20VersionConstraint(array $data)
- {
- static $dep20toOperatorMap = array('has' => '==', 'min' => '>=', 'max' => '<=', 'exclude' => '!=');
- $versions = array();
- $values = array_intersect_key($data, $dep20toOperatorMap);
- if (0 == count($values)) {
- return '*';
- }
- if (isset($values['min']) && isset($values['exclude']) && $data['min'] == $data['exclude']) {
- $versions[] = '>' . $this->parseVersion($values['min']);
- } elseif (isset($values['max']) && isset($values['exclude']) && $data['max'] == $data['exclude']) {
- $versions[] = '<' . $this->parseVersion($values['max']);
- } else {
- foreach ($values as $op => $version) {
- if ('exclude' == $op && is_array($version)) {
- foreach ($version as $versionPart) {
- $versions[] = $dep20toOperatorMap[$op] . $this->parseVersion($versionPart);
- }
- } else {
- $versions[] = $dep20toOperatorMap[$op] . $this->parseVersion($version);
- }
- }
- }
- return implode(',', $versions);
- }
- private function parseVersion($version)
- {
- if (preg_match('{^v?(\d{1,3})(\.\d+)?(\.\d+)?(\.\d+)?}i', $version, $matches)) {
- $version = $matches[1]
- .(!empty($matches[2]) ? $matches[2] : '.0')
- .(!empty($matches[3]) ? $matches[3] : '.0')
- .(!empty($matches[4]) ? $matches[4] : '.0');
- return $version;
- }
- return null;
- }
- private function isHash(array $array)
- {
- return !array_key_exists(1, $array) && !array_key_exists(0, $array);
- }
- }
- <?php
- namespace Composer\Repository\Pear;
- class PackageInfo
- {
- private $channelName;
- private $packageName;
- private $license;
- private $shortDescription;
- private $description;
- private $releases;
- public function __construct($channelName, $packageName, $license, $shortDescription, $description, $releases)
- {
- $this->channelName = $channelName;
- $this->packageName = $packageName;
- $this->license = $license;
- $this->shortDescription = $shortDescription;
- $this->description = $description;
- $this->releases = $releases;
- }
- public function getChannelName()
- {
- return $this->channelName;
- }
- public function getPackageName()
- {
- return $this->packageName;
- }
- public function getDescription()
- {
- return $this->description;
- }
- public function getShortDescription()
- {
- return $this->shortDescription;
- }
- public function getLicense()
- {
- return $this->license;
- }
- public function getReleases()
- {
- return $this->releases;
- }
- }
- <?php
- namespace Composer\Repository\Pear;
- class ReleaseInfo
- {
- private $stability;
- private $dependencyInfo;
- public function __construct($stability, $dependencyInfo)
- {
- $this->stability = $stability;
- $this->dependencyInfo = $dependencyInfo;
- }
- public function getDependencyInfo()
- {
- return $this->dependencyInfo;
- }
- public function getStability()
- {
- return $this->stability;
- }
- }
- <?php
- namespace Composer\Repository;
- use Composer\IO\IOInterface;
- use Composer\Package\Version\VersionParser;
- use Composer\Repository\Pear\ChannelReader;
- use Composer\Package\CompletePackage;
- use Composer\Repository\Pear\ChannelInfo;
- use Composer\EventDispatcher\EventDispatcher;
- use Composer\Package\Link;
- use Composer\Package\LinkConstraint\VersionConstraint;
- use Composer\Util\RemoteFilesystem;
- use Composer\Config;
- class PearRepository extends ArrayRepository
- {
- private $url;
- private $io;
- private $rfs;
- private $versionParser;
- private $vendorAlias;
- public function __construct(array $repoConfig, IOInterface $io, Config $config, EventDispatcher $dispatcher = null, RemoteFilesystem $rfs = null)
- {
- if (!preg_match('{^https?://}', $repoConfig['url'])) {
- $repoConfig['url'] = 'http://'.$repoConfig['url'];
- }
- $urlBits = parse_url($repoConfig['url']);
- if (empty($urlBits['scheme']) || empty($urlBits['host'])) {
- throw new \UnexpectedValueException('Invalid url given for PEAR repository: '.$repoConfig['url']);
- }
- $this->url = rtrim($repoConfig['url'], '/');
- $this->io = $io;
- $this->rfs = $rfs ?: new RemoteFilesystem($this->io, $config);
- $this->vendorAlias = isset($repoConfig['vendor-alias']) ? $repoConfig['vendor-alias'] : null;
- $this->versionParser = new VersionParser();
- }
- protected function initialize()
- {
- parent::initialize();
- $this->io->writeError('Initializing PEAR repository '.$this->url);
- $reader = new ChannelReader($this->rfs);
- try {
- $channelInfo = $reader->read($this->url);
- } catch (\Exception $e) {
- $this->io->writeError('<warning>PEAR repository from '.$this->url.' could not be loaded. '.$e->getMessage().'</warning>');
- return;
- }
- $packages = $this->buildComposerPackages($channelInfo, $this->versionParser);
- foreach ($packages as $package) {
- $this->addPackage($package);
- }
- }
- private function buildComposerPackages(ChannelInfo $channelInfo, VersionParser $versionParser)
- {
- $result = array();
- foreach ($channelInfo->getPackages() as $packageDefinition) {
- foreach ($packageDefinition->getReleases() as $version => $releaseInfo) {
- try {
- $normalizedVersion = $versionParser->normalize($version);
- } catch (\UnexpectedValueException $e) {
- if ($this->io->isVerbose()) {
- $this->io->writeError('Could not load '.$packageDefinition->getPackageName().' '.$version.': '.$e->getMessage());
- }
- continue;
- }
- $composerPackageName = $this->buildComposerPackageName($packageDefinition->getChannelName(), $packageDefinition->getPackageName());
-
- $urlBits = parse_url($this->url);
- $scheme = (isset($urlBits['scheme']) && 'https' === $urlBits['scheme'] && extension_loaded('openssl')) ? 'https' : 'http';
- $distUrl = "{$scheme}://{$packageDefinition->getChannelName()}/get/{$packageDefinition->getPackageName()}-{$version}.tgz";
- $requires = array();
- $suggests = array();
- $conflicts = array();
- $replaces = array();
-
- if ($channelInfo->getName() == $packageDefinition->getChannelName()) {
- $composerPackageAlias = $this->buildComposerPackageName($channelInfo->getAlias(), $packageDefinition->getPackageName());
- $aliasConstraint = new VersionConstraint('==', $normalizedVersion);
- $replaces[] = new Link($composerPackageName, $composerPackageAlias, $aliasConstraint, 'replaces', (string) $aliasConstraint);
- }
- if (!empty($this->vendorAlias)
- && ($this->vendorAlias != 'pear-'.$channelInfo->getAlias() || $channelInfo->getName() != $packageDefinition->getChannelName())
- ) {
- $composerPackageAlias = "{$this->vendorAlias}/{$packageDefinition->getPackageName()}";
- $aliasConstraint = new VersionConstraint('==', $normalizedVersion);
- $replaces[] = new Link($composerPackageName, $composerPackageAlias, $aliasConstraint, 'replaces', (string) $aliasConstraint);
- }
- foreach ($releaseInfo->getDependencyInfo()->getRequires() as $dependencyConstraint) {
- $dependencyPackageName = $this->buildComposerPackageName($dependencyConstraint->getChannelName(), $dependencyConstraint->getPackageName());
- $constraint = $versionParser->parseConstraints($dependencyConstraint->getConstraint());
- $link = new Link($composerPackageName, $dependencyPackageName, $constraint, $dependencyConstraint->getType(), $dependencyConstraint->getConstraint());
- switch ($dependencyConstraint->getType()) {
- case 'required':
- $requires[] = $link;
- break;
- case 'conflicts':
- $conflicts[] = $link;
- break;
- case 'replaces':
- $replaces[] = $link;
- break;
- }
- }
- foreach ($releaseInfo->getDependencyInfo()->getOptionals() as $group => $dependencyConstraints) {
- foreach ($dependencyConstraints as $dependencyConstraint) {
- $dependencyPackageName = $this->buildComposerPackageName($dependencyConstraint->getChannelName(), $dependencyConstraint->getPackageName());
- $suggests[$group.'-'.$dependencyPackageName] = $dependencyConstraint->getConstraint();
- }
- }
- $package = new CompletePackage($composerPackageName, $normalizedVersion, $version);
- $package->setType('pear-library');
- $package->setDescription($packageDefinition->getDescription());
- $package->setLicense(array($packageDefinition->getLicense()));
- $package->setDistType('file');
- $package->setDistUrl($distUrl);
- $package->setAutoload(array('classmap' => array('')));
- $package->setIncludePaths(array('/'));
- $package->setRequires($requires);
- $package->setConflicts($conflicts);
- $package->setSuggests($suggests);
- $package->setReplaces($replaces);
- $result[] = $package;
- }
- }
- return $result;
- }
- private function buildComposerPackageName($channelName, $packageName)
- {
- if ('php' === $channelName) {
- return "php";
- }
- if ('ext' === $channelName) {
- return "ext-{$packageName}";
- }
- return "pear-{$channelName}/{$packageName}";
- }
- }
- <?php
- namespace Composer\Repository;
- use Composer\Package\CompletePackage;
- use Composer\Package\Version\VersionParser;
- use Composer\Plugin\PluginInterface;
- class PlatformRepository extends ArrayRepository
- {
- const PLATFORM_PACKAGE_REGEX = '{^(?:php(?:-64bit)?|hhvm|(?:ext|lib)-[^/]+)$}i';
- protected function initialize()
- {
- parent::initialize();
- $versionParser = new VersionParser();
- $prettyVersion = PluginInterface::PLUGIN_API_VERSION;
- $version = $versionParser->normalize($prettyVersion);
- $composerPluginApi = new CompletePackage('composer-plugin-api', $version, $prettyVersion);
- $composerPluginApi->setDescription('The Composer Plugin API');
- parent::addPackage($composerPluginApi);
- try {
- $prettyVersion = PHP_VERSION;
- $version = $versionParser->normalize($prettyVersion);
- } catch (\UnexpectedValueException $e) {
- $prettyVersion = preg_replace('#^([^~+-]+).*$#', '$1', PHP_VERSION);
- $version = $versionParser->normalize($prettyVersion);
- }
- $php = new CompletePackage('php', $version, $prettyVersion);
- $php->setDescription('The PHP interpreter');
- parent::addPackage($php);
- if (PHP_INT_SIZE === 8) {
- $php64 = new CompletePackage('php-64bit', $version, $prettyVersion);
- $php64->setDescription('The PHP interpreter (64bit)');
- parent::addPackage($php64);
- }
- $loadedExtensions = get_loaded_extensions();
- foreach ($loadedExtensions as $name) {
- if (in_array($name, array('standard', 'Core'))) {
- continue;
- }
- $reflExt = new \ReflectionExtension($name);
- try {
- $prettyVersion = $reflExt->getVersion();
- $version = $versionParser->normalize($prettyVersion);
- } catch (\UnexpectedValueException $e) {
- $prettyVersion = '0';
- $version = $versionParser->normalize($prettyVersion);
- }
- $packageName = $this->buildPackageName($name);
- $ext = new CompletePackage($packageName, $version, $prettyVersion);
- $ext->setDescription('The '.$name.' PHP extension');
- parent::addPackage($ext);
- }
-
-
- foreach ($loadedExtensions as $name) {
- $prettyVersion = null;
- switch ($name) {
- case 'curl':
- $curlVersion = curl_version();
- $prettyVersion = $curlVersion['version'];
- break;
- case 'iconv':
- $prettyVersion = ICONV_VERSION;
- break;
- case 'intl':
- $name = 'ICU';
- if (defined('INTL_ICU_VERSION')) {
- $prettyVersion = INTL_ICU_VERSION;
- } else {
- $reflector = new \ReflectionExtension('intl');
- ob_start();
- $reflector->info();
- $output = ob_get_clean();
- preg_match('/^ICU version => (.*)$/m', $output, $matches);
- $prettyVersion = $matches[1];
- }
- break;
- case 'libxml':
- $prettyVersion = LIBXML_DOTTED_VERSION;
- break;
- case 'openssl':
- $prettyVersion = preg_replace_callback('{^(?:OpenSSL\s*)?([0-9.]+)([a-z]?).*}', function ($match) {
- return $match[1] . (empty($match[2]) ? '' : '.'.(ord($match[2]) - 96));
- }, OPENSSL_VERSION_TEXT);
- break;
- case 'pcre':
- $prettyVersion = preg_replace('{^(\S+).*}', '$1', PCRE_VERSION);
- break;
- case 'uuid':
- $prettyVersion = phpversion('uuid');
- break;
- case 'xsl':
- $prettyVersion = LIBXSLT_DOTTED_VERSION;
- break;
- default:
- continue 2;
- }
- try {
- $version = $versionParser->normalize($prettyVersion);
- } catch (\UnexpectedValueException $e) {
- continue;
- }
- $lib = new CompletePackage('lib-'.$name, $version, $prettyVersion);
- $lib->setDescription('The '.$name.' PHP library');
- parent::addPackage($lib);
- }
- if (defined('HHVM_VERSION')) {
- try {
- $prettyVersion = HHVM_VERSION;
- $version = $versionParser->normalize($prettyVersion);
- } catch (\UnexpectedValueException $e) {
- $prettyVersion = preg_replace('#^([^~+-]+).*$#', '$1', HHVM_VERSION);
- $version = $versionParser->normalize($prettyVersion);
- }
- $hhvm = new CompletePackage('hhvm', $version, $prettyVersion);
- $hhvm->setDescription('The HHVM Runtime (64bit)');
- parent::addPackage($hhvm);
- }
- }
- private function buildPackageName($name)
- {
- return 'ext-' . str_replace(' ', '-', $name);
- }
- }
- <?php
- namespace Composer\Repository;
- use Composer\Package\PackageInterface;
- interface RepositoryInterface extends \Countable
- {
- const SEARCH_FULLTEXT = 0;
- const SEARCH_NAME = 1;
- public function hasPackage(PackageInterface $package);
- public function findPackage($name, $version);
- public function findPackages($name, $version = null);
- public function getPackages();
- public function search($query, $mode = 0);
- }
- <?php
- namespace Composer\Repository;
- use Composer\IO\IOInterface;
- use Composer\Config;
- use Composer\EventDispatcher\EventDispatcher;
- class RepositoryManager
- {
- private $localRepository;
- private $repositories = array();
- private $repositoryClasses = array();
- private $io;
- private $config;
- private $eventDispatcher;
- public function __construct(IOInterface $io, Config $config, EventDispatcher $eventDispatcher = null)
- {
- $this->io = $io;
- $this->config = $config;
- $this->eventDispatcher = $eventDispatcher;
- }
- public function findPackage($name, $version)
- {
- foreach ($this->repositories as $repository) {
- if ($package = $repository->findPackage($name, $version)) {
- return $package;
- }
- }
- }
- public function findPackages($name, $version)
- {
- $packages = array();
- foreach ($this->repositories as $repository) {
- $packages = array_merge($packages, $repository->findPackages($name, $version));
- }
- return $packages;
- }
- public function addRepository(RepositoryInterface $repository)
- {
- $this->repositories[] = $repository;
- }
- public function createRepository($type, $config)
- {
- if (!isset($this->repositoryClasses[$type])) {
- throw new \InvalidArgumentException('Repository type is not registered: '.$type);
- }
- $class = $this->repositoryClasses[$type];
- return new $class($config, $this->io, $this->config, $this->eventDispatcher);
- }
- public function setRepositoryClass($type, $class)
- {
- $this->repositoryClasses[$type] = $class;
- }
- public function getRepositories()
- {
- return $this->repositories;
- }
- public function setLocalRepository(WritableRepositoryInterface $repository)
- {
- $this->localRepository = $repository;
- }
- public function getLocalRepository()
- {
- return $this->localRepository;
- }
- public function getLocalRepositories()
- {
- trigger_error('This method is deprecated, use getLocalRepository instead since the getLocalDevRepository is now gone', E_USER_DEPRECATED);
- return array($this->localRepository);
- }
- }
- <?php
- namespace Composer\Repository;
- class RepositorySecurityException extends \Exception
- {
- }
- <?php
- namespace Composer\Repository\Vcs;
- use Composer\Config;
- use Composer\Json\JsonFile;
- use Composer\IO\IOInterface;
- class GitBitbucketDriver extends VcsDriver implements VcsDriverInterface
- {
- protected $owner;
- protected $repository;
- protected $tags;
- protected $branches;
- protected $rootIdentifier;
- protected $infoCache = array();
- public function initialize()
- {
- preg_match('#^https?://bitbucket\.org/([^/]+)/(.+?)\.git$#', $this->url, $match);
- $this->owner = $match[1];
- $this->repository = $match[2];
- $this->originUrl = 'bitbucket.org';
- }
- public function getRootIdentifier()
- {
- if (null === $this->rootIdentifier) {
- $resource = $this->getScheme() . '://api.bitbucket.org/1.0/repositories/'.$this->owner.'/'.$this->repository;
- $repoData = JsonFile::parseJson($this->getContents($resource), $resource);
- $this->rootIdentifier = !empty($repoData['main_branch']) ? $repoData['main_branch'] : 'master';
- }
- return $this->rootIdentifier;
- }
- public function getUrl()
- {
- return $this->url;
- }
- public function getSource($identifier)
- {
- return array('type' => 'git', 'url' => $this->getUrl(), 'reference' => $identifier);
- }
- public function getDist($identifier)
- {
- $url = $this->getScheme() . '://bitbucket.org/'.$this->owner.'/'.$this->repository.'/get/'.$identifier.'.zip';
- return array('type' => 'zip', 'url' => $url, 'reference' => $identifier, 'shasum' => '');
- }
- public function getComposerInformation($identifier)
- {
- if (!isset($this->infoCache[$identifier])) {
- $resource = $this->getScheme() . '://bitbucket.org/'.$this->owner.'/'.$this->repository.'/raw/'.$identifier.'/composer.json';
- $composer = $this->getContents($resource);
- if (!$composer) {
- return;
- }
- $composer = JsonFile::parseJson($composer, $resource);
- if (empty($composer['time'])) {
- $resource = $this->getScheme() . '://api.bitbucket.org/1.0/repositories/'.$this->owner.'/'.$this->repository.'/changesets/'.$identifier;
- $changeset = JsonFile::parseJson($this->getContents($resource), $resource);
- $composer['time'] = $changeset['timestamp'];
- }
- $this->infoCache[$identifier] = $composer;
- }
- return $this->infoCache[$identifier];
- }
- public function getTags()
- {
- if (null === $this->tags) {
- $resource = $this->getScheme() . '://api.bitbucket.org/1.0/repositories/'.$this->owner.'/'.$this->repository.'/tags';
- $tagsData = JsonFile::parseJson($this->getContents($resource), $resource);
- $this->tags = array();
- foreach ($tagsData as $tag => $data) {
- $this->tags[$tag] = $data['raw_node'];
- }
- }
- return $this->tags;
- }
- public function getBranches()
- {
- if (null === $this->branches) {
- $resource = $this->getScheme() . '://api.bitbucket.org/1.0/repositories/'.$this->owner.'/'.$this->repository.'/branches';
- $branchData = JsonFile::parseJson($this->getContents($resource), $resource);
- $this->branches = array();
- foreach ($branchData as $branch => $data) {
- $this->branches[$branch] = $data['raw_node'];
- }
- }
- return $this->branches;
- }
- public static function supports(IOInterface $io, Config $config, $url, $deep = false)
- {
- if (!preg_match('#^https?://bitbucket\.org/([^/]+)/(.+?)\.git$#', $url)) {
- return false;
- }
- if (!extension_loaded('openssl')) {
- if ($io->isVerbose()) {
- $io->writeError('Skipping Bitbucket git driver for '.$url.' because the OpenSSL PHP extension is missing.');
- }
- return false;
- }
- return true;
- }
- }
- <?php
- namespace Composer\Repository\Vcs;
- use Composer\Json\JsonFile;
- use Composer\Util\ProcessExecutor;
- use Composer\Util\Filesystem;
- use Composer\Util\Git as GitUtil;
- use Composer\IO\IOInterface;
- use Composer\Cache;
- use Composer\Config;
- class GitDriver extends VcsDriver
- {
- protected $cache;
- protected $tags;
- protected $branches;
- protected $rootIdentifier;
- protected $repoDir;
- protected $infoCache = array();
- public function initialize()
- {
- if (Filesystem::isLocalPath($this->url)) {
- $this->repoDir = $this->url;
- $cacheUrl = realpath($this->url);
- } else {
- $this->repoDir = $this->config->get('cache-vcs-dir') . '/' . preg_replace('{[^a-z0-9.]}i', '-', $this->url) . '/';
- GitUtil::cleanEnv();
- $fs = new Filesystem();
- $fs->ensureDirectoryExists(dirname($this->repoDir));
- if (!is_writable(dirname($this->repoDir))) {
- throw new \RuntimeException('Can not clone '.$this->url.' to access package information. The "'.dirname($this->repoDir).'" directory is not writable by the current user.');
- }
- if (preg_match('{^ssh://[^@]+@[^:]+:[^0-9]+}', $this->url)) {
- throw new \InvalidArgumentException('The source URL '.$this->url.' is invalid, ssh URLs should have a port number after ":".'."\n".'Use ssh://git@example.com:22/path or just git@example.com:path if you do not want to provide a password or custom port.');
- }
- $gitUtil = new GitUtil($this->io, $this->config, $this->process, $fs);
- if (is_dir($this->repoDir) && 0 === $this->process->execute('git rev-parse --git-dir', $output, $this->repoDir) && trim($output) === '.') {
- try {
- $commandCallable = function ($url) {
- return sprintf('git remote set-url origin %s && git remote update --prune origin', ProcessExecutor::escape($url));
- };
- $gitUtil->runCommand($commandCallable, $this->url, $this->repoDir);
- } catch (\Exception $e) {
- $this->io->writeError('<error>Failed to update '.$this->url.', package information from this repository may be outdated ('.$e->getMessage().')</error>');
- }
- } else {
- $fs->removeDirectory($this->repoDir);
- $repoDir = $this->repoDir;
- $commandCallable = function ($url) use ($repoDir) {
- return sprintf('git clone --mirror %s %s', ProcessExecutor::escape($url), ProcessExecutor::escape($repoDir));
- };
- $gitUtil->runCommand($commandCallable, $this->url, $this->repoDir, true);
- }
- $cacheUrl = $this->url;
- }
- $this->getTags();
- $this->getBranches();
- $this->cache = new Cache($this->io, $this->config->get('cache-repo-dir').'/'.preg_replace('{[^a-z0-9.]}i', '-', $cacheUrl));
- }
- public function getRootIdentifier()
- {
- if (null === $this->rootIdentifier) {
- $this->rootIdentifier = 'master';
- $this->process->execute('git branch --no-color', $output, $this->repoDir);
- $branches = $this->process->splitLines($output);
- if (!in_array('* master', $branches)) {
- foreach ($branches as $branch) {
- if ($branch && preg_match('{^\* +(\S+)}', $branch, $match)) {
- $this->rootIdentifier = $match[1];
- break;
- }
- }
- }
- }
- return $this->rootIdentifier;
- }
- public function getUrl()
- {
- return $this->url;
- }
- public function getSource($identifier)
- {
- return array('type' => 'git', 'url' => $this->getUrl(), 'reference' => $identifier);
- }
- public function getDist($identifier)
- {
- return null;
- }
- public function getComposerInformation($identifier)
- {
- if (preg_match('{[a-f0-9]{40}}i', $identifier) && $res = $this->cache->read($identifier)) {
- $this->infoCache[$identifier] = JsonFile::parseJson($res);
- }
- if (!isset($this->infoCache[$identifier])) {
- $resource = sprintf('%s:composer.json', ProcessExecutor::escape($identifier));
- $this->process->execute(sprintf('git show %s', $resource), $composer, $this->repoDir);
- if (!trim($composer)) {
- return;
- }
- $composer = JsonFile::parseJson($composer, $resource);
- if (empty($composer['time'])) {
- $this->process->execute(sprintf('git log -1 --format=%%at %s', ProcessExecutor::escape($identifier)), $output, $this->repoDir);
- $date = new \DateTime('@'.trim($output), new \DateTimeZone('UTC'));
- $composer['time'] = $date->format('Y-m-d H:i:s');
- }
- if (preg_match('{[a-f0-9]{40}}i', $identifier)) {
- $this->cache->write($identifier, json_encode($composer));
- }
- $this->infoCache[$identifier] = $composer;
- }
- return $this->infoCache[$identifier];
- }
- public function getTags()
- {
- if (null === $this->tags) {
- $this->tags = array();
- $this->process->execute('git show-ref --tags', $output, $this->repoDir);
- foreach ($output = $this->process->splitLines($output) as $tag) {
- if ($tag && preg_match('{^([a-f0-9]{40}) refs/tags/(\S+)$}', $tag, $match)) {
- $this->tags[$match[2]] = $match[1];
- }
- }
- }
- return $this->tags;
- }
- public function getBranches()
- {
- if (null === $this->branches) {
- $branches = array();
- $this->process->execute('git branch --no-color --no-abbrev -v', $output, $this->repoDir);
- foreach ($this->process->splitLines($output) as $branch) {
- if ($branch && !preg_match('{^ *[^/]+/HEAD }', $branch)) {
- if (preg_match('{^(?:\* )? *(\S+) *([a-f0-9]+)(?: .*)?$}', $branch, $match)) {
- $branches[$match[1]] = $match[2];
- }
- }
- }
- $this->branches = $branches;
- }
- return $this->branches;
- }
- public static function supports(IOInterface $io, Config $config, $url, $deep = false)
- {
- if (preg_match('#(^git://|\.git$|git(?:olite)?@|//git\.|//github.com/)#i', $url)) {
- return true;
- }
- if (Filesystem::isLocalPath($url)) {
- $url = Filesystem::getPlatformPath($url);
- if (!is_dir($url)) {
- return false;
- }
- $process = new ProcessExecutor($io);
- if ($process->execute('git tag', $output, $url) === 0) {
- return true;
- }
- }
- if (!$deep) {
- return false;
- }
- $process = new ProcessExecutor($io);
- if ($process->execute('git ls-remote --heads ' . ProcessExecutor::escape($url), $output) === 0) {
- return true;
- }
- return false;
- }
- }
- <?php
- namespace Composer\Repository\Vcs;
- use Composer\Config;
- use Composer\Downloader\TransportException;
- use Composer\Json\JsonFile;
- use Composer\Cache;
- use Composer\IO\IOInterface;
- use Composer\Util\GitHub;
- class GitHubDriver extends VcsDriver
- {
- protected $cache;
- protected $owner;
- protected $repository;
- protected $tags;
- protected $branches;
- protected $rootIdentifier;
- protected $hasIssues;
- protected $infoCache = array();
- protected $isPrivate = false;
- protected $gitDriver;
- public function initialize()
- {
- preg_match('#^(?:(?:https?|git)://([^/]+)/|git@([^:]+):)([^/]+)/(.+?)(?:\.git|/)?$#', $this->url, $match);
- $this->owner = $match[3];
- $this->repository = $match[4];
- $this->originUrl = !empty($match[1]) ? $match[1] : $match[2];
- $this->cache = new Cache($this->io, $this->config->get('cache-repo-dir').'/'.$this->originUrl.'/'.$this->owner.'/'.$this->repository);
- if (isset($this->repoConfig['no-api']) && $this->repoConfig['no-api']) {
- $this->setupGitDriver($this->url);
- return;
- }
- $this->fetchRootIdentifier();
- }
- public function getRepositoryUrl()
- {
- return 'https://'.$this->originUrl.'/'.$this->owner.'/'.$this->repository;
- }
- public function getRootIdentifier()
- {
- if ($this->gitDriver) {
- return $this->gitDriver->getRootIdentifier();
- }
- return $this->rootIdentifier;
- }
- public function getUrl()
- {
- if ($this->gitDriver) {
- return $this->gitDriver->getUrl();
- }
- return 'https://' . $this->originUrl . '/'.$this->owner.'/'.$this->repository.'.git';
- }
- protected function getApiUrl()
- {
- if ('github.com' === $this->originUrl) {
- $apiUrl = 'api.github.com';
- } else {
- $apiUrl = $this->originUrl . '/api/v3';
- }
- return 'https://' . $apiUrl;
- }
- public function getSource($identifier)
- {
- if ($this->gitDriver) {
- return $this->gitDriver->getSource($identifier);
- }
- if ($this->isPrivate) {
-
- $url = $this->generateSshUrl();
- } else {
- $url = $this->getUrl();
- }
- return array('type' => 'git', 'url' => $url, 'reference' => $identifier);
- }
- public function getDist($identifier)
- {
- $url = $this->getApiUrl() . '/repos/'.$this->owner.'/'.$this->repository.'/zipball/'.$identifier;
- return array('type' => 'zip', 'url' => $url, 'reference' => $identifier, 'shasum' => '');
- }
- public function getComposerInformation($identifier)
- {
- if ($this->gitDriver) {
- return $this->gitDriver->getComposerInformation($identifier);
- }
- if (preg_match('{[a-f0-9]{40}}i', $identifier) && $res = $this->cache->read($identifier)) {
- $this->infoCache[$identifier] = JsonFile::parseJson($res);
- }
- if (!isset($this->infoCache[$identifier])) {
- $notFoundRetries = 2;
- while ($notFoundRetries) {
- try {
- $resource = $this->getApiUrl() . '/repos/'.$this->owner.'/'.$this->repository.'/contents/composer.json?ref='.urlencode($identifier);
- $composer = JsonFile::parseJson($this->getContents($resource));
- if (empty($composer['content']) || $composer['encoding'] !== 'base64' || !($composer = base64_decode($composer['content']))) {
- throw new \RuntimeException('Could not retrieve composer.json from '.$resource);
- }
- break;
- } catch (TransportException $e) {
- if (404 !== $e->getCode()) {
- throw $e;
- }
-
- $notFoundRetries--;
- $composer = false;
- }
- }
- if ($composer) {
- $composer = JsonFile::parseJson($composer, $resource);
- if (empty($composer['time'])) {
- $resource = $this->getApiUrl() . '/repos/'.$this->owner.'/'.$this->repository.'/commits/'.urlencode($identifier);
- $commit = JsonFile::parseJson($this->getContents($resource), $resource);
- $composer['time'] = $commit['commit']['committer']['date'];
- }
- if (!isset($composer['support']['source'])) {
- $label = array_search($identifier, $this->getTags()) ?: array_search($identifier, $this->getBranches()) ?: $identifier;
- $composer['support']['source'] = sprintf('https://%s/%s/%s/tree/%s', $this->originUrl, $this->owner, $this->repository, $label);
- }
- if (!isset($composer['support']['issues']) && $this->hasIssues) {
- $composer['support']['issues'] = sprintf('https://%s/%s/%s/issues', $this->originUrl, $this->owner, $this->repository);
- }
- }
- if (preg_match('{[a-f0-9]{40}}i', $identifier)) {
- $this->cache->write($identifier, json_encode($composer));
- }
- $this->infoCache[$identifier] = $composer;
- }
- return $this->infoCache[$identifier];
- }
- public function getTags()
- {
- if ($this->gitDriver) {
- return $this->gitDriver->getTags();
- }
- if (null === $this->tags) {
- $this->tags = array();
- $resource = $this->getApiUrl() . '/repos/'.$this->owner.'/'.$this->repository.'/tags?per_page=100';
- do {
- $tagsData = JsonFile::parseJson($this->getContents($resource), $resource);
- foreach ($tagsData as $tag) {
- $this->tags[$tag['name']] = $tag['commit']['sha'];
- }
- $resource = $this->getNextPage();
- } while ($resource);
- }
- return $this->tags;
- }
- public function getBranches()
- {
- if ($this->gitDriver) {
- return $this->gitDriver->getBranches();
- }
- if (null === $this->branches) {
- $this->branches = array();
- $resource = $this->getApiUrl() . '/repos/'.$this->owner.'/'.$this->repository.'/git/refs/heads?per_page=100';
- $branchBlacklist = array('gh-pages');
- do {
- $branchData = JsonFile::parseJson($this->getContents($resource), $resource);
- foreach ($branchData as $branch) {
- $name = substr($branch['ref'], 11);
- if (!in_array($name, $branchBlacklist)) {
- $this->branches[$name] = $branch['object']['sha'];
- }
- }
- $resource = $this->getNextPage();
- } while ($resource);
- }
- return $this->branches;
- }
- public static function supports(IOInterface $io, Config $config, $url, $deep = false)
- {
- if (!preg_match('#^((?:https?|git)://([^/]+)/|git@([^:]+):)([^/]+)/(.+?)(?:\.git|/)?$#', $url, $matches)) {
- return false;
- }
- $originUrl = !empty($matches[2]) ? $matches[2] : $matches[3];
- if (!in_array($originUrl, $config->get('github-domains'))) {
- return false;
- }
- if (!extension_loaded('openssl')) {
- if ($io->isVerbose()) {
- $io->writeError('Skipping GitHub driver for '.$url.' because the OpenSSL PHP extension is missing.');
- }
- return false;
- }
- return true;
- }
- protected function generateSshUrl()
- {
- return 'git@' . $this->originUrl . ':'.$this->owner.'/'.$this->repository.'.git';
- }
- protected function getContents($url, $fetchingRepoData = false)
- {
- try {
- return parent::getContents($url);
- } catch (TransportException $e) {
- $gitHubUtil = new GitHub($this->io, $this->config, $this->process, $this->remoteFilesystem);
- switch ($e->getCode()) {
- case 401:
- case 404:
- if (!$fetchingRepoData) {
- throw $e;
- }
- if ($gitHubUtil->authorizeOAuth($this->originUrl)) {
- return parent::getContents($url);
- }
- if (!$this->io->isInteractive()) {
- return $this->attemptCloneFallback();
- }
- $gitHubUtil->authorizeOAuthInteractively($this->originUrl, 'Your GitHub credentials are required to fetch private repository metadata (<info>'.$this->url.'</info>)');
- return parent::getContents($url);
- case 403:
- if (!$this->io->hasAuthentication($this->originUrl) && $gitHubUtil->authorizeOAuth($this->originUrl)) {
- return parent::getContents($url);
- }
- if (!$this->io->isInteractive() && $fetchingRepoData) {
- return $this->attemptCloneFallback();
- }
- $rateLimited = false;
- foreach ($e->getHeaders() as $header) {
- if (preg_match('{^X-RateLimit-Remaining: *0$}i', trim($header))) {
- $rateLimited = true;
- }
- }
- if (!$this->io->hasAuthentication($this->originUrl)) {
- if (!$this->io->isInteractive()) {
- $this->io->writeError('<error>GitHub API limit exhausted. Failed to get metadata for the '.$this->url.' repository, try running in interactive mode so that you can enter your GitHub credentials to increase the API limit</error>');
- throw $e;
- }
- $gitHubUtil->authorizeOAuthInteractively($this->originUrl, 'API limit exhausted. Enter your GitHub credentials to get a larger API limit (<info>'.$this->url.'</info>)');
- return parent::getContents($url);
- }
- if ($rateLimited) {
- $rateLimit = $this->getRateLimit($e->getHeaders());
- $this->io->writeError(sprintf(
- '<error>GitHub API limit (%d calls/hr) is exhausted. You are already authorized so you have to wait until %s before doing more requests</error>',
- $rateLimit['limit'],
- $rateLimit['reset']
- ));
- }
- throw $e;
- default:
- throw $e;
- }
- }
- }
- protected function getRateLimit(array $headers)
- {
- $rateLimit = array(
- 'limit' => '?',
- 'reset' => '?',
- );
- foreach ($headers as $header) {
- $header = trim($header);
- if (false === strpos($header, 'X-RateLimit-')) {
- continue;
- }
- list($type, $value) = explode(':', $header, 2);
- switch ($type) {
- case 'X-RateLimit-Limit':
- $rateLimit['limit'] = (int) trim($value);
- break;
- case 'X-RateLimit-Reset':
- $rateLimit['reset'] = date('Y-m-d H:i:s', (int) trim($value));
- break;
- }
- }
- return $rateLimit;
- }
- protected function fetchRootIdentifier()
- {
- $repoDataUrl = $this->getApiUrl() . '/repos/'.$this->owner.'/'.$this->repository;
- $repoData = JsonFile::parseJson($this->getContents($repoDataUrl, true), $repoDataUrl);
- if (null === $repoData && null !== $this->gitDriver) {
- return;
- }
- $this->owner = $repoData['owner']['login'];
- $this->repository = $repoData['name'];
- $this->isPrivate = !empty($repoData['private']);
- if (isset($repoData['default_branch'])) {
- $this->rootIdentifier = $repoData['default_branch'];
- } elseif (isset($repoData['master_branch'])) {
- $this->rootIdentifier = $repoData['master_branch'];
- } else {
- $this->rootIdentifier = 'master';
- }
- $this->hasIssues = !empty($repoData['has_issues']);
- }
- protected function attemptCloneFallback()
- {
- $this->isPrivate = true;
- try {
-
-
-
- $this->setupGitDriver($this->generateSshUrl());
- return;
- } catch (\RuntimeException $e) {
- $this->gitDriver = null;
- $this->io->writeError('<error>Failed to clone the '.$this->generateSshUrl().' repository, try running in interactive mode so that you can enter your GitHub credentials</error>');
- throw $e;
- }
- }
- protected function setupGitDriver($url)
- {
- $this->gitDriver = new GitDriver(
- array('url' => $url),
- $this->io,
- $this->config,
- $this->process,
- $this->remoteFilesystem
- );
- $this->gitDriver->initialize();
- }
- protected function getNextPage()
- {
- $headers = $this->remoteFilesystem->getLastHeaders();
- foreach ($headers as $header) {
- if (substr($header, 0, 5) === 'Link:') {
- $links = explode(',', substr($header, 5));
- foreach ($links as $link) {
- if (preg_match('{<(.+?)>; *rel="next"}', $link, $match)) {
- return $match[1];
- }
- }
- }
- }
- }
- }
- <?php
- namespace Composer\Repository\Vcs;
- use Composer\Config;
- use Composer\Cache;
- use Composer\IO\IOInterface;
- use Composer\Json\JsonFile;
- use Composer\Downloader\TransportException;
- use Composer\Util\RemoteFilesystem;
- class GitLabDriver extends VcsDriver
- {
- private $scheme;
- private $owner;
- private $repository;
- private $cache;
- private $infoCache = array();
- private $project;
- private $commits = array();
- private $tags;
- private $branches;
- public function initialize()
- {
- if (!preg_match('#^(https?)://([^/]+)/([^/]+)/([^/]+)(?:\.git|/)?$#', $this->url, $match)) {
- throw new \InvalidArgumentException('The URL provided is invalid. It must be the HTTP URL of a GitLab project.');
- }
- $this->scheme = $match[1];
- $this->originUrl = $match[2];
- $this->owner = $match[3];
- $this->repository = preg_replace('#(\.git)$#', '', $match[4]);
- $this->cache = new Cache($this->io, $this->config->get('cache-repo-dir').'/'.$this->originUrl.'/'.$this->owner.'/'.$this->repository);
- $this->fetchProject();
- }
- public function setRemoteFilesystem(RemoteFilesystem $remoteFilesystem)
- {
- $this->remoteFilesystem = $remoteFilesystem;
- }
- public function getComposerInformation($identifier)
- {
- if (!preg_match('{[a-f0-9]{40}}i', $identifier)) {
- $branches = $this->getBranches();
- if (isset($branches[$identifier])) {
- $identifier = $branches[$identifier];
- }
- }
- if (isset($this->infoCache[$identifier])) {
- return $this->infoCache[$identifier];
- }
- if (preg_match('{[a-f0-9]{40}}i', $identifier) && $res = $this->cache->read($identifier)) {
- return $this->infoCache[$identifier] = JsonFile::parseJson($res, $res);
- }
- try {
- $composer = $this->fetchComposerFile($identifier);
- } catch (TransportException $e) {
- if ($e->getCode() !== 404) {
- throw $e;
- }
- $composer = false;
- }
- if ($composer && !isset($composer['time']) && isset($this->commits[$identifier])) {
- $composer['time'] = $this->commits[$identifier]['committed_date'];
- }
- if (preg_match('{[a-f0-9]{40}}i', $identifier)) {
- $this->cache->write($identifier, json_encode($composer));
- }
- return $this->infoCache[$identifier] = $composer;
- }
- public function getRepositoryUrl()
- {
- return $this->project['ssh_url_to_repo'];
- }
- public function getUrl()
- {
- return $this->project['web_url'];
- }
- public function getDist($identifier)
- {
- $url = $this->getApiUrl().'/repository/archive.zip?sha='.$identifier;
- return array('type' => 'zip', 'url' => $url, 'reference' => $identifier, 'shasum' => '');
- }
- public function getSource($identifier)
- {
- return array('type' => 'git', 'url' => $this->getRepositoryUrl(), 'reference' => $identifier);
- }
- public function getRootIdentifier()
- {
- return $this->project['default_branch'];
- }
- public function getBranches()
- {
- if (!$this->branches) {
- $this->branches = $this->getReferences('branches');
- }
- return $this->branches;
- }
- public function getTags()
- {
- if (!$this->tags) {
- $this->tags = $this->getReferences('tags');
- }
- return $this->tags;
- }
- protected function fetchComposerFile($identifier)
- {
- $resource = $this->getApiUrl().'/repository/blobs/'.$identifier.'?filepath=composer.json';
- return JsonFile::parseJson($this->getContents($resource), $resource);
- }
- public function getApiUrl()
- {
- return $this->scheme.'://'.$this->originUrl.'/api/v3/projects/'.$this->owner.'%2F'.$this->repository;
- }
- protected function getReferences($type)
- {
- $resource = $this->getApiUrl().'/repository/'.$type;
- $data = JsonFile::parseJson($this->getContents($resource), $resource);
- $references = array();
- foreach ($data as $datum) {
- $references[$datum['name']] = $datum['commit']['id'];
-
- $this->commits[$datum['commit']['id']] = $datum['commit'];
- }
- return $references;
- }
- protected function fetchProject()
- {
- $resource = $this->getApiUrl();
- $this->project = JsonFile::parseJson($this->getContents($resource), $resource);
- }
- public static function supports(IOInterface $io, Config $config, $url, $deep = false)
- {
- if (!preg_match('#^(https?)://([^/]+)/([^/]+)/([^/]+)(?:\.git|/)?$#', $url, $match)) {
- return false;
- }
- $scheme = $match[1];
- $originUrl = $match[2];
- if (!in_array($originUrl, (array) $config->get('gitlab-domains'))) {
- return false;
- }
- if ('https' === $scheme && !extension_loaded('openssl')) {
- if ($io->isVerbose()) {
- $io->write('Skipping GitLab driver for '.$url.' because the OpenSSL PHP extension is missing.');
- }
- return false;
- }
- return true;
- }
- }
- <?php
- namespace Composer\Repository\Vcs;
- use Composer\Config;
- use Composer\Json\JsonFile;
- use Composer\IO\IOInterface;
- class HgBitbucketDriver extends VcsDriver
- {
- protected $owner;
- protected $repository;
- protected $tags;
- protected $branches;
- protected $rootIdentifier;
- protected $infoCache = array();
- public function initialize()
- {
- preg_match('#^https?://bitbucket\.org/([^/]+)/([^/]+)/?$#', $this->url, $match);
- $this->owner = $match[1];
- $this->repository = $match[2];
- $this->originUrl = 'bitbucket.org';
- }
- public function getRootIdentifier()
- {
- if (null === $this->rootIdentifier) {
- $resource = $this->getScheme() . '://bitbucket.org/api/1.0/repositories/'.$this->owner.'/'.$this->repository.'/tags';
- $repoData = JsonFile::parseJson($this->getContents($resource), $resource);
- if (array() === $repoData || !isset($repoData['tip'])) {
- throw new \RuntimeException($this->url.' does not appear to be a mercurial repository, use '.$this->url.'.git if this is a git bitbucket repository');
- }
- $this->rootIdentifier = $repoData['tip']['raw_node'];
- }
- return $this->rootIdentifier;
- }
- public function getUrl()
- {
- return $this->url;
- }
- public function getSource($identifier)
- {
- return array('type' => 'hg', 'url' => $this->getUrl(), 'reference' => $identifier);
- }
- public function getDist($identifier)
- {
- $url = $this->getScheme() . '://bitbucket.org/'.$this->owner.'/'.$this->repository.'/get/'.$identifier.'.zip';
- return array('type' => 'zip', 'url' => $url, 'reference' => $identifier, 'shasum' => '');
- }
- public function getComposerInformation($identifier)
- {
- if (!isset($this->infoCache[$identifier])) {
- $resource = $this->getScheme() . '://bitbucket.org/api/1.0/repositories/'.$this->owner.'/'.$this->repository.'/src/'.$identifier.'/composer.json';
- $repoData = JsonFile::parseJson($this->getContents($resource), $resource);
-
-
-
- if (!array_key_exists('data', $repoData)) {
- return;
- }
- $composer = JsonFile::parseJson($repoData['data'], $resource);
- if (empty($composer['time'])) {
- $resource = $this->getScheme() . '://bitbucket.org/api/1.0/repositories/'.$this->owner.'/'.$this->repository.'/changesets/'.$identifier;
- $changeset = JsonFile::parseJson($this->getContents($resource), $resource);
- $composer['time'] = $changeset['timestamp'];
- }
- $this->infoCache[$identifier] = $composer;
- }
- return $this->infoCache[$identifier];
- }
- public function getTags()
- {
- if (null === $this->tags) {
- $resource = $this->getScheme() . '://bitbucket.org/api/1.0/repositories/'.$this->owner.'/'.$this->repository.'/tags';
- $tagsData = JsonFile::parseJson($this->getContents($resource), $resource);
- $this->tags = array();
- foreach ($tagsData as $tag => $data) {
- $this->tags[$tag] = $data['raw_node'];
- }
- unset($this->tags['tip']);
- }
- return $this->tags;
- }
- public function getBranches()
- {
- if (null === $this->branches) {
- $resource = $this->getScheme() . '://bitbucket.org/api/1.0/repositories/'.$this->owner.'/'.$this->repository.'/branches';
- $branchData = JsonFile::parseJson($this->getContents($resource), $resource);
- $this->branches = array();
- foreach ($branchData as $branch => $data) {
- $this->branches[$branch] = $data['raw_node'];
- }
- }
- return $this->branches;
- }
- public static function supports(IOInterface $io, Config $config, $url, $deep = false)
- {
- if (!preg_match('#^https?://bitbucket\.org/([^/]+)/([^/]+)/?$#', $url)) {
- return false;
- }
- if (!extension_loaded('openssl')) {
- if ($io->isVerbose()) {
- $io->writeError('Skipping Bitbucket hg driver for '.$url.' because the OpenSSL PHP extension is missing.');
- }
- return false;
- }
- return true;
- }
- }
- <?php
- namespace Composer\Repository\Vcs;
- use Composer\Config;
- use Composer\Json\JsonFile;
- use Composer\Util\ProcessExecutor;
- use Composer\Util\Filesystem;
- use Composer\IO\IOInterface;
- class HgDriver extends VcsDriver
- {
- protected $tags;
- protected $branches;
- protected $rootIdentifier;
- protected $repoDir;
- protected $infoCache = array();
- public function initialize()
- {
- if (Filesystem::isLocalPath($this->url)) {
- $this->repoDir = $this->url;
- } else {
- $cacheDir = $this->config->get('cache-vcs-dir');
- $this->repoDir = $cacheDir . '/' . preg_replace('{[^a-z0-9]}i', '-', $this->url) . '/';
- $fs = new Filesystem();
- $fs->ensureDirectoryExists($cacheDir);
- if (!is_writable(dirname($this->repoDir))) {
- throw new \RuntimeException('Can not clone '.$this->url.' to access package information. The "'.$cacheDir.'" directory is not writable by the current user.');
- }
- if (is_dir($this->repoDir) && 0 === $this->process->execute('hg summary', $output, $this->repoDir)) {
- if (0 !== $this->process->execute('hg pull', $output, $this->repoDir)) {
- $this->io->writeError('<error>Failed to update '.$this->url.', package information from this repository may be outdated ('.$this->process->getErrorOutput().')</error>');
- }
- } else {
- $fs->removeDirectory($this->repoDir);
- if (0 !== $this->process->execute(sprintf('hg clone --noupdate %s %s', ProcessExecutor::escape($this->url), ProcessExecutor::escape($this->repoDir)), $output, $cacheDir)) {
- $output = $this->process->getErrorOutput();
- if (0 !== $this->process->execute('hg --version', $ignoredOutput)) {
- throw new \RuntimeException('Failed to clone '.$this->url.', hg was not found, check that it is installed and in your PATH env.' . "\n\n" . $this->process->getErrorOutput());
- }
- throw new \RuntimeException('Failed to clone '.$this->url.', could not read packages from it' . "\n\n" .$output);
- }
- }
- }
- $this->getTags();
- $this->getBranches();
- }
- public function getRootIdentifier()
- {
- if (null === $this->rootIdentifier) {
- $this->process->execute(sprintf('hg tip --template "{node}"'), $output, $this->repoDir);
- $output = $this->process->splitLines($output);
- $this->rootIdentifier = $output[0];
- }
- return $this->rootIdentifier;
- }
- public function getUrl()
- {
- return $this->url;
- }
- public function getSource($identifier)
- {
- return array('type' => 'hg', 'url' => $this->getUrl(), 'reference' => $identifier);
- }
- public function getDist($identifier)
- {
- return null;
- }
- public function getComposerInformation($identifier)
- {
- if (!isset($this->infoCache[$identifier])) {
- $this->process->execute(sprintf('hg cat -r %s composer.json', ProcessExecutor::escape($identifier)), $composer, $this->repoDir);
- if (!trim($composer)) {
- return;
- }
- $composer = JsonFile::parseJson($composer, $identifier);
- if (empty($composer['time'])) {
- $this->process->execute(sprintf('hg log --template "{date|rfc3339date}" -r %s', ProcessExecutor::escape($identifier)), $output, $this->repoDir);
- $date = new \DateTime(trim($output), new \DateTimeZone('UTC'));
- $composer['time'] = $date->format('Y-m-d H:i:s');
- }
- $this->infoCache[$identifier] = $composer;
- }
- return $this->infoCache[$identifier];
- }
- public function getTags()
- {
- if (null === $this->tags) {
- $tags = array();
- $this->process->execute('hg tags', $output, $this->repoDir);
- foreach ($this->process->splitLines($output) as $tag) {
- if ($tag && preg_match('(^([^\s]+)\s+\d+:(.*)$)', $tag, $match)) {
- $tags[$match[1]] = $match[2];
- }
- }
- unset($tags['tip']);
- $this->tags = $tags;
- }
- return $this->tags;
- }
- public function getBranches()
- {
- if (null === $this->branches) {
- $branches = array();
- $bookmarks = array();
- $this->process->execute('hg branches', $output, $this->repoDir);
- foreach ($this->process->splitLines($output) as $branch) {
- if ($branch && preg_match('(^([^\s]+)\s+\d+:([a-f0-9]+))', $branch, $match)) {
- $branches[$match[1]] = $match[2];
- }
- }
- $this->process->execute('hg bookmarks', $output, $this->repoDir);
- foreach ($this->process->splitLines($output) as $branch) {
- if ($branch && preg_match('(^(?:[\s*]*)([^\s]+)\s+\d+:(.*)$)', $branch, $match)) {
- $bookmarks[$match[1]] = $match[2];
- }
- }
- $this->branches = array_merge($bookmarks, $branches);
- }
- return $this->branches;
- }
- public static function supports(IOInterface $io, Config $config, $url, $deep = false)
- {
- if (preg_match('#(^(?:https?|ssh)://(?:[^@]@)?bitbucket.org|https://(?:.*?)\.kilnhg.com)#i', $url)) {
- return true;
- }
- if (Filesystem::isLocalPath($url)) {
- $url = Filesystem::getPlatformPath($url);
- if (!is_dir($url)) {
- return false;
- }
- $process = new ProcessExecutor();
- if ($process->execute('hg summary', $output, $url) === 0) {
- return true;
- }
- }
- if (!$deep) {
- return false;
- }
- $processExecutor = new ProcessExecutor();
- $exit = $processExecutor->execute(sprintf('hg identify %s', ProcessExecutor::escape($url)), $ignored);
- return $exit === 0;
- }
- }
- <?php
- namespace Composer\Repository\Vcs;
- use Composer\Config;
- use Composer\IO\IOInterface;
- use Composer\Util\ProcessExecutor;
- use Composer\Util\Perforce;
- class PerforceDriver extends VcsDriver
- {
- protected $depot;
- protected $branch;
- protected $perforce;
- protected $composerInfo;
- protected $composerInfoIdentifier;
- public function initialize()
- {
- $this->depot = $this->repoConfig['depot'];
- $this->branch = '';
- if (!empty($this->repoConfig['branch'])) {
- $this->branch = $this->repoConfig['branch'];
- }
- $this->initPerforce($this->repoConfig);
- $this->perforce->p4Login($this->io);
- $this->perforce->checkStream($this->depot);
- $this->perforce->writeP4ClientSpec();
- $this->perforce->connectClient();
- return true;
- }
- private function initPerforce($repoConfig)
- {
- if (!empty($this->perforce)) {
- return;
- }
- $repoDir = $this->config->get('cache-vcs-dir') . '/' . $this->depot;
- $this->perforce = Perforce::create($repoConfig, $this->getUrl(), $repoDir, $this->process, $this->io);
- }
- public function getComposerInformation($identifier)
- {
- if (!empty($this->composerInfoIdentifier)) {
- if (strcmp($identifier, $this->composerInfoIdentifier) === 0) {
- return $this->composerInfo;
- }
- }
- $composer_info = $this->perforce->getComposerInformation($identifier);
- return $composer_info;
- }
- public function getRootIdentifier()
- {
- return $this->branch;
- }
- public function getBranches()
- {
- $branches = $this->perforce->getBranches();
- return $branches;
- }
- public function getTags()
- {
- $tags = $this->perforce->getTags();
- return $tags;
- }
- public function getDist($identifier)
- {
- return null;
- }
- public function getSource($identifier)
- {
- $source = array(
- 'type' => 'perforce',
- 'url' => $this->repoConfig['url'],
- 'reference' => $identifier,
- 'p4user' => $this->perforce->getUser()
- );
- return $source;
- }
- public function getUrl()
- {
- return $this->url;
- }
- public function hasComposerFile($identifier)
- {
- $this->composerInfo = $this->perforce->getComposerInformation('//' . $this->depot . '/' . $identifier);
- $this->composerInfoIdentifier = $identifier;
- return !empty($this->composerInfo);
- }
- public function getContents($url)
- {
- return false;
- }
- public static function supports(IOInterface $io, Config $config, $url, $deep = false)
- {
- if ($deep || preg_match('#\b(perforce|p4)\b#i', $url)) {
- return Perforce::checkServerExists($url, new ProcessExecutor($io));
- }
- return false;
- }
- public function cleanup()
- {
- $this->perforce->cleanupClientSpec();
- $this->perforce = null;
- }
- public function getDepot()
- {
- return $this->depot;
- }
- public function getBranch()
- {
- return $this->branch;
- }
- }
- <?php
- namespace Composer\Repository\Vcs;
- use Composer\Cache;
- use Composer\Config;
- use Composer\Json\JsonFile;
- use Composer\Util\ProcessExecutor;
- use Composer\Util\Filesystem;
- use Composer\Util\Svn as SvnUtil;
- use Composer\IO\IOInterface;
- use Composer\Downloader\TransportException;
- class SvnDriver extends VcsDriver
- {
- protected $cache;
- protected $baseUrl;
- protected $tags;
- protected $branches;
- protected $rootIdentifier;
- protected $infoCache = array();
- protected $trunkPath = 'trunk';
- protected $branchesPath = 'branches';
- protected $tagsPath = 'tags';
- protected $packagePath = '';
- protected $cacheCredentials = true;
- private $util;
- public function initialize()
- {
- $this->url = $this->baseUrl = rtrim(self::normalizeUrl($this->url), '/');
- SvnUtil::cleanEnv();
- if (isset($this->repoConfig['trunk-path'])) {
- $this->trunkPath = $this->repoConfig['trunk-path'];
- }
- if (isset($this->repoConfig['branches-path'])) {
- $this->branchesPath = $this->repoConfig['branches-path'];
- }
- if (isset($this->repoConfig['tags-path'])) {
- $this->tagsPath = $this->repoConfig['tags-path'];
- }
- if (array_key_exists('svn-cache-credentials', $this->repoConfig)) {
- $this->cacheCredentials = (bool) $this->repoConfig['svn-cache-credentials'];
- }
- if (isset($this->repoConfig['package-path'])) {
- $this->packagePath = '/' . trim($this->repoConfig['package-path'], '/');
- }
- if (false !== ($pos = strrpos($this->url, '/' . $this->trunkPath))) {
- $this->baseUrl = substr($this->url, 0, $pos);
- }
- $this->cache = new Cache($this->io, $this->config->get('cache-repo-dir').'/'.preg_replace('{[^a-z0-9.]}i', '-', $this->baseUrl));
- $this->getBranches();
- $this->getTags();
- }
- public function getRootIdentifier()
- {
- return $this->rootIdentifier ?: $this->trunkPath;
- }
- public function getUrl()
- {
- return $this->url;
- }
- public function getSource($identifier)
- {
- return array('type' => 'svn', 'url' => $this->baseUrl, 'reference' => $identifier);
- }
- public function getDist($identifier)
- {
- return null;
- }
- public function getComposerInformation($identifier)
- {
- $identifier = '/' . trim($identifier, '/') . '/';
- if ($res = $this->cache->read($identifier.'.json')) {
- $this->infoCache[$identifier] = JsonFile::parseJson($res);
- }
- if (!isset($this->infoCache[$identifier])) {
- preg_match('{^(.+?)(@\d+)?/$}', $identifier, $match);
- if (!empty($match[2])) {
- $path = $match[1];
- $rev = $match[2];
- } else {
- $path = $identifier;
- $rev = '';
- }
- try {
- $resource = $path.'composer.json';
- $output = $this->execute('svn cat', $this->baseUrl . $resource . $rev);
- if (!trim($output)) {
- return;
- }
- } catch (\RuntimeException $e) {
- throw new TransportException($e->getMessage());
- }
- $composer = JsonFile::parseJson($output, $this->baseUrl . $resource . $rev);
- if (empty($composer['time'])) {
- $output = $this->execute('svn info', $this->baseUrl . $path . $rev);
- foreach ($this->process->splitLines($output) as $line) {
- if ($line && preg_match('{^Last Changed Date: ([^(]+)}', $line, $match)) {
- $date = new \DateTime($match[1], new \DateTimeZone('UTC'));
- $composer['time'] = $date->format('Y-m-d H:i:s');
- break;
- }
- }
- }
- $this->cache->write($identifier.'.json', json_encode($composer));
- $this->infoCache[$identifier] = $composer;
- }
- return $this->infoCache[$identifier];
- }
- public function getTags()
- {
- if (null === $this->tags) {
- $this->tags = array();
- if ($this->tagsPath !== false) {
- $output = $this->execute('svn ls --verbose', $this->baseUrl . '/' . $this->tagsPath);
- if ($output) {
- foreach ($this->process->splitLines($output) as $line) {
- $line = trim($line);
- if ($line && preg_match('{^\s*(\S+).*?(\S+)\s*$}', $line, $match)) {
- if (isset($match[1]) && isset($match[2]) && $match[2] !== './') {
- $this->tags[rtrim($match[2], '/')] = $this->buildIdentifier(
- '/' . $this->tagsPath . '/' . $match[2],
- $match[1]
- );
- }
- }
- }
- }
- }
- }
- return $this->tags;
- }
- public function getBranches()
- {
- if (null === $this->branches) {
- $this->branches = array();
- if (false === $this->trunkPath) {
- $trunkParent = $this->baseUrl . '/';
- } else {
- $trunkParent = $this->baseUrl . '/' . $this->trunkPath;
- }
- $output = $this->execute('svn ls --verbose', $trunkParent);
- if ($output) {
- foreach ($this->process->splitLines($output) as $line) {
- $line = trim($line);
- if ($line && preg_match('{^\s*(\S+).*?(\S+)\s*$}', $line, $match)) {
- if (isset($match[1]) && isset($match[2]) && $match[2] === './') {
- $this->branches['trunk'] = $this->buildIdentifier(
- '/' . $this->trunkPath,
- $match[1]
- );
- $this->rootIdentifier = $this->branches['trunk'];
- break;
- }
- }
- }
- }
- unset($output);
- if ($this->branchesPath !== false) {
- $output = $this->execute('svn ls --verbose', $this->baseUrl . '/' . $this->branchesPath);
- if ($output) {
- foreach ($this->process->splitLines(trim($output)) as $line) {
- $line = trim($line);
- if ($line && preg_match('{^\s*(\S+).*?(\S+)\s*$}', $line, $match)) {
- if (isset($match[1]) && isset($match[2]) && $match[2] !== './') {
- $this->branches[rtrim($match[2], '/')] = $this->buildIdentifier(
- '/' . $this->branchesPath . '/' . $match[2],
- $match[1]
- );
- }
- }
- }
- }
- }
- }
- return $this->branches;
- }
- public static function supports(IOInterface $io, Config $config, $url, $deep = false)
- {
- $url = self::normalizeUrl($url);
- if (preg_match('#(^svn://|^svn\+ssh://|svn\.)#i', $url)) {
- return true;
- }
- if (!$deep && !Filesystem::isLocalPath($url)) {
- return false;
- }
- $processExecutor = new ProcessExecutor();
- $exit = $processExecutor->execute(
- "svn info --non-interactive {$url}",
- $ignoredOutput
- );
- if ($exit === 0) {
- return true;
- }
- if (false !== stripos($processExecutor->getErrorOutput(), 'authorization failed:')) {
-
- return true;
- }
- return false;
- }
- protected static function normalizeUrl($url)
- {
- $fs = new Filesystem();
- if ($fs->isAbsolutePath($url)) {
- return 'file://' . strtr($url, '\\', '/');
- }
- return $url;
- }
- protected function execute($command, $url)
- {
- if (null === $this->util) {
- $this->util = new SvnUtil($this->baseUrl, $this->io, $this->config, $this->process);
- $this->util->setCacheCredentials($this->cacheCredentials);
- }
- try {
- return $this->util->execute($command, $url);
- } catch (\RuntimeException $e) {
- if (0 !== $this->process->execute('svn --version', $ignoredOutput)) {
- throw new \RuntimeException('Failed to load '.$this->url.', svn was not found, check that it is installed and in your PATH env.' . "\n\n" . $this->process->getErrorOutput());
- }
- throw new \RuntimeException(
- 'Repository '.$this->url.' could not be processed, '.$e->getMessage()
- );
- }
- }
- protected function buildIdentifier($baseDir, $revision)
- {
- return rtrim($baseDir, '/') . $this->packagePath . '/@' . $revision;
- }
- }
- <?php
- namespace Composer\Repository\Vcs;
- use Composer\Downloader\TransportException;
- use Composer\Config;
- use Composer\IO\IOInterface;
- use Composer\Util\ProcessExecutor;
- use Composer\Util\RemoteFilesystem;
- use Composer\Util\Filesystem;
- abstract class VcsDriver implements VcsDriverInterface
- {
- protected $url;
- protected $originUrl;
- protected $repoConfig;
- protected $io;
- protected $config;
- protected $process;
- protected $remoteFilesystem;
- final public function __construct(array $repoConfig, IOInterface $io, Config $config, ProcessExecutor $process = null, RemoteFilesystem $remoteFilesystem = null)
- {
- if (Filesystem::isLocalPath($repoConfig['url'])) {
- $repoConfig['url'] = Filesystem::getPlatformPath($repoConfig['url']);
- }
- $this->url = $repoConfig['url'];
- $this->originUrl = $repoConfig['url'];
- $this->repoConfig = $repoConfig;
- $this->io = $io;
- $this->config = $config;
- $this->process = $process ?: new ProcessExecutor($io);
- $this->remoteFilesystem = $remoteFilesystem ?: new RemoteFilesystem($io, $config);
- }
- public function hasComposerFile($identifier)
- {
- try {
- return (bool) $this->getComposerInformation($identifier);
- } catch (TransportException $e) {
- }
- return false;
- }
- protected function getScheme()
- {
- if (extension_loaded('openssl')) {
- return 'https';
- }
- return 'http';
- }
- protected function getContents($url)
- {
- return $this->remoteFilesystem->getContents($this->originUrl, $url, false);
- }
- public function cleanup()
- {
- return;
- }
- }
- <?php
- namespace Composer\Repository\Vcs;
- use Composer\Config;
- use Composer\IO\IOInterface;
- interface VcsDriverInterface
- {
- public function initialize();
- public function getComposerInformation($identifier);
- public function getRootIdentifier();
- public function getBranches();
- public function getTags();
- public function getDist($identifier);
- public function getSource($identifier);
- public function getUrl();
- public function hasComposerFile($identifier);
- public function cleanup();
- public static function supports(IOInterface $io, Config $config, $url, $deep = false);
- }
- <?php
- namespace Composer\Repository;
- use Composer\Downloader\TransportException;
- use Composer\Repository\Vcs\VcsDriverInterface;
- use Composer\Package\Version\VersionParser;
- use Composer\Package\Loader\ArrayLoader;
- use Composer\Package\Loader\ValidatingArrayLoader;
- use Composer\Package\Loader\InvalidPackageException;
- use Composer\Package\Loader\LoaderInterface;
- use Composer\EventDispatcher\EventDispatcher;
- use Composer\IO\IOInterface;
- use Composer\Config;
- class VcsRepository extends ArrayRepository
- {
- protected $url;
- protected $packageName;
- protected $verbose;
- protected $io;
- protected $config;
- protected $versionParser;
- protected $type;
- protected $loader;
- protected $repoConfig;
- protected $branchErrorOccurred = false;
- public function __construct(array $repoConfig, IOInterface $io, Config $config, EventDispatcher $dispatcher = null, array $drivers = null)
- {
- $this->drivers = $drivers ?: array(
- 'github' => 'Composer\Repository\Vcs\GitHubDriver',
- 'gitlab' => 'Composer\Repository\Vcs\GitLabDriver',
- 'git-bitbucket' => 'Composer\Repository\Vcs\GitBitbucketDriver',
- 'git' => 'Composer\Repository\Vcs\GitDriver',
- 'hg-bitbucket' => 'Composer\Repository\Vcs\HgBitbucketDriver',
- 'hg' => 'Composer\Repository\Vcs\HgDriver',
- 'perforce' => 'Composer\Repository\Vcs\PerforceDriver',
- 'svn' => 'Composer\Repository\Vcs\SvnDriver',
- );
- $this->url = $repoConfig['url'];
- $this->io = $io;
- $this->type = isset($repoConfig['type']) ? $repoConfig['type'] : 'vcs';
- $this->verbose = $io->isVerbose();
- $this->config = $config;
- $this->repoConfig = $repoConfig;
- }
- public function getRepoConfig()
- {
- return $this->repoConfig;
- }
- public function setLoader(LoaderInterface $loader)
- {
- $this->loader = $loader;
- }
- public function getDriver()
- {
- if (isset($this->drivers[$this->type])) {
- $class = $this->drivers[$this->type];
- $driver = new $class($this->repoConfig, $this->io, $this->config);
- $driver->initialize();
- return $driver;
- }
- foreach ($this->drivers as $driver) {
- if ($driver::supports($this->io, $this->config, $this->url)) {
- $driver = new $driver($this->repoConfig, $this->io, $this->config);
- $driver->initialize();
- return $driver;
- }
- }
- foreach ($this->drivers as $driver) {
- if ($driver::supports($this->io, $this->config, $this->url, true)) {
- $driver = new $driver($this->repoConfig, $this->io, $this->config);
- $driver->initialize();
- return $driver;
- }
- }
- }
- public function hadInvalidBranches()
- {
- return $this->branchErrorOccurred;
- }
- protected function initialize()
- {
- parent::initialize();
- $verbose = $this->verbose;
- $driver = $this->getDriver();
- if (!$driver) {
- throw new \InvalidArgumentException('No driver found to handle VCS repository '.$this->url);
- }
- $this->versionParser = new VersionParser;
- if (!$this->loader) {
- $this->loader = new ArrayLoader($this->versionParser);
- }
- try {
- if ($driver->hasComposerFile($driver->getRootIdentifier())) {
- $data = $driver->getComposerInformation($driver->getRootIdentifier());
- $this->packageName = !empty($data['name']) ? $data['name'] : null;
- }
- } catch (\Exception $e) {
- if ($verbose) {
- $this->io->writeError('<error>Skipped parsing '.$driver->getRootIdentifier().', '.$e->getMessage().'</error>');
- }
- }
- foreach ($driver->getTags() as $tag => $identifier) {
- $msg = 'Reading composer.json of <info>' . ($this->packageName ?: $this->url) . '</info> (<comment>' . $tag . '</comment>)';
- if ($verbose) {
- $this->io->writeError($msg);
- } else {
- $this->io->overwriteError($msg, false);
- }
- $tag = str_replace('release-', '', $tag);
- if (!$parsedTag = $this->validateTag($tag)) {
- if ($verbose) {
- $this->io->writeError('<warning>Skipped tag '.$tag.', invalid tag name</warning>');
- }
- continue;
- }
- try {
- if (!$data = $driver->getComposerInformation($identifier)) {
- if ($verbose) {
- $this->io->writeError('<warning>Skipped tag '.$tag.', no composer file</warning>');
- }
- continue;
- }
- if (isset($data['version'])) {
- $data['version_normalized'] = $this->versionParser->normalize($data['version']);
- } else {
- $data['version'] = $tag;
- $data['version_normalized'] = $parsedTag;
- }
- $data['version'] = preg_replace('{[.-]?dev$}i', '', $data['version']);
- $data['version_normalized'] = preg_replace('{(^dev-|[.-]?dev$)}i', '', $data['version_normalized']);
- if ($data['version_normalized'] !== $parsedTag) {
- if ($verbose) {
- $this->io->writeError('<warning>Skipped tag '.$tag.', tag ('.$parsedTag.') does not match version ('.$data['version_normalized'].') in composer.json</warning>');
- }
- continue;
- }
- if ($verbose) {
- $this->io->writeError('Importing tag '.$tag.' ('.$data['version_normalized'].')');
- }
- $this->addPackage($this->loader->load($this->preProcess($driver, $data, $identifier)));
- } catch (\Exception $e) {
- if ($verbose) {
- $this->io->writeError('<warning>Skipped tag '.$tag.', '.($e instanceof TransportException ? 'no composer file was found' : $e->getMessage()).'</warning>');
- }
- continue;
- }
- }
- if (!$verbose) {
- $this->io->overwriteError('', false);
- }
- foreach ($driver->getBranches() as $branch => $identifier) {
- $msg = 'Reading composer.json of <info>' . ($this->packageName ?: $this->url) . '</info> (<comment>' . $branch . '</comment>)';
- if ($verbose) {
- $this->io->writeError($msg);
- } else {
- $this->io->overwriteError($msg, false);
- }
- if (!$parsedBranch = $this->validateBranch($branch)) {
- if ($verbose) {
- $this->io->writeError('<warning>Skipped branch '.$branch.', invalid name</warning>');
- }
- continue;
- }
- try {
- if (!$data = $driver->getComposerInformation($identifier)) {
- if ($verbose) {
- $this->io->writeError('<warning>Skipped branch '.$branch.', no composer file</warning>');
- }
- continue;
- }
- $data['version'] = $branch;
- $data['version_normalized'] = $parsedBranch;
- if ('dev-' === substr($parsedBranch, 0, 4) || '9999999-dev' === $parsedBranch) {
- $data['version'] = 'dev-' . $data['version'];
- } else {
- $data['version'] = preg_replace('{(\.9{7})+}', '.x', $parsedBranch);
- }
- if ($verbose) {
- $this->io->writeError('Importing branch '.$branch.' ('.$data['version'].')');
- }
- $packageData = $this->preProcess($driver, $data, $identifier);
- $package = $this->loader->load($packageData);
- if ($this->loader instanceof ValidatingArrayLoader && $this->loader->getWarnings()) {
- throw new InvalidPackageException($this->loader->getErrors(), $this->loader->getWarnings(), $packageData);
- }
- $this->addPackage($package);
- } catch (TransportException $e) {
- if ($verbose) {
- $this->io->writeError('<warning>Skipped branch '.$branch.', no composer file was found</warning>');
- }
- continue;
- } catch (\Exception $e) {
- if (!$verbose) {
- $this->io->writeError('');
- }
- $this->branchErrorOccurred = true;
- $this->io->writeError('<error>Skipped branch '.$branch.', '.$e->getMessage().'</error>');
- $this->io->writeError('');
- continue;
- }
- }
- $driver->cleanup();
- if (!$verbose) {
- $this->io->overwriteError('', false);
- }
- if (!$this->getPackages()) {
- throw new InvalidRepositoryException('No valid composer.json was found in any branch or tag of '.$this->url.', could not load a package from it.');
- }
- }
- protected function preProcess(VcsDriverInterface $driver, array $data, $identifier)
- {
- $data['name'] = $this->packageName ?: $data['name'];
- if (!isset($data['dist'])) {
- $data['dist'] = $driver->getDist($identifier);
- }
- if (!isset($data['source'])) {
- $data['source'] = $driver->getSource($identifier);
- }
- return $data;
- }
- private function validateBranch($branch)
- {
- try {
- return $this->versionParser->normalizeBranch($branch);
- } catch (\Exception $e) {
- }
- return false;
- }
- private function validateTag($version)
- {
- try {
- return $this->versionParser->normalize($version);
- } catch (\Exception $e) {
- }
- return false;
- }
- }
- <?php
- namespace Composer\Repository;
- use Composer\Package\AliasPackage;
- class WritableArrayRepository extends ArrayRepository implements WritableRepositoryInterface
- {
- public function write()
- {
- }
- public function reload()
- {
- }
- public function getCanonicalPackages()
- {
- $packages = $this->getPackages();
- $packagesByName = array();
- foreach ($packages as $package) {
- if (!isset($packagesByName[$package->getName()]) || $packagesByName[$package->getName()] instanceof AliasPackage) {
- $packagesByName[$package->getName()] = $package;
- }
- }
- $canonicalPackages = array();
- foreach ($packagesByName as $package) {
- while ($package instanceof AliasPackage) {
- $package = $package->getAliasOf();
- }
- $canonicalPackages[] = $package;
- }
- return $canonicalPackages;
- }
- }
- <?php
- namespace Composer\Repository;
- use Composer\Package\PackageInterface;
- interface WritableRepositoryInterface extends RepositoryInterface
- {
- public function write();
- public function addPackage(PackageInterface $package);
- public function removePackage(PackageInterface $package);
- public function getCanonicalPackages();
- public function reload();
- }
- <?php
- namespace Composer\Script;
- class CommandEvent extends Event
- {
- }
- <?php
- namespace Composer\Script;
- use Composer\Composer;
- use Composer\IO\IOInterface;
- use Composer\EventDispatcher\Event as BaseEvent;
- class Event extends BaseEvent
- {
- private $composer;
- private $io;
- private $devMode;
- public function __construct($name, Composer $composer, IOInterface $io, $devMode = false, array $args = array(), array $flags = array())
- {
- parent::__construct($name, $args, $flags);
- $this->composer = $composer;
- $this->io = $io;
- $this->devMode = $devMode;
- }
- public function getComposer()
- {
- return $this->composer;
- }
- public function getIO()
- {
- return $this->io;
- }
- public function isDevMode()
- {
- return $this->devMode;
- }
- }
- <?php
- namespace Composer\Script;
- use Composer\Installer\PackageEvent as BasePackageEvent;
- class PackageEvent extends BasePackageEvent
- {
- }
- <?php
- namespace Composer\Script;
- class ScriptEvents
- {
- const PRE_INSTALL_CMD = 'pre-install-cmd';
- const POST_INSTALL_CMD = 'post-install-cmd';
- const PRE_UPDATE_CMD = 'pre-update-cmd';
- const POST_UPDATE_CMD = 'post-update-cmd';
- const PRE_STATUS_CMD = 'pre-status-cmd';
- const POST_STATUS_CMD = 'post-status-cmd';
- const PRE_AUTOLOAD_DUMP = 'pre-autoload-dump';
- const POST_AUTOLOAD_DUMP = 'post-autoload-dump';
- const POST_ROOT_PACKAGE_INSTALL = 'post-root-package-install';
- const POST_CREATE_PROJECT_CMD = 'post-create-project-cmd';
- const PRE_ARCHIVE_CMD = 'pre-archive-cmd';
- const POST_ARCHIVE_CMD = 'post-archive-cmd';
- const PRE_PACKAGE_INSTALL = 'pre-package-install';
- const POST_PACKAGE_INSTALL = 'post-package-install';
- const PRE_PACKAGE_UPDATE = 'pre-package-update';
- const POST_PACKAGE_UPDATE = 'post-package-update';
- const PRE_PACKAGE_UNINSTALL = 'pre-package-uninstall';
- const POST_PACKAGE_UNINSTALL = 'post-package-uninstall';
- }
- <?php
- namespace Composer\Util;
- use Composer\Config;
- use Composer\IO\IOInterface;
- class AuthHelper
- {
- protected $io;
- protected $config;
- public function __construct(IOInterface $io, Config $config)
- {
- $this->io = $io;
- $this->config = $config;
- }
- public function storeAuth($originUrl, $storeAuth)
- {
- $store = false;
- $configSource = $this->config->getAuthConfigSource();
- if ($storeAuth === true) {
- $store = $configSource;
- } elseif ($storeAuth === 'prompt') {
- $answer = $this->io->askAndValidate(
- 'Do you want to store credentials for '.$originUrl.' in '.$configSource->getName().' ? [Yn] ',
- function ($value) {
- $input = strtolower(substr(trim($value), 0, 1));
- if (in_array($input, array('y','n'))) {
- return $input;
- }
- throw new \RuntimeException('Please answer (y)es or (n)o');
- },
- false,
- 'y'
- );
- if ($answer === 'y') {
- $store = $configSource;
- }
- }
- if ($store) {
- $store->addConfigSetting(
- 'http-basic.'.$originUrl,
- $this->io->getAuthentication($originUrl)
- );
- }
- }
- }
- <?php
- namespace Composer\Util;
- class ComposerMirror
- {
- public static function processUrl($mirrorUrl, $packageName, $version, $reference, $type)
- {
- if ($reference) {
- $reference = preg_match('{^([a-f0-9]*|%reference%)$}', $reference) ? $reference : md5($reference);
- }
- $version = strpos($version, '/') === false ? $version : md5($version);
- return str_replace(
- array('%package%', '%version%', '%reference%', '%type%'),
- array($packageName, $version, $reference, $type),
- $mirrorUrl
- );
- }
- public static function processGitUrl($mirrorUrl, $packageName, $url, $type)
- {
- if (preg_match('#^(?:(?:https?|git)://github\.com/|git@github\.com:)([^/]+)/(.+?)(?:\.git)?$#', $url, $match)) {
- $url = 'gh-'.$match[1].'/'.$match[2];
- } elseif (preg_match('#^https://bitbucket\.org/([^/]+)/(.+?)(?:\.git)?/?$#', $url, $match)) {
- $url = 'bb-'.$match[1].'/'.$match[2];
- } else {
- $url = preg_replace('{[^a-z0-9_.-]}i', '-', trim($url, '/'));
- }
- return str_replace(
- array('%package%', '%normalizedUrl%', '%type%'),
- array($packageName, $url, $type),
- $mirrorUrl
- );
- }
- public static function processHgUrl($mirrorUrl, $packageName, $url, $type)
- {
- return self::processGitUrl($mirrorUrl, $packageName, $url, $type);
- }
- }
- <?php
- namespace Composer\Util;
- use Composer\Package\Loader\ArrayLoader;
- use Composer\Package\Loader\ValidatingArrayLoader;
- use Composer\Package\Loader\InvalidPackageException;
- use Composer\Json\JsonValidationException;
- use Composer\IO\IOInterface;
- use Composer\Json\JsonFile;
- class ConfigValidator
- {
- private $io;
- public function __construct(IOInterface $io)
- {
- $this->io = $io;
- }
- public function validate($file, $arrayLoaderValidationFlags = ValidatingArrayLoader::CHECK_ALL)
- {
- $errors = array();
- $publishErrors = array();
- $warnings = array();
- $laxValid = false;
- try {
- $json = new JsonFile($file, new RemoteFilesystem($this->io));
- $manifest = $json->read();
- $json->validateSchema(JsonFile::LAX_SCHEMA);
- $laxValid = true;
- $json->validateSchema();
- } catch (JsonValidationException $e) {
- foreach ($e->getErrors() as $message) {
- if ($laxValid) {
- $publishErrors[] = $message;
- } else {
- $errors[] = $message;
- }
- }
- } catch (\Exception $e) {
- $errors[] = $e->getMessage();
- return array($errors, $publishErrors, $warnings);
- }
- if (!empty($manifest['license'])) {
- if (is_array($manifest['license'])) {
- foreach ($manifest['license'] as $key => $license) {
- if ('proprietary' === $license) {
- unset($manifest['license'][$key]);
- }
- }
- }
- $licenseValidator = new SpdxLicenseIdentifier();
- if ('proprietary' !== $manifest['license'] && array() !== $manifest['license'] && !$licenseValidator->validate($manifest['license'])) {
- $warnings[] = sprintf(
- 'License %s is not a valid SPDX license identifier, see http://www.spdx.org/licenses/ if you use an open license.'
- ."\nIf the software is closed-source, you may use \"proprietary\" as license.",
- json_encode($manifest['license'])
- );
- }
- } else {
- $warnings[] = 'No license specified, it is recommended to do so. For closed-source software you may use "proprietary" as license.';
- }
- if (isset($manifest['version'])) {
- $warnings[] = 'The version field is present, it is recommended to leave it out if the package is published on Packagist.';
- }
- if (!empty($manifest['name']) && preg_match('{[A-Z]}', $manifest['name'])) {
- $suggestName = preg_replace('{(?:([a-z])([A-Z])|([A-Z])([A-Z][a-z]))}', '\\1\\3-\\2\\4', $manifest['name']);
- $suggestName = strtolower($suggestName);
- $warnings[] = sprintf(
- 'Name "%s" does not match the best practice (e.g. lower-cased/with-dashes). We suggest using "%s" instead. As such you will not be able to submit it to Packagist.',
- $manifest['name'],
- $suggestName
- );
- }
- if (!empty($manifest['type']) && $manifest['type'] == 'composer-installer') {
- $warnings[] = "The package type 'composer-installer' is deprecated. Please distribute your custom installers as plugins from now on. See http://getcomposer.org/doc/articles/plugins.md for plugin documentation.";
- }
- if (isset($manifest['require']) && isset($manifest['require-dev'])) {
- $requireOverrides = array_intersect_key($manifest['require'], $manifest['require-dev']);
- if (!empty($requireOverrides)) {
- $plural = (count($requireOverrides) > 1) ? 'are' : 'is';
- $warnings[] = implode(', ', array_keys($requireOverrides)). " {$plural} required both in require and require-dev, this can lead to unexpected behavior";
- }
- }
- try {
- $loader = new ValidatingArrayLoader(new ArrayLoader(), true, null, $arrayLoaderValidationFlags);
- if (!isset($manifest['version'])) {
- $manifest['version'] = '1.0.0';
- }
- if (!isset($manifest['name'])) {
- $manifest['name'] = 'dummy/dummy';
- }
- $loader->load($manifest);
- } catch (InvalidPackageException $e) {
- $errors = array_merge($errors, $e->getErrors());
- }
- $warnings = array_merge($warnings, $loader->getWarnings());
- return array($errors, $publishErrors, $warnings);
- }
- }
- <?php
- namespace Composer\Util;
- class ErrorHandler
- {
- public static function handle($level, $message, $file, $line)
- {
- if (!error_reporting()) {
- return;
- }
- if (ini_get('xdebug.scream')) {
- $message .= "\n\nWarning: You have xdebug.scream enabled, the warning above may be".
- "\na legitimately suppressed error that you were not supposed to see.";
- }
- throw new \ErrorException($message, 0, $level, $file, $line);
- }
- public static function register()
- {
- set_error_handler(array(__CLASS__, 'handle'));
- }
- }
- <?php
- namespace Composer\Util;
- use RecursiveDirectoryIterator;
- use RecursiveIteratorIterator;
- use Symfony\Component\Finder\Finder;
- class Filesystem
- {
- private $processExecutor;
- public function __construct(ProcessExecutor $executor = null)
- {
- $this->processExecutor = $executor ?: new ProcessExecutor();
- }
- public function remove($file)
- {
- if (is_dir($file)) {
- return $this->removeDirectory($file);
- }
- if (file_exists($file)) {
- return $this->unlink($file);
- }
- return false;
- }
- public function isDirEmpty($dir)
- {
- $finder = Finder::create()
- ->ignoreVCS(false)
- ->ignoreDotFiles(false)
- ->depth(0)
- ->in($dir);
- return count($finder) === 0;
- }
- public function emptyDirectory($dir, $ensureDirectoryExists = true)
- {
- if (file_exists($dir) && is_link($dir)) {
- $this->unlink($dir);
- }
- if ($ensureDirectoryExists) {
- $this->ensureDirectoryExists($dir);
- }
- if (is_dir($dir)) {
- $finder = Finder::create()
- ->ignoreVCS(false)
- ->ignoreDotFiles(false)
- ->depth(0)
- ->in($dir);
- foreach ($finder as $path) {
- $this->remove((string) $path);
- }
- }
- }
- public function removeDirectory($directory)
- {
- if ($this->isSymlinkedDirectory($directory)) {
- return $this->unlinkSymlinkedDirectory($directory);
- }
- if (!file_exists($directory) || !is_dir($directory)) {
- return true;
- }
- if (preg_match('{^(?:[a-z]:)?[/\\\\]+$}i', $directory)) {
- throw new \RuntimeException('Aborting an attempted deletion of '.$directory.', this was probably not intended, if it is a real use case please report it.');
- }
- if (!function_exists('proc_open')) {
- return $this->removeDirectoryPhp($directory);
- }
- if (defined('PHP_WINDOWS_VERSION_BUILD')) {
- $cmd = sprintf('rmdir /S /Q %s', ProcessExecutor::escape(realpath($directory)));
- } else {
- $cmd = sprintf('rm -rf %s', ProcessExecutor::escape($directory));
- }
- $result = $this->getProcess()->execute($cmd, $output) === 0;
- clearstatcache();
- if ($result && !file_exists($directory)) {
- return true;
- }
- return $this->removeDirectoryPhp($directory);
- }
- public function removeDirectoryPhp($directory)
- {
- $it = new RecursiveDirectoryIterator($directory, RecursiveDirectoryIterator::SKIP_DOTS);
- $ri = new RecursiveIteratorIterator($it, RecursiveIteratorIterator::CHILD_FIRST);
- foreach ($ri as $file) {
- if ($file->isDir()) {
- $this->rmdir($file->getPathname());
- } else {
- $this->unlink($file->getPathname());
- }
- }
- return $this->rmdir($directory);
- }
- public function ensureDirectoryExists($directory)
- {
- if (!is_dir($directory)) {
- if (file_exists($directory)) {
- throw new \RuntimeException(
- $directory.' exists and is not a directory.'
- );
- }
- if (!@mkdir($directory, 0777, true)) {
- throw new \RuntimeException(
- $directory.' does not exist and could not be created.'
- );
- }
- }
- }
- public function unlink($path)
- {
- if (!@$this->unlinkImplementation($path)) {
- if (!defined('PHP_WINDOWS_VERSION_BUILD') || (usleep(350000) && !@$this->unlinkImplementation($path))) {
- $error = error_get_last();
- $message = 'Could not delete '.$path.': ' . @$error['message'];
- if (defined('PHP_WINDOWS_VERSION_BUILD')) {
- $message .= "\nThis can be due to an antivirus or the Windows Search Indexer locking the file while they are analyzed";
- }
- throw new \RuntimeException($message);
- }
- }
- return true;
- }
- public function rmdir($path)
- {
- if (!@rmdir($path)) {
- if (!defined('PHP_WINDOWS_VERSION_BUILD') || (usleep(350000) && !@rmdir($path))) {
- $error = error_get_last();
- $message = 'Could not delete '.$path.': ' . @$error['message'];
- if (defined('PHP_WINDOWS_VERSION_BUILD')) {
- $message .= "\nThis can be due to an antivirus or the Windows Search Indexer locking the file while they are analyzed";
- }
- throw new \RuntimeException($message);
- }
- }
- return true;
- }
- public function copyThenRemove($source, $target)
- {
- if (!is_dir($source)) {
- copy($source, $target);
- $this->unlink($source);
- return;
- }
- $it = new RecursiveDirectoryIterator($source, RecursiveDirectoryIterator::SKIP_DOTS);
- $ri = new RecursiveIteratorIterator($it, RecursiveIteratorIterator::SELF_FIRST);
- $this->ensureDirectoryExists($target);
- foreach ($ri as $file) {
- $targetPath = $target . DIRECTORY_SEPARATOR . $ri->getSubPathName();
- if ($file->isDir()) {
- $this->ensureDirectoryExists($targetPath);
- } else {
- copy($file->getPathname(), $targetPath);
- }
- }
- $this->removeDirectoryPhp($source);
- }
- public function rename($source, $target)
- {
- if (true === @rename($source, $target)) {
- return;
- }
- if (!function_exists('proc_open')) {
- return $this->copyThenRemove($source, $target);
- }
- if (defined('PHP_WINDOWS_VERSION_BUILD')) {
- $command = sprintf('xcopy %s %s /E /I /Q', ProcessExecutor::escape($source), ProcessExecutor::escape($target));
- $result = $this->processExecutor->execute($command, $output);
- clearstatcache();
- if (0 === $result) {
- $this->remove($source);
- return;
- }
- } else {
-
- $command = sprintf('mv %s %s', ProcessExecutor::escape($source), ProcessExecutor::escape($target));
- $result = $this->processExecutor->execute($command, $output);
- clearstatcache();
- if (0 === $result) {
- return;
- }
- }
- return $this->copyThenRemove($source, $target);
- }
- public function findShortestPath($from, $to, $directories = false)
- {
- if (!$this->isAbsolutePath($from) || !$this->isAbsolutePath($to)) {
- throw new \InvalidArgumentException(sprintf('$from (%s) and $to (%s) must be absolute paths.', $from, $to));
- }
- $from = lcfirst($this->normalizePath($from));
- $to = lcfirst($this->normalizePath($to));
- if ($directories) {
- $from .= '/dummy_file';
- }
- if (dirname($from) === dirname($to)) {
- return './'.basename($to);
- }
- $commonPath = $to;
- while (strpos($from.'/', $commonPath.'/') !== 0 && '/' !== $commonPath && !preg_match('{^[a-z]:/?$}i', $commonPath)) {
- $commonPath = strtr(dirname($commonPath), '\\', '/');
- }
- if (0 !== strpos($from, $commonPath) || '/' === $commonPath) {
- return $to;
- }
- $commonPath = rtrim($commonPath, '/') . '/';
- $sourcePathDepth = substr_count(substr($from, strlen($commonPath)), '/');
- $commonPathCode = str_repeat('../', $sourcePathDepth);
- return ($commonPathCode . substr($to, strlen($commonPath))) ?: './';
- }
- public function findShortestPathCode($from, $to, $directories = false)
- {
- if (!$this->isAbsolutePath($from) || !$this->isAbsolutePath($to)) {
- throw new \InvalidArgumentException(sprintf('$from (%s) and $to (%s) must be absolute paths.', $from, $to));
- }
- $from = lcfirst($this->normalizePath($from));
- $to = lcfirst($this->normalizePath($to));
- if ($from === $to) {
- return $directories ? '__DIR__' : '__FILE__';
- }
- $commonPath = $to;
- while (strpos($from.'/', $commonPath.'/') !== 0 && '/' !== $commonPath && !preg_match('{^[a-z]:/?$}i', $commonPath) && '.' !== $commonPath) {
- $commonPath = strtr(dirname($commonPath), '\\', '/');
- }
- if (0 !== strpos($from, $commonPath) || '/' === $commonPath || '.' === $commonPath) {
- return var_export($to, true);
- }
- $commonPath = rtrim($commonPath, '/') . '/';
- if (strpos($to, $from.'/') === 0) {
- return '__DIR__ . '.var_export(substr($to, strlen($from)), true);
- }
- $sourcePathDepth = substr_count(substr($from, strlen($commonPath)), '/') + $directories;
- $commonPathCode = str_repeat('dirname(', $sourcePathDepth).'__DIR__'.str_repeat(')', $sourcePathDepth);
- $relTarget = substr($to, strlen($commonPath));
- return $commonPathCode . (strlen($relTarget) ? '.' . var_export('/' . $relTarget, true) : '');
- }
- public function isAbsolutePath($path)
- {
- return substr($path, 0, 1) === '/' || substr($path, 1, 1) === ':';
- }
- public function size($path)
- {
- if (!file_exists($path)) {
- throw new \RuntimeException("$path does not exist.");
- }
- if (is_dir($path)) {
- return $this->directorySize($path);
- }
- return filesize($path);
- }
- public function normalizePath($path)
- {
- $parts = array();
- $path = strtr($path, '\\', '/');
- $prefix = '';
- $absolute = false;
- if (preg_match('{^([0-9a-z]+:(?://(?:[a-z]:)?)?)}i', $path, $match)) {
- $prefix = $match[1];
- $path = substr($path, strlen($prefix));
- }
- if (substr($path, 0, 1) === '/') {
- $absolute = true;
- $path = substr($path, 1);
- }
- $up = false;
- foreach (explode('/', $path) as $chunk) {
- if ('..' === $chunk && ($absolute || $up)) {
- array_pop($parts);
- $up = !(empty($parts) || '..' === end($parts));
- } elseif ('.' !== $chunk && '' !== $chunk) {
- $parts[] = $chunk;
- $up = '..' !== $chunk;
- }
- }
- return $prefix.($absolute ? '/' : '').implode('/', $parts);
- }
- public static function isLocalPath($path)
- {
- return (bool) preg_match('{^(file://|/|[a-z]:[\\\\/]|\.\.[\\\\/]|[a-z0-9_.-]+[\\\\/])}i', $path);
- }
- public static function getPlatformPath($path)
- {
- if (defined('PHP_WINDOWS_VERSION_BUILD')) {
- $path = preg_replace('{^(?:file:///([a-z])/)}i', 'file://$1:/', $path);
- }
- return preg_replace('{^file://}i', '', $path);
- }
- protected function directorySize($directory)
- {
- $it = new RecursiveDirectoryIterator($directory, RecursiveDirectoryIterator::SKIP_DOTS);
- $ri = new RecursiveIteratorIterator($it, RecursiveIteratorIterator::CHILD_FIRST);
- $size = 0;
- foreach ($ri as $file) {
- if ($file->isFile()) {
- $size += $file->getSize();
- }
- }
- return $size;
- }
- protected function getProcess()
- {
- return new ProcessExecutor;
- }
- private function unlinkImplementation($path)
- {
- if (defined('PHP_WINDOWS_VERSION_BUILD') && is_dir($path) && is_link($path)) {
- return rmdir($path);
- }
- return unlink($path);
- }
- private function isSymlinkedDirectory($directory)
- {
- if (!is_dir($directory)) {
- return false;
- }
- $resolved = $this->resolveSymlinkedDirectorySymlink($directory);
- return is_link($resolved);
- }
- private function unlinkSymlinkedDirectory($directory)
- {
- $resolved = $this->resolveSymlinkedDirectorySymlink($directory);
- return $this->unlink($resolved);
- }
- private function resolveSymlinkedDirectorySymlink($pathname)
- {
- if (!is_dir($pathname)) {
- return $pathname;
- }
- $resolved = rtrim($pathname, '/');
- if (!strlen($resolved)) {
- return $pathname;
- }
- return $resolved;
- }
- }
- <?php
- namespace Composer\Util;
- use Composer\Config;
- use Composer\IO\IOInterface;
- class Git
- {
- protected $io;
- protected $config;
- protected $process;
- protected $filesystem;
- public function __construct(IOInterface $io, Config $config, ProcessExecutor $process, Filesystem $fs)
- {
- $this->io = $io;
- $this->config = $config;
- $this->process = $process;
- $this->filesystem = $fs;
- }
- public function runCommand($commandCallable, $url, $cwd, $initialClone = false)
- {
- if ($initialClone) {
- $origCwd = $cwd;
- $cwd = null;
- }
- if (preg_match('{^ssh://[^@]+@[^:]+:[^0-9]+}', $url)) {
- throw new \InvalidArgumentException('The source URL '.$url.' is invalid, ssh URLs should have a port number after ":".'."\n".'Use ssh://git@example.com:22/path or just git@example.com:path if you do not want to provide a password or custom port.');
- }
- if (!$initialClone) {
- $this->process->execute('git remote -v', $output, $cwd);
- if (preg_match('{^(?:composer|origin)\s+https?://(.+):(.+)@([^/]+)}im', $output, $match)) {
- $this->io->setAuthentication($match[3], urldecode($match[1]), urldecode($match[2]));
- }
- }
- $protocols = $this->config->get('github-protocols');
- if (!is_array($protocols)) {
- throw new \RuntimeException('Config value "github-protocols" must be an array, got '.gettype($protocols));
- }
- if (preg_match('{^(?:https?|git)://'.self::getGitHubDomainsRegex($this->config).'/(.*)}', $url, $match)) {
- $messages = array();
- foreach ($protocols as $protocol) {
- if ('ssh' === $protocol) {
- $url = "git@" . $match[1] . ":" . $match[2];
- } else {
- $url = $protocol ."://" . $match[1] . "/" . $match[2];
- }
- if (0 === $this->process->execute(call_user_func($commandCallable, $url), $ignoredOutput, $cwd)) {
- return;
- }
- $messages[] = '- ' . $url . "\n" . preg_replace('#^#m', ' ', $this->process->getErrorOutput());
- if ($initialClone) {
- $this->filesystem->removeDirectory($origCwd);
- }
- }
- $this->throwException('Failed to clone ' . self::sanitizeUrl($url) .' via '.implode(', ', $protocols).' protocols, aborting.' . "\n\n" . implode("\n", $messages), $url);
- }
- $bypassSshForGitHub = preg_match('{^git@'.self::getGitHubDomainsRegex($this->config).':(.+?)\.git$}i', $url) && !in_array('ssh', $protocols, true);
- $bypassSshForGitLab = preg_match('{^git@'.self::getGitLabDomainsRegex($this->config).':(.+?)\.git$}i', $url) && !in_array('ssh', $protocols, true);
- $command = call_user_func($commandCallable, $url);
- if ($bypassSshForGitHub || $bypassSshForGitLab || 0 !== $this->process->execute($command, $ignoredOutput, $cwd)) {
- if (preg_match('{^git@'.self::getGitHubDomainsRegex($this->config).':(.+?)\.git$}i', $url, $match)) {
- if (!$this->io->hasAuthentication($match[1])) {
- $gitHubUtil = new GitHub($this->io, $this->config, $this->process);
- $message = 'Cloning failed using an ssh key for authentication, enter your GitHub credentials to access private repos';
- if (!$gitHubUtil->authorizeOAuth($match[1]) && $this->io->isInteractive()) {
- $gitHubUtil->authorizeOAuthInteractively($match[1], $message);
- }
- }
- if ($this->io->hasAuthentication($match[1])) {
- $auth = $this->io->getAuthentication($match[1]);
- $url = 'https://'.rawurlencode($auth['username']) . ':' . rawurlencode($auth['password']) . '@'.$match[1].'/'.$match[2].'.git';
- $command = call_user_func($commandCallable, $url);
- if (0 === $this->process->execute($command, $ignoredOutput, $cwd)) {
- return;
- }
- }
- } elseif (preg_match('{^git@'.self::getGitLabDomainsRegex($this->config).':(.+?)\.git$}i', $url, $match)) {
- if (!$this->io->hasAuthentication($match[1])) {
- $gitLabUtil = new GitLab($this->io, $this->config, $this->process);
- $message = 'Cloning failed using an ssh key for authentication, enter your GitHub credentials to access private repos';
- if (!$gitLabUtil->authorizeOAuth($match[1]) && $this->io->isInteractive()) {
- $gitLabUtil->authorizeOAuthInteractively($match[1], $message);
- }
- }
- if ($this->io->hasAuthentication($match[1])) {
- $auth = $this->io->getAuthentication($match[1]);
- $url = 'http://oauth2:' . rawurlencode($auth['username']) . '@'.$match[1].'/'.$match[2].'.git';
- $command = call_user_func($commandCallable, $url);
- if (0 === $this->process->execute($command, $ignoredOutput, $cwd)) {
- return;
- }
- }
- } elseif (
- preg_match('{(https?://)([^/]+)(.*)$}i', $url, $match) &&
- strpos($this->process->getErrorOutput(), 'fatal: Authentication failed') !== false
- ) {
- if (strpos($match[2], '@')) {
- list($authParts, $match[2]) = explode('@', $match[2], 2);
- }
- $storeAuth = false;
- if ($this->io->hasAuthentication($match[2])) {
- $auth = $this->io->getAuthentication($match[2]);
- } elseif ($this->io->isInteractive()) {
- $defaultUsername = null;
- if (isset($authParts) && $authParts) {
- if (false !== strpos($authParts, ':')) {
- list($defaultUsername,) = explode(':', $authParts, 2);
- } else {
- $defaultUsername = $authParts;
- }
- }
- $this->io->writeError(' Authentication required (<info>'.parse_url($url, PHP_URL_HOST).'</info>):');
- $auth = array(
- 'username' => $this->io->ask(' Username: ', $defaultUsername),
- 'password' => $this->io->askAndHideAnswer(' Password: '),
- );
- $storeAuth = $this->config->get('store-auths');
- }
- if ($auth) {
- $url = $match[1].rawurlencode($auth['username']).':'.rawurlencode($auth['password']).'@'.$match[2].$match[3];
- $command = call_user_func($commandCallable, $url);
- if (0 === $this->process->execute($command, $ignoredOutput, $cwd)) {
- $this->io->setAuthentication($match[2], $auth['username'], $auth['password']);
- $authHelper = new AuthHelper($this->io, $this->config);
- $authHelper->storeAuth($match[2], $storeAuth);
- return;
- }
- }
- }
- if ($initialClone) {
- $this->filesystem->removeDirectory($origCwd);
- }
- $this->throwException('Failed to execute ' . self::sanitizeUrl($command) . "\n\n" . $this->process->getErrorOutput(), $url);
- }
- }
- public static function cleanEnv()
- {
- if (ini_get('safe_mode') && false === strpos(ini_get('safe_mode_allowed_env_vars'), 'GIT_ASKPASS')) {
- throw new \RuntimeException('safe_mode is enabled and safe_mode_allowed_env_vars does not contain GIT_ASKPASS, can not set env var. You can disable safe_mode with "-dsafe_mode=0" when running composer');
- }
- if (getenv('GIT_ASKPASS') !== 'echo') {
- putenv('GIT_ASKPASS=echo');
- }
- if (getenv('GIT_DIR')) {
- putenv('GIT_DIR');
- }
- if (getenv('GIT_WORK_TREE')) {
- putenv('GIT_WORK_TREE');
- }
- putenv("DYLD_LIBRARY_PATH");
- }
- public static function getGitHubDomainsRegex(Config $config)
- {
- return '('.implode('|', array_map('preg_quote', $config->get('github-domains'))).')';
- }
- public static function getGitLabDomainsRegex(Config $config)
- {
- return '('.implode('|', array_map('preg_quote', $config->get('gitlab-domains'))).')';
- }
- public static function sanitizeUrl($message)
- {
- return preg_replace('{://([^@]+?):.+?@}', '://$1:***@', $message);
- }
- private function throwException($message, $url)
- {
- if (0 !== $this->process->execute('git --version', $ignoredOutput)) {
- throw new \RuntimeException('Failed to clone '.self::sanitizeUrl($url).', git was not found, check that it is installed and in your PATH env.' . "\n\n" . $this->process->getErrorOutput());
- }
- throw new \RuntimeException($message);
- }
- }
- <?php
- namespace Composer\Util;
- use Composer\IO\IOInterface;
- use Composer\Config;
- use Composer\Downloader\TransportException;
- use Composer\Json\JsonFile;
- class GitHub
- {
- protected $io;
- protected $config;
- protected $process;
- protected $remoteFilesystem;
- public function __construct(IOInterface $io, Config $config, ProcessExecutor $process = null, RemoteFilesystem $remoteFilesystem = null)
- {
- $this->io = $io;
- $this->config = $config;
- $this->process = $process ?: new ProcessExecutor;
- $this->remoteFilesystem = $remoteFilesystem ?: new RemoteFilesystem($io, $config);
- }
- public function authorizeOAuth($originUrl)
- {
- if (!in_array($originUrl, $this->config->get('github-domains'))) {
- return false;
- }
- if (0 === $this->process->execute('git config github.accesstoken', $output)) {
- $this->io->setAuthentication($originUrl, trim($output), 'x-oauth-basic');
- return true;
- }
- return false;
- }
- public function authorizeOAuthInteractively($originUrl, $message = null)
- {
- if ($message) {
- $this->io->writeError($message);
- }
- $this->io->writeError(sprintf('A token will be created and stored in "%s", your password will never be stored', $this->config->getAuthConfigSource()->getName()));
- $this->io->writeError('To revoke access to this token you can visit https://github.com/settings/applications');
- $otp = null;
- $attemptCounter = 0;
- while ($attemptCounter++ < 5) {
- try {
- $response = $this->createToken($originUrl, $otp);
- } catch (TransportException $e) {
-
-
- if (in_array($e->getCode(), array(403, 401))) {
- if (401 === $e->getCode() && $this->io->hasAuthentication($originUrl)) {
- $otp = $this->checkTwoFactorAuthentication($e->getHeaders());
- if (null !== $otp) {
- continue;
- }
- }
- if (401 === $e->getCode()) {
- $this->io->writeError('Bad credentials.');
- } else {
- $this->io->writeError('Maximum number of login attempts exceeded. Please try again later.');
- }
- $this->io->writeError('You can also manually create a personal token at https://github.com/settings/applications');
- $this->io->writeError('Add it using "composer config github-oauth.github.com <token>"');
- continue;
- }
- throw $e;
- }
- $this->io->setAuthentication($originUrl, $response['token'], 'x-oauth-basic');
- $this->config->getConfigSource()->removeConfigSetting('github-oauth.'.$originUrl);
- $this->config->getAuthConfigSource()->addConfigSetting('github-oauth.'.$originUrl, $response['token']);
- return true;
- }
- throw new \RuntimeException("Invalid GitHub credentials 5 times in a row, aborting.");
- }
- private function createToken($originUrl, $otp = null)
- {
- if (null === $otp || !$this->io->hasAuthentication($originUrl)) {
- $username = $this->io->ask('Username: ');
- $password = $this->io->askAndHideAnswer('Password: ');
- $this->io->setAuthentication($originUrl, $username, $password);
- }
- $headers = array('Content-Type: application/json');
- if ($otp) {
- $headers[] = 'X-GitHub-OTP: ' . $otp;
- }
- $note = 'Composer';
- if ($this->config->get('github-expose-hostname') === true && 0 === $this->process->execute('hostname', $output)) {
- $note .= ' on ' . trim($output);
- }
- $note .= ' [' . date('YmdHis') . ']';
- $apiUrl = ('github.com' === $originUrl) ? 'api.github.com' : $originUrl . '/api/v3';
- $json = $this->remoteFilesystem->getContents($originUrl, 'https://'. $apiUrl . '/authorizations', false, array(
- 'retry-auth-failure' => false,
- 'http' => array(
- 'method' => 'POST',
- 'follow_location' => false,
- 'header' => $headers,
- 'content' => json_encode(array(
- 'scopes' => array('repo'),
- 'note' => $note,
- 'note_url' => 'https://getcomposer.org/',
- )),
- )
- ));
- $this->io->writeError('Token successfully created');
- return JsonFile::parseJson($json);
- }
- private function checkTwoFactorAuthentication(array $headers)
- {
- $headerNames = array_map(
- function ($header) {
- return strtolower(strstr($header, ':', true));
- },
- $headers
- );
- if (false !== ($key = array_search('x-github-otp', $headerNames))) {
- list($required, $method) = array_map('trim', explode(';', substr(strstr($headers[$key], ':'), 1)));
- if ('required' === $required) {
- $this->io->writeError('Two-factor Authentication');
- if ('app' === $method) {
- $this->io->writeError('Open the two-factor authentication app on your device to view your authentication code and verify your identity.');
- }
- if ('sms' === $method) {
- $this->io->writeError('You have been sent an SMS message with an authentication code to verify your identity.');
- }
- return $this->io->ask('Authentication Code: ');
- }
- }
- return null;
- }
- }
- <?php
- namespace Composer\Util;
- use Composer\IO\IOInterface;
- use Composer\Config;
- use Composer\Downloader\TransportException;
- use Composer\Json\JsonFile;
- class GitLab
- {
- protected $io;
- protected $config;
- protected $process;
- protected $remoteFilesystem;
- public function __construct(IOInterface $io, Config $config, ProcessExecutor $process = null, RemoteFilesystem $remoteFilesystem = null)
- {
- $this->io = $io;
- $this->config = $config;
- $this->process = $process ?: new ProcessExecutor;
- $this->remoteFilesystem = $remoteFilesystem ?: new RemoteFilesystem($io, $config);
- }
- public function authorizeOAuth($originUrl)
- {
- if (!in_array($originUrl, $this->config->get('gitlab-domains'))) {
- return false;
- }
- if (0 === $this->process->execute('git config gitlab.accesstoken', $output)) {
- $this->io->setAuthentication($originUrl, trim($output), 'oauth2');
- return true;
- }
- return false;
- }
- public function authorizeOAuthInteractively($originUrl, $message = null)
- {
- if ($message) {
- $this->io->writeError($message);
- }
- $this->io->writeError(sprintf('A token will be created and stored in "%s", your password will never be stored', $this->config->getAuthConfigSource()->getName()));
- $this->io->writeError('To revoke access to this token you can visit ' . $this->config->get('gitlab-domains')[0] . '/profile/applications');
- $otp = null;
- $attemptCounter = 0;
- while ($attemptCounter++ < 5) {
- try {
- $response = $this->createToken($originUrl, $otp);
- } catch (TransportException $e) {
-
-
- if (in_array($e->getCode(), array(403, 401))) {
- if (401 === $e->getCode() && $this->io->hasAuthentication($originUrl)) {
- $otp = $this->checkTwoFactorAuthentication($e->getHeaders());
- if (null !== $otp) {
- continue;
- }
- }
- if (401 === $e->getCode()) {
- $this->io->writeError('Bad credentials.');
- } else {
- $this->io->writeError('Maximum number of login attempts exceeded. Please try again later.');
- }
- $this->io->writeError('You can also manually create a personal token at ' . $this->config->get('gitlab-domains')[0] . '/profile/applications');
- $this->io->writeError('Add it using "composer config gitlab-oauth.' . $this->config->get('gitlab-domains')[0] . ' <token>"');
- continue;
- }
- throw $e;
- }
- $this->io->setAuthentication($originUrl, $response['access_token'], 'oauth2');
- $this->config->getConfigSource()->removeConfigSetting('gitlab-oauth.'.$originUrl);
- $this->config->getAuthConfigSource()->addConfigSetting('gitlab-oauth.'.$originUrl, $response['access_token']);
- return true;
- }
- throw new \RuntimeException("Invalid GitLab credentials 5 times in a row, aborting.");
- }
- private function createToken($originUrl, $otp = null)
- {
- if (null === $otp || !$this->io->hasAuthentication($originUrl)) {
- $username = $this->io->ask('Username: ');
- $password = $this->io->askAndHideAnswer('Password: ');
- $this->io->setAuthentication($originUrl, $username, $password);
- }
- $headers = array('Content-Type: application/x-www-form-urlencoded');
- if ($otp) {
- $headers[] = 'X-GitLab-OTP: ' . $otp;
- }
- $note = 'Composer';
- if ($this->config->get('GitLab-expose-hostname') === true && 0 === $this->process->execute('hostname', $output)) {
- $note .= ' on ' . trim($output);
- }
- $note .= ' [' . date('YmdHis') . ']';
- $apiUrl = $originUrl ;
- $data = http_build_query(
- array(
- 'username' => $username,
- 'password' => $password,
- 'grant_type' => 'password',
- )
- );
- $options = array(
- 'retry-auth-failure' => false,
- 'http' => array(
- 'method' => 'POST',
- 'header' => $headers,
- 'content' => $data
- ));
- $json = $this->remoteFilesystem->getContents($originUrl, 'http://'. $apiUrl . '/oauth/token', false, $options);
- $this->io->writeError('Token successfully created');
- return JsonFile::parseJson($json);
- }
- private function checkTwoFactorAuthentication(array $headers)
- {
- $headerNames = array_map(
- function ($header) {
- return strtolower(strstr($header, ':', true));
- },
- $headers
- );
- if (false !== ($key = array_search('x-GitLab-otp', $headerNames))) {
- list($required, $method) = array_map('trim', explode(';', substr(strstr($headers[$key], ':'), 1)));
- if ('required' === $required) {
- $this->io->writeError('Two-factor Authentication');
- if ('app' === $method) {
- $this->io->writeError('Open the two-factor authentication app on your device to view your authentication code and verify your identity.');
- }
- if ('sms' === $method) {
- $this->io->writeError('You have been sent an SMS message with an authentication code to verify your identity.');
- }
- return $this->io->ask('Authentication Code: ');
- }
- }
- return null;
- }
- }
- <?php
- namespace Composer\Util;
- class NoProxyPattern
- {
- protected $rules = array();
- public function __construct($pattern)
- {
- $this->rules = preg_split("/[\s,]+/", $pattern);
- }
- public function test($url)
- {
- $host = parse_url($url, PHP_URL_HOST);
- $port = parse_url($url, PHP_URL_PORT);
- if (empty($port)) {
- switch (parse_url($url, PHP_URL_SCHEME)) {
- case 'http':
- $port = 80;
- break;
- case 'https':
- $port = 443;
- break;
- }
- }
- foreach ($this->rules as $rule) {
- if ($rule == '*') {
- return true;
- }
- $match = false;
- list($ruleHost) = explode(':', $rule);
- list($base) = explode('/', $ruleHost);
- if (filter_var($base, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) {
- if (!isset($ip)) {
- $ip = gethostbyname($host);
- }
- if (strpos($ruleHost, '/') === false) {
- $match = $ip === $ruleHost;
- } else {
-
- if ($ip === $host) {
- $match = false;
- } else {
- $match = self::inCIDRBlock($ruleHost, $ip);
- }
- }
- } else {
- $haystack = '.' . trim($host, '.') . '.';
- $needle = '.'. trim($ruleHost, '.') .'.';
- $match = stripos(strrev($haystack), strrev($needle)) === 0;
- }
- if ($match && strpos($rule, ':') !== false) {
- list(, $rulePort) = explode(':', $rule);
- if (!empty($rulePort) && $port != $rulePort) {
- $match = false;
- }
- }
- if ($match) {
- return true;
- }
- }
- return false;
- }
- private static function inCIDRBlock($cidr, $ip)
- {
- list($base, $bits) = explode('/', $cidr);
- list($a, $b, $c, $d) = explode('.', $base);
- $i = ($a << 24) + ($b << 16) + ($c << 8) + $d;
- $mask = $bits == 0 ? 0 : (~0 << (32 - $bits));
- $low = $i & $mask;
- $high = $i | (~$mask & 0xFFFFFFFF);
- list($a, $b, $c, $d) = explode('.', $ip);
- $check = ($a << 24) + ($b << 16) + ($c << 8) + $d;
-
- return $check >= $low && $check <= $high;
- }
- }
- <?php
- namespace Composer\Util;
- use Composer\IO\IOInterface;
- use Symfony\Component\Process\Process;
- class Perforce
- {
- protected $path;
- protected $p4Depot;
- protected $p4Client;
- protected $p4User;
- protected $p4Password;
- protected $p4Port;
- protected $p4Stream;
- protected $p4ClientSpec;
- protected $p4DepotType;
- protected $p4Branch;
- protected $process;
- protected $uniquePerforceClientName;
- protected $windowsFlag;
- protected $commandResult;
- protected $io;
- protected $filesystem;
- public function __construct($repoConfig, $port, $path, ProcessExecutor $process, $isWindows, IOInterface $io)
- {
- $this->windowsFlag = $isWindows;
- $this->p4Port = $port;
- $this->initializePath($path);
- $this->process = $process;
- $this->initialize($repoConfig);
- $this->io = $io;
- }
- public static function create($repoConfig, $port, $path, ProcessExecutor $process, IOInterface $io)
- {
- $isWindows = defined('PHP_WINDOWS_VERSION_BUILD');
- $perforce = new Perforce($repoConfig, $port, $path, $process, $isWindows, $io);
- return $perforce;
- }
- public static function checkServerExists($url, ProcessExecutor $processExecutor)
- {
- $output = null;
- return 0 === $processExecutor->execute('p4 -p ' . $url . ' info -s', $output);
- }
- public function initialize($repoConfig)
- {
- $this->uniquePerforceClientName = $this->generateUniquePerforceClientName();
- if (null == $repoConfig) {
- return;
- }
- if (isset($repoConfig['unique_perforce_client_name'])) {
- $this->uniquePerforceClientName = $repoConfig['unique_perforce_client_name'];
- }
- if (isset($repoConfig['depot'])) {
- $this->p4Depot = $repoConfig['depot'];
- }
- if (isset($repoConfig['branch'])) {
- $this->p4Branch = $repoConfig['branch'];
- }
- if (isset($repoConfig['p4user'])) {
- $this->p4User = $repoConfig['p4user'];
- } else {
- $this->p4User = $this->getP4variable('P4USER');
- }
- if (isset($repoConfig['p4password'])) {
- $this->p4Password = $repoConfig['p4password'];
- }
- }
- public function initializeDepotAndBranch($depot, $branch)
- {
- if (isset($depot)) {
- $this->p4Depot = $depot;
- }
- if (isset($branch)) {
- $this->p4Branch = $branch;
- }
- }
- public function generateUniquePerforceClientName()
- {
- return gethostname() . "_" . time();
- }
- public function cleanupClientSpec()
- {
- $client = $this->getClient();
- $task = 'client -d ' . $client;
- $useP4Client = false;
- $command = $this->generateP4Command($task, $useP4Client);
- $this->executeCommand($command);
- $clientSpec = $this->getP4ClientSpec();
- $fileSystem = $this->getFilesystem();
- $fileSystem->remove($clientSpec);
- }
- protected function executeCommand($command)
- {
- $this->commandResult = "";
- $exit_code = $this->process->execute($command, $this->commandResult);
- return $exit_code;
- }
- public function getClient()
- {
- if (!isset($this->p4Client)) {
- $cleanStreamName = str_replace('@', '', str_replace('/', '_', str_replace('//', '', $this->getStream())));
- $this->p4Client = 'composer_perforce_' . $this->uniquePerforceClientName . '_' . $cleanStreamName;
- }
- return $this->p4Client;
- }
- protected function getPath()
- {
- return $this->path;
- }
- public function initializePath($path)
- {
- $this->path = $path;
- $fs = $this->getFilesystem();
- $fs->ensureDirectoryExists($path);
- }
- protected function getPort()
- {
- return $this->p4Port;
- }
- public function setStream($stream)
- {
- $this->p4Stream = $stream;
- $index = strrpos($stream, '/');
- if ($index > 2) {
- $this->p4DepotType = 'stream';
- }
- }
- public function isStream()
- {
- return (strcmp($this->p4DepotType, 'stream') === 0);
- }
- public function getStream()
- {
- if (!isset($this->p4Stream)) {
- if ($this->isStream()) {
- $this->p4Stream = '//' . $this->p4Depot . '/' . $this->p4Branch;
- } else {
- $this->p4Stream = '//' . $this->p4Depot;
- }
- }
- return $this->p4Stream;
- }
- public function getStreamWithoutLabel($stream)
- {
- $index = strpos($stream, '@');
- if ($index === false) {
- return $stream;
- }
- return substr($stream, 0, $index);
- }
- public function getP4ClientSpec()
- {
- $p4clientSpec = $this->path . '/' . $this->getClient() . '.p4.spec';
- return $p4clientSpec;
- }
- public function getUser()
- {
- return $this->p4User;
- }
- public function setUser($user)
- {
- $this->p4User = $user;
- }
- public function queryP4User()
- {
- $this->getUser();
- if (strlen($this->p4User) > 0) {
- return;
- }
- $this->p4User = $this->getP4variable('P4USER');
- if (strlen($this->p4User) > 0) {
- return;
- }
- $this->p4User = $this->io->ask('Enter P4 User:');
- if ($this->windowsFlag) {
- $command = 'p4 set P4USER=' . $this->p4User;
- } else {
- $command = 'export P4USER=' . $this->p4User;
- }
- $this->executeCommand($command);
- }
- protected function getP4variable($name)
- {
- if ($this->windowsFlag) {
- $command = 'p4 set';
- $this->executeCommand($command);
- $result = trim($this->commandResult);
- $resArray = explode(PHP_EOL, $result);
- foreach ($resArray as $line) {
- $fields = explode('=', $line);
- if (strcmp($name, $fields[0]) == 0) {
- $index = strpos($fields[1], ' ');
- if ($index === false) {
- $value = $fields[1];
- } else {
- $value = substr($fields[1], 0, $index);
- }
- $value = trim($value);
- return $value;
- }
- }
- } else {
- $command = 'echo $' . $name;
- $this->executeCommand($command);
- $result = trim($this->commandResult);
- return $result;
- }
- }
- public function queryP4Password()
- {
- if (isset($this->p4Password)) {
- return $this->p4Password;
- }
- $password = $this->getP4variable('P4PASSWD');
- if (strlen($password) <= 0) {
- $password = $this->io->askAndHideAnswer('Enter password for Perforce user ' . $this->getUser() . ': ');
- }
- $this->p4Password = $password;
- return $password;
- }
- public function generateP4Command($command, $useClient = true)
- {
- $p4Command = 'p4 ';
- $p4Command = $p4Command . '-u ' . $this->getUser() . ' ';
- if ($useClient) {
- $p4Command = $p4Command . '-c ' . $this->getClient() . ' ';
- }
- $p4Command = $p4Command . '-p ' . $this->getPort() . ' ';
- $p4Command = $p4Command . $command;
- return $p4Command;
- }
- public function isLoggedIn()
- {
- $command = $this->generateP4Command('login -s', false);
- $exitCode = $this->executeCommand($command);
- if ($exitCode) {
- $errorOutput = $this->process->getErrorOutput();
- $index = strpos($errorOutput, $this->getUser());
- if ($index === false) {
- $index = strpos($errorOutput, 'p4');
- if ($index === false) {
- return false;
- }
- throw new \Exception('p4 command not found in path: ' . $errorOutput);
- }
- throw new \Exception('Invalid user name: ' . $this->getUser() );
- }
- return true;
- }
- public function connectClient()
- {
- $p4CreateClientCommand = $this->generateP4Command('client -i < ' . str_replace( " ", "\\ ", $this->getP4ClientSpec() ));
- $this->executeCommand($p4CreateClientCommand);
- }
- public function syncCodeBase($sourceReference)
- {
- $prevDir = getcwd();
- chdir($this->path);
- $p4SyncCommand = $this->generateP4Command('sync -f ');
- if (null != $sourceReference) {
- $p4SyncCommand = $p4SyncCommand . '@' . $sourceReference;
- }
- $this->executeCommand($p4SyncCommand);
- chdir($prevDir);
- }
- public function writeClientSpecToFile($spec)
- {
- fwrite($spec, 'Client: ' . $this->getClient() . PHP_EOL . PHP_EOL);
- fwrite($spec, 'Update: ' . date('Y/m/d H:i:s') . PHP_EOL . PHP_EOL);
- fwrite($spec, 'Access: ' . date('Y/m/d H:i:s') . PHP_EOL);
- fwrite($spec, 'Owner: ' . $this->getUser() . PHP_EOL . PHP_EOL);
- fwrite($spec, 'Description:' . PHP_EOL);
- fwrite($spec, ' Created by ' . $this->getUser() . ' from composer.' . PHP_EOL . PHP_EOL);
- fwrite($spec, 'Root: ' . $this->getPath() . PHP_EOL . PHP_EOL);
- fwrite($spec, 'Options: noallwrite noclobber nocompress unlocked modtime rmdir' . PHP_EOL . PHP_EOL);
- fwrite($spec, 'SubmitOptions: revertunchanged' . PHP_EOL . PHP_EOL);
- fwrite($spec, 'LineEnd: local' . PHP_EOL . PHP_EOL);
- if ($this->isStream()) {
- fwrite($spec, 'Stream:' . PHP_EOL);
- fwrite($spec, ' ' . $this->getStreamWithoutLabel($this->p4Stream) . PHP_EOL);
- } else {
- fwrite(
- $spec,
- 'View: ' . $this->getStream() . '/... //' . $this->getClient() . '/... ' . PHP_EOL
- );
- }
- }
- public function writeP4ClientSpec()
- {
- $clientSpec = $this->getP4ClientSpec();
- $spec = fopen($clientSpec, 'w');
- try {
- $this->writeClientSpecToFile($spec);
- } catch (\Exception $e) {
- fclose($spec);
- throw $e;
- }
- fclose($spec);
- }
- protected function read($pipe, $name)
- {
- if (feof($pipe)) {
- return;
- }
- $line = fgets($pipe);
- while ($line != false) {
- $line = fgets($pipe);
- }
- return;
- }
- public function windowsLogin($password)
- {
- $command = $this->generateP4Command(' login -a');
- $process = new Process($command, null, null, $password);
- return $process->run();
- }
- public function p4Login()
- {
- $this->queryP4User();
- if (!$this->isLoggedIn()) {
- $password = $this->queryP4Password();
- if ($this->windowsFlag) {
- $this->windowsLogin($password);
- } else {
- $command = 'echo ' . $password . ' | ' . $this->generateP4Command(' login -a', false);
- $exitCode = $this->executeCommand($command);
- $result = trim($this->commandResult);
- if ($exitCode) {
- throw new \Exception("Error logging in:" . $this->process->getErrorOutput());
- }
- }
- }
- }
- public function getComposerInformation($identifier)
- {
- $index = strpos($identifier, '@');
- if ($index === false) {
- $composerJson = $identifier. '/composer.json';
- return $this->getComposerInformationFromPath($composerJson);
- }
- return $this->getComposerInformationFromLabel($identifier, $index);
- }
- public function getComposerInformationFromPath($composerJson)
- {
- $command = $this->generateP4Command(' print ' . $composerJson);
- $this->executeCommand($command);
- $result = $this->commandResult;
- $index = strpos($result, '{');
- if ($index === false) {
- return '';
- }
- if ($index >= 0) {
- $rawData = substr($result, $index);
- $composer_info = json_decode($rawData, true);
- return $composer_info;
- }
- return '';
- }
- public function getComposerInformationFromLabel($identifier, $index)
- {
- $composerJsonPath = substr($identifier, 0, $index) . '/composer.json' . substr($identifier, $index);
- $command = $this->generateP4Command(' files ' . $composerJsonPath, false);
- $this->executeCommand($command);
- $result = $this->commandResult;
- $index2 = strpos($result, 'no such file(s).');
- if ($index2 === false) {
- $index3 = strpos($result, 'change');
- if (!($index3 === false)) {
- $phrase = trim(substr($result, $index3));
- $fields = explode(' ', $phrase);
- $id = $fields[1];
- $composerJson = substr($identifier, 0, $index) . '/composer.json@' . $id;
- return $this->getComposerInformationFromPath($composerJson);
- }
- }
- return "";
- }
- public function getBranches()
- {
- $possibleBranches = array();
- if (!$this->isStream()) {
- $possibleBranches[$this->p4Branch] = $this->getStream();
- } else {
- $command = $this->generateP4Command('streams //' . $this->p4Depot . '/...');
- $this->executeCommand($command);
- $result = $this->commandResult;
- $resArray = explode(PHP_EOL, $result);
- foreach ($resArray as $line) {
- $resBits = explode(' ', $line);
- if (count($resBits) > 4) {
- $branch = preg_replace('/[^A-Za-z0-9 ]/', '', $resBits[4]);
- $possibleBranches[$branch] = $resBits[1];
- }
- }
- }
- $command = $this->generateP4Command('changes '. $this->getStream() . '/...', false);
- $this->executeCommand($command);
- $result = $this->commandResult;
- $resArray = explode(PHP_EOL, $result);
- $lastCommit = $resArray[0];
- $lastCommitArr = explode(' ', $lastCommit);
- $lastCommitNum = $lastCommitArr[1];
- $branches = array('master' => $possibleBranches[$this->p4Branch] . '@'. $lastCommitNum);
- return $branches;
- }
- public function getTags()
- {
- $command = $this->generateP4Command('labels');
- $this->executeCommand($command);
- $result = $this->commandResult;
- $resArray = explode(PHP_EOL, $result);
- $tags = array();
- foreach ($resArray as $line) {
- $index = strpos($line, 'Label');
- if (!($index === false)) {
- $fields = explode(' ', $line);
- $tags[$fields[1]] = $this->getStream() . '@' . $fields[1];
- }
- }
- return $tags;
- }
- public function checkStream()
- {
- $command = $this->generateP4Command('depots', false);
- $this->executeCommand($command);
- $result = $this->commandResult;
- $resArray = explode(PHP_EOL, $result);
- foreach ($resArray as $line) {
- $index = strpos($line, 'Depot');
- if (!($index === false)) {
- $fields = explode(' ', $line);
- if (strcmp($this->p4Depot, $fields[1]) === 0) {
- $this->p4DepotType = $fields[3];
- return $this->isStream();
- }
- }
- }
- return false;
- }
- protected function getChangeList($reference)
- {
- $index = strpos($reference, '@');
- if ($index === false) {
- return;
- }
- $label = substr($reference, $index);
- $command = $this->generateP4Command(' changes -m1 ' . $label);
- $this->executeCommand($command);
- $changes = $this->commandResult;
- if (strpos($changes, 'Change') !== 0) {
- return;
- }
- $fields = explode(' ', $changes);
- $changeList = $fields[1];
- return $changeList;
- }
- public function getCommitLogs($fromReference, $toReference)
- {
- $fromChangeList = $this->getChangeList($fromReference);
- if ($fromChangeList == null) {
- return;
- }
- $toChangeList = $this->getChangeList($toReference);
- if ($toChangeList == null) {
- return;
- }
- $index = strpos($fromReference, '@');
- $main = substr($fromReference, 0, $index) . '/...';
- $command = $this->generateP4Command('filelog ' . $main . '@' . $fromChangeList. ',' . $toChangeList);
- $this->executeCommand($command);
- $result = $this->commandResult;
- return $result;
- }
- public function getFilesystem()
- {
- if (empty($this->filesystem)) {
- $this->filesystem = new Filesystem($this->process);
- }
- return $this->filesystem;
- }
- public function setFilesystem(Filesystem $fs)
- {
- $this->filesystem = $fs;
- }
- }
- <?php
- namespace Composer\Util;
- use Symfony\Component\Process\Process;
- use Symfony\Component\Process\ProcessUtils;
- use Composer\IO\IOInterface;
- class ProcessExecutor
- {
- protected static $timeout = 300;
- protected $captureOutput;
- protected $errorOutput;
- protected $io;
- public function __construct(IOInterface $io = null)
- {
- $this->io = $io;
- }
- public function execute($command, &$output = null, $cwd = null)
- {
- if ($this->io && $this->io->isDebug()) {
- $safeCommand = preg_replace('{(://[^:/\s]+:)[^@\s/]+}i', '$1****', $command);
- $this->io->writeError('Executing command ('.($cwd ?: 'CWD').'): '.$safeCommand);
- }
-
- if (null === $cwd && defined('PHP_WINDOWS_VERSION_BUILD') && false !== strpos($command, 'git') && getcwd()) {
- $cwd = realpath(getcwd());
- }
- $this->captureOutput = count(func_get_args()) > 1;
- $this->errorOutput = null;
- $process = new Process($command, $cwd, null, null, static::getTimeout());
- $callback = is_callable($output) ? $output : array($this, 'outputHandler');
- $process->run($callback);
- if ($this->captureOutput && !is_callable($output)) {
- $output = $process->getOutput();
- }
- $this->errorOutput = $process->getErrorOutput();
- return $process->getExitCode();
- }
- public function splitLines($output)
- {
- $output = trim($output);
- return ((string) $output === '') ? array() : preg_split('{\r?\n}', $output);
- }
- public function getErrorOutput()
- {
- return $this->errorOutput;
- }
- public function outputHandler($type, $buffer)
- {
- if ($this->captureOutput) {
- return;
- }
- echo $buffer;
- }
- public static function getTimeout()
- {
- return static::$timeout;
- }
- public static function setTimeout($timeout)
- {
- static::$timeout = $timeout;
- }
- public static function escape($argument)
- {
- return ProcessUtils::escapeArgument($argument);
- }
- }
- <?php
- namespace Composer\Util;
- use Composer\Composer;
- use Composer\Config;
- use Composer\IO\IOInterface;
- use Composer\Downloader\TransportException;
- class RemoteFilesystem
- {
- private $io;
- private $config;
- private $bytesMax;
- private $originUrl;
- private $fileUrl;
- private $fileName;
- private $retry;
- private $progress;
- private $lastProgress;
- private $options;
- private $retryAuthFailure;
- private $lastHeaders;
- private $storeAuth;
- public function __construct(IOInterface $io, Config $config = null, array $options = array())
- {
- $this->io = $io;
- $this->config = $config;
- $this->options = $options;
- }
- public function copy($originUrl, $fileUrl, $fileName, $progress = true, $options = array())
- {
- return $this->get($originUrl, $fileUrl, $options, $fileName, $progress);
- }
- public function getContents($originUrl, $fileUrl, $progress = true, $options = array())
- {
- return $this->get($originUrl, $fileUrl, $options, null, $progress);
- }
- public function getOptions()
- {
- return $this->options;
- }
- public function getLastHeaders()
- {
- return $this->lastHeaders;
- }
- protected function get($originUrl, $fileUrl, $additionalOptions = array(), $fileName = null, $progress = true)
- {
- if (strpos($originUrl, '.github.com') === (strlen($originUrl) - 11)) {
- $originUrl = 'github.com';
- }
- $this->bytesMax = 0;
- $this->originUrl = $originUrl;
- $this->fileUrl = $fileUrl;
- $this->fileName = $fileName;
- $this->progress = $progress;
- $this->lastProgress = null;
- $this->retryAuthFailure = true;
- $this->lastHeaders = array();
- if (preg_match('{^https?://(.+):(.+)@([^/]+)}i', $fileUrl, $match)) {
- $this->io->setAuthentication($originUrl, urldecode($match[1]), urldecode($match[2]));
- }
- if (isset($additionalOptions['retry-auth-failure'])) {
- $this->retryAuthFailure = (bool) $additionalOptions['retry-auth-failure'];
- unset($additionalOptions['retry-auth-failure']);
- }
- $options = $this->getOptionsForUrl($originUrl, $additionalOptions);
- if (isset($options['retry-auth-failure'])) {
- $this->retryAuthFailure = (bool) $options['retry-auth-failure'];
- unset($options['retry-auth-failure']);
- }
- if ($this->io->isDebug()) {
- $this->io->writeError((substr($fileUrl, 0, 4) === 'http' ? 'Downloading ' : 'Reading ') . $fileUrl);
- }
- if (isset($options['github-token'])) {
- $fileUrl .= (false === strpos($fileUrl, '?') ? '?' : '&') . 'access_token='.$options['github-token'];
- unset($options['github-token']);
- }
- if (isset($options['gitlab-token'])) {
- $fileUrl .= (false === strpos($fileUrl, '?') ? '?' : '&') . 'access_token='.$options['gitlab-token'];
- unset($options['gitlab-token']);
- }
- if (isset($options['http'])) {
- $options['http']['ignore_errors'] = true;
- }
- $ctx = StreamContextFactory::getContext($fileUrl, $options, array('notification' => array($this, 'callbackGet')));
- if ($this->progress) {
- $this->io->writeError(" Downloading: <comment>connection...</comment>", false);
- }
- $errorMessage = '';
- $errorCode = 0;
- $result = false;
- set_error_handler(function ($code, $msg) use (&$errorMessage) {
- if ($errorMessage) {
- $errorMessage .= "\n";
- }
- $errorMessage .= preg_replace('{^file_get_contents\(.*?\): }', '', $msg);
- });
- try {
- $result = file_get_contents($fileUrl, false, $ctx);
- } catch (\Exception $e) {
- if ($e instanceof TransportException && !empty($http_response_header[0])) {
- $e->setHeaders($http_response_header);
- }
- if ($e instanceof TransportException && $result !== false) {
- $e->setResponse($result);
- }
- $result = false;
- }
- if ($errorMessage && !ini_get('allow_url_fopen')) {
- $errorMessage = 'allow_url_fopen must be enabled in php.ini ('.$errorMessage.')';
- }
- restore_error_handler();
- if (isset($e) && !$this->retry) {
- throw $e;
- }
- if (!empty($http_response_header[0]) && preg_match('{^HTTP/\S+ ([45]\d\d)}i', $http_response_header[0], $match)) {
- $errorCode = $match[1];
- if (!$this->retry) {
- $e = new TransportException('The "'.$this->fileUrl.'" file could not be downloaded ('.$http_response_header[0].')', $errorCode);
- $e->setHeaders($http_response_header);
- $e->setResponse($result);
- throw $e;
- }
- $result = false;
- }
- if ($result && extension_loaded('zlib') && substr($fileUrl, 0, 4) === 'http') {
- $decode = false;
- foreach ($http_response_header as $header) {
- if (preg_match('{^content-encoding: *gzip *$}i', $header)) {
- $decode = true;
- continue;
- } elseif (preg_match('{^HTTP/}i', $header)) {
- $decode = false;
- }
- }
- if ($decode) {
- if (version_compare(PHP_VERSION, '5.4.0', '>=')) {
- $result = zlib_decode($result);
- } else {
- $result = file_get_contents('compress.zlib://data:application/octet-stream;base64,'.base64_encode($result));
- }
- if (!$result) {
- throw new TransportException('Failed to decode zlib stream');
- }
- }
- }
- if ($this->progress && !$this->retry) {
- $this->io->overwriteError(" Downloading: <comment>100%</comment>");
- }
- if (false !== $result && null !== $fileName) {
- if ('' === $result) {
- throw new TransportException('"'.$this->fileUrl.'" appears broken, and returned an empty 200 response');
- }
- $errorMessage = '';
- set_error_handler(function ($code, $msg) use (&$errorMessage) {
- if ($errorMessage) {
- $errorMessage .= "\n";
- }
- $errorMessage .= preg_replace('{^file_put_contents\(.*?\): }', '', $msg);
- });
- $result = (bool) file_put_contents($fileName, $result);
- restore_error_handler();
- if (false === $result) {
- throw new TransportException('The "'.$this->fileUrl.'" file could not be written to '.$fileName.': '.$errorMessage);
- }
- }
- if ($this->retry) {
- $this->retry = false;
- $result = $this->get($this->originUrl, $this->fileUrl, $additionalOptions, $this->fileName, $this->progress);
- $authHelper = new AuthHelper($this->io, $this->config);
- $authHelper->storeAuth($this->originUrl, $this->storeAuth);
- $this->storeAuth = false;
- return $result;
- }
- if (false === $result) {
- $e = new TransportException('The "'.$this->fileUrl.'" file could not be downloaded: '.$errorMessage, $errorCode);
- if (!empty($http_response_header[0])) {
- $e->setHeaders($http_response_header);
- }
- throw $e;
- }
- if (!empty($http_response_header[0])) {
- $this->lastHeaders = $http_response_header;
- }
- return $result;
- }
- protected function callbackGet($notificationCode, $severity, $message, $messageCode, $bytesTransferred, $bytesMax)
- {
- switch ($notificationCode) {
- case STREAM_NOTIFY_FAILURE:
- case STREAM_NOTIFY_AUTH_REQUIRED:
- if (401 === $messageCode) {
- if (!$this->retryAuthFailure) {
- break;
- }
- $this->promptAuthAndRetry($messageCode);
- break;
- }
- break;
- case STREAM_NOTIFY_AUTH_RESULT:
- if (403 === $messageCode) {
- $this->promptAuthAndRetry($messageCode, $message);
- break;
- }
- break;
- case STREAM_NOTIFY_FILE_SIZE_IS:
- if ($this->bytesMax < $bytesMax) {
- $this->bytesMax = $bytesMax;
- }
- break;
- case STREAM_NOTIFY_PROGRESS:
- if ($this->bytesMax > 0 && $this->progress) {
- $progression = 0;
- if ($this->bytesMax > 0) {
- $progression = round($bytesTransferred / $this->bytesMax * 100);
- }
- if ((0 === $progression % 5) && $progression !== $this->lastProgress) {
- $this->lastProgress = $progression;
- $this->io->overwriteError(" Downloading: <comment>$progression%</comment>", false);
- }
- }
- break;
- default:
- break;
- }
- }
- protected function promptAuthAndRetry($httpStatus, $reason = null)
- {
- if ($this->config && in_array($this->originUrl, $this->config->get('github-domains'), true)) {
- $message = "\n".'Could not fetch '.$this->fileUrl.', enter your GitHub credentials '.($httpStatus === 404 ? 'to access private repos' : 'to go over the API rate limit');
- $gitHubUtil = new GitHub($this->io, $this->config, null);
- if (!$gitHubUtil->authorizeOAuth($this->originUrl)
- && (!$this->io->isInteractive() || !$gitHubUtil->authorizeOAuthInteractively($this->originUrl, $message))
- ) {
- throw new TransportException('Could not authenticate against '.$this->originUrl, 401);
- }
- } else if ($this->config && in_array($this->originUrl, $this->config->get('gitlab-domains'), true)) {
- $message = "\n".'Could not fetch '.$this->fileUrl.', enter your ' . $this->config->get('gitlab-domains')[0] . ' credentials ' .($httpStatus === 401 ? 'to access private repos' : 'to go over the API rate limit');
- $gitLabUtil = new GitLab($this->io, $this->config, null);
- if (!$gitLabUtil->authorizeOAuth($this->originUrl)
- && (!$this->io->isInteractive() || !$gitLabUtil->authorizeOAuthInteractively($this->originUrl, $message))
- ) {
- throw new TransportException('Could not authenticate against '.$this->originUrl, 401);
- }
- } else {
- if ($httpStatus === 404) {
- return;
- }
- if (!$this->io->isInteractive()) {
- if ($httpStatus === 401) {
- $message = "The '" . $this->fileUrl . "' URL required authentication.\nYou must be using the interactive console to authenticate";
- }
- if ($httpStatus === 403) {
- $message = "The '" . $this->fileUrl . "' URL could not be accessed: " . $reason;
- }
- throw new TransportException($message, $httpStatus);
- }
- if ($this->io->hasAuthentication($this->originUrl)) {
- throw new TransportException("Invalid credentials for '" . $this->fileUrl . "', aborting.", $httpStatus);
- }
- $this->io->overwriteError(' Authentication required (<info>'.parse_url($this->fileUrl, PHP_URL_HOST).'</info>):');
- $username = $this->io->ask(' Username: ');
- $password = $this->io->askAndHideAnswer(' Password: ');
- $this->io->setAuthentication($this->originUrl, $username, $password);
- $this->storeAuth = $this->config->get('store-auths');
- }
- $this->retry = true;
- throw new TransportException('RETRY');
- }
- protected function getOptionsForUrl($originUrl, $additionalOptions)
- {
- if (defined('HHVM_VERSION')) {
- $phpVersion = 'HHVM ' . HHVM_VERSION;
- } else {
- $phpVersion = 'PHP ' . PHP_MAJOR_VERSION . '.' . PHP_MINOR_VERSION . '.' . PHP_RELEASE_VERSION;
- }
- $headers = array(
- sprintf(
- 'User-Agent: Composer/%s (%s; %s; %s)',
- Composer::VERSION === '@package_version@' ? 'source' : Composer::VERSION,
- php_uname('s'),
- php_uname('r'),
- $phpVersion
- )
- );
- if (extension_loaded('zlib')) {
- $headers[] = 'Accept-Encoding: gzip';
- }
- $options = array_replace_recursive($this->options, $additionalOptions);
- if ($this->io->hasAuthentication($originUrl)) {
- $auth = $this->io->getAuthentication($originUrl);
- if ('github.com' === $originUrl && 'x-oauth-basic' === $auth['password']) {
- $options['github-token'] = $auth['username'];
- } elseif ($originUrl === $this->config->get('gitlab-domains')[0]) {
- if($auth['password'] === 'oauth2') {
- $headers[] = 'Authorization: Bearer '.$auth['username'];
- }
- } else {
- $authStr = base64_encode($auth['username'] . ':' . $auth['password']);
- $headers[] = 'Authorization: Basic '.$authStr;
- }
- }
- if (isset($options['http']['header']) && !is_array($options['http']['header'])) {
- $options['http']['header'] = explode("\r\n", trim($options['http']['header'], "\r\n"));
- }
- foreach ($headers as $header) {
- $options['http']['header'][] = $header;
- }
- if($this->config && $this->config->get('gitlab-domains') && $originUrl == $this->config->get('gitlab-domains')[0]) {
- $options['retry-auth-failure'] = false;
- }
- return $options;
- }
- }
- <?php
- namespace Composer\Util;
- use Composer\Json\JsonFile;
- class SpdxLicenseIdentifier
- {
- private $identifiers;
- public function __construct()
- {
- $this->initIdentifiers();
- }
- public function validate($license)
- {
- if (is_array($license)) {
- $count = count($license);
- if ($count !== count(array_filter($license, 'is_string'))) {
- throw new \InvalidArgumentException('Array of strings expected.');
- }
- $license = $count > 1 ? '('.implode(' or ', $license).')' : (string) reset($license);
- }
- if (!is_string($license)) {
- throw new \InvalidArgumentException(sprintf(
- 'Array or String expected, %s given.', gettype($license)
- ));
- }
- return $this->isValidLicenseString($license);
- }
- private function initIdentifiers()
- {
- $jsonFile = new JsonFile(__DIR__ . '/../../../res/spdx-identifier.json');
- $this->identifiers = $jsonFile->read();
- }
- private function isValidLicenseIdentifier($identifier)
- {
- return in_array($identifier, $this->identifiers);
- }
- private function isValidLicenseString($license)
- {
- $tokens = array(
- 'po' => '\(',
- 'pc' => '\)',
- 'op' => '(?:or|and)',
- 'lix' => '(?:NONE|NOASSERTION)',
- 'lir' => 'LicenseRef-\d+',
- 'lic' => '[-+_.a-zA-Z0-9]{3,}',
- 'ws' => '\s+',
- '_' => '.',
- );
- $next = function () use ($license, $tokens) {
- static $offset = 0;
- if ($offset >= strlen($license)) {
- return null;
- }
- foreach ($tokens as $name => $token) {
- if (false === $r = preg_match('{' . $token . '}', $license, $matches, PREG_OFFSET_CAPTURE, $offset)) {
- throw new \RuntimeException('Pattern for token %s failed (regex error).', $name);
- }
- if ($r === 0) {
- continue;
- }
- if ($matches[0][1] !== $offset) {
- continue;
- }
- $offset += strlen($matches[0][0]);
- return array($name, $matches[0][0]);
- }
- throw new \RuntimeException('At least the last pattern needs to match, but it did not (dot-match-all is missing?).');
- };
- $open = 0;
- $require = 1;
- $lastop = null;
- while (list($token, $string) = $next()) {
- switch ($token) {
- case 'po':
- if ($open || !$require) {
- return false;
- }
- $open = 1;
- break;
- case 'pc':
- if ($open !== 1 || $require || !$lastop) {
- return false;
- }
- $open = 2;
- break;
- case 'op':
- if ($require || !$open) {
- return false;
- }
- $lastop || $lastop = $string;
- if ($lastop !== $string) {
- return false;
- }
- $require = 1;
- break;
- case 'lix':
- if ($open) {
- return false;
- }
- goto lir;
- case 'lic':
- if (!$this->isValidLicenseIdentifier($string)) {
- return false;
- }
- case 'lir':
- lir:
- if (!$require) {
- return false;
- }
- $require = 0;
- break;
- case 'ws':
- break;
- case '_':
- return false;
- default:
- throw new \RuntimeException(sprintf('Unparsed token: %s.', print_r($token, true)));
- }
- }
- return !($open % 2 || $require);
- }
- }
- <?php
- namespace Composer\Util;
- final class StreamContextFactory
- {
- public static function getContext($url, array $defaultOptions = array(), array $defaultParams = array())
- {
- $options = array('http' => array(
- 'follow_location' => 1,
- 'max_redirects' => 20,
- ));
- if (!empty($_SERVER['HTTP_PROXY']) || !empty($_SERVER['http_proxy'])) {
- $proxy = parse_url(!empty($_SERVER['http_proxy']) ? $_SERVER['http_proxy'] : $_SERVER['HTTP_PROXY']);
- }
- if (preg_match('{^https://}i', $url) && (!empty($_SERVER['HTTPS_PROXY']) || !empty($_SERVER['https_proxy']))) {
- $proxy = parse_url(!empty($_SERVER['https_proxy']) ? $_SERVER['https_proxy'] : $_SERVER['HTTPS_PROXY']);
- }
- if (!empty($_SERVER['no_proxy']) && parse_url($url, PHP_URL_HOST)) {
- $pattern = new NoProxyPattern($_SERVER['no_proxy']);
- if ($pattern->test($url)) {
- unset($proxy);
- }
- }
- if (!empty($proxy)) {
- $proxyURL = isset($proxy['scheme']) ? $proxy['scheme'] . '://' : '';
- $proxyURL .= isset($proxy['host']) ? $proxy['host'] : '';
- if (isset($proxy['port'])) {
- $proxyURL .= ":" . $proxy['port'];
- } elseif ('http://' == substr($proxyURL, 0, 7)) {
- $proxyURL .= ":80";
- } elseif ('https://' == substr($proxyURL, 0, 8)) {
- $proxyURL .= ":443";
- }
- $proxyURL = str_replace(array('http://', 'https://'), array('tcp://', 'ssl://'), $proxyURL);
- if (0 === strpos($proxyURL, 'ssl:') && !extension_loaded('openssl')) {
- throw new \RuntimeException('You must enable the openssl extension to use a proxy over https');
- }
- $options['http']['proxy'] = $proxyURL;
- switch (parse_url($url, PHP_URL_SCHEME)) {
- case 'http':
- $reqFullUriEnv = getenv('HTTP_PROXY_REQUEST_FULLURI');
- if ($reqFullUriEnv === false || $reqFullUriEnv === '' || (strtolower($reqFullUriEnv) !== 'false' && (bool) $reqFullUriEnv)) {
- $options['http']['request_fulluri'] = true;
- }
- break;
- case 'https':
- $reqFullUriEnv = getenv('HTTPS_PROXY_REQUEST_FULLURI');
- if ($reqFullUriEnv === false || $reqFullUriEnv === '' || (strtolower($reqFullUriEnv) !== 'false' && (bool) $reqFullUriEnv)) {
- $options['http']['request_fulluri'] = true;
- }
- break;
- }
- if ('https' === parse_url($url, PHP_URL_SCHEME)) {
- $options['ssl']['SNI_enabled'] = true;
- if (version_compare(PHP_VERSION, '5.6.0', '<')) {
- $options['ssl']['SNI_server_name'] = parse_url($url, PHP_URL_HOST);
- }
- }
- if (isset($proxy['user'])) {
- $auth = urldecode($proxy['user']);
- if (isset($proxy['pass'])) {
- $auth .= ':' . urldecode($proxy['pass']);
- }
- $auth = base64_encode($auth);
- if (isset($defaultOptions['http']['header'])) {
- if (is_string($defaultOptions['http']['header'])) {
- $defaultOptions['http']['header'] = array($defaultOptions['http']['header']);
- }
- $defaultOptions['http']['header'][] = "Proxy-Authorization: Basic {$auth}";
- } else {
- $options['http']['header'] = array("Proxy-Authorization: Basic {$auth}");
- }
- }
- }
- $options = array_replace_recursive($options, $defaultOptions);
- if (isset($options['http']['header'])) {
- $options['http']['header'] = self::fixHttpHeaderField($options['http']['header']);
- }
- return stream_context_create($options, $defaultParams);
- }
- private static function fixHttpHeaderField($header)
- {
- if (!is_array($header)) {
- $header = explode("\r\n", $header);
- }
- uasort($header, function ($el) {
- return preg_match('{^content-type}i', $el) ? 1 : -1;
- });
- return $header;
- }
- }
- <?php
- namespace Composer\Util;
- use Composer\Config;
- use Composer\IO\IOInterface;
- class Svn
- {
- const MAX_QTY_AUTH_TRIES = 5;
- protected $credentials;
- protected $hasAuth;
- protected $io;
- protected $url;
- protected $cacheCredentials = true;
- protected $process;
- protected $qtyAuthTries = 0;
- protected $config;
- public function __construct($url, IOInterface $io, Config $config, ProcessExecutor $process = null)
- {
- $this->url = $url;
- $this->io = $io;
- $this->config = $config;
- $this->process = $process ?: new ProcessExecutor;
- }
- public static function cleanEnv()
- {
- putenv("DYLD_LIBRARY_PATH");
- }
- public function execute($command, $url, $cwd = null, $path = null, $verbose = false)
- {
- $svnCommand = $this->getCommand($command, $url, $path);
- $output = null;
- $io = $this->io;
- $handler = function ($type, $buffer) use (&$output, $io, $verbose) {
- if ($type !== 'out') {
- return;
- }
- if ('Redirecting to URL ' === substr($buffer, 0, 19)) {
- return;
- }
- $output .= $buffer;
- if ($verbose) {
- $io->writeError($buffer, false);
- }
- };
- $status = $this->process->execute($svnCommand, $handler, $cwd);
- if (0 === $status) {
- return $output;
- }
- if (empty($output)) {
- $output = $this->process->getErrorOutput();
- }
- if (false === stripos($output, 'Could not authenticate to server:')
- && false === stripos($output, 'authorization failed')
- && false === stripos($output, 'svn: E170001:')
- && false === stripos($output, 'svn: E215004:')) {
- throw new \RuntimeException($output);
- }
- if (!$this->hasAuth()) {
- $this->doAuthDance();
- }
- if ($this->qtyAuthTries++ < self::MAX_QTY_AUTH_TRIES) {
- return $this->execute($command, $url, $cwd, $path, $verbose);
- }
- throw new \RuntimeException(
- 'wrong credentials provided ('.$output.')'
- );
- }
- public function setCacheCredentials($cacheCredentials)
- {
- $this->cacheCredentials = $cacheCredentials;
- }
- protected function doAuthDance()
- {
- if (!$this->io->isInteractive()) {
- throw new \RuntimeException(
- 'can not ask for authentication in non interactive mode'
- );
- }
- $this->io->writeError("The Subversion server ({$this->url}) requested credentials:");
- $this->hasAuth = true;
- $this->credentials['username'] = $this->io->ask("Username: ");
- $this->credentials['password'] = $this->io->askAndHideAnswer("Password: ");
- $this->cacheCredentials = $this->io->askConfirmation("Should Subversion cache these credentials? (yes/no) ", true);
- return $this;
- }
- protected function getCommand($cmd, $url, $path = null)
- {
- $cmd = sprintf('%s %s%s %s',
- $cmd,
- '--non-interactive ',
- $this->getCredentialString(),
- ProcessExecutor::escape($url)
- );
- if ($path) {
- $cmd .= ' ' . ProcessExecutor::escape($path);
- }
- return $cmd;
- }
- protected function getCredentialString()
- {
- if (!$this->hasAuth()) {
- return '';
- }
- return sprintf(
- ' %s--username %s --password %s ',
- $this->getAuthCache(),
- ProcessExecutor::escape($this->getUsername()),
- ProcessExecutor::escape($this->getPassword())
- );
- }
- protected function getPassword()
- {
- if ($this->credentials === null) {
- throw new \LogicException("No svn auth detected.");
- }
- return isset($this->credentials['password']) ? $this->credentials['password'] : '';
- }
- protected function getUsername()
- {
- if ($this->credentials === null) {
- throw new \LogicException("No svn auth detected.");
- }
- return $this->credentials['username'];
- }
- protected function hasAuth()
- {
- if (null !== $this->hasAuth) {
- return $this->hasAuth;
- }
- if (false === $this->createAuthFromConfig()) {
- $this->createAuthFromUrl();
- }
- return $this->hasAuth;
- }
- protected function getAuthCache()
- {
- return $this->cacheCredentials ? '' : '--no-auth-cache ';
- }
- private function createAuthFromConfig()
- {
- if (!$this->config->has('http-basic')) {
- return $this->hasAuth = false;
- }
- $authConfig = $this->config->get('http-basic');
- $host = parse_url($this->url, PHP_URL_HOST);
- if (isset($authConfig[$host])) {
- $this->credentials['username'] = $authConfig[$host]['username'];
- $this->credentials['password'] = $authConfig[$host]['password'];
- return $this->hasAuth = true;
- }
- return $this->hasAuth = false;
- }
- private function createAuthFromUrl()
- {
- $uri = parse_url($this->url);
- if (empty($uri['user'])) {
- return $this->hasAuth = false;
- }
- $this->credentials['username'] = $uri['user'];
- if (!empty($uri['pass'])) {
- $this->credentials['password'] = $uri['pass'];
- }
- return $this->hasAuth = true;
- }
- }
- <?php
- /*
- * This file is part of Composer.
- *
- * (c) Nils Adermann <naderman@naderman.de>
- * Jordi Boggiano <j.boggiano@seld.be>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
- namespace Composer\Autoload;
- /**
- * ClassLoader implements a PSR-0 class loader
- *
- * See https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-0.md
- *
- * $loader = new \Composer\Autoload\ClassLoader();
- *
- * // register classes with namespaces
- * $loader->add('Symfony\Component', __DIR__.'/component');
- * $loader->add('Symfony', __DIR__.'/framework');
- *
- * // activate the autoloader
- * $loader->register();
- *
- * // to enable searching the include path (eg. for PEAR packages)
- * $loader->setUseIncludePath(true);
- *
- * In this example, if you try to use a class in the Symfony\Component
- * namespace or one of its children (Symfony\Component\Console for instance),
- * the autoloader will first look for the class under the component/
- * directory, and it will then fallback to the framework/ directory if not
- * found before giving up.
- *
- * This class is loosely based on the Symfony UniversalClassLoader.
- *
- * @author Fabien Potencier <fabien@symfony.com>
- * @author Jordi Boggiano <j.boggiano@seld.be>
- */
- class ClassLoader
- {
- // PSR-4
- private $prefixLengthsPsr4 = array();
- private $prefixDirsPsr4 = array();
- private $fallbackDirsPsr4 = array();
- // PSR-0
- private $prefixesPsr0 = array();
- private $fallbackDirsPsr0 = array();
- private $useIncludePath = false;
- private $classMap = array();
- private $classMapAuthoritative = false;
- public function getPrefixes()
- {
- if (!empty($this->prefixesPsr0)) {
- return call_user_func_array('array_merge', $this->prefixesPsr0);
- }
- return array();
- }
- public function getPrefixesPsr4()
- {
- return $this->prefixDirsPsr4;
- }
- public function getFallbackDirs()
- {
- return $this->fallbackDirsPsr0;
- }
- public function getFallbackDirsPsr4()
- {
- return $this->fallbackDirsPsr4;
- }
- public function getClassMap()
- {
- return $this->classMap;
- }
- /**
- * @param array $classMap Class to filename map
- */
- public function addClassMap(array $classMap)
- {
- if ($this->classMap) {
- $this->classMap = array_merge($this->classMap, $classMap);
- } else {
- $this->classMap = $classMap;
- }
- }
- /**
- * Registers a set of PSR-0 directories for a given prefix, either
- * appending or prepending to the ones previously set for this prefix.
- *
- * @param string $prefix The prefix
- * @param array|string $paths The PSR-0 root directories
- * @param bool $prepend Whether to prepend the directories
- */
- public function add($prefix, $paths, $prepend = false)
- {
- if (!$prefix) {
- if ($prepend) {
- $this->fallbackDirsPsr0 = array_merge(
- (array) $paths,
- $this->fallbackDirsPsr0
- );
- } else {
- $this->fallbackDirsPsr0 = array_merge(
- $this->fallbackDirsPsr0,
- (array) $paths
- );
- }
- return;
- }
- $first = $prefix[0];
- if (!isset($this->prefixesPsr0[$first][$prefix])) {
- $this->prefixesPsr0[$first][$prefix] = (array) $paths;
- return;
- }
- if ($prepend) {
- $this->prefixesPsr0[$first][$prefix] = array_merge(
- (array) $paths,
- $this->prefixesPsr0[$first][$prefix]
- );
- } else {
- $this->prefixesPsr0[$first][$prefix] = array_merge(
- $this->prefixesPsr0[$first][$prefix],
- (array) $paths
- );
- }
- }
- /**
- * Registers a set of PSR-4 directories for a given namespace, either
- * appending or prepending to the ones previously set for this namespace.
- *
- * @param string $prefix The prefix/namespace, with trailing '\\'
- * @param array|string $paths The PSR-0 base directories
- * @param bool $prepend Whether to prepend the directories
- *
- * @throws \InvalidArgumentException
- */
- public function addPsr4($prefix, $paths, $prepend = false)
- {
- if (!$prefix) {
- // Register directories for the root namespace.
- if ($prepend) {
- $this->fallbackDirsPsr4 = array_merge(
- (array) $paths,
- $this->fallbackDirsPsr4
- );
- } else {
- $this->fallbackDirsPsr4 = array_merge(
- $this->fallbackDirsPsr4,
- (array) $paths
- );
- }
- } elseif (!isset($this->prefixDirsPsr4[$prefix])) {
- // Register directories for a new namespace.
- $length = strlen($prefix);
- if ('\\' !== $prefix[$length - 1]) {
- throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
- }
- $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
- $this->prefixDirsPsr4[$prefix] = (array) $paths;
- } elseif ($prepend) {
- // Prepend directories for an already registered namespace.
- $this->prefixDirsPsr4[$prefix] = array_merge(
- (array) $paths,
- $this->prefixDirsPsr4[$prefix]
- );
- } else {
- // Append directories for an already registered namespace.
- $this->prefixDirsPsr4[$prefix] = array_merge(
- $this->prefixDirsPsr4[$prefix],
- (array) $paths
- );
- }
- }
- /**
- * Registers a set of PSR-0 directories for a given prefix,
- * replacing any others previously set for this prefix.
- *
- * @param string $prefix The prefix
- * @param array|string $paths The PSR-0 base directories
- */
- public function set($prefix, $paths)
- {
- if (!$prefix) {
- $this->fallbackDirsPsr0 = (array) $paths;
- } else {
- $this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths;
- }
- }
- /**
- * Registers a set of PSR-4 directories for a given namespace,
- * replacing any others previously set for this namespace.
- *
- * @param string $prefix The prefix/namespace, with trailing '\\'
- * @param array|string $paths The PSR-4 base directories
- *
- * @throws \InvalidArgumentException
- */
- public function setPsr4($prefix, $paths)
- {
- if (!$prefix) {
- $this->fallbackDirsPsr4 = (array) $paths;
- } else {
- $length = strlen($prefix);
- if ('\\' !== $prefix[$length - 1]) {
- throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
- }
- $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
- $this->prefixDirsPsr4[$prefix] = (array) $paths;
- }
- }
- /**
- * Turns on searching the include path for class files.
- *
- * @param bool $useIncludePath
- */
- public function setUseIncludePath($useIncludePath)
- {
- $this->useIncludePath = $useIncludePath;
- }
- /**
- * Can be used to check if the autoloader uses the include path to check
- * for classes.
- *
- * @return bool
- */
- public function getUseIncludePath()
- {
- return $this->useIncludePath;
- }
- /**
- * Turns off searching the prefix and fallback directories for classes
- * that have not been registered with the class map.
- *
- * @param bool $classMapAuthoritative
- */
- public function setClassMapAuthoritative($classMapAuthoritative)
- {
- $this->classMapAuthoritative = $classMapAuthoritative;
- }
- /**
- * Should class lookup fail if not found in the current class map?
- *
- * @return bool
- */
- public function isClassMapAuthoritative()
- {
- return $this->classMapAuthoritative;
- }
- /**
- * Registers this instance as an autoloader.
- *
- * @param bool $prepend Whether to prepend the autoloader or not
- */
- public function register($prepend = false)
- {
- spl_autoload_register(array($this, 'loadClass'), true, $prepend);
- }
- /**
- * Unregisters this instance as an autoloader.
- */
- public function unregister()
- {
- spl_autoload_unregister(array($this, 'loadClass'));
- }
- /**
- * Loads the given class or interface.
- *
- * @param string $class The name of the class
- * @return bool|null True if loaded, null otherwise
- */
- public function loadClass($class)
- {
- if ($file = $this->findFile($class)) {
- includeFile($file);
- return true;
- }
- }
- /**
- * Finds the path to the file where the class is defined.
- *
- * @param string $class The name of the class
- *
- * @return string|false The path if found, false otherwise
- */
- public function findFile($class)
- {
- // work around for PHP 5.3.0 - 5.3.2 https://bugs.php.net/50731
- if ('\\' == $class[0]) {
- $class = substr($class, 1);
- }
- // class map lookup
- if (isset($this->classMap[$class])) {
- return $this->classMap[$class];
- }
- if ($this->classMapAuthoritative) {
- return false;
- }
- $file = $this->findFileWithExtension($class, '.php');
- // Search for Hack files if we are running on HHVM
- if ($file === null && defined('HHVM_VERSION')) {
- $file = $this->findFileWithExtension($class, '.hh');
- }
- if ($file === null) {
- // Remember that this class does not exist.
- return $this->classMap[$class] = false;
- }
- return $file;
- }
- private function findFileWithExtension($class, $ext)
- {
- // PSR-4 lookup
- $logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext;
- $first = $class[0];
- if (isset($this->prefixLengthsPsr4[$first])) {
- foreach ($this->prefixLengthsPsr4[$first] as $prefix => $length) {
- if (0 === strpos($class, $prefix)) {
- foreach ($this->prefixDirsPsr4[$prefix] as $dir) {
- if (file_exists($file = $dir . DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $length))) {
- return $file;
- }
- }
- }
- }
- }
- // PSR-4 fallback dirs
- foreach ($this->fallbackDirsPsr4 as $dir) {
- if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) {
- return $file;
- }
- }
- // PSR-0 lookup
- if (false !== $pos = strrpos($class, '\\')) {
- // namespaced class name
- $logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1)
- . strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR);
- } else {
- // PEAR-like class name
- $logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext;
- }
- if (isset($this->prefixesPsr0[$first])) {
- foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) {
- if (0 === strpos($class, $prefix)) {
- foreach ($dirs as $dir) {
- if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
- return $file;
- }
- }
- }
- }
- }
- // PSR-0 fallback dirs
- foreach ($this->fallbackDirsPsr0 as $dir) {
- if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
- return $file;
- }
- }
- // PSR-0 include paths.
- if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) {
- return $file;
- }
- }
- }
- /**
- * Scope isolated include.
- *
- * Prevents access to $this/self from included files.
- */
- function includeFile($file)
- {
- include $file;
- }
- {
- "$schema": "http://json-schema.org/draft-04/schema#",
- "name": "Package",
- "type": "object",
- "additionalProperties": false,
- "required": [ "name", "description" ],
- "properties": {
- "name": {
- "type": "string",
- "description": "Package name, including 'vendor-name/' prefix."
- },
- "type": {
- "description": "Package type, either 'library' for common packages, 'composer-plugin' for plugins, 'metapackage' for empty packages, or a custom type ([a-z0-9-]+) defined by whatever project this package applies to.",
- "type": "string"
- },
- "target-dir": {
- "description": "DEPRECATED: Forces the package to be installed into the given subdirectory path. This is used for autoloading PSR-0 packages that do not contain their full path. Use forward slashes for cross-platform compatibility.",
- "type": "string"
- },
- "description": {
- "type": "string",
- "description": "Short package description."
- },
- "keywords": {
- "type": "array",
- "items": {
- "type": "string",
- "description": "A tag/keyword that this package relates to."
- }
- },
- "homepage": {
- "type": "string",
- "description": "Homepage URL for the project.",
- "format": "uri"
- },
- "version": {
- "type": "string",
- "description": "Package version, see http://getcomposer.org/doc/04-schema.md#version for more info on valid schemes."
- },
- "time": {
- "type": "string",
- "description": "Package release date, in 'YYYY-MM-DD', 'YYYY-MM-DD HH:MM:SS' or 'YYYY-MM-DDTHH:MM:SSZ' format."
- },
- "license": {
- "type": ["string", "array"],
- "description": "License name. Or an array of license names."
- },
- "authors": {
- "type": "array",
- "description": "List of authors that contributed to the package. This is typically the main maintainers, not the full list.",
- "items": {
- "type": "object",
- "additionalProperties": false,
- "required": [ "name"],
- "properties": {
- "name": {
- "type": "string",
- "description": "Full name of the author."
- },
- "email": {
- "type": "string",
- "description": "Email address of the author.",
- "format": "email"
- },
- "homepage": {
- "type": "string",
- "description": "Homepage URL for the author.",
- "format": "uri"
- },
- "role": {
- "type": "string",
- "description": "Author's role in the project."
- }
- }
- }
- },
- "require": {
- "type": "object",
- "description": "This is a hash of package name (keys) and version constraints (values) that are required to run this package.",
- "additionalProperties": true
- },
- "replace": {
- "type": "object",
- "description": "This is a hash of package name (keys) and version constraints (values) that can be replaced by this package.",
- "additionalProperties": true
- },
- "conflict": {
- "type": "object",
- "description": "This is a hash of package name (keys) and version constraints (values) that conflict with this package.",
- "additionalProperties": true
- },
- "provide": {
- "type": "object",
- "description": "This is a hash of package name (keys) and version constraints (values) that this package provides in addition to this package's name.",
- "additionalProperties": true
- },
- "require-dev": {
- "type": "object",
- "description": "This is a hash of package name (keys) and version constraints (values) that this package requires for developing it (testing tools and such).",
- "additionalProperties": true
- },
- "suggest": {
- "type": "object",
- "description": "This is a hash of package name (keys) and descriptions (values) that this package suggests work well with it (this will be suggested to the user during installation).",
- "additionalProperties": true
- },
- "config": {
- "type": "object",
- "description": "Composer options.",
- "properties": {
- "process-timeout": {
- "type": "integer",
- "description": "The timeout in seconds for process executions, defaults to 300 (5mins)."
- },
- "use-include-path": {
- "type": "boolean",
- "description": "If true, the Composer autoloader will also look for classes in the PHP include path."
- },
- "preferred-install": {
- "type": "string",
- "description": "The install method Composer will prefer to use, defaults to auto and can be any of source, dist or auto."
- },
- "notify-on-install": {
- "type": "boolean",
- "description": "Composer allows repositories to define a notification URL, so that they get notified whenever a package from that repository is installed. This option allows you to disable that behaviour, defaults to true."
- },
- "github-protocols": {
- "type": "array",
- "description": "A list of protocols to use for github.com clones, in priority order, defaults to [\"git\", \"https\", \"http\"].",
- "items": {
- "type": "string"
- }
- },
- "github-oauth": {
- "type": "object",
- "description": "A hash of domain name => github API oauth tokens, typically {\"github.com\":\"<token>\"}.",
- "additionalProperties": true
- },
- "http-basic": {
- "type": "object",
- "description": "A hash of domain name => {\"username\": \"...\", \"password\": \"...\"}.",
- "additionalProperties": true
- },
- "store-auths": {
- "type": ["string", "boolean"],
- "description": "What to do after prompting for authentication, one of: true (store), false (do not store) or \"prompt\" (ask every time), defaults to prompt."
- },
- "vendor-dir": {
- "type": "string",
- "description": "The location where all packages are installed, defaults to \"vendor\"."
- },
- "bin-dir": {
- "type": "string",
- "description": "The location where all binaries are linked, defaults to \"vendor/bin\"."
- },
- "cache-dir": {
- "type": "string",
- "description": "The location where all caches are located, defaults to \"~/.composer/cache\" on *nix and \"%LOCALAPPDATA%\\Composer\" on windows."
- },
- "cache-files-dir": {
- "type": "string",
- "description": "The location where files (zip downloads) are cached, defaults to \"{$cache-dir}/files\"."
- },
- "cache-repo-dir": {
- "type": "string",
- "description": "The location where repo (git/hg repo clones) are cached, defaults to \"{$cache-dir}/repo\"."
- },
- "cache-vcs-dir": {
- "type": "string",
- "description": "The location where vcs infos (git clones, github api calls, etc. when reading vcs repos) are cached, defaults to \"{$cache-dir}/vcs\"."
- },
- "cache-ttl": {
- "type": "integer",
- "description": "The default cache time-to-live, defaults to 15552000 (6 months)."
- },
- "cache-files-ttl": {
- "type": "integer",
- "description": "The cache time-to-live for files, defaults to the value of cache-ttl."
- },
- "cache-files-maxsize": {
- "type": ["string", "integer"],
- "description": "The cache max size for the files cache, defaults to \"300MiB\"."
- },
- "discard-changes": {
- "type": ["string", "boolean"],
- "description": "The default style of handling dirty updates, defaults to false and can be any of true, false or \"stash\"."
- },
- "autoloader-suffix": {
- "type": "string",
- "description": "Optional string to be used as a suffix for the generated Composer autoloader. When null a random one will be generated."
- },
- "optimize-autoloader": {
- "type": "boolean",
- "description": "Always optimize when dumping the autoloader."
- },
- "prepend-autoloader": {
- "type": "boolean",
- "description": "If false, the composer autoloader will not be prepended to existing autoloaders, defaults to true."
- },
- "classmap-authoritative": {
- "type": "boolean",
- "description": "If true, the composer autoloader will not scan the filesystem for classes that are not found in the class map, defaults to false."
- },
- "github-domains": {
- "type": "array",
- "description": "A list of domains to use in github mode. This is used for GitHub Enterprise setups, defaults to [\"github.com\"].",
- "items": {
- "type": "string"
- }
- },
- "github-expose-hostname": {
- "type": "boolean",
- "description": "Defaults to true. If set to false, the OAuth tokens created to access the github API will have a date instead of the machine hostname."
- }
- }
- },
- "extra": {
- "type": ["object", "array"],
- "description": "Arbitrary extra data that can be used by plugins, for example, package of type composer-plugin may have a 'class' key defining an installer class name.",
- "additionalProperties": true
- },
- "autoload": {
- "type": "object",
- "description": "Description of how the package can be autoloaded.",
- "properties": {
- "psr-0": {
- "type": "object",
- "description": "This is a hash of namespaces (keys) and the directories they can be found into (values, can be arrays of paths) by the autoloader.",
- "additionalProperties": true
- },
- "psr-4": {
- "type": "object",
- "description": "This is a hash of namespaces (keys) and the PSR-4 directories they can map to (values, can be arrays of paths) by the autoloader.",
- "additionalProperties": true
- },
- "classmap": {
- "type": "array",
- "description": "This is an array of directories that contain classes to be included in the class-map generation process."
- },
- "files": {
- "type": "array",
- "description": "This is an array of files that are always required on every request."
- }
- }
- },
- "autoload-dev": {
- "type": "object",
- "description": "Description of additional autoload rules for development purpose (eg. a test suite).",
- "properties": {
- "psr-0": {
- "type": "object",
- "description": "This is a hash of namespaces (keys) and the directories they can be found into (values, can be arrays of paths) by the autoloader.",
- "additionalProperties": true
- },
- "psr-4": {
- "type": "object",
- "description": "This is a hash of namespaces (keys) and the PSR-4 directories they can map to (values, can be arrays of paths) by the autoloader.",
- "additionalProperties": true
- },
- "classmap": {
- "type": "array",
- "description": "This is an array of directories that contain classes to be included in the class-map generation process."
- },
- "files": {
- "type": "array",
- "description": "This is an array of files that are always required on every request."
- }
- }
- },
- "archive": {
- "type": ["object"],
- "description": "Options for creating package archives for distribution.",
- "properties": {
- "exclude": {
- "type": "array",
- "description": "A list of patterns for paths to exclude or include if prefixed with an exclamation mark."
- }
- }
- },
- "repositories": {
- "type": ["object", "array"],
- "description": "A set of additional repositories where packages can be found.",
- "additionalProperties": true
- },
- "minimum-stability": {
- "type": ["string"],
- "description": "The minimum stability the packages must have to be install-able. Possible values are: dev, alpha, beta, RC, stable.",
- "pattern": "^dev|alpha|beta|rc|RC|stable$"
- },
- "prefer-stable": {
- "type": ["boolean"],
- "description": "If set to true, stable packages will be prefered to dev packages when possible, even if the minimum-stability allows unstable packages."
- },
- "bin": {
- "type": ["array"],
- "description": "A set of files that should be treated as binaries and symlinked into bin-dir (from config).",
- "items": {
- "type": "string"
- }
- },
- "include-path": {
- "type": ["array"],
- "description": "DEPRECATED: A list of directories which should get added to PHP's include path. This is only present to support legacy projects, and all new code should preferably use autoloading.",
- "items": {
- "type": "string"
- }
- },
- "scripts": {
- "type": ["object"],
- "description": "Scripts listeners that will be executed before/after some events.",
- "properties": {
- "pre-install-cmd": {
- "type": ["array", "string"],
- "description": "Occurs before the install command is executed, contains one or more Class::method callables or shell commands."
- },
- "post-install-cmd": {
- "type": ["array", "string"],
- "description": "Occurs after the install command is executed, contains one or more Class::method callables or shell commands."
- },
- "pre-update-cmd": {
- "type": ["array", "string"],
- "description": "Occurs before the update command is executed, contains one or more Class::method callables or shell commands."
- },
- "post-update-cmd": {
- "type": ["array", "string"],
- "description": "Occurs after the update command is executed, contains one or more Class::method callables or shell commands."
- },
- "pre-status-cmd": {
- "type": ["array", "string"],
- "description": "Occurs before the status command is executed, contains one or more Class::method callables or shell commands."
- },
- "post-status-cmd": {
- "type": ["array", "string"],
- "description": "Occurs after the status command is executed, contains one or more Class::method callables or shell commands."
- },
- "pre-package-install": {
- "type": ["array", "string"],
- "description": "Occurs before a package is installed, contains one or more Class::method callables or shell commands."
- },
- "post-package-install": {
- "type": ["array", "string"],
- "description": "Occurs after a package is installed, contains one or more Class::method callables or shell commands."
- },
- "pre-package-update": {
- "type": ["array", "string"],
- "description": "Occurs before a package is updated, contains one or more Class::method callables or shell commands."
- },
- "post-package-update": {
- "type": ["array", "string"],
- "description": "Occurs after a package is updated, contains one or more Class::method callables or shell commands."
- },
- "pre-package-uninstall": {
- "type": ["array", "string"],
- "description": "Occurs before a package has been uninstalled, contains one or more Class::method callables or shell commands."
- },
- "post-package-uninstall": {
- "type": ["array", "string"],
- "description": "Occurs after a package has been uninstalled, contains one or more Class::method callables or shell commands."
- },
- "pre-autoload-dump": {
- "type": ["array", "string"],
- "description": "Occurs before the autoloader is dumped, contains one or more Class::method callables or shell commands."
- },
- "post-autoload-dump": {
- "type": ["array", "string"],
- "description": "Occurs after the autoloader is dumped, contains one or more Class::method callables or shell commands."
- },
- "post-root-package-install": {
- "type": ["array", "string"],
- "description": "Occurs after the root-package is installed, contains one or more Class::method callables or shell commands."
- },
- "post-create-project-cmd": {
- "type": ["array", "string"],
- "description": "Occurs after the create-project command is executed, contains one or more Class::method callables or shell commands."
- }
- }
- },
- "support": {
- "type": "object",
- "properties": {
- "email": {
- "type": "string",
- "description": "Email address for support.",
- "format": "email"
- },
- "issues": {
- "type": "string",
- "description": "URL to the Issue Tracker.",
- "format": "uri"
- },
- "forum": {
- "type": "string",
- "description": "URL to the Forum.",
- "format": "uri"
- },
- "wiki": {
- "type": "string",
- "description": "URL to the Wiki.",
- "format": "uri"
- },
- "irc": {
- "type": "string",
- "description": "IRC channel for support, as irc://server/channel.",
- "format": "uri"
- },
- "source": {
- "type": "string",
- "description": "URL to browse or download the sources.",
- "format": "uri"
- }
- }
- },
- "non-feature-branches": {
- "type": ["array"],
- "description": "A set of string or regex patterns for non-numeric branch names that will not be handles as feature branches.",
- "items": {
- "type": "string"
- }
- }
- }
- }
- [
- "Glide", "Abstyles", "AFL-1.1", "AFL-1.2", "AFL-2.0", "AFL-2.1", "AFL-3.0",
- "AMPAS", "APL-1.0", "Adobe-Glyph", "APAFML", "Adobe-2006", "AGPL-1.0",
- "Afmparse", "Aladdin", "ADSL", "AMDPLPA", "ANTLR-PD", "Apache-1.0",
- "Apache-1.1", "Apache-2.0", "AML", "APSL-1.0", "APSL-1.1", "APSL-1.2",
- "APSL-2.0", "Artistic-1.0", "Artistic-1.0-Perl", "Artistic-1.0-cl8",
- "Artistic-2.0", "AAL", "Bahyph", "Barr", "Beerware", "BitTorrent-1.0",
- "BitTorrent-1.1", "BSL-1.0", "Borceux", "BSD-2-Clause",
- "BSD-2-Clause-FreeBSD", "BSD-2-Clause-NetBSD", "BSD-3-Clause",
- "BSD-3-Clause-Clear", "BSD-4-Clause", "BSD-Protection",
- "BSD-3-Clause-Attribution", "BSD-4-Clause-UC", "bzip2-1.0.5", "bzip2-1.0.6",
- "Caldera", "CECILL-1.0", "CECILL-1.1", "CECILL-2.0", "CECILL-B", "CECILL-C",
- "ClArtistic", "MIT-CMU", "CNRI-Python", "CNRI-Python-GPL-Compatible",
- "CPOL-1.02", "CDDL-1.0", "CDDL-1.1", "CPAL-1.0", "CPL-1.0", "CATOSL-1.1",
- "Condor-1.1", "CC-BY-1.0", "CC-BY-2.0", "CC-BY-2.5", "CC-BY-3.0",
- "CC-BY-4.0", "CC-BY-ND-1.0", "CC-BY-ND-2.0", "CC-BY-ND-2.5", "CC-BY-ND-3.0",
- "CC-BY-ND-4.0", "CC-BY-NC-1.0", "CC-BY-NC-2.0", "CC-BY-NC-2.5",
- "CC-BY-NC-3.0", "CC-BY-NC-4.0", "CC-BY-NC-ND-1.0", "CC-BY-NC-ND-2.0",
- "CC-BY-NC-ND-2.5", "CC-BY-NC-ND-3.0", "CC-BY-NC-ND-4.0", "CC-BY-NC-SA-1.0",
- "CC-BY-NC-SA-2.0", "CC-BY-NC-SA-2.5", "CC-BY-NC-SA-3.0", "CC-BY-NC-SA-4.0",
- "CC-BY-SA-1.0", "CC-BY-SA-2.0", "CC-BY-SA-2.5", "CC-BY-SA-3.0",
- "CC-BY-SA-4.0", "CC0-1.0", "Crossword", "CUA-OPL-1.0", "Cube", "D-FSL-1.0",
- "diffmark", "WTFPL", "DOC", "Dotseqn", "DSDP", "dvipdfm", "EPL-1.0",
- "eCos-2.0", "ECL-1.0", "ECL-2.0", "eGenix", "EFL-1.0", "EFL-2.0",
- "MIT-advertising", "MIT-enna", "Entessa", "ErlPL-1.1", "EUDatagrid",
- "EUPL-1.0", "EUPL-1.1", "Eurosym", "Fair", "MIT-feh", "Frameworx-1.0",
- "FTL", "FSFUL", "FSFULLR", "Giftware", "GL2PS", "Glulxe", "AGPL-3.0",
- "GFDL-1.1", "GFDL-1.2", "GFDL-1.3", "GPL-1.0", "GPL-1.0+", "GPL-2.0",
- "GPL-2.0+", "GPL-2.0-with-autoconf-exception",
- "GPL-2.0-with-bison-exception", "GPL-2.0-with-classpath-exception",
- "GPL-2.0-with-font-exception", "GPL-2.0-with-GCC-exception", "GPL-3.0",
- "GPL-3.0+", "GPL-3.0-with-autoconf-exception", "GPL-3.0-with-GCC-exception",
- "LGPL-2.1", "LGPL-2.1+", "LGPL-3.0", "LGPL-3.0+", "LGPL-2.0", "LGPL-2.0+",
- "gnuplot", "gSOAP-1.3b", "HaskellReport", "HPND", "IBM-pibs", "IPL-1.0",
- "ImageMagick", "iMatix", "Imlib2", "IJG", "Intel-ACPI", "Intel", "IPA",
- "ISC", "JasPer-2.0", "JSON", "LPPL-1.3a", "LPPL-1.0", "LPPL-1.1",
- "LPPL-1.2", "LPPL-1.3c", "Latex2e", "BSD-3-Clause-LBNL", "Leptonica",
- "Libpng", "libtiff", "LPL-1.02", "LPL-1.0", "MakeIndex", "MTLL", "MS-PL",
- "MS-RL", "MirOS", "MITNFA", "MIT", "Motosoto", "MPL-1.0", "MPL-1.1",
- "MPL-2.0", "MPL-2.0-no-copyleft-exception", "mpich2", "Multics", "Mup",
- "NASA-1.3", "Naumen", "NBPL-1.0", "NetCDF", "NGPL", "NOSL", "NPL-1.0",
- "NPL-1.1", "Newsletr", "NLPL", "Nokia", "NPOSL-3.0", "Noweb", "NRL", "NTP",
- "Nunit", "OCLC-2.0", "ODbL-1.0", "PDDL-1.0", "OGTSL", "OLDAP-2.2.2",
- "OLDAP-1.1", "OLDAP-1.2", "OLDAP-1.3", "OLDAP-1.4", "OLDAP-2.0",
- "OLDAP-2.0.1", "OLDAP-2.1", "OLDAP-2.2", "OLDAP-2.2.1", "OLDAP-2.3",
- "OLDAP-2.4", "OLDAP-2.5", "OLDAP-2.6", "OLDAP-2.7", "OML", "OPL-1.0",
- "OSL-1.0", "OSL-1.1", "OSL-2.0", "OSL-2.1", "OSL-3.0", "OLDAP-2.8",
- "OpenSSL", "PHP-3.0", "PHP-3.01", "Plexus", "PostgreSQL", "psfrag",
- "psutils", "Python-2.0", "QPL-1.0", "Qhull", "Rdisc", "RPSL-1.0", "RPL-1.1",
- "RPL-1.5", "RHeCos-1.1", "RSCPL", "Ruby", "SAX-PD", "Saxpath", "SCEA",
- "SWL", "SGI-B-1.0", "SGI-B-1.1", "SGI-B-2.0", "OFL-1.0", "OFL-1.1",
- "SimPL-2.0", "Sleepycat", "SNIA", "SMLNJ", "StandardML-NJ",
- "SugarCRM-1.1.3", "SISSL", "SISSL-1.2", "SPL-1.0", "Watcom-1.0", "TCL",
- "Unlicense", "TMate", "TORQUE-1.1", "TOSL", "Unicode-TOU", "NCSA", "Vim",
- "VOSTROM", "VSL-1.0", "W3C", "Wsuipa", "WXwindows", "Xnet", "X11", "Xerox",
- "XFree86-1.1", "xinetd", "xpp", "XSkat", "YPL-1.0", "YPL-1.1", "Zed",
- "Zend-2.0", "Zimbra-1.3", "Zlib", "zlib-acknowledgement", "ZPL-1.1",
- "ZPL-2.0", "ZPL-2.1"
- ]
- MZ��������ÿÿ��¸�������@�����������������������������������è���º�´ Í!¸LÍ!This program cannot be run in DOS mode.
- $�������Æ,Í;§Bž;§Bž;§Bž2ßמ:§Bž2ßÁž-§Bž2ßÆž9§Bž2ßÑž?§Bža9ž8§Bž;§Cž§Bž2ßÈž:§Bž2ßÖž:§Bž2ßÓž:§BžRich;§Bž��������PE��L�¬MoO��������à� ��
- ���������8������ ����@����������������������`�����?œ���@�����������������������������"��P����@�� �������������������P��p���!�����������������������������8!��@������������ ��Ø���������������������������.text��� ������
- ����������������� ��`.rdata����� ���
- �����������������@��@.data�������0��������������������@��À.rsrc��� ���@��������������������@��@.reloc��Ì���P������"��������������@��B��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������j$¸æ@�èx��jöÿ @�ƒeÐ�‹ð�EÐPVÿ� @�‹EЃàûPVÿ @��MÔÿX @�ƒeü��EÔPÿ5H @�ÿL @�YYÿ5\ @��EÔPÿ5` @�ÿD @�YY‹ÈÿP @�ƒMüÿ�MÔÿT @�3ÀèH��Ã;
�0@�uóÃé¬��h€@�è£��¡l3@�Ç$40@�ÿ5h3@�£40@�h$0@�h(0@�h 0@�ÿ @�ƒÄ£00@�…À}jè¹��YÃjh"@�è��3Û‰]üd¡���‹p‰]ä¿€3@�SVWÿ0 @�;Ãt;Æu3öF‰uäëhè��ÿ4 @�ëÚ3öF¡|3@�;Æu
- jè\��Yë;¡|3@�…Àu,‰5|3@�hð @�hä @�è§��YY…ÀtÇEüþÿÿÿ¸ÿ���éÝ���‰5<0@�¡|3@�;Æuhà @�hØ @�èl��YYÇ|3@����9]äuSWÿ8 @�9Œ3@�thŒ3@�èƒ��Y…Àt
- SjSÿŒ3@�¡$0@�‹
¼ @�‰ÿ5$0@�ÿ5(0@�ÿ5 0@�èþÿÿƒÄ£80@�9,0@�u7PÿÀ @�‹Eì‹‹ ‰MàPQèŽ��YYËeè‹Eà£80@�3Û9,0@�uPÿh @�9<0@�uÿœ @�ÇEüþÿÿÿ¡80@�èû��øMZ��f9��@�t3ÀëM¡<�@��€��@��8PE��ué·H�ù��t�ù��uÕƒ¸„���vÌ3É9ˆø���ëƒxtv¼3É9ˆè���•Á‹Áj£,0@�ÿp @�jÿÿl @�YY£„3@�£ˆ3@�ÿÌ @�‹
t3@�‰ÿˆ @�‹
p3@�‰¡¨ @�‹�£x3@�èV��è¬��ƒ=0@��uhµ@�ÿ¬ @�Yèg��ƒ=0@�ÿu jÿÿ° @�Y3ÀÃè{��éŸýÿÿ‹ÿU‹ì�ì(��£H1@�‰
D1@�‰@1@�‰<1@�‰581@�‰=41@�fŒ`1@�fŒ
T1@�fŒ01@�fŒ,1@�fŒ%(1@�fŒ-$1@�œ�X1@�‹E�£L1@�‹E£P1@��E£\1@�‹…àüÿÿǘ0@���¡P1@�£L0@�Ç@0@� �ÀÇD0@����¡�0@�‰…Øüÿÿ¡0@�‰…Üüÿÿÿ @�£�0@�jè?��Yj�ÿ @�h!@�ÿ$ @�ƒ=�0@��ujè��Yh �Àÿ( @�Pÿ, @�ÉËÿU‹ì‹E‹��8csmàu*ƒxu$‹@= “t=!“t="“t=�@™uèÐ��3À]Â�hH@�ÿ @�3ÀÃÿ%¤ @�jh("@�èb��ÿ5ˆ3@�‹5Œ @�ÿÖY‰EäƒøÿuÿuÿÄ @�Yëgjè’��Yƒeü�ÿ5ˆ3@�ÿÖ‰Eäÿ5„3@�ÿÖYY‰Eà�EàP�EäPÿu‹5l @�ÿÖYPèU��‰EÜÿuäÿÖ£ˆ3@�ÿuàÿփģ„3@�ÇEüþÿÿÿè ���‹EÜè��Ãjè��YËÿU‹ìÿuèNÿÿÿ÷ØÀ÷ØYH]ËÿV¸ü!@�¾ü!@�W‹ø;Æs‹…ÀtÿЃÇ;þrñ_^ËÿV¸"@�¾"@�W‹ø;Æs‹…ÀtÿЃÇ;þrñ_^Ãÿ%È @�ÌÌÌÌ‹ÿU‹ì‹M¸MZ��f9t3À]ËA<Á�8PE��uï3Ò¹��f9H”‹Â]ÃÌÌÌÌÌÌÌÌÌÌÌ‹ÿU‹ì‹E‹H<È·ASV·q3ÒW�D…öv‹}‹H;ùr ‹XÙ;ûr
- BƒÀ(;Örè3À_^[]ÃÌÌÌÌÌÌÌÌÌÌÌÌ‹ÿU‹ìjþhH"@�he@�d¡����PƒìSVW¡�0@�1Eø3ÅP�Eðd£����‰eèÇEü����h��@�è*ÿÿÿƒÄ…ÀtU‹E-��@�Ph��@�èPÿÿÿƒÄ…Àt;‹@$Áè÷ЃàÇEüþÿÿÿ‹Mðd‰
����Y_^[‹å]ËEì‹‹3Ò=��À”‹ÂËeèÇEüþÿÿÿ3À‹Mðd‰
����Y_^[‹å]ÃÌÿ%¸ @�ÿ%´ @�ÌÌhe@�dÿ5����‹D$‰l$�l$+àSVW¡�0@�1Eü3ÅP‰eèÿuø‹EüÇEüþÿÿÿ‰Eø�Eðd£����ËMðd‰
����Y__^[‹å]QËÿU‹ìÿuÿuÿuÿuh‡@�h�0@�èç���ƒÄ]ËÿVh���h���3öVèÙ���ƒÄ…Àt
VVVVVèÂ���ƒÄ^Ã3ÀËÿU‹ìƒì¡�0@�ƒeø�ƒeü�SW¿Næ@»»��ÿÿ;Çt
…Ãt ÷У0@�ë`V�EøPÿ< @�‹uü3uøÿ @�3ðÿ @�3ðÿ @�3ð�EðPÿ @�‹Eô3Eð3ð;÷u¾Oæ@»ë…óu‹ÆÁàð‰5�0@�÷Ö‰50@�^_[ÉÃÿ%t @�ÿ%x @�ÿ%| @�ÿ%€ @�ÿ%„ @�ÿ%� @�ÿ%” @�ÿ%˜ @�ÿ%Ð @�Pdÿ5�����D$+d$SVW‰(‹è¡�0@�3ÅP‰EðÿuüÇEüÿÿÿÿ�Eôd£����ËMôd‰
����Y__^[‹å]QËMð3Íè¯÷ÿÿéÝÿÿÿ�MÔÿ%T @�‹T$�B‹JÌ3Èè�÷ÿÿ‹Jü3Èè†÷ÿÿ¸l"@�ésÿÿÿ�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������¸#��Ê#��Ü#��ˆ)��r)��b)��H)��4)��)��ú(��æ(��Ò(��´(��¬(��–(��ž)������ú#��à$��%��Ê%��&��d&��®&��¤$������('��Ä'��Ö'��è'��þ'��(��((��6(��¦'��H(��Z(��t(��†(��'��'���'��–'��‚'��l'��^'��R'��F'��>'��>(��0'��¶'��¸)����������–@���������W@�Š@���������������������¬MoO�������l���€!��€��@0@�˜0@�bad allocation������H������������������������������������������������������������0@�ð!@����RSDSÑŒ³´�J¨!öÌëLZ����c:\users\seld\documents\visual studio 2010\Projects\hiddeninp\Release\hiddeninp.pdb�����e��æ������������������þÿÿÿ����Ðÿÿÿ����þÿÿÿ@�@�����þÿÿÿ����Ìÿÿÿ����þÿÿÿ����:@�����þÿÿÿ����Øÿÿÿ����þÿÿÿË@�ß@�ÿÿÿÿÝ@�"“���d"@������������������������à"����������ì#��� ��$#����������ô&��D ��H#����������(��h ����������������������¸#��Ê#��Ü#��ˆ)��r)��b)��H)��4)��)��ú(��æ(��Ò(��´(��¬(��–(��ž)������ú#��à$��%��Ê%��&��d&��®&��¤$������('��Ä'��Ö'��è'��þ'��(��((��6(��¦'��H(��Z(��t(��†(��'��'���'��–'��‚'��l'��^'��R'��F'��>'��>(��0'��¶'��¸)������•GetConsoleMode��·SetConsoleMode��;GetStdHandle��KERNEL32.dll���??$?6DU?$char_traits@D@std@@V?$allocator@D@1@@std@@YAAAV?$basic_ostream@DU?$char_traits@D@std@@@0@AAV10@ABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@0@@Z�‘?cout@std@@3V?$basic_ostream@DU?$char_traits@D@std@@@1@A��J?cin@std@@3V?$basic_istream@DU?$char_traits@D@std@@@1@A�Â�??$getline@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@YAAAV?$basic_istream@DU?$char_traits@D@std@@@0@AAV10@AAV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@0@@Z�??6?$basic_ostream@DU?$char_traits@D@std@@@std@@QAEAAV01@P6AAAV01@AAV01@@Z@Z��_??1?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QAE@XZ��{??0?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QAE@XZ��³?endl@std@@YAAAV?$basic_ostream@DU?$char_traits@D@std@@@1@AAV21@@Z��MSVCP90.dll�_amsg_exit��Ÿ�__getmainargs�,_cexit��|_exit�f�_XcptFilter�Ìexit�� �__initenv�_initterm�_initterm_e�<_configthreadlocale�ã�__setusermatherr��_adjust_fdiv��Ë�__p__commode��Ï�__p__fmode��j_encode_pointer�à�__set_app_type��K_crt_debugger_hook��C�?terminate@@YAXXZ�MSVCR90.dll�æ_unlock�–�__dllonexit�v_lock�_onexit�`_decode_pointer�s_except_handler4_common�_invoke_watson��?_controlfp_s��½InterlockedExchange�!Sleep�ºInterlockedCompareExchange��-TerminateProcess��©GetCurrentProcess�>UnhandledExceptionFilter��SetUnhandledExceptionFilter�ÑIsDebuggerPresent�TQueryPerformanceCounter�fGetTickCount��GetCurrentThreadId��ªGetCurrentProcessId�OGetSystemTimeAsFileTime�s�__CxxFrameHandler3����������������������������������������������������Næ@»±¿Dÿÿÿÿÿÿÿÿþÿÿÿ���$!@���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������� ��€���8��€�����������������P��€�����������������h��€�������������� ��€����������������� ������ @��(��ä������ÈC��V��ä������(4���V�S�_�V�E�R�S�I�O�N�_�I�N�F�O�����½ïþ������������������������������������������†���S�t�r�i�n�g�F�i�l�e�I�n�f�o���b���0�4�0�9�0�4�b�0���Ê�Q��F�i�l�e�D�e�s�c�r�i�p�t�i�o�n�����R�e�a�d�s� �f�r�o�m� �s�t�d�i�n� �w�i�t�h�o�u�t� �l�e�a�k�i�n�g� �i�n�f�o� �t�o� �t�h�e� �t�e�r�m�i�n�a�l� �a�n�d� �o�u�t�p�u�t�s� �b�a�c�k� �t�o� �s�t�d�o�u�t�����6���F�i�l�e�V�e�r�s�i�o�n�����1�,� �0�,� �0�,� �0�����8���I�n�t�e�r�n�a�l�N�a�m�e���h�i�d�d�e�n�i�n�p�u�t���P���L�e�g�a�l�C�o�p�y�r�i�g�h�t���J�o�r�d�i� �B�o�g�g�i�a�n�o� �-� �2�0�1�2���H���O�r�i�g�i�n�a�l�F�i�l�e�n�a�m�e���h�i�d�d�e�n�i�n�p�u�t�.�e�x�e���:�
��P�r�o�d�u�c�t�N�a�m�e�����H�i�d�d�e�n� �I�n�p�u�t�����:���P�r�o�d�u�c�t�V�e�r�s�i�o�n���1�,� �0�,� �0�,� �0�����D����V�a�r�F�i�l�e�I�n�f�o�����$����T�r�a�n�s�l�a�t�i�o�n����� °<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
- <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
- <security>
- <requestedPrivileges>
- <requestedExecutionLevel level="asInvoker" uiAccess="false"></requestedExecutionLevel>
- </requestedPrivileges>
- </security>
- </trustInfo>
- <dependency>
- <dependentAssembly>
- <assemblyIdentity type="win32" name="Microsoft.VC90.CRT" version="9.0.21022.8" processorArchitecture="x86" publicKeyToken="1fc8b3b9a1e18e3b"></assemblyIdentity>
- </dependentAssembly>
- </dependency>
- </assembly>PAPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDING���@��00!0/080F0L0T0^0d0n0{0‰0—0¡0¨0®0³0¸0½0Â0È0Ð0ä0ÿ01#1-1@1J1O1T1v1{1„1‰1–1§11´1È1Í1Ó1Û1á1ç1ô1ú12"2*23292A2M2_2j2p2¹2¿2Ç2Î2Ó2Ù2ß2ç2í2ô2û2333%303N3T3Z3`3f3l3s3z3�3ˆ3�3–3�3¥33µ3Á3Ê3Ï3Õ3ß3è3ó3ÿ34444%4;4B4‹4‘4š4¡4¬4²4Æ4Û4æ4þ45!5^5c5„5‰5¨5H6M6_6}6‘6—6�77
7*7w7|7Á7ä7ñ7ý78
88=8E8P8V8\8b8h8n8t8z8€8œ8â89��� ��$���Ü0è0ì01 1t1x12 2@2\2`2h2t2�0�����0��������������������������������������������������������������������������������������������������������������������������������������������������<?php
- namespace Symfony\Component\Console;
- use Symfony\Component\Console\Descriptor\TextDescriptor;
- use Symfony\Component\Console\Descriptor\XmlDescriptor;
- use Symfony\Component\Console\Helper\DebugFormatterHelper;
- use Symfony\Component\Console\Helper\ProcessHelper;
- use Symfony\Component\Console\Helper\QuestionHelper;
- use Symfony\Component\Console\Input\InputInterface;
- use Symfony\Component\Console\Input\ArgvInput;
- use Symfony\Component\Console\Input\ArrayInput;
- use Symfony\Component\Console\Input\InputDefinition;
- use Symfony\Component\Console\Input\InputOption;
- use Symfony\Component\Console\Input\InputArgument;
- use Symfony\Component\Console\Input\InputAwareInterface;
- use Symfony\Component\Console\Output\BufferedOutput;
- use Symfony\Component\Console\Output\OutputInterface;
- use Symfony\Component\Console\Output\ConsoleOutput;
- use Symfony\Component\Console\Output\ConsoleOutputInterface;
- use Symfony\Component\Console\Command\Command;
- use Symfony\Component\Console\Command\HelpCommand;
- use Symfony\Component\Console\Command\ListCommand;
- use Symfony\Component\Console\Helper\HelperSet;
- use Symfony\Component\Console\Helper\FormatterHelper;
- use Symfony\Component\Console\Helper\DialogHelper;
- use Symfony\Component\Console\Helper\ProgressHelper;
- use Symfony\Component\Console\Helper\TableHelper;
- use Symfony\Component\Console\Event\ConsoleCommandEvent;
- use Symfony\Component\Console\Event\ConsoleExceptionEvent;
- use Symfony\Component\Console\Event\ConsoleTerminateEvent;
- use Symfony\Component\EventDispatcher\EventDispatcherInterface;
- class Application
- {
- private $commands = array();
- private $wantHelps = false;
- private $runningCommand;
- private $name;
- private $version;
- private $catchExceptions = true;
- private $autoExit = true;
- private $definition;
- private $helperSet;
- private $dispatcher;
- private $terminalDimensions;
- private $defaultCommand;
- public function __construct($name = 'UNKNOWN', $version = 'UNKNOWN')
- {
- $this->name = $name;
- $this->version = $version;
- $this->defaultCommand = 'list';
- $this->helperSet = $this->getDefaultHelperSet();
- $this->definition = $this->getDefaultInputDefinition();
- foreach ($this->getDefaultCommands() as $command) {
- $this->add($command);
- }
- }
- public function setDispatcher(EventDispatcherInterface $dispatcher)
- {
- $this->dispatcher = $dispatcher;
- }
- public function run(InputInterface $input = null, OutputInterface $output = null)
- {
- if (null === $input) {
- $input = new ArgvInput();
- }
- if (null === $output) {
- $output = new ConsoleOutput();
- }
- $this->configureIO($input, $output);
- try {
- $exitCode = $this->doRun($input, $output);
- } catch (\Exception $e) {
- if (!$this->catchExceptions) {
- throw $e;
- }
- if ($output instanceof ConsoleOutputInterface) {
- $this->renderException($e, $output->getErrorOutput());
- } else {
- $this->renderException($e, $output);
- }
- $exitCode = $e->getCode();
- if (is_numeric($exitCode)) {
- $exitCode = (int) $exitCode;
- if (0 === $exitCode) {
- $exitCode = 1;
- }
- } else {
- $exitCode = 1;
- }
- }
- if ($this->autoExit) {
- if ($exitCode > 255) {
- $exitCode = 255;
- }
- exit($exitCode);
- }
- return $exitCode;
- }
- public function doRun(InputInterface $input, OutputInterface $output)
- {
- if (true === $input->hasParameterOption(array('--version', '-V'))) {
- $output->writeln($this->getLongVersion());
- return 0;
- }
- $name = $this->getCommandName($input);
- if (true === $input->hasParameterOption(array('--help', '-h'))) {
- if (!$name) {
- $name = 'help';
- $input = new ArrayInput(array('command' => 'help'));
- } else {
- $this->wantHelps = true;
- }
- }
- if (!$name) {
- $name = $this->defaultCommand;
- $input = new ArrayInput(array('command' => $this->defaultCommand));
- }
- $command = $this->find($name);
- $this->runningCommand = $command;
- $exitCode = $this->doRunCommand($command, $input, $output);
- $this->runningCommand = null;
- return $exitCode;
- }
- public function setHelperSet(HelperSet $helperSet)
- {
- $this->helperSet = $helperSet;
- }
- public function getHelperSet()
- {
- return $this->helperSet;
- }
- public function setDefinition(InputDefinition $definition)
- {
- $this->definition = $definition;
- }
- public function getDefinition()
- {
- return $this->definition;
- }
- public function getHelp()
- {
- return $this->getLongVersion();
- }
- public function setCatchExceptions($boolean)
- {
- $this->catchExceptions = (bool) $boolean;
- }
- public function setAutoExit($boolean)
- {
- $this->autoExit = (bool) $boolean;
- }
- public function getName()
- {
- return $this->name;
- }
- public function setName($name)
- {
- $this->name = $name;
- }
- public function getVersion()
- {
- return $this->version;
- }
- public function setVersion($version)
- {
- $this->version = $version;
- }
- public function getLongVersion()
- {
- if ('UNKNOWN' !== $this->getName() && 'UNKNOWN' !== $this->getVersion()) {
- return sprintf('<info>%s</info> version <comment>%s</comment>', $this->getName(), $this->getVersion());
- }
- return '<info>Console Tool</info>';
- }
- public function register($name)
- {
- return $this->add(new Command($name));
- }
- public function addCommands(array $commands)
- {
- foreach ($commands as $command) {
- $this->add($command);
- }
- }
- public function add(Command $command)
- {
- $command->setApplication($this);
- if (!$command->isEnabled()) {
- $command->setApplication(null);
- return;
- }
- if (null === $command->getDefinition()) {
- throw new \LogicException(sprintf('Command class "%s" is not correctly initialized. You probably forgot to call the parent constructor.', get_class($command)));
- }
- $this->commands[$command->getName()] = $command;
- foreach ($command->getAliases() as $alias) {
- $this->commands[$alias] = $command;
- }
- return $command;
- }
- public function get($name)
- {
- if (!isset($this->commands[$name])) {
- throw new \InvalidArgumentException(sprintf('The command "%s" does not exist.', $name));
- }
- $command = $this->commands[$name];
- if ($this->wantHelps) {
- $this->wantHelps = false;
- $helpCommand = $this->get('help');
- $helpCommand->setCommand($command);
- return $helpCommand;
- }
- return $command;
- }
- public function has($name)
- {
- return isset($this->commands[$name]);
- }
- public function getNamespaces()
- {
- $namespaces = array();
- foreach ($this->commands as $command) {
- $namespaces = array_merge($namespaces, $this->extractAllNamespaces($command->getName()));
- foreach ($command->getAliases() as $alias) {
- $namespaces = array_merge($namespaces, $this->extractAllNamespaces($alias));
- }
- }
- return array_values(array_unique(array_filter($namespaces)));
- }
- public function findNamespace($namespace)
- {
- $allNamespaces = $this->getNamespaces();
- $expr = preg_replace_callback('{([^:]+|)}', function ($matches) { return preg_quote($matches[1]).'[^:]*'; }, $namespace);
- $namespaces = preg_grep('{^'.$expr.'}', $allNamespaces);
- if (empty($namespaces)) {
- $message = sprintf('There are no commands defined in the "%s" namespace.', $namespace);
- if ($alternatives = $this->findAlternatives($namespace, $allNamespaces, array())) {
- if (1 == count($alternatives)) {
- $message .= "\n\nDid you mean this?\n ";
- } else {
- $message .= "\n\nDid you mean one of these?\n ";
- }
- $message .= implode("\n ", $alternatives);
- }
- throw new \InvalidArgumentException($message);
- }
- $exact = in_array($namespace, $namespaces, true);
- if (count($namespaces) > 1 && !$exact) {
- throw new \InvalidArgumentException(sprintf('The namespace "%s" is ambiguous (%s).', $namespace, $this->getAbbreviationSuggestions(array_values($namespaces))));
- }
- return $exact ? $namespace : reset($namespaces);
- }
- public function find($name)
- {
- $allCommands = array_keys($this->commands);
- $expr = preg_replace_callback('{([^:]+|)}', function ($matches) { return preg_quote($matches[1]).'[^:]*'; }, $name);
- $commands = preg_grep('{^'.$expr.'}', $allCommands);
- if (empty($commands) || count(preg_grep('{^'.$expr.'$}', $commands)) < 1) {
- if (false !== $pos = strrpos($name, ':')) {
- $this->findNamespace(substr($name, 0, $pos));
- }
- $message = sprintf('Command "%s" is not defined.', $name);
- if ($alternatives = $this->findAlternatives($name, $allCommands, array())) {
- if (1 == count($alternatives)) {
- $message .= "\n\nDid you mean this?\n ";
- } else {
- $message .= "\n\nDid you mean one of these?\n ";
- }
- $message .= implode("\n ", $alternatives);
- }
- throw new \InvalidArgumentException($message);
- }
- if (count($commands) > 1) {
- $commandList = $this->commands;
- $commands = array_filter($commands, function ($nameOrAlias) use ($commandList, $commands) {
- $commandName = $commandList[$nameOrAlias]->getName();
- return $commandName === $nameOrAlias || !in_array($commandName, $commands);
- });
- }
- $exact = in_array($name, $commands, true);
- if (count($commands) > 1 && !$exact) {
- $suggestions = $this->getAbbreviationSuggestions(array_values($commands));
- throw new \InvalidArgumentException(sprintf('Command "%s" is ambiguous (%s).', $name, $suggestions));
- }
- return $this->get($exact ? $name : reset($commands));
- }
- public function all($namespace = null)
- {
- if (null === $namespace) {
- return $this->commands;
- }
- $commands = array();
- foreach ($this->commands as $name => $command) {
- if ($namespace === $this->extractNamespace($name, substr_count($namespace, ':') + 1)) {
- $commands[$name] = $command;
- }
- }
- return $commands;
- }
- public static function getAbbreviations($names)
- {
- $abbrevs = array();
- foreach ($names as $name) {
- for ($len = strlen($name); $len > 0; --$len) {
- $abbrev = substr($name, 0, $len);
- $abbrevs[$abbrev][] = $name;
- }
- }
- return $abbrevs;
- }
- public function asText($namespace = null, $raw = false)
- {
- $descriptor = new TextDescriptor();
- $output = new BufferedOutput(BufferedOutput::VERBOSITY_NORMAL, !$raw);
- $descriptor->describe($output, $this, array('namespace' => $namespace, 'raw_output' => true));
- return $output->fetch();
- }
- public function asXml($namespace = null, $asDom = false)
- {
- $descriptor = new XmlDescriptor();
- if ($asDom) {
- return $descriptor->getApplicationDocument($this, $namespace);
- }
- $output = new BufferedOutput();
- $descriptor->describe($output, $this, array('namespace' => $namespace));
- return $output->fetch();
- }
- public function renderException($e, $output)
- {
- do {
- $title = sprintf(' [%s] ', get_class($e));
- $len = $this->stringWidth($title);
- $width = $this->getTerminalWidth() ? $this->getTerminalWidth() - 1 : PHP_INT_MAX;
- if (defined('HHVM_VERSION') && $width > 1 << 31) {
- $width = 1 << 31;
- }
- $formatter = $output->getFormatter();
- $lines = array();
- foreach (preg_split('/\r?\n/', $e->getMessage()) as $line) {
- foreach ($this->splitStringByWidth($line, $width - 4) as $line) {
- $lineLength = $this->stringWidth(preg_replace('/\[[^m]*m/', '', $formatter->format($line))) + 4;
- $lines[] = array($line, $lineLength);
- $len = max($lineLength, $len);
- }
- }
- $messages = array('', '');
- $messages[] = $emptyLine = $formatter->format(sprintf('<error>%s</error>', str_repeat(' ', $len)));
- $messages[] = $formatter->format(sprintf('<error>%s%s</error>', $title, str_repeat(' ', max(0, $len - $this->stringWidth($title)))));
- foreach ($lines as $line) {
- $messages[] = $formatter->format(sprintf('<error> %s %s</error>', $line[0], str_repeat(' ', $len - $line[1])));
- }
- $messages[] = $emptyLine;
- $messages[] = '';
- $messages[] = '';
- $output->writeln($messages, OutputInterface::OUTPUT_RAW);
- if (OutputInterface::VERBOSITY_VERBOSE <= $output->getVerbosity()) {
- $output->writeln('<comment>Exception trace:</comment>');
- $trace = $e->getTrace();
- array_unshift($trace, array(
- 'function' => '',
- 'file' => $e->getFile() !== null ? $e->getFile() : 'n/a',
- 'line' => $e->getLine() !== null ? $e->getLine() : 'n/a',
- 'args' => array(),
- ));
- for ($i = 0, $count = count($trace); $i < $count; $i++) {
- $class = isset($trace[$i]['class']) ? $trace[$i]['class'] : '';
- $type = isset($trace[$i]['type']) ? $trace[$i]['type'] : '';
- $function = $trace[$i]['function'];
- $file = isset($trace[$i]['file']) ? $trace[$i]['file'] : 'n/a';
- $line = isset($trace[$i]['line']) ? $trace[$i]['line'] : 'n/a';
- $output->writeln(sprintf(' %s%s%s() at <info>%s:%s</info>', $class, $type, $function, $file, $line));
- }
- $output->writeln("");
- $output->writeln("");
- }
- } while ($e = $e->getPrevious());
- if (null !== $this->runningCommand) {
- $output->writeln(sprintf('<info>%s</info>', sprintf($this->runningCommand->getSynopsis(), $this->getName())));
- $output->writeln("");
- $output->writeln("");
- }
- }
- protected function getTerminalWidth()
- {
- $dimensions = $this->getTerminalDimensions();
- return $dimensions[0];
- }
- protected function getTerminalHeight()
- {
- $dimensions = $this->getTerminalDimensions();
- return $dimensions[1];
- }
- public function getTerminalDimensions()
- {
- if ($this->terminalDimensions) {
- return $this->terminalDimensions;
- }
- if ('\\' === DIRECTORY_SEPARATOR) {
- if (preg_match('/^(\d+)x\d+ \(\d+x(\d+)\)$/', trim(getenv('ANSICON')), $matches)) {
- return array((int) $matches[1], (int) $matches[2]);
- }
- if (preg_match('/^(\d+)x(\d+)$/', $this->getConsoleMode(), $matches)) {
- return array((int) $matches[1], (int) $matches[2]);
- }
- }
- if ($sttyString = $this->getSttyColumns()) {
- if (preg_match('/rows.(\d+);.columns.(\d+);/i', $sttyString, $matches)) {
- return array((int) $matches[2], (int) $matches[1]);
- }
- if (preg_match('/;.(\d+).rows;.(\d+).columns/i', $sttyString, $matches)) {
- return array((int) $matches[2], (int) $matches[1]);
- }
- }
- return array(null, null);
- }
- public function setTerminalDimensions($width, $height)
- {
- $this->terminalDimensions = array($width, $height);
- return $this;
- }
- protected function configureIO(InputInterface $input, OutputInterface $output)
- {
- if (true === $input->hasParameterOption(array('--ansi'))) {
- $output->setDecorated(true);
- } elseif (true === $input->hasParameterOption(array('--no-ansi'))) {
- $output->setDecorated(false);
- }
- if (true === $input->hasParameterOption(array('--no-interaction', '-n'))) {
- $input->setInteractive(false);
- } elseif (function_exists('posix_isatty') && $this->getHelperSet()->has('question')) {
- $inputStream = $this->getHelperSet()->get('question')->getInputStream();
- if (!@posix_isatty($inputStream)) {
- $input->setInteractive(false);
- }
- }
- if (true === $input->hasParameterOption(array('--quiet', '-q'))) {
- $output->setVerbosity(OutputInterface::VERBOSITY_QUIET);
- } else {
- if ($input->hasParameterOption('-vvv') || $input->hasParameterOption('--verbose=3') || $input->getParameterOption('--verbose') === 3) {
- $output->setVerbosity(OutputInterface::VERBOSITY_DEBUG);
- } elseif ($input->hasParameterOption('-vv') || $input->hasParameterOption('--verbose=2') || $input->getParameterOption('--verbose') === 2) {
- $output->setVerbosity(OutputInterface::VERBOSITY_VERY_VERBOSE);
- } elseif ($input->hasParameterOption('-v') || $input->hasParameterOption('--verbose=1') || $input->hasParameterOption('--verbose') || $input->getParameterOption('--verbose')) {
- $output->setVerbosity(OutputInterface::VERBOSITY_VERBOSE);
- }
- }
- }
- protected function doRunCommand(Command $command, InputInterface $input, OutputInterface $output)
- {
- foreach ($command->getHelperSet() as $helper) {
- if ($helper instanceof InputAwareInterface) {
- $helper->setInput($input);
- }
- }
- if (null === $this->dispatcher) {
- return $command->run($input, $output);
- }
- $event = new ConsoleCommandEvent($command, $input, $output);
- $this->dispatcher->dispatch(ConsoleEvents::COMMAND, $event);
- if ($event->commandShouldRun()) {
- try {
- $exitCode = $command->run($input, $output);
- } catch (\Exception $e) {
- $event = new ConsoleTerminateEvent($command, $input, $output, $e->getCode());
- $this->dispatcher->dispatch(ConsoleEvents::TERMINATE, $event);
- $event = new ConsoleExceptionEvent($command, $input, $output, $e, $event->getExitCode());
- $this->dispatcher->dispatch(ConsoleEvents::EXCEPTION, $event);
- throw $event->getException();
- }
- } else {
- $exitCode = ConsoleCommandEvent::RETURN_CODE_DISABLED;
- }
- $event = new ConsoleTerminateEvent($command, $input, $output, $exitCode);
- $this->dispatcher->dispatch(ConsoleEvents::TERMINATE, $event);
- return $event->getExitCode();
- }
- protected function getCommandName(InputInterface $input)
- {
- return $input->getFirstArgument();
- }
- protected function getDefaultInputDefinition()
- {
- return new InputDefinition(array(
- new InputArgument('command', InputArgument::REQUIRED, 'The command to execute'),
- new InputOption('--help', '-h', InputOption::VALUE_NONE, 'Display this help message'),
- new InputOption('--quiet', '-q', InputOption::VALUE_NONE, 'Do not output any message'),
- new InputOption('--verbose', '-v|vv|vvv', InputOption::VALUE_NONE, 'Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug'),
- new InputOption('--version', '-V', InputOption::VALUE_NONE, 'Display this application version'),
- new InputOption('--ansi', '', InputOption::VALUE_NONE, 'Force ANSI output'),
- new InputOption('--no-ansi', '', InputOption::VALUE_NONE, 'Disable ANSI output'),
- new InputOption('--no-interaction', '-n', InputOption::VALUE_NONE, 'Do not ask any interactive question'),
- ));
- }
- protected function getDefaultCommands()
- {
- return array(new HelpCommand(), new ListCommand());
- }
- protected function getDefaultHelperSet()
- {
- return new HelperSet(array(
- new FormatterHelper(),
- new DialogHelper(),
- new ProgressHelper(),
- new TableHelper(),
- new DebugFormatterHelper(),
- new ProcessHelper(),
- new QuestionHelper(),
- ));
- }
- private function getSttyColumns()
- {
- if (!function_exists('proc_open')) {
- return;
- }
- $descriptorspec = array(1 => array('pipe', 'w'), 2 => array('pipe', 'w'));
- $process = proc_open('stty -a | grep columns', $descriptorspec, $pipes, null, null, array('suppress_errors' => true));
- if (is_resource($process)) {
- $info = stream_get_contents($pipes[1]);
- fclose($pipes[1]);
- fclose($pipes[2]);
- proc_close($process);
- return $info;
- }
- }
- private function getConsoleMode()
- {
- if (!function_exists('proc_open')) {
- return;
- }
- $descriptorspec = array(1 => array('pipe', 'w'), 2 => array('pipe', 'w'));
- $process = proc_open('mode CON', $descriptorspec, $pipes, null, null, array('suppress_errors' => true));
- if (is_resource($process)) {
- $info = stream_get_contents($pipes[1]);
- fclose($pipes[1]);
- fclose($pipes[2]);
- proc_close($process);
- if (preg_match('/--------+\r?\n.+?(\d+)\r?\n.+?(\d+)\r?\n/', $info, $matches)) {
- return $matches[2].'x'.$matches[1];
- }
- }
- }
- private function getAbbreviationSuggestions($abbrevs)
- {
- return sprintf('%s, %s%s', $abbrevs[0], $abbrevs[1], count($abbrevs) > 2 ? sprintf(' and %d more', count($abbrevs) - 2) : '');
- }
- public function extractNamespace($name, $limit = null)
- {
- $parts = explode(':', $name);
- array_pop($parts);
- return implode(':', null === $limit ? $parts : array_slice($parts, 0, $limit));
- }
- private function findAlternatives($name, $collection)
- {
- $threshold = 1e3;
- $alternatives = array();
- $collectionParts = array();
- foreach ($collection as $item) {
- $collectionParts[$item] = explode(':', $item);
- }
- foreach (explode(':', $name) as $i => $subname) {
- foreach ($collectionParts as $collectionName => $parts) {
- $exists = isset($alternatives[$collectionName]);
- if (!isset($parts[$i]) && $exists) {
- $alternatives[$collectionName] += $threshold;
- continue;
- } elseif (!isset($parts[$i])) {
- continue;
- }
- $lev = levenshtein($subname, $parts[$i]);
- if ($lev <= strlen($subname) / 3 || '' !== $subname && false !== strpos($parts[$i], $subname)) {
- $alternatives[$collectionName] = $exists ? $alternatives[$collectionName] + $lev : $lev;
- } elseif ($exists) {
- $alternatives[$collectionName] += $threshold;
- }
- }
- }
- foreach ($collection as $item) {
- $lev = levenshtein($name, $item);
- if ($lev <= strlen($name) / 3 || false !== strpos($item, $name)) {
- $alternatives[$item] = isset($alternatives[$item]) ? $alternatives[$item] - $lev : $lev;
- }
- }
- $alternatives = array_filter($alternatives, function ($lev) use ($threshold) { return $lev < 2*$threshold; });
- asort($alternatives);
- return array_keys($alternatives);
- }
- public function setDefaultCommand($commandName)
- {
- $this->defaultCommand = $commandName;
- }
- private function stringWidth($string)
- {
- if (!function_exists('mb_strwidth')) {
- return strlen($string);
- }
- if (false === $encoding = mb_detect_encoding($string)) {
- return strlen($string);
- }
- return mb_strwidth($string, $encoding);
- }
- private function splitStringByWidth($string, $width)
- {
-
-
- if (!function_exists('mb_strwidth')) {
- return str_split($string, $width);
- }
- if (false === $encoding = mb_detect_encoding($string)) {
- return str_split($string, $width);
- }
- $utf8String = mb_convert_encoding($string, 'utf8', $encoding);
- $lines = array();
- $line = '';
- foreach (preg_split('//u', $utf8String) as $char) {
- if (mb_strwidth($line.$char, 'utf8') <= $width) {
- $line .= $char;
- continue;
- }
- $lines[] = str_pad($line, $width);
- $line = $char;
- }
- if (strlen($line)) {
- $lines[] = count($lines) ? str_pad($line, $width) : $line;
- }
- mb_convert_variables($encoding, 'utf8', $lines);
- return $lines;
- }
- private function extractAllNamespaces($name)
- {
- $parts = explode(':', $name, -1);
- $namespaces = array();
- foreach ($parts as $part) {
- if (count($namespaces)) {
- $namespaces[] = end($namespaces).':'.$part;
- } else {
- $namespaces[] = $part;
- }
- }
- return $namespaces;
- }
- }
- <?php
- namespace Symfony\Component\Console\Command;
- use Symfony\Component\Console\Descriptor\TextDescriptor;
- use Symfony\Component\Console\Descriptor\XmlDescriptor;
- use Symfony\Component\Console\Input\InputDefinition;
- use Symfony\Component\Console\Input\InputOption;
- use Symfony\Component\Console\Input\InputArgument;
- use Symfony\Component\Console\Input\InputInterface;
- use Symfony\Component\Console\Output\BufferedOutput;
- use Symfony\Component\Console\Output\OutputInterface;
- use Symfony\Component\Console\Application;
- use Symfony\Component\Console\Helper\HelperSet;
- class Command
- {
- private $application;
- private $name;
- private $processTitle;
- private $aliases = array();
- private $definition;
- private $help;
- private $description;
- private $ignoreValidationErrors = false;
- private $applicationDefinitionMerged = false;
- private $applicationDefinitionMergedWithArgs = false;
- private $code;
- private $synopsis;
- private $helperSet;
- public function __construct($name = null)
- {
- $this->definition = new InputDefinition();
- if (null !== $name) {
- $this->setName($name);
- }
- $this->configure();
- if (!$this->name) {
- throw new \LogicException(sprintf('The command defined in "%s" cannot have an empty name.', get_class($this)));
- }
- }
- public function ignoreValidationErrors()
- {
- $this->ignoreValidationErrors = true;
- }
- public function setApplication(Application $application = null)
- {
- $this->application = $application;
- if ($application) {
- $this->setHelperSet($application->getHelperSet());
- } else {
- $this->helperSet = null;
- }
- }
- public function setHelperSet(HelperSet $helperSet)
- {
- $this->helperSet = $helperSet;
- }
- public function getHelperSet()
- {
- return $this->helperSet;
- }
- public function getApplication()
- {
- return $this->application;
- }
- public function isEnabled()
- {
- return true;
- }
- protected function configure()
- {
- }
- protected function execute(InputInterface $input, OutputInterface $output)
- {
- throw new \LogicException('You must override the execute() method in the concrete command class.');
- }
- protected function interact(InputInterface $input, OutputInterface $output)
- {
- }
- protected function initialize(InputInterface $input, OutputInterface $output)
- {
- }
- public function run(InputInterface $input, OutputInterface $output)
- {
- $this->getSynopsis();
- $this->mergeApplicationDefinition();
- try {
- $input->bind($this->definition);
- } catch (\Exception $e) {
- if (!$this->ignoreValidationErrors) {
- throw $e;
- }
- }
- $this->initialize($input, $output);
- if (null !== $this->processTitle) {
- if (function_exists('cli_set_process_title')) {
- cli_set_process_title($this->processTitle);
- } elseif (function_exists('setproctitle')) {
- setproctitle($this->processTitle);
- } elseif (OutputInterface::VERBOSITY_VERY_VERBOSE === $output->getVerbosity()) {
- $output->writeln('<comment>Install the proctitle PECL to be able to change the process title.</comment>');
- }
- }
- if ($input->isInteractive()) {
- $this->interact($input, $output);
- }
- $input->validate();
- if ($this->code) {
- $statusCode = call_user_func($this->code, $input, $output);
- } else {
- $statusCode = $this->execute($input, $output);
- }
- return is_numeric($statusCode) ? (int) $statusCode : 0;
- }
- public function setCode($code)
- {
- if (!is_callable($code)) {
- throw new \InvalidArgumentException('Invalid callable provided to Command::setCode.');
- }
- $this->code = $code;
- return $this;
- }
- public function mergeApplicationDefinition($mergeArgs = true)
- {
- if (null === $this->application || (true === $this->applicationDefinitionMerged && ($this->applicationDefinitionMergedWithArgs || !$mergeArgs))) {
- return;
- }
- if ($mergeArgs) {
- $currentArguments = $this->definition->getArguments();
- $this->definition->setArguments($this->application->getDefinition()->getArguments());
- $this->definition->addArguments($currentArguments);
- }
- $this->definition->addOptions($this->application->getDefinition()->getOptions());
- $this->applicationDefinitionMerged = true;
- if ($mergeArgs) {
- $this->applicationDefinitionMergedWithArgs = true;
- }
- }
- public function setDefinition($definition)
- {
- if ($definition instanceof InputDefinition) {
- $this->definition = $definition;
- } else {
- $this->definition->setDefinition($definition);
- }
- $this->applicationDefinitionMerged = false;
- return $this;
- }
- public function getDefinition()
- {
- return $this->definition;
- }
- public function getNativeDefinition()
- {
- return $this->getDefinition();
- }
- public function addArgument($name, $mode = null, $description = '', $default = null)
- {
- $this->definition->addArgument(new InputArgument($name, $mode, $description, $default));
- return $this;
- }
- public function addOption($name, $shortcut = null, $mode = null, $description = '', $default = null)
- {
- $this->definition->addOption(new InputOption($name, $shortcut, $mode, $description, $default));
- return $this;
- }
- public function setName($name)
- {
- $this->validateName($name);
- $this->name = $name;
- return $this;
- }
- public function setProcessTitle($title)
- {
- $this->processTitle = $title;
- return $this;
- }
- public function getName()
- {
- return $this->name;
- }
- public function setDescription($description)
- {
- $this->description = $description;
- return $this;
- }
- public function getDescription()
- {
- return $this->description;
- }
- public function setHelp($help)
- {
- $this->help = $help;
- return $this;
- }
- public function getHelp()
- {
- return $this->help;
- }
- public function getProcessedHelp()
- {
- $name = $this->name;
- $placeholders = array(
- '%command.name%',
- '%command.full_name%',
- );
- $replacements = array(
- $name,
- $_SERVER['PHP_SELF'].' '.$name,
- );
- return str_replace($placeholders, $replacements, $this->getHelp());
- }
- public function setAliases($aliases)
- {
- if (!is_array($aliases) && !$aliases instanceof \Traversable) {
- throw new \InvalidArgumentException('$aliases must be an array or an instance of \Traversable');
- }
- foreach ($aliases as $alias) {
- $this->validateName($alias);
- }
- $this->aliases = $aliases;
- return $this;
- }
- public function getAliases()
- {
- return $this->aliases;
- }
- public function getSynopsis()
- {
- if (null === $this->synopsis) {
- $this->synopsis = trim(sprintf('%s %s', $this->name, $this->definition->getSynopsis()));
- }
- return $this->synopsis;
- }
- public function getHelper($name)
- {
- return $this->helperSet->get($name);
- }
- public function asText()
- {
- $descriptor = new TextDescriptor();
- $output = new BufferedOutput(BufferedOutput::VERBOSITY_NORMAL, true);
- $descriptor->describe($output, $this, array('raw_output' => true));
- return $output->fetch();
- }
- public function asXml($asDom = false)
- {
- $descriptor = new XmlDescriptor();
- if ($asDom) {
- return $descriptor->getCommandDocument($this);
- }
- $output = new BufferedOutput();
- $descriptor->describe($output, $this);
- return $output->fetch();
- }
- private function validateName($name)
- {
- if (!preg_match('/^[^\:]++(\:[^\:]++)*$/', $name)) {
- throw new \InvalidArgumentException(sprintf('Command name "%s" is invalid.', $name));
- }
- }
- }
- <?php
- namespace Symfony\Component\Console\Command;
- use Symfony\Component\Console\Helper\DescriptorHelper;
- use Symfony\Component\Console\Input\InputArgument;
- use Symfony\Component\Console\Input\InputOption;
- use Symfony\Component\Console\Input\InputInterface;
- use Symfony\Component\Console\Output\OutputInterface;
- class HelpCommand extends Command
- {
- private $command;
- protected function configure()
- {
- $this->ignoreValidationErrors();
- $this
- ->setName('help')
- ->setDefinition(array(
- new InputArgument('command_name', InputArgument::OPTIONAL, 'The command name', 'help'),
- new InputOption('xml', null, InputOption::VALUE_NONE, 'To output help as XML'),
- new InputOption('format', null, InputOption::VALUE_REQUIRED, 'To output help in other formats', 'txt'),
- new InputOption('raw', null, InputOption::VALUE_NONE, 'To output raw command help'),
- ))
- ->setDescription('Displays help for a command')
- ->setHelp(<<<EOF
- The <info>%command.name%</info> command displays help for a given command:
- <info>php %command.full_name% list</info>
- You can also output the help in other formats by using the <comment>--format</comment> option:
- <info>php %command.full_name% --format=xml list</info>
- To display the list of available commands, please use the <info>list</info> command.
- EOF
- )
- ;
- }
- public function setCommand(Command $command)
- {
- $this->command = $command;
- }
- protected function execute(InputInterface $input, OutputInterface $output)
- {
- if (null === $this->command) {
- $this->command = $this->getApplication()->find($input->getArgument('command_name'));
- }
- if ($input->getOption('xml')) {
- $input->setOption('format', 'xml');
- }
- $helper = new DescriptorHelper();
- $helper->describe($output, $this->command, array(
- 'format' => $input->getOption('format'),
- 'raw' => $input->getOption('raw'),
- ));
- $this->command = null;
- }
- }
- <?php
- namespace Symfony\Component\Console\Command;
- use Symfony\Component\Console\Helper\DescriptorHelper;
- use Symfony\Component\Console\Input\InputArgument;
- use Symfony\Component\Console\Input\InputOption;
- use Symfony\Component\Console\Input\InputInterface;
- use Symfony\Component\Console\Output\OutputInterface;
- use Symfony\Component\Console\Input\InputDefinition;
- class ListCommand extends Command
- {
- protected function configure()
- {
- $this
- ->setName('list')
- ->setDefinition($this->createDefinition())
- ->setDescription('Lists commands')
- ->setHelp(<<<EOF
- The <info>%command.name%</info> command lists all commands:
- <info>php %command.full_name%</info>
- You can also display the commands for a specific namespace:
- <info>php %command.full_name% test</info>
- You can also output the information in other formats by using the <comment>--format</comment> option:
- <info>php %command.full_name% --format=xml</info>
- It's also possible to get raw list of commands (useful for embedding command runner):
- <info>php %command.full_name% --raw</info>
- EOF
- )
- ;
- }
- public function getNativeDefinition()
- {
- return $this->createDefinition();
- }
- protected function execute(InputInterface $input, OutputInterface $output)
- {
- if ($input->getOption('xml')) {
- $input->setOption('format', 'xml');
- }
- $helper = new DescriptorHelper();
- $helper->describe($output, $this->getApplication(), array(
- 'format' => $input->getOption('format'),
- 'raw_text' => $input->getOption('raw'),
- 'namespace' => $input->getArgument('namespace'),
- ));
- }
- private function createDefinition()
- {
- return new InputDefinition(array(
- new InputArgument('namespace', InputArgument::OPTIONAL, 'The namespace name'),
- new InputOption('xml', null, InputOption::VALUE_NONE, 'To output list as XML'),
- new InputOption('raw', null, InputOption::VALUE_NONE, 'To output raw command list'),
- new InputOption('format', null, InputOption::VALUE_REQUIRED, 'To output list in other formats', 'txt'),
- ));
- }
- }
- <?php
- namespace Symfony\Component\Console;
- final class ConsoleEvents
- {
- const COMMAND = 'console.command';
- const TERMINATE = 'console.terminate';
- const EXCEPTION = 'console.exception';
- }
- <?php
- namespace Symfony\Component\Console\Descriptor;
- use Symfony\Component\Console\Application;
- use Symfony\Component\Console\Command\Command;
- class ApplicationDescription
- {
- const GLOBAL_NAMESPACE = '_global';
- private $application;
- private $namespace;
- private $namespaces;
- private $commands;
- private $aliases;
- public function __construct(Application $application, $namespace = null)
- {
- $this->application = $application;
- $this->namespace = $namespace;
- }
- public function getNamespaces()
- {
- if (null === $this->namespaces) {
- $this->inspectApplication();
- }
- return $this->namespaces;
- }
- public function getCommands()
- {
- if (null === $this->commands) {
- $this->inspectApplication();
- }
- return $this->commands;
- }
- public function getCommand($name)
- {
- if (!isset($this->commands[$name]) && !isset($this->aliases[$name])) {
- throw new \InvalidArgumentException(sprintf('Command %s does not exist.', $name));
- }
- return isset($this->commands[$name]) ? $this->commands[$name] : $this->aliases[$name];
- }
- private function inspectApplication()
- {
- $this->commands = array();
- $this->namespaces = array();
- $all = $this->application->all($this->namespace ? $this->application->findNamespace($this->namespace) : null);
- foreach ($this->sortCommands($all) as $namespace => $commands) {
- $names = array();
- foreach ($commands as $name => $command) {
- if (!$command->getName()) {
- continue;
- }
- if ($command->getName() === $name) {
- $this->commands[$name] = $command;
- } else {
- $this->aliases[$name] = $command;
- }
- $names[] = $name;
- }
- $this->namespaces[$namespace] = array('id' => $namespace, 'commands' => $names);
- }
- }
- private function sortCommands(array $commands)
- {
- $namespacedCommands = array();
- foreach ($commands as $name => $command) {
- $key = $this->application->extractNamespace($name, 1);
- if (!$key) {
- $key = '_global';
- }
- $namespacedCommands[$key][$name] = $command;
- }
- ksort($namespacedCommands);
- foreach ($namespacedCommands as &$commands) {
- ksort($commands);
- }
- return $namespacedCommands;
- }
- }
- <?php
- namespace Symfony\Component\Console\Descriptor;
- use Symfony\Component\Console\Application;
- use Symfony\Component\Console\Command\Command;
- use Symfony\Component\Console\Input\InputArgument;
- use Symfony\Component\Console\Input\InputDefinition;
- use Symfony\Component\Console\Input\InputOption;
- use Symfony\Component\Console\Output\OutputInterface;
- abstract class Descriptor implements DescriptorInterface
- {
- private $output;
- public function describe(OutputInterface $output, $object, array $options = array())
- {
- $this->output = $output;
- switch (true) {
- case $object instanceof InputArgument:
- $this->describeInputArgument($object, $options);
- break;
- case $object instanceof InputOption:
- $this->describeInputOption($object, $options);
- break;
- case $object instanceof InputDefinition:
- $this->describeInputDefinition($object, $options);
- break;
- case $object instanceof Command:
- $this->describeCommand($object, $options);
- break;
- case $object instanceof Application:
- $this->describeApplication($object, $options);
- break;
- default:
- throw new \InvalidArgumentException(sprintf('Object of type "%s" is not describable.', get_class($object)));
- }
- }
- protected function write($content, $decorated = false)
- {
- $this->output->write($content, false, $decorated ? OutputInterface::OUTPUT_NORMAL : OutputInterface::OUTPUT_RAW);
- }
- abstract protected function describeInputArgument(InputArgument $argument, array $options = array());
- abstract protected function describeInputOption(InputOption $option, array $options = array());
- abstract protected function describeInputDefinition(InputDefinition $definition, array $options = array());
- abstract protected function describeCommand(Command $command, array $options = array());
- abstract protected function describeApplication(Application $application, array $options = array());
- }
- <?php
- namespace Symfony\Component\Console\Descriptor;
- use Symfony\Component\Console\Output\OutputInterface;
- interface DescriptorInterface
- {
- public function describe(OutputInterface $output, $object, array $options = array());
- }
- <?php
- namespace Symfony\Component\Console\Descriptor;
- use Symfony\Component\Console\Application;
- use Symfony\Component\Console\Command\Command;
- use Symfony\Component\Console\Input\InputArgument;
- use Symfony\Component\Console\Input\InputDefinition;
- use Symfony\Component\Console\Input\InputOption;
- class JsonDescriptor extends Descriptor
- {
- protected function describeInputArgument(InputArgument $argument, array $options = array())
- {
- $this->writeData($this->getInputArgumentData($argument), $options);
- }
- protected function describeInputOption(InputOption $option, array $options = array())
- {
- $this->writeData($this->getInputOptionData($option), $options);
- }
- protected function describeInputDefinition(InputDefinition $definition, array $options = array())
- {
- $this->writeData($this->getInputDefinitionData($definition), $options);
- }
- protected function describeCommand(Command $command, array $options = array())
- {
- $this->writeData($this->getCommandData($command), $options);
- }
- protected function describeApplication(Application $application, array $options = array())
- {
- $describedNamespace = isset($options['namespace']) ? $options['namespace'] : null;
- $description = new ApplicationDescription($application, $describedNamespace);
- $commands = array();
- foreach ($description->getCommands() as $command) {
- $commands[] = $this->getCommandData($command);
- }
- $data = $describedNamespace
- ? array('commands' => $commands, 'namespace' => $describedNamespace)
- : array('commands' => $commands, 'namespaces' => array_values($description->getNamespaces()));
- $this->writeData($data, $options);
- }
- private function writeData(array $data, array $options)
- {
- $this->write(json_encode($data, isset($options['json_encoding']) ? $options['json_encoding'] : 0));
- }
- private function getInputArgumentData(InputArgument $argument)
- {
- return array(
- 'name' => $argument->getName(),
- 'is_required' => $argument->isRequired(),
- 'is_array' => $argument->isArray(),
- 'description' => $argument->getDescription(),
- 'default' => $argument->getDefault(),
- );
- }
- private function getInputOptionData(InputOption $option)
- {
- return array(
- 'name' => '--'.$option->getName(),
- 'shortcut' => $option->getShortcut() ? '-'.implode('|-', explode('|', $option->getShortcut())) : '',
- 'accept_value' => $option->acceptValue(),
- 'is_value_required' => $option->isValueRequired(),
- 'is_multiple' => $option->isArray(),
- 'description' => $option->getDescription(),
- 'default' => $option->getDefault(),
- );
- }
- private function getInputDefinitionData(InputDefinition $definition)
- {
- $inputArguments = array();
- foreach ($definition->getArguments() as $name => $argument) {
- $inputArguments[$name] = $this->getInputArgumentData($argument);
- }
- $inputOptions = array();
- foreach ($definition->getOptions() as $name => $option) {
- $inputOptions[$name] = $this->getInputOptionData($option);
- }
- return array('arguments' => $inputArguments, 'options' => $inputOptions);
- }
- private function getCommandData(Command $command)
- {
- $command->getSynopsis();
- $command->mergeApplicationDefinition(false);
- return array(
- 'name' => $command->getName(),
- 'usage' => $command->getSynopsis(),
- 'description' => $command->getDescription(),
- 'help' => $command->getProcessedHelp(),
- 'aliases' => $command->getAliases(),
- 'definition' => $this->getInputDefinitionData($command->getNativeDefinition()),
- );
- }
- }
- <?php
- namespace Symfony\Component\Console\Descriptor;
- use Symfony\Component\Console\Application;
- use Symfony\Component\Console\Command\Command;
- use Symfony\Component\Console\Input\InputArgument;
- use Symfony\Component\Console\Input\InputDefinition;
- use Symfony\Component\Console\Input\InputOption;
- class MarkdownDescriptor extends Descriptor
- {
- protected function describeInputArgument(InputArgument $argument, array $options = array())
- {
- $this->write(
- '**'.$argument->getName().':**'."\n\n"
- .'* Name: '.($argument->getName() ?: '<none>')."\n"
- .'* Is required: '.($argument->isRequired() ? 'yes' : 'no')."\n"
- .'* Is array: '.($argument->isArray() ? 'yes' : 'no')."\n"
- .'* Description: '.($argument->getDescription() ?: '<none>')."\n"
- .'* Default: `'.str_replace("\n", '', var_export($argument->getDefault(), true)).'`'
- );
- }
- protected function describeInputOption(InputOption $option, array $options = array())
- {
- $this->write(
- '**'.$option->getName().':**'."\n\n"
- .'* Name: `--'.$option->getName().'`'."\n"
- .'* Shortcut: '.($option->getShortcut() ? '`-'.implode('|-', explode('|', $option->getShortcut())).'`' : '<none>')."\n"
- .'* Accept value: '.($option->acceptValue() ? 'yes' : 'no')."\n"
- .'* Is value required: '.($option->isValueRequired() ? 'yes' : 'no')."\n"
- .'* Is multiple: '.($option->isArray() ? 'yes' : 'no')."\n"
- .'* Description: '.($option->getDescription() ?: '<none>')."\n"
- .'* Default: `'.str_replace("\n", '', var_export($option->getDefault(), true)).'`'
- );
- }
- protected function describeInputDefinition(InputDefinition $definition, array $options = array())
- {
- if ($showArguments = count($definition->getArguments()) > 0) {
- $this->write('### Arguments:');
- foreach ($definition->getArguments() as $argument) {
- $this->write("\n\n");
- $this->write($this->describeInputArgument($argument));
- }
- }
- if (count($definition->getOptions()) > 0) {
- if ($showArguments) {
- $this->write("\n\n");
- }
- $this->write('### Options:');
- foreach ($definition->getOptions() as $option) {
- $this->write("\n\n");
- $this->write($this->describeInputOption($option));
- }
- }
- }
- protected function describeCommand(Command $command, array $options = array())
- {
- $command->getSynopsis();
- $command->mergeApplicationDefinition(false);
- $this->write(
- $command->getName()."\n"
- .str_repeat('-', strlen($command->getName()))."\n\n"
- .'* Description: '.($command->getDescription() ?: '<none>')."\n"
- .'* Usage: `'.$command->getSynopsis().'`'."\n"
- .'* Aliases: '.(count($command->getAliases()) ? '`'.implode('`, `', $command->getAliases()).'`' : '<none>')
- );
- if ($help = $command->getProcessedHelp()) {
- $this->write("\n\n");
- $this->write($help);
- }
- if ($command->getNativeDefinition()) {
- $this->write("\n\n");
- $this->describeInputDefinition($command->getNativeDefinition());
- }
- }
- protected function describeApplication(Application $application, array $options = array())
- {
- $describedNamespace = isset($options['namespace']) ? $options['namespace'] : null;
- $description = new ApplicationDescription($application, $describedNamespace);
- $this->write($application->getName()."\n".str_repeat('=', strlen($application->getName())));
- foreach ($description->getNamespaces() as $namespace) {
- if (ApplicationDescription::GLOBAL_NAMESPACE !== $namespace['id']) {
- $this->write("\n\n");
- $this->write('**'.$namespace['id'].':**');
- }
- $this->write("\n\n");
- $this->write(implode("\n", array_map(function ($commandName) {
- return '* '.$commandName;
- }, $namespace['commands'])));
- }
- foreach ($description->getCommands() as $command) {
- $this->write("\n\n");
- $this->write($this->describeCommand($command));
- }
- }
- }
- <?php
- namespace Symfony\Component\Console\Descriptor;
- use Symfony\Component\Console\Application;
- use Symfony\Component\Console\Command\Command;
- use Symfony\Component\Console\Input\InputArgument;
- use Symfony\Component\Console\Input\InputDefinition;
- use Symfony\Component\Console\Input\InputOption;
- class TextDescriptor extends Descriptor
- {
- protected function describeInputArgument(InputArgument $argument, array $options = array())
- {
- if (null !== $argument->getDefault() && (!is_array($argument->getDefault()) || count($argument->getDefault()))) {
- $default = sprintf('<comment> (default: %s)</comment>', $this->formatDefaultValue($argument->getDefault()));
- } else {
- $default = '';
- }
- $nameWidth = isset($options['name_width']) ? $options['name_width'] : strlen($argument->getName());
- $this->writeText(sprintf(" <info>%-${nameWidth}s</info> %s%s",
- $argument->getName(),
- str_replace("\n", "\n".str_repeat(' ', $nameWidth + 2), $argument->getDescription()),
- $default
- ), $options);
- }
- protected function describeInputOption(InputOption $option, array $options = array())
- {
- if ($option->acceptValue() && null !== $option->getDefault() && (!is_array($option->getDefault()) || count($option->getDefault()))) {
- $default = sprintf('<comment> (default: %s)</comment>', $this->formatDefaultValue($option->getDefault()));
- } else {
- $default = '';
- }
- $nameWidth = isset($options['name_width']) ? $options['name_width'] : strlen($option->getName());
- $nameWithShortcutWidth = $nameWidth - strlen($option->getName()) - 2;
- $this->writeText(sprintf(" <info>%s</info> %-${nameWithShortcutWidth}s%s%s%s",
- '--'.$option->getName(),
- $option->getShortcut() ? sprintf('(-%s) ', $option->getShortcut()) : '',
- str_replace("\n", "\n".str_repeat(' ', $nameWidth + 2), $option->getDescription()),
- $default,
- $option->isArray() ? '<comment> (multiple values allowed)</comment>' : ''
- ), $options);
- }
- protected function describeInputDefinition(InputDefinition $definition, array $options = array())
- {
- $nameWidth = 0;
- foreach ($definition->getOptions() as $option) {
- $nameLength = strlen($option->getName()) + 2;
- if ($option->getShortcut()) {
- $nameLength += strlen($option->getShortcut()) + 3;
- }
- $nameWidth = max($nameWidth, $nameLength);
- }
- foreach ($definition->getArguments() as $argument) {
- $nameWidth = max($nameWidth, strlen($argument->getName()));
- }
- ++$nameWidth;
- if ($definition->getArguments()) {
- $this->writeText('<comment>Arguments:</comment>', $options);
- $this->writeText("\n");
- foreach ($definition->getArguments() as $argument) {
- $this->describeInputArgument($argument, array_merge($options, array('name_width' => $nameWidth)));
- $this->writeText("\n");
- }
- }
- if ($definition->getArguments() && $definition->getOptions()) {
- $this->writeText("\n");
- }
- if ($definition->getOptions()) {
- $this->writeText('<comment>Options:</comment>', $options);
- $this->writeText("\n");
- foreach ($definition->getOptions() as $option) {
- $this->describeInputOption($option, array_merge($options, array('name_width' => $nameWidth)));
- $this->writeText("\n");
- }
- }
- }
- protected function describeCommand(Command $command, array $options = array())
- {
- $command->getSynopsis();
- $command->mergeApplicationDefinition(false);
- $this->writeText('<comment>Usage:</comment>', $options);
- $this->writeText("\n");
- $this->writeText(' '.$command->getSynopsis(), $options);
- $this->writeText("\n");
- if (count($command->getAliases()) > 0) {
- $this->writeText("\n");
- $this->writeText('<comment>Aliases:</comment> <info>'.implode(', ', $command->getAliases()).'</info>', $options);
- }
- if ($definition = $command->getNativeDefinition()) {
- $this->writeText("\n");
- $this->describeInputDefinition($definition, $options);
- }
- $this->writeText("\n");
- if ($help = $command->getProcessedHelp()) {
- $this->writeText('<comment>Help:</comment>', $options);
- $this->writeText("\n");
- $this->writeText(' '.str_replace("\n", "\n ", $help), $options);
- $this->writeText("\n");
- }
- }
- protected function describeApplication(Application $application, array $options = array())
- {
- $describedNamespace = isset($options['namespace']) ? $options['namespace'] : null;
- $description = new ApplicationDescription($application, $describedNamespace);
- if (isset($options['raw_text']) && $options['raw_text']) {
- $width = $this->getColumnWidth($description->getCommands());
- foreach ($description->getCommands() as $command) {
- $this->writeText(sprintf("%-${width}s %s", $command->getName(), $command->getDescription()), $options);
- $this->writeText("\n");
- }
- } else {
- if ('' != $help = $application->getHelp()) {
- $this->writeText("$help\n\n", $options);
- }
- $this->writeText("<comment>Usage:</comment>\n", $options);
- $this->writeText(" [options] command [arguments]\n\n", $options);
- $this->writeText('<comment>Options:</comment>', $options);
- $inputOptions = $application->getDefinition()->getOptions();
- $width = 0;
- foreach ($inputOptions as $option) {
- $nameLength = strlen($option->getName()) + 2;
- if ($option->getShortcut()) {
- $nameLength += strlen($option->getShortcut()) + 3;
- }
- $width = max($width, $nameLength);
- }
- ++$width;
- foreach ($inputOptions as $option) {
- $this->writeText("\n", $options);
- $this->describeInputOption($option, array_merge($options, array('name_width' => $width)));
- }
- $this->writeText("\n\n", $options);
- $width = $this->getColumnWidth($description->getCommands());
- if ($describedNamespace) {
- $this->writeText(sprintf("<comment>Available commands for the \"%s\" namespace:</comment>", $describedNamespace), $options);
- } else {
- $this->writeText('<comment>Available commands:</comment>', $options);
- }
- foreach ($description->getNamespaces() as $namespace) {
- if (!$describedNamespace && ApplicationDescription::GLOBAL_NAMESPACE !== $namespace['id']) {
- $this->writeText("\n");
- $this->writeText('<comment>'.$namespace['id'].'</comment>', $options);
- }
- foreach ($namespace['commands'] as $name) {
- $this->writeText("\n");
- $this->writeText(sprintf(" <info>%-${width}s</info> %s", $name, $description->getCommand($name)->getDescription()), $options);
- }
- }
- $this->writeText("\n");
- }
- }
- private function writeText($content, array $options = array())
- {
- $this->write(
- isset($options['raw_text']) && $options['raw_text'] ? strip_tags($content) : $content,
- isset($options['raw_output']) ? !$options['raw_output'] : true
- );
- }
- private function formatDefaultValue($default)
- {
- if (PHP_VERSION_ID < 50400) {
- return str_replace('\/', '/', json_encode($default));
- }
- return json_encode($default, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
- }
- private function getColumnWidth(array $commands)
- {
- $width = 0;
- foreach ($commands as $command) {
- $width = strlen($command->getName()) > $width ? strlen($command->getName()) : $width;
- }
- return $width + 2;
- }
- }
- <?php
- namespace Symfony\Component\Console\Descriptor;
- use Symfony\Component\Console\Application;
- use Symfony\Component\Console\Command\Command;
- use Symfony\Component\Console\Input\InputArgument;
- use Symfony\Component\Console\Input\InputDefinition;
- use Symfony\Component\Console\Input\InputOption;
- class XmlDescriptor extends Descriptor
- {
- public function getInputDefinitionDocument(InputDefinition $definition)
- {
- $dom = new \DOMDocument('1.0', 'UTF-8');
- $dom->appendChild($definitionXML = $dom->createElement('definition'));
- $definitionXML->appendChild($argumentsXML = $dom->createElement('arguments'));
- foreach ($definition->getArguments() as $argument) {
- $this->appendDocument($argumentsXML, $this->getInputArgumentDocument($argument));
- }
- $definitionXML->appendChild($optionsXML = $dom->createElement('options'));
- foreach ($definition->getOptions() as $option) {
- $this->appendDocument($optionsXML, $this->getInputOptionDocument($option));
- }
- return $dom;
- }
- public function getCommandDocument(Command $command)
- {
- $dom = new \DOMDocument('1.0', 'UTF-8');
- $dom->appendChild($commandXML = $dom->createElement('command'));
- $command->getSynopsis();
- $command->mergeApplicationDefinition(false);
- $commandXML->setAttribute('id', $command->getName());
- $commandXML->setAttribute('name', $command->getName());
- $commandXML->appendChild($usageXML = $dom->createElement('usage'));
- $usageXML->appendChild($dom->createTextNode(sprintf($command->getSynopsis(), '')));
- $commandXML->appendChild($descriptionXML = $dom->createElement('description'));
- $descriptionXML->appendChild($dom->createTextNode(str_replace("\n", "\n ", $command->getDescription())));
- $commandXML->appendChild($helpXML = $dom->createElement('help'));
- $helpXML->appendChild($dom->createTextNode(str_replace("\n", "\n ", $command->getProcessedHelp())));
- $commandXML->appendChild($aliasesXML = $dom->createElement('aliases'));
- foreach ($command->getAliases() as $alias) {
- $aliasesXML->appendChild($aliasXML = $dom->createElement('alias'));
- $aliasXML->appendChild($dom->createTextNode($alias));
- }
- $definitionXML = $this->getInputDefinitionDocument($command->getNativeDefinition());
- $this->appendDocument($commandXML, $definitionXML->getElementsByTagName('definition')->item(0));
- return $dom;
- }
- public function getApplicationDocument(Application $application, $namespace = null)
- {
- $dom = new \DOMDocument('1.0', 'UTF-8');
- $dom->appendChild($rootXml = $dom->createElement('symfony'));
- if ($application->getName() !== 'UNKNOWN') {
- $rootXml->setAttribute('name', $application->getName());
- if ($application->getVersion() !== 'UNKNOWN') {
- $rootXml->setAttribute('version', $application->getVersion());
- }
- }
- $rootXml->appendChild($commandsXML = $dom->createElement('commands'));
- $description = new ApplicationDescription($application, $namespace);
- if ($namespace) {
- $commandsXML->setAttribute('namespace', $namespace);
- }
- foreach ($description->getCommands() as $command) {
- $this->appendDocument($commandsXML, $this->getCommandDocument($command));
- }
- if (!$namespace) {
- $rootXml->appendChild($namespacesXML = $dom->createElement('namespaces'));
- foreach ($description->getNamespaces() as $namespaceDescription) {
- $namespacesXML->appendChild($namespaceArrayXML = $dom->createElement('namespace'));
- $namespaceArrayXML->setAttribute('id', $namespaceDescription['id']);
- foreach ($namespaceDescription['commands'] as $name) {
- $namespaceArrayXML->appendChild($commandXML = $dom->createElement('command'));
- $commandXML->appendChild($dom->createTextNode($name));
- }
- }
- }
- return $dom;
- }
- protected function describeInputArgument(InputArgument $argument, array $options = array())
- {
- $this->writeDocument($this->getInputArgumentDocument($argument));
- }
- protected function describeInputOption(InputOption $option, array $options = array())
- {
- $this->writeDocument($this->getInputOptionDocument($option));
- }
- protected function describeInputDefinition(InputDefinition $definition, array $options = array())
- {
- $this->writeDocument($this->getInputDefinitionDocument($definition));
- }
- protected function describeCommand(Command $command, array $options = array())
- {
- $this->writeDocument($this->getCommandDocument($command));
- }
- protected function describeApplication(Application $application, array $options = array())
- {
- $this->writeDocument($this->getApplicationDocument($application, isset($options['namespace']) ? $options['namespace'] : null));
- }
- private function appendDocument(\DOMNode $parentNode, \DOMNode $importedParent)
- {
- foreach ($importedParent->childNodes as $childNode) {
- $parentNode->appendChild($parentNode->ownerDocument->importNode($childNode, true));
- }
- }
- private function writeDocument(\DOMDocument $dom)
- {
- $dom->formatOutput = true;
- $this->write($dom->saveXML());
- }
- private function getInputArgumentDocument(InputArgument $argument)
- {
- $dom = new \DOMDocument('1.0', 'UTF-8');
- $dom->appendChild($objectXML = $dom->createElement('argument'));
- $objectXML->setAttribute('name', $argument->getName());
- $objectXML->setAttribute('is_required', $argument->isRequired() ? 1 : 0);
- $objectXML->setAttribute('is_array', $argument->isArray() ? 1 : 0);
- $objectXML->appendChild($descriptionXML = $dom->createElement('description'));
- $descriptionXML->appendChild($dom->createTextNode($argument->getDescription()));
- $objectXML->appendChild($defaultsXML = $dom->createElement('defaults'));
- $defaults = is_array($argument->getDefault()) ? $argument->getDefault() : (is_bool($argument->getDefault()) ? array(var_export($argument->getDefault(), true)) : ($argument->getDefault() ? array($argument->getDefault()) : array()));
- foreach ($defaults as $default) {
- $defaultsXML->appendChild($defaultXML = $dom->createElement('default'));
- $defaultXML->appendChild($dom->createTextNode($default));
- }
- return $dom;
- }
- private function getInputOptionDocument(InputOption $option)
- {
- $dom = new \DOMDocument('1.0', 'UTF-8');
- $dom->appendChild($objectXML = $dom->createElement('option'));
- $objectXML->setAttribute('name', '--'.$option->getName());
- $pos = strpos($option->getShortcut(), '|');
- if (false !== $pos) {
- $objectXML->setAttribute('shortcut', '-'.substr($option->getShortcut(), 0, $pos));
- $objectXML->setAttribute('shortcuts', '-'.implode('|-', explode('|', $option->getShortcut())));
- } else {
- $objectXML->setAttribute('shortcut', $option->getShortcut() ? '-'.$option->getShortcut() : '');
- }
- $objectXML->setAttribute('accept_value', $option->acceptValue() ? 1 : 0);
- $objectXML->setAttribute('is_value_required', $option->isValueRequired() ? 1 : 0);
- $objectXML->setAttribute('is_multiple', $option->isArray() ? 1 : 0);
- $objectXML->appendChild($descriptionXML = $dom->createElement('description'));
- $descriptionXML->appendChild($dom->createTextNode($option->getDescription()));
- if ($option->acceptValue()) {
- $defaults = is_array($option->getDefault()) ? $option->getDefault() : (is_bool($option->getDefault()) ? array(var_export($option->getDefault(), true)) : ($option->getDefault() ? array($option->getDefault()) : array()));
- $objectXML->appendChild($defaultsXML = $dom->createElement('defaults'));
- if (!empty($defaults)) {
- foreach ($defaults as $default) {
- $defaultsXML->appendChild($defaultXML = $dom->createElement('default'));
- $defaultXML->appendChild($dom->createTextNode($default));
- }
- }
- }
- return $dom;
- }
- }
- <?php
- namespace Symfony\Component\Console\Event;
- class ConsoleCommandEvent extends ConsoleEvent
- {
- const RETURN_CODE_DISABLED = 113;
- private $commandShouldRun = true;
- public function disableCommand()
- {
- return $this->commandShouldRun = false;
- }
- public function enableCommand()
- {
- return $this->commandShouldRun = true;
- }
- public function commandShouldRun()
- {
- return $this->commandShouldRun;
- }
- }
- <?php
- namespace Symfony\Component\Console\Event;
- use Symfony\Component\Console\Command\Command;
- use Symfony\Component\Console\Input\InputInterface;
- use Symfony\Component\Console\Output\OutputInterface;
- use Symfony\Component\EventDispatcher\Event;
- class ConsoleEvent extends Event
- {
- protected $command;
- private $input;
- private $output;
- public function __construct(Command $command, InputInterface $input, OutputInterface $output)
- {
- $this->command = $command;
- $this->input = $input;
- $this->output = $output;
- }
- public function getCommand()
- {
- return $this->command;
- }
- public function getInput()
- {
- return $this->input;
- }
- public function getOutput()
- {
- return $this->output;
- }
- }
- <?php
- namespace Symfony\Component\Console\Event;
- use Symfony\Component\Console\Command\Command;
- use Symfony\Component\Console\Input\InputInterface;
- use Symfony\Component\Console\Output\OutputInterface;
- class ConsoleExceptionEvent extends ConsoleEvent
- {
- private $exception;
- private $exitCode;
- public function __construct(Command $command, InputInterface $input, OutputInterface $output, \Exception $exception, $exitCode)
- {
- parent::__construct($command, $input, $output);
- $this->setException($exception);
- $this->exitCode = (int) $exitCode;
- }
- public function getException()
- {
- return $this->exception;
- }
- public function setException(\Exception $exception)
- {
- $this->exception = $exception;
- }
- public function getExitCode()
- {
- return $this->exitCode;
- }
- }
- <?php
- namespace Symfony\Component\Console\Event;
- use Symfony\Component\Console\Command\Command;
- use Symfony\Component\Console\Input\InputInterface;
- use Symfony\Component\Console\Output\OutputInterface;
- class ConsoleTerminateEvent extends ConsoleEvent
- {
- private $exitCode;
- public function __construct(Command $command, InputInterface $input, OutputInterface $output, $exitCode)
- {
- parent::__construct($command, $input, $output);
- $this->setExitCode($exitCode);
- }
- public function setExitCode($exitCode)
- {
- $this->exitCode = (int) $exitCode;
- }
- public function getExitCode()
- {
- return $this->exitCode;
- }
- }
- <?php
- namespace Symfony\Component\Console\Formatter;
- class OutputFormatter implements OutputFormatterInterface
- {
- private $decorated;
- private $styles = array();
- private $styleStack;
- public static function escape($text)
- {
- return preg_replace('/([^\\\\]?)</is', '$1\\<', $text);
- }
- public function __construct($decorated = false, array $styles = array())
- {
- $this->decorated = (bool) $decorated;
- $this->setStyle('error', new OutputFormatterStyle('white', 'red'));
- $this->setStyle('info', new OutputFormatterStyle('green'));
- $this->setStyle('comment', new OutputFormatterStyle('yellow'));
- $this->setStyle('question', new OutputFormatterStyle('black', 'cyan'));
- foreach ($styles as $name => $style) {
- $this->setStyle($name, $style);
- }
- $this->styleStack = new OutputFormatterStyleStack();
- }
- public function setDecorated($decorated)
- {
- $this->decorated = (bool) $decorated;
- }
- public function isDecorated()
- {
- return $this->decorated;
- }
- public function setStyle($name, OutputFormatterStyleInterface $style)
- {
- $this->styles[strtolower($name)] = $style;
- }
- public function hasStyle($name)
- {
- return isset($this->styles[strtolower($name)]);
- }
- public function getStyle($name)
- {
- if (!$this->hasStyle($name)) {
- throw new \InvalidArgumentException(sprintf('Undefined style: %s', $name));
- }
- return $this->styles[strtolower($name)];
- }
- public function format($message)
- {
- $offset = 0;
- $output = '';
- $tagRegex = '[a-z][a-z0-9_=;-]*';
- preg_match_all("#<(($tagRegex) | /($tagRegex)?)>#isx", $message, $matches, PREG_OFFSET_CAPTURE);
- foreach ($matches[0] as $i => $match) {
- $pos = $match[1];
- $text = $match[0];
- $output .= $this->applyCurrentStyle(substr($message, $offset, $pos - $offset));
- $offset = $pos + strlen($text);
- if ($open = '/' != $text[1]) {
- $tag = $matches[1][$i][0];
- } else {
- $tag = isset($matches[3][$i][0]) ? $matches[3][$i][0] : '';
- }
- if (!$open && !$tag) {
- $this->styleStack->pop();
- } elseif ($pos && '\\' == $message[$pos - 1]) {
- $output .= $this->applyCurrentStyle($text);
- } elseif (false === $style = $this->createStyleFromString(strtolower($tag))) {
- $output .= $this->applyCurrentStyle($text);
- } elseif ($open) {
- $this->styleStack->push($style);
- } else {
- $this->styleStack->pop($style);
- }
- }
- $output .= $this->applyCurrentStyle(substr($message, $offset));
- return str_replace('\\<', '<', $output);
- }
- public function getStyleStack()
- {
- return $this->styleStack;
- }
- private function createStyleFromString($string)
- {
- if (isset($this->styles[$string])) {
- return $this->styles[$string];
- }
- if (!preg_match_all('/([^=]+)=([^;]+)(;|$)/', strtolower($string), $matches, PREG_SET_ORDER)) {
- return false;
- }
- $style = new OutputFormatterStyle();
- foreach ($matches as $match) {
- array_shift($match);
- if ('fg' == $match[0]) {
- $style->setForeground($match[1]);
- } elseif ('bg' == $match[0]) {
- $style->setBackground($match[1]);
- } else {
- try {
- $style->setOption($match[1]);
- } catch (\InvalidArgumentException $e) {
- return false;
- }
- }
- }
- return $style;
- }
- private function applyCurrentStyle($text)
- {
- return $this->isDecorated() && strlen($text) > 0 ? $this->styleStack->getCurrent()->apply($text) : $text;
- }
- }
- <?php
- namespace Symfony\Component\Console\Formatter;
- interface OutputFormatterInterface
- {
- public function setDecorated($decorated);
- public function isDecorated();
- public function setStyle($name, OutputFormatterStyleInterface $style);
- public function hasStyle($name);
- public function getStyle($name);
- public function format($message);
- }
- <?php
- namespace Symfony\Component\Console\Formatter;
- class OutputFormatterStyle implements OutputFormatterStyleInterface
- {
- private static $availableForegroundColors = array(
- 'black' => array('set' => 30, 'unset' => 39),
- 'red' => array('set' => 31, 'unset' => 39),
- 'green' => array('set' => 32, 'unset' => 39),
- 'yellow' => array('set' => 33, 'unset' => 39),
- 'blue' => array('set' => 34, 'unset' => 39),
- 'magenta' => array('set' => 35, 'unset' => 39),
- 'cyan' => array('set' => 36, 'unset' => 39),
- 'white' => array('set' => 37, 'unset' => 39),
- );
- private static $availableBackgroundColors = array(
- 'black' => array('set' => 40, 'unset' => 49),
- 'red' => array('set' => 41, 'unset' => 49),
- 'green' => array('set' => 42, 'unset' => 49),
- 'yellow' => array('set' => 43, 'unset' => 49),
- 'blue' => array('set' => 44, 'unset' => 49),
- 'magenta' => array('set' => 45, 'unset' => 49),
- 'cyan' => array('set' => 46, 'unset' => 49),
- 'white' => array('set' => 47, 'unset' => 49),
- );
- private static $availableOptions = array(
- 'bold' => array('set' => 1, 'unset' => 22),
- 'underscore' => array('set' => 4, 'unset' => 24),
- 'blink' => array('set' => 5, 'unset' => 25),
- 'reverse' => array('set' => 7, 'unset' => 27),
- 'conceal' => array('set' => 8, 'unset' => 28),
- );
- private $foreground;
- private $background;
- private $options = array();
- public function __construct($foreground = null, $background = null, array $options = array())
- {
- if (null !== $foreground) {
- $this->setForeground($foreground);
- }
- if (null !== $background) {
- $this->setBackground($background);
- }
- if (count($options)) {
- $this->setOptions($options);
- }
- }
- public function setForeground($color = null)
- {
- if (null === $color) {
- $this->foreground = null;
- return;
- }
- if (!isset(static::$availableForegroundColors[$color])) {
- throw new \InvalidArgumentException(sprintf(
- 'Invalid foreground color specified: "%s". Expected one of (%s)',
- $color,
- implode(', ', array_keys(static::$availableForegroundColors))
- ));
- }
- $this->foreground = static::$availableForegroundColors[$color];
- }
- public function setBackground($color = null)
- {
- if (null === $color) {
- $this->background = null;
- return;
- }
- if (!isset(static::$availableBackgroundColors[$color])) {
- throw new \InvalidArgumentException(sprintf(
- 'Invalid background color specified: "%s". Expected one of (%s)',
- $color,
- implode(', ', array_keys(static::$availableBackgroundColors))
- ));
- }
- $this->background = static::$availableBackgroundColors[$color];
- }
- public function setOption($option)
- {
- if (!isset(static::$availableOptions[$option])) {
- throw new \InvalidArgumentException(sprintf(
- 'Invalid option specified: "%s". Expected one of (%s)',
- $option,
- implode(', ', array_keys(static::$availableOptions))
- ));
- }
- if (false === array_search(static::$availableOptions[$option], $this->options)) {
- $this->options[] = static::$availableOptions[$option];
- }
- }
- public function unsetOption($option)
- {
- if (!isset(static::$availableOptions[$option])) {
- throw new \InvalidArgumentException(sprintf(
- 'Invalid option specified: "%s". Expected one of (%s)',
- $option,
- implode(', ', array_keys(static::$availableOptions))
- ));
- }
- $pos = array_search(static::$availableOptions[$option], $this->options);
- if (false !== $pos) {
- unset($this->options[$pos]);
- }
- }
- public function setOptions(array $options)
- {
- $this->options = array();
- foreach ($options as $option) {
- $this->setOption($option);
- }
- }
- public function apply($text)
- {
- $setCodes = array();
- $unsetCodes = array();
- if (null !== $this->foreground) {
- $setCodes[] = $this->foreground['set'];
- $unsetCodes[] = $this->foreground['unset'];
- }
- if (null !== $this->background) {
- $setCodes[] = $this->background['set'];
- $unsetCodes[] = $this->background['unset'];
- }
- if (count($this->options)) {
- foreach ($this->options as $option) {
- $setCodes[] = $option['set'];
- $unsetCodes[] = $option['unset'];
- }
- }
- if (0 === count($setCodes)) {
- return $text;
- }
- return sprintf("\033[%sm%s\033[%sm", implode(';', $setCodes), $text, implode(';', $unsetCodes));
- }
- }
- <?php
- namespace Symfony\Component\Console\Formatter;
- interface OutputFormatterStyleInterface
- {
- public function setForeground($color = null);
- public function setBackground($color = null);
- public function setOption($option);
- public function unsetOption($option);
- public function setOptions(array $options);
- public function apply($text);
- }
- <?php
- namespace Symfony\Component\Console\Formatter;
- class OutputFormatterStyleStack
- {
- private $styles;
- private $emptyStyle;
- public function __construct(OutputFormatterStyleInterface $emptyStyle = null)
- {
- $this->emptyStyle = $emptyStyle ?: new OutputFormatterStyle();
- $this->reset();
- }
- public function reset()
- {
- $this->styles = array();
- }
- public function push(OutputFormatterStyleInterface $style)
- {
- $this->styles[] = $style;
- }
- public function pop(OutputFormatterStyleInterface $style = null)
- {
- if (empty($this->styles)) {
- return $this->emptyStyle;
- }
- if (null === $style) {
- return array_pop($this->styles);
- }
- foreach (array_reverse($this->styles, true) as $index => $stackedStyle) {
- if ($style->apply('') === $stackedStyle->apply('')) {
- $this->styles = array_slice($this->styles, 0, $index);
- return $stackedStyle;
- }
- }
- throw new \InvalidArgumentException('Incorrectly nested style tag found.');
- }
- public function getCurrent()
- {
- if (empty($this->styles)) {
- return $this->emptyStyle;
- }
- return $this->styles[count($this->styles)-1];
- }
- public function setEmptyStyle(OutputFormatterStyleInterface $emptyStyle)
- {
- $this->emptyStyle = $emptyStyle;
- return $this;
- }
- public function getEmptyStyle()
- {
- return $this->emptyStyle;
- }
- }
- <?php
- namespace Symfony\Component\Console\Helper;
- class DebugFormatterHelper extends Helper
- {
- private $colors = array('black', 'red', 'green', 'yellow', 'blue', 'magenta', 'cyan', 'white');
- private $started = array();
- private $count = -1;
- public function start($id, $message, $prefix = 'RUN')
- {
- $this->started[$id] = array('border' => ++$this->count % count($this->colors));
- return sprintf("%s<bg=blue;fg=white> %s </> <fg=blue>%s</>\n", $this->getBorder($id), $prefix, $message);
- }
- public function progress($id, $buffer, $error = false, $prefix = 'OUT', $errorPrefix = 'ERR')
- {
- $message = '';
- if ($error) {
- if (isset($this->started[$id]['out'])) {
- $message .= "\n";
- unset($this->started[$id]['out']);
- }
- if (!isset($this->started[$id]['err'])) {
- $message .= sprintf("%s<bg=red;fg=white> %s </> ", $this->getBorder($id), $errorPrefix);
- $this->started[$id]['err'] = true;
- }
- $message .= str_replace("\n", sprintf("\n%s<bg=red;fg=white> %s </> ", $this->getBorder($id), $errorPrefix), $buffer);
- } else {
- if (isset($this->started[$id]['err'])) {
- $message .= "\n";
- unset($this->started[$id]['err']);
- }
- if (!isset($this->started[$id]['out'])) {
- $message .= sprintf("%s<bg=green;fg=white> %s </> ", $this->getBorder($id), $prefix);
- $this->started[$id]['out'] = true;
- }
- $message .= str_replace("\n", sprintf("\n%s<bg=green;fg=white> %s </> ", $this->getBorder($id), $prefix), $buffer);
- }
- return $message;
- }
- public function stop($id, $message, $successful, $prefix = 'RES')
- {
- $trailingEOL = isset($this->started[$id]['out']) || isset($this->started[$id]['err']) ? "\n" : '';
- if ($successful) {
- return sprintf("%s%s<bg=green;fg=white> %s </> <fg=green>%s</>\n", $trailingEOL, $this->getBorder($id), $prefix, $message);
- }
- $message = sprintf("%s%s<bg=red;fg=white> %s </> <fg=red>%s</>\n", $trailingEOL, $this->getBorder($id), $prefix, $message);
- unset($this->started[$id]['out'], $this->started[$id]['err']);
- return $message;
- }
- private function getBorder($id)
- {
- return sprintf('<bg=%s> </>', $this->colors[$this->started[$id]['border']]);
- }
- public function getName()
- {
- return 'debug_formatter';
- }
- }
- <?php
- namespace Symfony\Component\Console\Helper;
- use Symfony\Component\Console\Descriptor\DescriptorInterface;
- use Symfony\Component\Console\Descriptor\JsonDescriptor;
- use Symfony\Component\Console\Descriptor\MarkdownDescriptor;
- use Symfony\Component\Console\Descriptor\TextDescriptor;
- use Symfony\Component\Console\Descriptor\XmlDescriptor;
- use Symfony\Component\Console\Output\OutputInterface;
- class DescriptorHelper extends Helper
- {
- private $descriptors = array();
- public function __construct()
- {
- $this
- ->register('txt', new TextDescriptor())
- ->register('xml', new XmlDescriptor())
- ->register('json', new JsonDescriptor())
- ->register('md', new MarkdownDescriptor())
- ;
- }
- public function describe(OutputInterface $output, $object, array $options = array())
- {
- $options = array_merge(array(
- 'raw_text' => false,
- 'format' => 'txt',
- ), $options);
- if (!isset($this->descriptors[$options['format']])) {
- throw new \InvalidArgumentException(sprintf('Unsupported format "%s".', $options['format']));
- }
- $descriptor = $this->descriptors[$options['format']];
- $descriptor->describe($output, $object, $options);
- }
- public function register($format, DescriptorInterface $descriptor)
- {
- $this->descriptors[$format] = $descriptor;
- return $this;
- }
- public function getName()
- {
- return 'descriptor';
- }
- }
- <?php
- namespace Symfony\Component\Console\Helper;
- use Symfony\Component\Console\Output\OutputInterface;
- use Symfony\Component\Console\Formatter\OutputFormatterStyle;
- class DialogHelper extends InputAwareHelper
- {
- private $inputStream;
- private static $shell;
- private static $stty;
- public function select(OutputInterface $output, $question, $choices, $default = null, $attempts = false, $errorMessage = 'Value "%s" is invalid', $multiselect = false)
- {
- $width = max(array_map('strlen', array_keys($choices)));
- $messages = (array) $question;
- foreach ($choices as $key => $value) {
- $messages[] = sprintf(" [<info>%-${width}s</info>] %s", $key, $value);
- }
- $output->writeln($messages);
- $result = $this->askAndValidate($output, '> ', function ($picked) use ($choices, $errorMessage, $multiselect) {
- $selectedChoices = str_replace(" ", "", $picked);
- if ($multiselect) {
- if (!preg_match('/^[a-zA-Z0-9_-]+(?:,[a-zA-Z0-9_-]+)*$/', $selectedChoices, $matches)) {
- throw new \InvalidArgumentException(sprintf($errorMessage, $picked));
- }
- $selectedChoices = explode(",", $selectedChoices);
- } else {
- $selectedChoices = array($picked);
- }
- $multiselectChoices = array();
- foreach ($selectedChoices as $value) {
- if (empty($choices[$value])) {
- throw new \InvalidArgumentException(sprintf($errorMessage, $value));
- }
- array_push($multiselectChoices, $value);
- }
- if ($multiselect) {
- return $multiselectChoices;
- }
- return $picked;
- }, $attempts, $default);
- return $result;
- }
- public function ask(OutputInterface $output, $question, $default = null, array $autocomplete = null)
- {
- if ($this->input && !$this->input->isInteractive()) {
- return $default;
- }
- $output->write($question);
- $inputStream = $this->inputStream ?: STDIN;
- if (null === $autocomplete || !$this->hasSttyAvailable()) {
- $ret = fgets($inputStream, 4096);
- if (false === $ret) {
- throw new \RuntimeException('Aborted');
- }
- $ret = trim($ret);
- } else {
- $ret = '';
- $i = 0;
- $ofs = -1;
- $matches = $autocomplete;
- $numMatches = count($matches);
- $sttyMode = shell_exec('stty -g');
- shell_exec('stty -icanon -echo');
- $output->getFormatter()->setStyle('hl', new OutputFormatterStyle('black', 'white'));
- while (!feof($inputStream)) {
- $c = fread($inputStream, 1);
- if ("\177" === $c) {
- if (0 === $numMatches && 0 !== $i) {
- $i--;
- $output->write("\033[1D");
- }
- if ($i === 0) {
- $ofs = -1;
- $matches = $autocomplete;
- $numMatches = count($matches);
- } else {
- $numMatches = 0;
- }
- $ret = substr($ret, 0, $i);
- } elseif ("\033" === $c) {
- $c .= fread($inputStream, 2);
- if (isset($c[2]) && ('A' === $c[2] || 'B' === $c[2])) {
- if ('A' === $c[2] && -1 === $ofs) {
- $ofs = 0;
- }
- if (0 === $numMatches) {
- continue;
- }
- $ofs += ('A' === $c[2]) ? -1 : 1;
- $ofs = ($numMatches + $ofs) % $numMatches;
- }
- } elseif (ord($c) < 32) {
- if ("\t" === $c || "\n" === $c) {
- if ($numMatches > 0 && -1 !== $ofs) {
- $ret = $matches[$ofs];
- $output->write(substr($ret, $i));
- $i = strlen($ret);
- }
- if ("\n" === $c) {
- $output->write($c);
- break;
- }
- $numMatches = 0;
- }
- continue;
- } else {
- $output->write($c);
- $ret .= $c;
- $i++;
- $numMatches = 0;
- $ofs = 0;
- foreach ($autocomplete as $value) {
- if (0 === strpos($value, $ret) && $i !== strlen($value)) {
- $matches[$numMatches++] = $value;
- }
- }
- }
- $output->write("\033[K");
- if ($numMatches > 0 && -1 !== $ofs) {
- $output->write("\0337");
- $output->write('<hl>'.substr($matches[$ofs], $i).'</hl>');
- $output->write("\0338");
- }
- }
- shell_exec(sprintf('stty %s', $sttyMode));
- }
- return strlen($ret) > 0 ? $ret : $default;
- }
- public function askConfirmation(OutputInterface $output, $question, $default = true)
- {
- $answer = 'z';
- while ($answer && !in_array(strtolower($answer[0]), array('y', 'n'))) {
- $answer = $this->ask($output, $question);
- }
- if (false === $default) {
- return $answer && 'y' == strtolower($answer[0]);
- }
- return !$answer || 'y' == strtolower($answer[0]);
- }
- public function askHiddenResponse(OutputInterface $output, $question, $fallback = true)
- {
- if ('\\' === DIRECTORY_SEPARATOR) {
- $exe = __DIR__.'/../Resources/bin/hiddeninput.exe';
- if ('phar:' === substr(__FILE__, 0, 5)) {
- $tmpExe = sys_get_temp_dir().'/hiddeninput.exe';
- copy($exe, $tmpExe);
- $exe = $tmpExe;
- }
- $output->write($question);
- $value = rtrim(shell_exec($exe));
- $output->writeln('');
- if (isset($tmpExe)) {
- unlink($tmpExe);
- }
- return $value;
- }
- if ($this->hasSttyAvailable()) {
- $output->write($question);
- $sttyMode = shell_exec('stty -g');
- shell_exec('stty -echo');
- $value = fgets($this->inputStream ?: STDIN, 4096);
- shell_exec(sprintf('stty %s', $sttyMode));
- if (false === $value) {
- throw new \RuntimeException('Aborted');
- }
- $value = trim($value);
- $output->writeln('');
- return $value;
- }
- if (false !== $shell = $this->getShell()) {
- $output->write($question);
- $readCmd = $shell === 'csh' ? 'set mypassword = $<' : 'read -r mypassword';
- $command = sprintf("/usr/bin/env %s -c 'stty -echo; %s; stty echo; echo \$mypassword'", $shell, $readCmd);
- $value = rtrim(shell_exec($command));
- $output->writeln('');
- return $value;
- }
- if ($fallback) {
- return $this->ask($output, $question);
- }
- throw new \RuntimeException('Unable to hide the response');
- }
- public function askAndValidate(OutputInterface $output, $question, $validator, $attempts = false, $default = null, array $autocomplete = null)
- {
- $that = $this;
- $interviewer = function () use ($output, $question, $default, $autocomplete, $that) {
- return $that->ask($output, $question, $default, $autocomplete);
- };
- return $this->validateAttempts($interviewer, $output, $validator, $attempts);
- }
- public function askHiddenResponseAndValidate(OutputInterface $output, $question, $validator, $attempts = false, $fallback = true)
- {
- $that = $this;
- $interviewer = function () use ($output, $question, $fallback, $that) {
- return $that->askHiddenResponse($output, $question, $fallback);
- };
- return $this->validateAttempts($interviewer, $output, $validator, $attempts);
- }
- public function setInputStream($stream)
- {
- $this->inputStream = $stream;
- }
- public function getInputStream()
- {
- return $this->inputStream;
- }
- public function getName()
- {
- return 'dialog';
- }
- private function getShell()
- {
- if (null !== self::$shell) {
- return self::$shell;
- }
- self::$shell = false;
- if (file_exists('/usr/bin/env')) {
- $test = "/usr/bin/env %s -c 'echo OK' 2> /dev/null";
- foreach (array('bash', 'zsh', 'ksh', 'csh') as $sh) {
- if ('OK' === rtrim(shell_exec(sprintf($test, $sh)))) {
- self::$shell = $sh;
- break;
- }
- }
- }
- return self::$shell;
- }
- private function hasSttyAvailable()
- {
- if (null !== self::$stty) {
- return self::$stty;
- }
- exec('stty 2>&1', $output, $exitcode);
- return self::$stty = $exitcode === 0;
- }
- private function validateAttempts($interviewer, OutputInterface $output, $validator, $attempts)
- {
- $error = null;
- while (false === $attempts || $attempts--) {
- if (null !== $error) {
- $output->writeln($this->getHelperSet()->get('formatter')->formatBlock($error->getMessage(), 'error'));
- }
- try {
- return call_user_func($validator, $interviewer());
- } catch (\Exception $error) {
- }
- }
- throw $error;
- }
- }
- <?php
- namespace Symfony\Component\Console\Helper;
- use Symfony\Component\Console\Formatter\OutputFormatter;
- class FormatterHelper extends Helper
- {
- public function formatSection($section, $message, $style = 'info')
- {
- return sprintf('<%s>[%s]</%s> %s', $style, $section, $style, $message);
- }
- public function formatBlock($messages, $style, $large = false)
- {
- $messages = (array) $messages;
- $len = 0;
- $lines = array();
- foreach ($messages as $message) {
- $message = OutputFormatter::escape($message);
- $lines[] = sprintf($large ? ' %s ' : ' %s ', $message);
- $len = max($this->strlen($message) + ($large ? 4 : 2), $len);
- }
- $messages = $large ? array(str_repeat(' ', $len)) : array();
- foreach ($lines as $line) {
- $messages[] = $line.str_repeat(' ', $len - $this->strlen($line));
- }
- if ($large) {
- $messages[] = str_repeat(' ', $len);
- }
- foreach ($messages as &$message) {
- $message = sprintf('<%s>%s</%s>', $style, $message, $style);
- }
- return implode("\n", $messages);
- }
- public function getName()
- {
- return 'formatter';
- }
- }
- <?php
- namespace Symfony\Component\Console\Helper;
- use Symfony\Component\Console\Formatter\OutputFormatterInterface;
- abstract class Helper implements HelperInterface
- {
- protected $helperSet = null;
- public function setHelperSet(HelperSet $helperSet = null)
- {
- $this->helperSet = $helperSet;
- }
- public function getHelperSet()
- {
- return $this->helperSet;
- }
- public static function strlen($string)
- {
- if (!function_exists('mb_strwidth')) {
- return strlen($string);
- }
- if (false === $encoding = mb_detect_encoding($string)) {
- return strlen($string);
- }
- return mb_strwidth($string, $encoding);
- }
- public static function formatTime($secs)
- {
- static $timeFormats = array(
- array(0, '< 1 sec'),
- array(2, '1 sec'),
- array(59, 'secs', 1),
- array(60, '1 min'),
- array(3600, 'mins', 60),
- array(5400, '1 hr'),
- array(86400, 'hrs', 3600),
- array(129600, '1 day'),
- array(604800, 'days', 86400),
- );
- foreach ($timeFormats as $format) {
- if ($secs >= $format[0]) {
- continue;
- }
- if (2 == count($format)) {
- return $format[1];
- }
- return ceil($secs / $format[2]).' '.$format[1];
- }
- }
- public static function formatMemory($memory)
- {
- if ($memory >= 1024 * 1024 * 1024) {
- return sprintf('%.1f GiB', $memory / 1024 / 1024 / 1024);
- }
- if ($memory >= 1024 * 1024) {
- return sprintf('%.1f MiB', $memory / 1024 / 1024);
- }
- if ($memory >= 1024) {
- return sprintf('%d KiB', $memory / 1024);
- }
- return sprintf('%d B', $memory);
- }
- public static function strlenWithoutDecoration(OutputFormatterInterface $formatter, $string)
- {
- $isDecorated = $formatter->isDecorated();
- $formatter->setDecorated(false);
- $string = $formatter->format($string);
- $string = preg_replace("/\033\[[^m]*m/", '', $string);
- $formatter->setDecorated($isDecorated);
- return self::strlen($string);
- }
- }
- <?php
- namespace Symfony\Component\Console\Helper;
- interface HelperInterface
- {
- public function setHelperSet(HelperSet $helperSet = null);
- public function getHelperSet();
- public function getName();
- }
- <?php
- namespace Symfony\Component\Console\Helper;
- use Symfony\Component\Console\Command\Command;
- class HelperSet implements \IteratorAggregate
- {
- private $helpers = array();
- private $command;
- public function __construct(array $helpers = array())
- {
- foreach ($helpers as $alias => $helper) {
- $this->set($helper, is_int($alias) ? null : $alias);
- }
- }
- public function set(HelperInterface $helper, $alias = null)
- {
- $this->helpers[$helper->getName()] = $helper;
- if (null !== $alias) {
- $this->helpers[$alias] = $helper;
- }
- $helper->setHelperSet($this);
- }
- public function has($name)
- {
- return isset($this->helpers[$name]);
- }
- public function get($name)
- {
- if (!$this->has($name)) {
- throw new \InvalidArgumentException(sprintf('The helper "%s" is not defined.', $name));
- }
- return $this->helpers[$name];
- }
- public function setCommand(Command $command = null)
- {
- $this->command = $command;
- }
- public function getCommand()
- {
- return $this->command;
- }
- public function getIterator()
- {
- return new \ArrayIterator($this->helpers);
- }
- }
- <?php
- namespace Symfony\Component\Console\Helper;
- use Symfony\Component\Console\Input\InputInterface;
- use Symfony\Component\Console\Input\InputAwareInterface;
- abstract class InputAwareHelper extends Helper implements InputAwareInterface
- {
- protected $input;
- public function setInput(InputInterface $input)
- {
- $this->input = $input;
- }
- }
- <?php
- namespace Symfony\Component\Console\Helper;
- use Symfony\Component\Console\Output\OutputInterface;
- use Symfony\Component\Process\Exception\ProcessFailedException;
- use Symfony\Component\Process\Process;
- use Symfony\Component\Process\ProcessBuilder;
- class ProcessHelper extends Helper
- {
- public function run(OutputInterface $output, $cmd, $error = null, $callback = null, $verbosity = OutputInterface::VERBOSITY_VERY_VERBOSE)
- {
- $formatter = $this->getHelperSet()->get('debug_formatter');
- if (is_array($cmd)) {
- $process = ProcessBuilder::create($cmd)->getProcess();
- } elseif ($cmd instanceof Process) {
- $process = $cmd;
- } else {
- $process = new Process($cmd);
- }
- if ($verbosity <= $output->getVerbosity()) {
- $output->write($formatter->start(spl_object_hash($process), $this->escapeString($process->getCommandLine())));
- }
- if ($output->isDebug()) {
- $callback = $this->wrapCallback($output, $process, $callback);
- }
- $process->run($callback);
- if ($verbosity <= $output->getVerbosity()) {
- $message = $process->isSuccessful() ? 'Command ran successfully' : sprintf('%s Command did not run successfully', $process->getExitCode());
- $output->write($formatter->stop(spl_object_hash($process), $message, $process->isSuccessful()));
- }
- if (!$process->isSuccessful() && null !== $error) {
- $output->writeln(sprintf('<error>%s</error>', $this->escapeString($error)));
- }
- return $process;
- }
- public function mustRun(OutputInterface $output, $cmd, $error = null, $callback = null)
- {
- $process = $this->run($output, $cmd, $error, $callback);
- if (!$process->isSuccessful()) {
- throw new ProcessFailedException($process);
- }
- return $process;
- }
- public function wrapCallback(OutputInterface $output, Process $process, $callback = null)
- {
- $formatter = $this->getHelperSet()->get('debug_formatter');
- $that = $this;
- return function ($type, $buffer) use ($output, $process, $callback, $formatter, $that) {
- $output->write($formatter->progress(spl_object_hash($process), $that->escapeString($buffer), Process::ERR === $type));
- if (null !== $callback) {
- call_user_func($callback, $type, $buffer);
- }
- };
- }
- public function escapeString($str)
- {
- return str_replace('<', '\\<', $str);
- }
- public function getName()
- {
- return 'process';
- }
- }
- <?php
- namespace Symfony\Component\Console\Helper;
- use Symfony\Component\Console\Output\OutputInterface;
- class ProgressBar
- {
- private $barWidth = 28;
- private $barChar;
- private $emptyBarChar = '-';
- private $progressChar = '>';
- private $format = null;
- private $redrawFreq = 1;
- private $output;
- private $step = 0;
- private $max;
- private $startTime;
- private $stepWidth;
- private $percent = 0.0;
- private $lastMessagesLength = 0;
- private $formatLineCount;
- private $messages;
- private $overwrite = true;
- private static $formatters;
- private static $formats;
- public function __construct(OutputInterface $output, $max = 0)
- {
- $this->output = $output;
- $this->setMaxSteps($max);
- if (!$this->output->isDecorated()) {
- $this->overwrite = false;
- if ($this->max > 10) {
- $this->setRedrawFrequency($max / 10);
- }
- }
- $this->setFormat($this->determineBestFormat());
- $this->startTime = time();
- }
- public static function setPlaceholderFormatterDefinition($name, $callable)
- {
- if (!self::$formatters) {
- self::$formatters = self::initPlaceholderFormatters();
- }
- self::$formatters[$name] = $callable;
- }
- public static function getPlaceholderFormatterDefinition($name)
- {
- if (!self::$formatters) {
- self::$formatters = self::initPlaceholderFormatters();
- }
- return isset(self::$formatters[$name]) ? self::$formatters[$name] : null;
- }
- public static function setFormatDefinition($name, $format)
- {
- if (!self::$formats) {
- self::$formats = self::initFormats();
- }
- self::$formats[$name] = $format;
- }
- public static function getFormatDefinition($name)
- {
- if (!self::$formats) {
- self::$formats = self::initFormats();
- }
- return isset(self::$formats[$name]) ? self::$formats[$name] : null;
- }
- public function setMessage($message, $name = 'message')
- {
- $this->messages[$name] = $message;
- }
- public function getMessage($name = 'message')
- {
- return $this->messages[$name];
- }
- public function getStartTime()
- {
- return $this->startTime;
- }
- public function getMaxSteps()
- {
- return $this->max;
- }
- public function getStep()
- {
- return $this->getProgress();
- }
- public function getProgress()
- {
- return $this->step;
- }
- public function getStepWidth()
- {
- return $this->stepWidth;
- }
- public function getProgressPercent()
- {
- return $this->percent;
- }
- public function setBarWidth($size)
- {
- $this->barWidth = (int) $size;
- }
- public function getBarWidth()
- {
- return $this->barWidth;
- }
- public function setBarCharacter($char)
- {
- $this->barChar = $char;
- }
- public function getBarCharacter()
- {
- if (null === $this->barChar) {
- return $this->max ? '=' : $this->emptyBarChar;
- }
- return $this->barChar;
- }
- public function setEmptyBarCharacter($char)
- {
- $this->emptyBarChar = $char;
- }
- public function getEmptyBarCharacter()
- {
- return $this->emptyBarChar;
- }
- public function setProgressCharacter($char)
- {
- $this->progressChar = $char;
- }
- public function getProgressCharacter()
- {
- return $this->progressChar;
- }
- public function setFormat($format)
- {
- if (!$this->max && null !== self::getFormatDefinition($format.'_nomax')) {
- $this->format = self::getFormatDefinition($format.'_nomax');
- } elseif (null !== self::getFormatDefinition($format)) {
- $this->format = self::getFormatDefinition($format);
- } else {
- $this->format = $format;
- }
- $this->formatLineCount = substr_count($this->format, "\n");
- }
- public function setRedrawFrequency($freq)
- {
- $this->redrawFreq = (int) $freq;
- }
- public function start($max = null)
- {
- $this->startTime = time();
- $this->step = 0;
- $this->percent = 0.0;
- if (null !== $max) {
- $this->setMaxSteps($max);
- }
- $this->display();
- }
- public function advance($step = 1)
- {
- $this->setProgress($this->step + $step);
- }
- public function setCurrent($step)
- {
- $this->setProgress($step);
- }
- public function setOverwrite($overwrite)
- {
- $this->overwrite = (bool) $overwrite;
- }
- public function setProgress($step)
- {
- $step = (int) $step;
- if ($step < $this->step) {
- throw new \LogicException('You can\'t regress the progress bar.');
- }
- if ($this->max && $step > $this->max) {
- $this->max = $step;
- }
- $prevPeriod = intval($this->step / $this->redrawFreq);
- $currPeriod = intval($step / $this->redrawFreq);
- $this->step = $step;
- $this->percent = $this->max ? (float) $this->step / $this->max : 0;
- if ($prevPeriod !== $currPeriod || $this->max === $step) {
- $this->display();
- }
- }
- public function finish()
- {
- if (!$this->max) {
- $this->max = $this->step;
- }
- if ($this->step === $this->max && !$this->overwrite) {
- return;
- }
- $this->setProgress($this->max);
- }
- public function display()
- {
- if (OutputInterface::VERBOSITY_QUIET === $this->output->getVerbosity()) {
- return;
- }
- $self = $this;
- $output = $this->output;
- $messages = $this->messages;
- $this->overwrite(preg_replace_callback("{%([a-z\-_]+)(?:\:([^%]+))?%}i", function ($matches) use ($self, $output, $messages) {
- if ($formatter = $self::getPlaceholderFormatterDefinition($matches[1])) {
- $text = call_user_func($formatter, $self, $output);
- } elseif (isset($messages[$matches[1]])) {
- $text = $messages[$matches[1]];
- } else {
- return $matches[0];
- }
- if (isset($matches[2])) {
- $text = sprintf('%'.$matches[2], $text);
- }
- return $text;
- }, $this->format));
- }
- public function clear()
- {
- if (!$this->overwrite) {
- return;
- }
- $this->overwrite(str_repeat("\n", $this->formatLineCount));
- }
- private function setMaxSteps($max)
- {
- $this->max = max(0, (int) $max);
- $this->stepWidth = $this->max ? Helper::strlen($this->max) : 4;
- }
- private function overwrite($message)
- {
- $lines = explode("\n", $message);
- if (null !== $this->lastMessagesLength) {
- foreach ($lines as $i => $line) {
- if ($this->lastMessagesLength > Helper::strlenWithoutDecoration($this->output->getFormatter(), $line)) {
- $lines[$i] = str_pad($line, $this->lastMessagesLength, "\x20", STR_PAD_RIGHT);
- }
- }
- }
- if ($this->overwrite) {
- $this->output->write("\x0D");
- } elseif ($this->step > 0) {
- $this->output->writeln('');
- }
- if ($this->formatLineCount) {
- $this->output->write(sprintf("\033[%dA", $this->formatLineCount));
- }
- $this->output->write(implode("\n", $lines));
- $this->lastMessagesLength = 0;
- foreach ($lines as $line) {
- $len = Helper::strlenWithoutDecoration($this->output->getFormatter(), $line);
- if ($len > $this->lastMessagesLength) {
- $this->lastMessagesLength = $len;
- }
- }
- }
- private function determineBestFormat()
- {
- switch ($this->output->getVerbosity()) {
- case OutputInterface::VERBOSITY_VERBOSE:
- return $this->max ? 'verbose' : 'verbose_nomax';
- case OutputInterface::VERBOSITY_VERY_VERBOSE:
- return $this->max ? 'very_verbose' : 'very_verbose_nomax';
- case OutputInterface::VERBOSITY_DEBUG:
- return $this->max ? 'debug' : 'debug_nomax';
- default:
- return $this->max ? 'normal' : 'normal_nomax';
- }
- }
- private static function initPlaceholderFormatters()
- {
- return array(
- 'bar' => function (ProgressBar $bar, OutputInterface $output) {
- $completeBars = floor($bar->getMaxSteps() > 0 ? $bar->getProgressPercent() * $bar->getBarWidth() : $bar->getProgress() % $bar->getBarWidth());
- $display = str_repeat($bar->getBarCharacter(), $completeBars);
- if ($completeBars < $bar->getBarWidth()) {
- $emptyBars = $bar->getBarWidth() - $completeBars - Helper::strlenWithoutDecoration($output->getFormatter(), $bar->getProgressCharacter());
- $display .= $bar->getProgressCharacter().str_repeat($bar->getEmptyBarCharacter(), $emptyBars);
- }
- return $display;
- },
- 'elapsed' => function (ProgressBar $bar) {
- return Helper::formatTime(time() - $bar->getStartTime());
- },
- 'remaining' => function (ProgressBar $bar) {
- if (!$bar->getMaxSteps()) {
- throw new \LogicException('Unable to display the remaining time if the maximum number of steps is not set.');
- }
- if (!$bar->getProgress()) {
- $remaining = 0;
- } else {
- $remaining = round((time() - $bar->getStartTime()) / $bar->getProgress() * ($bar->getMaxSteps() - $bar->getProgress()));
- }
- return Helper::formatTime($remaining);
- },
- 'estimated' => function (ProgressBar $bar) {
- if (!$bar->getMaxSteps()) {
- throw new \LogicException('Unable to display the estimated time if the maximum number of steps is not set.');
- }
- if (!$bar->getProgress()) {
- $estimated = 0;
- } else {
- $estimated = round((time() - $bar->getStartTime()) / $bar->getProgress() * $bar->getMaxSteps());
- }
- return Helper::formatTime($estimated);
- },
- 'memory' => function (ProgressBar $bar) {
- return Helper::formatMemory(memory_get_usage(true));
- },
- 'current' => function (ProgressBar $bar) {
- return str_pad($bar->getProgress(), $bar->getStepWidth(), ' ', STR_PAD_LEFT);
- },
- 'max' => function (ProgressBar $bar) {
- return $bar->getMaxSteps();
- },
- 'percent' => function (ProgressBar $bar) {
- return floor($bar->getProgressPercent() * 100);
- },
- );
- }
- private static function initFormats()
- {
- return array(
- 'normal' => ' %current%/%max% [%bar%] %percent:3s%%',
- 'normal_nomax' => ' %current% [%bar%]',
- 'verbose' => ' %current%/%max% [%bar%] %percent:3s%% %elapsed:6s%',
- 'verbose_nomax' => ' %current% [%bar%] %elapsed:6s%',
- 'very_verbose' => ' %current%/%max% [%bar%] %percent:3s%% %elapsed:6s%/%estimated:-6s%',
- 'very_verbose_nomax' => ' %current% [%bar%] %elapsed:6s%',
- 'debug' => ' %current%/%max% [%bar%] %percent:3s%% %elapsed:6s%/%estimated:-6s% %memory:6s%',
- 'debug_nomax' => ' %current% [%bar%] %elapsed:6s% %memory:6s%',
- );
- }
- }
- <?php
- namespace Symfony\Component\Console\Helper;
- use Symfony\Component\Console\Output\NullOutput;
- use Symfony\Component\Console\Output\OutputInterface;
- class ProgressHelper extends Helper
- {
- const FORMAT_QUIET = ' %percent%%';
- const FORMAT_NORMAL = ' %current%/%max% [%bar%] %percent%%';
- const FORMAT_VERBOSE = ' %current%/%max% [%bar%] %percent%% Elapsed: %elapsed%';
- const FORMAT_QUIET_NOMAX = ' %current%';
- const FORMAT_NORMAL_NOMAX = ' %current% [%bar%]';
- const FORMAT_VERBOSE_NOMAX = ' %current% [%bar%] Elapsed: %elapsed%';
- private $barWidth = 28;
- private $barChar = '=';
- private $emptyBarChar = '-';
- private $progressChar = '>';
- private $format = null;
- private $redrawFreq = 1;
- private $lastMessagesLength;
- private $barCharOriginal;
- private $output;
- private $current;
- private $max;
- private $startTime;
- private $defaultFormatVars = array(
- 'current',
- 'max',
- 'bar',
- 'percent',
- 'elapsed',
- );
- private $formatVars;
- private $widths = array(
- 'current' => 4,
- 'max' => 4,
- 'percent' => 3,
- 'elapsed' => 6,
- );
- private $timeFormats = array(
- array(0, '???'),
- array(2, '1 sec'),
- array(59, 'secs', 1),
- array(60, '1 min'),
- array(3600, 'mins', 60),
- array(5400, '1 hr'),
- array(86400, 'hrs', 3600),
- array(129600, '1 day'),
- array(604800, 'days', 86400),
- );
- public function setBarWidth($size)
- {
- $this->barWidth = (int) $size;
- }
- public function setBarCharacter($char)
- {
- $this->barChar = $char;
- }
- public function setEmptyBarCharacter($char)
- {
- $this->emptyBarChar = $char;
- }
- public function setProgressCharacter($char)
- {
- $this->progressChar = $char;
- }
- public function setFormat($format)
- {
- $this->format = $format;
- }
- public function setRedrawFrequency($freq)
- {
- $this->redrawFreq = (int) $freq;
- }
- public function start(OutputInterface $output, $max = null)
- {
- $this->startTime = time();
- $this->current = 0;
- $this->max = (int) $max;
- $this->output = $output->isDecorated() ? $output : new NullOutput();
- $this->lastMessagesLength = 0;
- $this->barCharOriginal = '';
- if (null === $this->format) {
- switch ($output->getVerbosity()) {
- case OutputInterface::VERBOSITY_QUIET:
- $this->format = self::FORMAT_QUIET_NOMAX;
- if ($this->max > 0) {
- $this->format = self::FORMAT_QUIET;
- }
- break;
- case OutputInterface::VERBOSITY_VERBOSE:
- case OutputInterface::VERBOSITY_VERY_VERBOSE:
- case OutputInterface::VERBOSITY_DEBUG:
- $this->format = self::FORMAT_VERBOSE_NOMAX;
- if ($this->max > 0) {
- $this->format = self::FORMAT_VERBOSE;
- }
- break;
- default:
- $this->format = self::FORMAT_NORMAL_NOMAX;
- if ($this->max > 0) {
- $this->format = self::FORMAT_NORMAL;
- }
- break;
- }
- }
- $this->initialize();
- }
- public function advance($step = 1, $redraw = false)
- {
- $this->setCurrent($this->current + $step, $redraw);
- }
- public function setCurrent($current, $redraw = false)
- {
- if (null === $this->startTime) {
- throw new \LogicException('You must start the progress bar before calling setCurrent().');
- }
- $current = (int) $current;
- if ($current < $this->current) {
- throw new \LogicException('You can\'t regress the progress bar');
- }
- if (0 === $this->current) {
- $redraw = true;
- }
- $prevPeriod = intval($this->current / $this->redrawFreq);
- $this->current = $current;
- $currPeriod = intval($this->current / $this->redrawFreq);
- if ($redraw || $prevPeriod !== $currPeriod || $this->max === $this->current) {
- $this->display();
- }
- }
- public function display($finish = false)
- {
- if (null === $this->startTime) {
- throw new \LogicException('You must start the progress bar before calling display().');
- }
- $message = $this->format;
- foreach ($this->generate($finish) as $name => $value) {
- $message = str_replace("%{$name}%", $value, $message);
- }
- $this->overwrite($this->output, $message);
- }
- public function clear()
- {
- $this->overwrite($this->output, '');
- }
- public function finish()
- {
- if (null === $this->startTime) {
- throw new \LogicException('You must start the progress bar before calling finish().');
- }
- if (null !== $this->startTime) {
- if (!$this->max) {
- $this->barChar = $this->barCharOriginal;
- $this->display(true);
- }
- $this->startTime = null;
- $this->output->writeln('');
- $this->output = null;
- }
- }
- private function initialize()
- {
- $this->formatVars = array();
- foreach ($this->defaultFormatVars as $var) {
- if (false !== strpos($this->format, "%{$var}%")) {
- $this->formatVars[$var] = true;
- }
- }
- if ($this->max > 0) {
- $this->widths['max'] = $this->strlen($this->max);
- $this->widths['current'] = $this->widths['max'];
- } else {
- $this->barCharOriginal = $this->barChar;
- $this->barChar = $this->emptyBarChar;
- }
- }
- private function generate($finish = false)
- {
- $vars = array();
- $percent = 0;
- if ($this->max > 0) {
- $percent = (float) $this->current / $this->max;
- }
- if (isset($this->formatVars['bar'])) {
- $completeBars = 0;
- if ($this->max > 0) {
- $completeBars = floor($percent * $this->barWidth);
- } else {
- if (!$finish) {
- $completeBars = floor($this->current % $this->barWidth);
- } else {
- $completeBars = $this->barWidth;
- }
- }
- $emptyBars = $this->barWidth - $completeBars - $this->strlen($this->progressChar);
- $bar = str_repeat($this->barChar, $completeBars);
- if ($completeBars < $this->barWidth) {
- $bar .= $this->progressChar;
- $bar .= str_repeat($this->emptyBarChar, $emptyBars);
- }
- $vars['bar'] = $bar;
- }
- if (isset($this->formatVars['elapsed'])) {
- $elapsed = time() - $this->startTime;
- $vars['elapsed'] = str_pad($this->humaneTime($elapsed), $this->widths['elapsed'], ' ', STR_PAD_LEFT);
- }
- if (isset($this->formatVars['current'])) {
- $vars['current'] = str_pad($this->current, $this->widths['current'], ' ', STR_PAD_LEFT);
- }
- if (isset($this->formatVars['max'])) {
- $vars['max'] = $this->max;
- }
- if (isset($this->formatVars['percent'])) {
- $vars['percent'] = str_pad(floor($percent * 100), $this->widths['percent'], ' ', STR_PAD_LEFT);
- }
- return $vars;
- }
- private function humaneTime($secs)
- {
- $text = '';
- foreach ($this->timeFormats as $format) {
- if ($secs < $format[0]) {
- if (count($format) == 2) {
- $text = $format[1];
- break;
- } else {
- $text = ceil($secs / $format[2]).' '.$format[1];
- break;
- }
- }
- }
- return $text;
- }
- private function overwrite(OutputInterface $output, $message)
- {
- $length = $this->strlen($message);
- if (null !== $this->lastMessagesLength && $this->lastMessagesLength > $length) {
- $message = str_pad($message, $this->lastMessagesLength, "\x20", STR_PAD_RIGHT);
- }
- $output->write("\x0D");
- $output->write($message);
- $this->lastMessagesLength = $this->strlen($message);
- }
- public function getName()
- {
- return 'progress';
- }
- }
- <?php
- namespace Symfony\Component\Console\Helper;
- use Symfony\Component\Console\Input\InputInterface;
- use Symfony\Component\Console\Output\OutputInterface;
- use Symfony\Component\Console\Formatter\OutputFormatterStyle;
- use Symfony\Component\Console\Question\Question;
- use Symfony\Component\Console\Question\ChoiceQuestion;
- class QuestionHelper extends Helper
- {
- private $inputStream;
- private static $shell;
- private static $stty;
- public function ask(InputInterface $input, OutputInterface $output, Question $question)
- {
- if (!$input->isInteractive()) {
- return $question->getDefault();
- }
- if (!$question->getValidator()) {
- return $this->doAsk($output, $question);
- }
- $that = $this;
- $interviewer = function () use ($output, $question, $that) {
- return $that->doAsk($output, $question);
- };
- return $this->validateAttempts($interviewer, $output, $question);
- }
- public function setInputStream($stream)
- {
- if (!is_resource($stream)) {
- throw new \InvalidArgumentException('Input stream must be a valid resource.');
- }
- $this->inputStream = $stream;
- }
- public function getInputStream()
- {
- return $this->inputStream;
- }
- public function getName()
- {
- return 'question';
- }
- public function doAsk(OutputInterface $output, Question $question)
- {
- $inputStream = $this->inputStream ?: STDIN;
- $message = $question->getQuestion();
- if ($question instanceof ChoiceQuestion) {
- $width = max(array_map('strlen', array_keys($question->getChoices())));
- $messages = (array) $question->getQuestion();
- foreach ($question->getChoices() as $key => $value) {
- $messages[] = sprintf(" [<info>%-${width}s</info>] %s", $key, $value);
- }
- $output->writeln($messages);
- $message = $question->getPrompt();
- }
- $output->write($message);
- $autocomplete = $question->getAutocompleterValues();
- if (null === $autocomplete || !$this->hasSttyAvailable()) {
- $ret = false;
- if ($question->isHidden()) {
- try {
- $ret = trim($this->getHiddenResponse($output, $inputStream));
- } catch (\RuntimeException $e) {
- if (!$question->isHiddenFallback()) {
- throw $e;
- }
- }
- }
- if (false === $ret) {
- $ret = fgets($inputStream, 4096);
- if (false === $ret) {
- throw new \RuntimeException('Aborted');
- }
- $ret = trim($ret);
- }
- } else {
- $ret = trim($this->autocomplete($output, $question, $inputStream));
- }
- $ret = strlen($ret) > 0 ? $ret : $question->getDefault();
- if ($normalizer = $question->getNormalizer()) {
- return $normalizer($ret);
- }
- return $ret;
- }
- private function autocomplete(OutputInterface $output, Question $question, $inputStream)
- {
- $autocomplete = $question->getAutocompleterValues();
- $ret = '';
- $i = 0;
- $ofs = -1;
- $matches = $autocomplete;
- $numMatches = count($matches);
- $sttyMode = shell_exec('stty -g');
- shell_exec('stty -icanon -echo');
- $output->getFormatter()->setStyle('hl', new OutputFormatterStyle('black', 'white'));
- while (!feof($inputStream)) {
- $c = fread($inputStream, 1);
- if ("\177" === $c) {
- if (0 === $numMatches && 0 !== $i) {
- $i--;
- $output->write("\033[1D");
- }
- if ($i === 0) {
- $ofs = -1;
- $matches = $autocomplete;
- $numMatches = count($matches);
- } else {
- $numMatches = 0;
- }
- $ret = substr($ret, 0, $i);
- } elseif ("\033" === $c) {
- $c .= fread($inputStream, 2);
- if (isset($c[2]) && ('A' === $c[2] || 'B' === $c[2])) {
- if ('A' === $c[2] && -1 === $ofs) {
- $ofs = 0;
- }
- if (0 === $numMatches) {
- continue;
- }
- $ofs += ('A' === $c[2]) ? -1 : 1;
- $ofs = ($numMatches + $ofs) % $numMatches;
- }
- } elseif (ord($c) < 32) {
- if ("\t" === $c || "\n" === $c) {
- if ($numMatches > 0 && -1 !== $ofs) {
- $ret = $matches[$ofs];
- $output->write(substr($ret, $i));
- $i = strlen($ret);
- }
- if ("\n" === $c) {
- $output->write($c);
- break;
- }
- $numMatches = 0;
- }
- continue;
- } else {
- $output->write($c);
- $ret .= $c;
- $i++;
- $numMatches = 0;
- $ofs = 0;
- foreach ($autocomplete as $value) {
- if (0 === strpos($value, $ret) && $i !== strlen($value)) {
- $matches[$numMatches++] = $value;
- }
- }
- }
- $output->write("\033[K");
- if ($numMatches > 0 && -1 !== $ofs) {
- $output->write("\0337");
- $output->write('<hl>'.substr($matches[$ofs], $i).'</hl>');
- $output->write("\0338");
- }
- }
- shell_exec(sprintf('stty %s', $sttyMode));
- return $ret;
- }
- private function getHiddenResponse(OutputInterface $output, $inputStream)
- {
- if ('\\' === DIRECTORY_SEPARATOR) {
- $exe = __DIR__.'/../Resources/bin/hiddeninput.exe';
- if ('phar:' === substr(__FILE__, 0, 5)) {
- $tmpExe = sys_get_temp_dir().'/hiddeninput.exe';
- copy($exe, $tmpExe);
- $exe = $tmpExe;
- }
- $value = rtrim(shell_exec($exe));
- $output->writeln('');
- if (isset($tmpExe)) {
- unlink($tmpExe);
- }
- return $value;
- }
- if ($this->hasSttyAvailable()) {
- $sttyMode = shell_exec('stty -g');
- shell_exec('stty -echo');
- $value = fgets($inputStream, 4096);
- shell_exec(sprintf('stty %s', $sttyMode));
- if (false === $value) {
- throw new \RuntimeException('Aborted');
- }
- $value = trim($value);
- $output->writeln('');
- return $value;
- }
- if (false !== $shell = $this->getShell()) {
- $readCmd = $shell === 'csh' ? 'set mypassword = $<' : 'read -r mypassword';
- $command = sprintf("/usr/bin/env %s -c 'stty -echo; %s; stty echo; echo \$mypassword'", $shell, $readCmd);
- $value = rtrim(shell_exec($command));
- $output->writeln('');
- return $value;
- }
- throw new \RuntimeException('Unable to hide the response.');
- }
- private function validateAttempts($interviewer, OutputInterface $output, Question $question)
- {
- $error = null;
- $attempts = $question->getMaxAttempts();
- while (null === $attempts || $attempts--) {
- if (null !== $error) {
- if (null !== $this->getHelperSet() && $this->getHelperSet()->has('formatter')) {
- $message = $this->getHelperSet()->get('formatter')->formatBlock($error->getMessage(), 'error');
- } else {
- $message = '<error>'.$error->getMessage().'</error>';
- }
- $output->writeln($message);
- }
- try {
- return call_user_func($question->getValidator(), $interviewer());
- } catch (\Exception $error) {
- }
- }
- throw $error;
- }
- private function getShell()
- {
- if (null !== self::$shell) {
- return self::$shell;
- }
- self::$shell = false;
- if (file_exists('/usr/bin/env')) {
- $test = "/usr/bin/env %s -c 'echo OK' 2> /dev/null";
- foreach (array('bash', 'zsh', 'ksh', 'csh') as $sh) {
- if ('OK' === rtrim(shell_exec(sprintf($test, $sh)))) {
- self::$shell = $sh;
- break;
- }
- }
- }
- return self::$shell;
- }
- private function hasSttyAvailable()
- {
- if (null !== self::$stty) {
- return self::$stty;
- }
- exec('stty 2>&1', $output, $exitcode);
- return self::$stty = $exitcode === 0;
- }
- }
- <?php
- namespace Symfony\Component\Console\Helper;
- use Symfony\Component\Console\Output\OutputInterface;
- class Table
- {
- private $headers = array();
- private $rows = array();
- private $columnWidths = array();
- private $numberOfColumns;
- private $output;
- private $style;
- private static $styles;
- public function __construct(OutputInterface $output)
- {
- $this->output = $output;
- if (!self::$styles) {
- self::$styles = self::initStyles();
- }
- $this->setStyle('default');
- }
- public static function setStyleDefinition($name, TableStyle $style)
- {
- if (!self::$styles) {
- self::$styles = self::initStyles();
- }
- self::$styles[$name] = $style;
- }
- public static function getStyleDefinition($name)
- {
- if (!self::$styles) {
- self::$styles = self::initStyles();
- }
- if (!self::$styles[$name]) {
- throw new \InvalidArgumentException(sprintf('Style "%s" is not defined.', $name));
- }
- return self::$styles[$name];
- }
- public function setStyle($name)
- {
- if ($name instanceof TableStyle) {
- $this->style = $name;
- } elseif (isset(self::$styles[$name])) {
- $this->style = self::$styles[$name];
- } else {
- throw new \InvalidArgumentException(sprintf('Style "%s" is not defined.', $name));
- }
- return $this;
- }
- public function getStyle()
- {
- return $this->style;
- }
- public function setHeaders(array $headers)
- {
- $this->headers = array_values($headers);
- return $this;
- }
- public function setRows(array $rows)
- {
- $this->rows = array();
- return $this->addRows($rows);
- }
- public function addRows(array $rows)
- {
- foreach ($rows as $row) {
- $this->addRow($row);
- }
- return $this;
- }
- public function addRow($row)
- {
- if ($row instanceof TableSeparator) {
- $this->rows[] = $row;
- return;
- }
- if (!is_array($row)) {
- throw new \InvalidArgumentException('A row must be an array or a TableSeparator instance.');
- }
- $this->rows[] = array_values($row);
- end($this->rows);
- $rowKey = key($this->rows);
- reset($this->rows);
- foreach ($row as $key => $cellValue) {
- if (!strstr($cellValue, "\n")) {
- continue;
- }
- $lines = explode("\n", $cellValue);
- $this->rows[$rowKey][$key] = $lines[0];
- unset($lines[0]);
- foreach ($lines as $lineKey => $line) {
- $nextRowKey = $rowKey + $lineKey + 1;
- if (isset($this->rows[$nextRowKey])) {
- $this->rows[$nextRowKey][$key] = $line;
- } else {
- $this->rows[$nextRowKey] = array($key => $line);
- }
- }
- }
- return $this;
- }
- public function setRow($column, array $row)
- {
- $this->rows[$column] = $row;
- return $this;
- }
- public function render()
- {
- $this->renderRowSeparator();
- $this->renderRow($this->headers, $this->style->getCellHeaderFormat());
- if (!empty($this->headers)) {
- $this->renderRowSeparator();
- }
- foreach ($this->rows as $row) {
- if ($row instanceof TableSeparator) {
- $this->renderRowSeparator();
- } else {
- $this->renderRow($row, $this->style->getCellRowFormat());
- }
- }
- if (!empty($this->rows)) {
- $this->renderRowSeparator();
- }
- $this->cleanup();
- }
- private function renderRowSeparator()
- {
- if (0 === $count = $this->getNumberOfColumns()) {
- return;
- }
- if (!$this->style->getHorizontalBorderChar() && !$this->style->getCrossingChar()) {
- return;
- }
- $markup = $this->style->getCrossingChar();
- for ($column = 0; $column < $count; $column++) {
- $markup .= str_repeat($this->style->getHorizontalBorderChar(), $this->getColumnWidth($column)).$this->style->getCrossingChar();
- }
- $this->output->writeln(sprintf($this->style->getBorderFormat(), $markup));
- }
- private function renderColumnSeparator()
- {
- $this->output->write(sprintf($this->style->getBorderFormat(), $this->style->getVerticalBorderChar()));
- }
- private function renderRow(array $row, $cellFormat)
- {
- if (empty($row)) {
- return;
- }
- $this->renderColumnSeparator();
- for ($column = 0, $count = $this->getNumberOfColumns(); $column < $count; $column++) {
- $this->renderCell($row, $column, $cellFormat);
- $this->renderColumnSeparator();
- }
- $this->output->writeln('');
- }
- private function renderCell(array $row, $column, $cellFormat)
- {
- $cell = isset($row[$column]) ? $row[$column] : '';
- $width = $this->getColumnWidth($column);
- if (function_exists('mb_strlen') && false !== $encoding = mb_detect_encoding($cell)) {
- $width += strlen($cell) - mb_strlen($cell, $encoding);
- }
- $width += Helper::strlen($cell) - Helper::strlenWithoutDecoration($this->output->getFormatter(), $cell);
- $content = sprintf($this->style->getCellRowContentFormat(), $cell);
- $this->output->write(sprintf($cellFormat, str_pad($content, $width, $this->style->getPaddingChar(), $this->style->getPadType())));
- }
- private function getNumberOfColumns()
- {
- if (null !== $this->numberOfColumns) {
- return $this->numberOfColumns;
- }
- $columns = array(count($this->headers));
- foreach ($this->rows as $row) {
- $columns[] = count($row);
- }
- return $this->numberOfColumns = max($columns);
- }
- private function getColumnWidth($column)
- {
- if (isset($this->columnWidths[$column])) {
- return $this->columnWidths[$column];
- }
- $lengths = array($this->getCellWidth($this->headers, $column));
- foreach ($this->rows as $row) {
- if ($row instanceof TableSeparator) {
- continue;
- }
- $lengths[] = $this->getCellWidth($row, $column);
- }
- return $this->columnWidths[$column] = max($lengths) + strlen($this->style->getCellRowContentFormat()) - 2;
- }
- private function getCellWidth(array $row, $column)
- {
- return isset($row[$column]) ? Helper::strlenWithoutDecoration($this->output->getFormatter(), $row[$column]) : 0;
- }
- private function cleanup()
- {
- $this->columnWidths = array();
- $this->numberOfColumns = null;
- }
- private static function initStyles()
- {
- $borderless = new TableStyle();
- $borderless
- ->setHorizontalBorderChar('=')
- ->setVerticalBorderChar(' ')
- ->setCrossingChar(' ')
- ;
- $compact = new TableStyle();
- $compact
- ->setHorizontalBorderChar('')
- ->setVerticalBorderChar(' ')
- ->setCrossingChar('')
- ->setCellRowContentFormat('%s')
- ;
- return array(
- 'default' => new TableStyle(),
- 'borderless' => $borderless,
- 'compact' => $compact,
- );
- }
- }
- <?php
- namespace Symfony\Component\Console\Helper;
- use Symfony\Component\Console\Output\OutputInterface;
- use Symfony\Component\Console\Output\NullOutput;
- class TableHelper extends Helper
- {
- const LAYOUT_DEFAULT = 0;
- const LAYOUT_BORDERLESS = 1;
- const LAYOUT_COMPACT = 2;
- private $table;
- public function __construct()
- {
- $this->table = new Table(new NullOutput());
- }
- public function setLayout($layout)
- {
- switch ($layout) {
- case self::LAYOUT_BORDERLESS:
- $this->table->setStyle('borderless');
- break;
- case self::LAYOUT_COMPACT:
- $this->table->setStyle('compact');
- break;
- case self::LAYOUT_DEFAULT:
- $this->table->setStyle('default');
- break;
- default:
- throw new \InvalidArgumentException(sprintf('Invalid table layout "%s".', $layout));
- };
- return $this;
- }
- public function setHeaders(array $headers)
- {
- $this->table->setHeaders($headers);
- return $this;
- }
- public function setRows(array $rows)
- {
- $this->table->setRows($rows);
- return $this;
- }
- public function addRows(array $rows)
- {
- $this->table->addRows($rows);
- return $this;
- }
- public function addRow(array $row)
- {
- $this->table->addRow($row);
- return $this;
- }
- public function setRow($column, array $row)
- {
- $this->table->setRow($column, $row);
- return $this;
- }
- public function setPaddingChar($paddingChar)
- {
- $this->table->getStyle()->setPaddingChar($paddingChar);
- return $this;
- }
- public function setHorizontalBorderChar($horizontalBorderChar)
- {
- $this->table->getStyle()->setHorizontalBorderChar($horizontalBorderChar);
- return $this;
- }
- public function setVerticalBorderChar($verticalBorderChar)
- {
- $this->table->getStyle()->setVerticalBorderChar($verticalBorderChar);
- return $this;
- }
- public function setCrossingChar($crossingChar)
- {
- $this->table->getStyle()->setCrossingChar($crossingChar);
- return $this;
- }
- public function setCellHeaderFormat($cellHeaderFormat)
- {
- $this->table->getStyle()->setCellHeaderFormat($cellHeaderFormat);
- return $this;
- }
- public function setCellRowFormat($cellRowFormat)
- {
- $this->table->getStyle()->setCellHeaderFormat($cellRowFormat);
- return $this;
- }
- public function setCellRowContentFormat($cellRowContentFormat)
- {
- $this->table->getStyle()->setCellRowContentFormat($cellRowContentFormat);
- return $this;
- }
- public function setBorderFormat($borderFormat)
- {
- $this->table->getStyle()->setBorderFormat($borderFormat);
- return $this;
- }
- public function setPadType($padType)
- {
- $this->table->getStyle()->setPadType($padType);
- return $this;
- }
- public function render(OutputInterface $output)
- {
- $p = new \ReflectionProperty($this->table, 'output');
- $p->setAccessible(true);
- $p->setValue($this->table, $output);
- $this->table->render();
- }
- public function getName()
- {
- return 'table';
- }
- }
- <?php
- namespace Symfony\Component\Console\Helper;
- class TableSeparator
- {
- }
- <?php
- namespace Symfony\Component\Console\Helper;
- class TableStyle
- {
- private $paddingChar = ' ';
- private $horizontalBorderChar = '-';
- private $verticalBorderChar = '|';
- private $crossingChar = '+';
- private $cellHeaderFormat = '<info>%s</info>';
- private $cellRowFormat = '%s';
- private $cellRowContentFormat = ' %s ';
- private $borderFormat = '%s';
- private $padType = STR_PAD_RIGHT;
- public function setPaddingChar($paddingChar)
- {
- if (!$paddingChar) {
- throw new \LogicException('The padding char must not be empty');
- }
- $this->paddingChar = $paddingChar;
- return $this;
- }
- public function getPaddingChar()
- {
- return $this->paddingChar;
- }
- public function setHorizontalBorderChar($horizontalBorderChar)
- {
- $this->horizontalBorderChar = $horizontalBorderChar;
- return $this;
- }
- public function getHorizontalBorderChar()
- {
- return $this->horizontalBorderChar;
- }
- public function setVerticalBorderChar($verticalBorderChar)
- {
- $this->verticalBorderChar = $verticalBorderChar;
- return $this;
- }
- public function getVerticalBorderChar()
- {
- return $this->verticalBorderChar;
- }
- public function setCrossingChar($crossingChar)
- {
- $this->crossingChar = $crossingChar;
- return $this;
- }
- public function getCrossingChar()
- {
- return $this->crossingChar;
- }
- public function setCellHeaderFormat($cellHeaderFormat)
- {
- $this->cellHeaderFormat = $cellHeaderFormat;
- return $this;
- }
- public function getCellHeaderFormat()
- {
- return $this->cellHeaderFormat;
- }
- public function setCellRowFormat($cellRowFormat)
- {
- $this->cellRowFormat = $cellRowFormat;
- return $this;
- }
- public function getCellRowFormat()
- {
- return $this->cellRowFormat;
- }
- public function setCellRowContentFormat($cellRowContentFormat)
- {
- $this->cellRowContentFormat = $cellRowContentFormat;
- return $this;
- }
- public function getCellRowContentFormat()
- {
- return $this->cellRowContentFormat;
- }
- public function setBorderFormat($borderFormat)
- {
- $this->borderFormat = $borderFormat;
- return $this;
- }
- public function getBorderFormat()
- {
- return $this->borderFormat;
- }
- public function setPadType($padType)
- {
- $this->padType = $padType;
- return $this;
- }
- public function getPadType()
- {
- return $this->padType;
- }
- }
- <?php
- namespace Symfony\Component\Console\Input;
- class ArgvInput extends Input
- {
- private $tokens;
- private $parsed;
- public function __construct(array $argv = null, InputDefinition $definition = null)
- {
- if (null === $argv) {
- $argv = $_SERVER['argv'];
- }
- array_shift($argv);
- $this->tokens = $argv;
- parent::__construct($definition);
- }
- protected function setTokens(array $tokens)
- {
- $this->tokens = $tokens;
- }
- protected function parse()
- {
- $parseOptions = true;
- $this->parsed = $this->tokens;
- while (null !== $token = array_shift($this->parsed)) {
- if ($parseOptions && '' == $token) {
- $this->parseArgument($token);
- } elseif ($parseOptions && '--' == $token) {
- $parseOptions = false;
- } elseif ($parseOptions && 0 === strpos($token, '--')) {
- $this->parseLongOption($token);
- } elseif ($parseOptions && '-' === $token[0] && '-' !== $token) {
- $this->parseShortOption($token);
- } else {
- $this->parseArgument($token);
- }
- }
- }
- private function parseShortOption($token)
- {
- $name = substr($token, 1);
- if (strlen($name) > 1) {
- if ($this->definition->hasShortcut($name[0]) && $this->definition->getOptionForShortcut($name[0])->acceptValue()) {
- $this->addShortOption($name[0], substr($name, 1));
- } else {
- $this->parseShortOptionSet($name);
- }
- } else {
- $this->addShortOption($name, null);
- }
- }
- private function parseShortOptionSet($name)
- {
- $len = strlen($name);
- for ($i = 0; $i < $len; $i++) {
- if (!$this->definition->hasShortcut($name[$i])) {
- throw new \RuntimeException(sprintf('The "-%s" option does not exist.', $name[$i]));
- }
- $option = $this->definition->getOptionForShortcut($name[$i]);
- if ($option->acceptValue()) {
- $this->addLongOption($option->getName(), $i === $len - 1 ? null : substr($name, $i + 1));
- break;
- } else {
- $this->addLongOption($option->getName(), null);
- }
- }
- }
- private function parseLongOption($token)
- {
- $name = substr($token, 2);
- if (false !== $pos = strpos($name, '=')) {
- $this->addLongOption(substr($name, 0, $pos), substr($name, $pos + 1));
- } else {
- $this->addLongOption($name, null);
- }
- }
- private function parseArgument($token)
- {
- $c = count($this->arguments);
- if ($this->definition->hasArgument($c)) {
- $arg = $this->definition->getArgument($c);
- $this->arguments[$arg->getName()] = $arg->isArray() ? array($token) : $token;
- } elseif ($this->definition->hasArgument($c - 1) && $this->definition->getArgument($c - 1)->isArray()) {
- $arg = $this->definition->getArgument($c - 1);
- $this->arguments[$arg->getName()][] = $token;
- } else {
- throw new \RuntimeException('Too many arguments.');
- }
- }
- private function addShortOption($shortcut, $value)
- {
- if (!$this->definition->hasShortcut($shortcut)) {
- throw new \RuntimeException(sprintf('The "-%s" option does not exist.', $shortcut));
- }
- $this->addLongOption($this->definition->getOptionForShortcut($shortcut)->getName(), $value);
- }
- private function addLongOption($name, $value)
- {
- if (!$this->definition->hasOption($name)) {
- throw new \RuntimeException(sprintf('The "--%s" option does not exist.', $name));
- }
- $option = $this->definition->getOption($name);
- if (false === $value) {
- $value = null;
- }
- if (null !== $value && !$option->acceptValue()) {
- throw new \RuntimeException(sprintf('The "--%s" option does not accept a value.', $name, $value));
- }
- if (null === $value && $option->acceptValue() && count($this->parsed)) {
-
- $next = array_shift($this->parsed);
- if (isset($next[0]) && '-' !== $next[0]) {
- $value = $next;
- } elseif (empty($next)) {
- $value = '';
- } else {
- array_unshift($this->parsed, $next);
- }
- }
- if (null === $value) {
- if ($option->isValueRequired()) {
- throw new \RuntimeException(sprintf('The "--%s" option requires a value.', $name));
- }
- if (!$option->isArray()) {
- $value = $option->isValueOptional() ? $option->getDefault() : true;
- }
- }
- if ($option->isArray()) {
- $this->options[$name][] = $value;
- } else {
- $this->options[$name] = $value;
- }
- }
- public function getFirstArgument()
- {
- foreach ($this->tokens as $token) {
- if ($token && '-' === $token[0]) {
- continue;
- }
- return $token;
- }
- }
- public function hasParameterOption($values)
- {
- $values = (array) $values;
- foreach ($this->tokens as $token) {
- foreach ($values as $value) {
- if ($token === $value || 0 === strpos($token, $value.'=')) {
- return true;
- }
- }
- }
- return false;
- }
- public function getParameterOption($values, $default = false)
- {
- $values = (array) $values;
- $tokens = $this->tokens;
- while (0 < count($tokens)) {
- $token = array_shift($tokens);
- foreach ($values as $value) {
- if ($token === $value || 0 === strpos($token, $value.'=')) {
- if (false !== $pos = strpos($token, '=')) {
- return substr($token, $pos + 1);
- }
- return array_shift($tokens);
- }
- }
- }
- return $default;
- }
- public function __toString()
- {
- $self = $this;
- $tokens = array_map(function ($token) use ($self) {
- if (preg_match('{^(-[^=]+=)(.+)}', $token, $match)) {
- return $match[1].$self->escapeToken($match[2]);
- }
- if ($token && $token[0] !== '-') {
- return $self->escapeToken($token);
- }
- return $token;
- }, $this->tokens);
- return implode(' ', $tokens);
- }
- }
- <?php
- namespace Symfony\Component\Console\Input;
- class ArrayInput extends Input
- {
- private $parameters;
- public function __construct(array $parameters, InputDefinition $definition = null)
- {
- $this->parameters = $parameters;
- parent::__construct($definition);
- }
- public function getFirstArgument()
- {
- foreach ($this->parameters as $key => $value) {
- if ($key && '-' === $key[0]) {
- continue;
- }
- return $value;
- }
- }
- public function hasParameterOption($values)
- {
- $values = (array) $values;
- foreach ($this->parameters as $k => $v) {
- if (!is_int($k)) {
- $v = $k;
- }
- if (in_array($v, $values)) {
- return true;
- }
- }
- return false;
- }
- public function getParameterOption($values, $default = false)
- {
- $values = (array) $values;
- foreach ($this->parameters as $k => $v) {
- if (is_int($k) && in_array($v, $values)) {
- return true;
- } elseif (in_array($k, $values)) {
- return $v;
- }
- }
- return $default;
- }
- public function __toString()
- {
- $params = array();
- foreach ($this->parameters as $param => $val) {
- if ($param && '-' === $param[0]) {
- $params[] = $param.('' != $val ? '='.$this->escapeToken($val) : '');
- } else {
- $params[] = $this->escapeToken($val);
- }
- }
- return implode(' ', $params);
- }
- protected function parse()
- {
- foreach ($this->parameters as $key => $value) {
- if (0 === strpos($key, '--')) {
- $this->addLongOption(substr($key, 2), $value);
- } elseif ('-' === $key[0]) {
- $this->addShortOption(substr($key, 1), $value);
- } else {
- $this->addArgument($key, $value);
- }
- }
- }
- private function addShortOption($shortcut, $value)
- {
- if (!$this->definition->hasShortcut($shortcut)) {
- throw new \InvalidArgumentException(sprintf('The "-%s" option does not exist.', $shortcut));
- }
- $this->addLongOption($this->definition->getOptionForShortcut($shortcut)->getName(), $value);
- }
- private function addLongOption($name, $value)
- {
- if (!$this->definition->hasOption($name)) {
- throw new \InvalidArgumentException(sprintf('The "--%s" option does not exist.', $name));
- }
- $option = $this->definition->getOption($name);
- if (null === $value) {
- if ($option->isValueRequired()) {
- throw new \InvalidArgumentException(sprintf('The "--%s" option requires a value.', $name));
- }
- $value = $option->isValueOptional() ? $option->getDefault() : true;
- }
- $this->options[$name] = $value;
- }
- private function addArgument($name, $value)
- {
- if (!$this->definition->hasArgument($name)) {
- throw new \InvalidArgumentException(sprintf('The "%s" argument does not exist.', $name));
- }
- $this->arguments[$name] = $value;
- }
- }
- <?php
- namespace Symfony\Component\Console\Input;
- abstract class Input implements InputInterface
- {
- protected $definition;
- protected $options = array();
- protected $arguments = array();
- protected $interactive = true;
- public function __construct(InputDefinition $definition = null)
- {
- if (null === $definition) {
- $this->definition = new InputDefinition();
- } else {
- $this->bind($definition);
- $this->validate();
- }
- }
- public function bind(InputDefinition $definition)
- {
- $this->arguments = array();
- $this->options = array();
- $this->definition = $definition;
- $this->parse();
- }
- abstract protected function parse();
- public function validate()
- {
- if (count($this->arguments) < $this->definition->getArgumentRequiredCount()) {
- throw new \RuntimeException('Not enough arguments.');
- }
- }
- public function isInteractive()
- {
- return $this->interactive;
- }
- public function setInteractive($interactive)
- {
- $this->interactive = (bool) $interactive;
- }
- public function getArguments()
- {
- return array_merge($this->definition->getArgumentDefaults(), $this->arguments);
- }
- public function getArgument($name)
- {
- if (!$this->definition->hasArgument($name)) {
- throw new \InvalidArgumentException(sprintf('The "%s" argument does not exist.', $name));
- }
- return isset($this->arguments[$name]) ? $this->arguments[$name] : $this->definition->getArgument($name)->getDefault();
- }
- public function setArgument($name, $value)
- {
- if (!$this->definition->hasArgument($name)) {
- throw new \InvalidArgumentException(sprintf('The "%s" argument does not exist.', $name));
- }
- $this->arguments[$name] = $value;
- }
- public function hasArgument($name)
- {
- return $this->definition->hasArgument($name);
- }
- public function getOptions()
- {
- return array_merge($this->definition->getOptionDefaults(), $this->options);
- }
- public function getOption($name)
- {
- if (!$this->definition->hasOption($name)) {
- throw new \InvalidArgumentException(sprintf('The "%s" option does not exist.', $name));
- }
- return isset($this->options[$name]) ? $this->options[$name] : $this->definition->getOption($name)->getDefault();
- }
- public function setOption($name, $value)
- {
- if (!$this->definition->hasOption($name)) {
- throw new \InvalidArgumentException(sprintf('The "%s" option does not exist.', $name));
- }
- $this->options[$name] = $value;
- }
- public function hasOption($name)
- {
- return $this->definition->hasOption($name);
- }
- public function escapeToken($token)
- {
- return preg_match('{^[\w-]+$}', $token) ? $token : escapeshellarg($token);
- }
- }
- <?php
- namespace Symfony\Component\Console\Input;
- class InputArgument
- {
- const REQUIRED = 1;
- const OPTIONAL = 2;
- const IS_ARRAY = 4;
- private $name;
- private $mode;
- private $default;
- private $description;
- public function __construct($name, $mode = null, $description = '', $default = null)
- {
- if (null === $mode) {
- $mode = self::OPTIONAL;
- } elseif (!is_int($mode) || $mode > 7 || $mode < 1) {
- throw new \InvalidArgumentException(sprintf('Argument mode "%s" is not valid.', $mode));
- }
- $this->name = $name;
- $this->mode = $mode;
- $this->description = $description;
- $this->setDefault($default);
- }
- public function getName()
- {
- return $this->name;
- }
- public function isRequired()
- {
- return self::REQUIRED === (self::REQUIRED & $this->mode);
- }
- public function isArray()
- {
- return self::IS_ARRAY === (self::IS_ARRAY & $this->mode);
- }
- public function setDefault($default = null)
- {
- if (self::REQUIRED === $this->mode && null !== $default) {
- throw new \LogicException('Cannot set a default value except for InputArgument::OPTIONAL mode.');
- }
- if ($this->isArray()) {
- if (null === $default) {
- $default = array();
- } elseif (!is_array($default)) {
- throw new \LogicException('A default value for an array argument must be an array.');
- }
- }
- $this->default = $default;
- }
- public function getDefault()
- {
- return $this->default;
- }
- public function getDescription()
- {
- return $this->description;
- }
- }
- <?php
- namespace Symfony\Component\Console\Input;
- interface InputAwareInterface
- {
- public function setInput(InputInterface $input);
- }
- <?php
- namespace Symfony\Component\Console\Input;
- use Symfony\Component\Console\Descriptor\TextDescriptor;
- use Symfony\Component\Console\Descriptor\XmlDescriptor;
- use Symfony\Component\Console\Output\BufferedOutput;
- class InputDefinition
- {
- private $arguments;
- private $requiredCount;
- private $hasAnArrayArgument = false;
- private $hasOptional;
- private $options;
- private $shortcuts;
- public function __construct(array $definition = array())
- {
- $this->setDefinition($definition);
- }
- public function setDefinition(array $definition)
- {
- $arguments = array();
- $options = array();
- foreach ($definition as $item) {
- if ($item instanceof InputOption) {
- $options[] = $item;
- } else {
- $arguments[] = $item;
- }
- }
- $this->setArguments($arguments);
- $this->setOptions($options);
- }
- public function setArguments($arguments = array())
- {
- $this->arguments = array();
- $this->requiredCount = 0;
- $this->hasOptional = false;
- $this->hasAnArrayArgument = false;
- $this->addArguments($arguments);
- }
- public function addArguments($arguments = array())
- {
- if (null !== $arguments) {
- foreach ($arguments as $argument) {
- $this->addArgument($argument);
- }
- }
- }
- public function addArgument(InputArgument $argument)
- {
- if (isset($this->arguments[$argument->getName()])) {
- throw new \LogicException(sprintf('An argument with name "%s" already exists.', $argument->getName()));
- }
- if ($this->hasAnArrayArgument) {
- throw new \LogicException('Cannot add an argument after an array argument.');
- }
- if ($argument->isRequired() && $this->hasOptional) {
- throw new \LogicException('Cannot add a required argument after an optional one.');
- }
- if ($argument->isArray()) {
- $this->hasAnArrayArgument = true;
- }
- if ($argument->isRequired()) {
- ++$this->requiredCount;
- } else {
- $this->hasOptional = true;
- }
- $this->arguments[$argument->getName()] = $argument;
- }
- public function getArgument($name)
- {
- if (!$this->hasArgument($name)) {
- throw new \InvalidArgumentException(sprintf('The "%s" argument does not exist.', $name));
- }
- $arguments = is_int($name) ? array_values($this->arguments) : $this->arguments;
- return $arguments[$name];
- }
- public function hasArgument($name)
- {
- $arguments = is_int($name) ? array_values($this->arguments) : $this->arguments;
- return isset($arguments[$name]);
- }
- public function getArguments()
- {
- return $this->arguments;
- }
- public function getArgumentCount()
- {
- return $this->hasAnArrayArgument ? PHP_INT_MAX : count($this->arguments);
- }
- public function getArgumentRequiredCount()
- {
- return $this->requiredCount;
- }
- public function getArgumentDefaults()
- {
- $values = array();
- foreach ($this->arguments as $argument) {
- $values[$argument->getName()] = $argument->getDefault();
- }
- return $values;
- }
- public function setOptions($options = array())
- {
- $this->options = array();
- $this->shortcuts = array();
- $this->addOptions($options);
- }
- public function addOptions($options = array())
- {
- foreach ($options as $option) {
- $this->addOption($option);
- }
- }
- public function addOption(InputOption $option)
- {
- if (isset($this->options[$option->getName()]) && !$option->equals($this->options[$option->getName()])) {
- throw new \LogicException(sprintf('An option named "%s" already exists.', $option->getName()));
- }
- if ($option->getShortcut()) {
- foreach (explode('|', $option->getShortcut()) as $shortcut) {
- if (isset($this->shortcuts[$shortcut]) && !$option->equals($this->options[$this->shortcuts[$shortcut]])) {
- throw new \LogicException(sprintf('An option with shortcut "%s" already exists.', $shortcut));
- }
- }
- }
- $this->options[$option->getName()] = $option;
- if ($option->getShortcut()) {
- foreach (explode('|', $option->getShortcut()) as $shortcut) {
- $this->shortcuts[$shortcut] = $option->getName();
- }
- }
- }
- public function getOption($name)
- {
- if (!$this->hasOption($name)) {
- throw new \InvalidArgumentException(sprintf('The "--%s" option does not exist.', $name));
- }
- return $this->options[$name];
- }
- public function hasOption($name)
- {
- return isset($this->options[$name]);
- }
- public function getOptions()
- {
- return $this->options;
- }
- public function hasShortcut($name)
- {
- return isset($this->shortcuts[$name]);
- }
- public function getOptionForShortcut($shortcut)
- {
- return $this->getOption($this->shortcutToName($shortcut));
- }
- public function getOptionDefaults()
- {
- $values = array();
- foreach ($this->options as $option) {
- $values[$option->getName()] = $option->getDefault();
- }
- return $values;
- }
- private function shortcutToName($shortcut)
- {
- if (!isset($this->shortcuts[$shortcut])) {
- throw new \InvalidArgumentException(sprintf('The "-%s" option does not exist.', $shortcut));
- }
- return $this->shortcuts[$shortcut];
- }
- public function getSynopsis()
- {
- $elements = array();
- foreach ($this->getOptions() as $option) {
- $shortcut = $option->getShortcut() ? sprintf('-%s|', $option->getShortcut()) : '';
- $elements[] = sprintf('['.($option->isValueRequired() ? '%s--%s="..."' : ($option->isValueOptional() ? '%s--%s[="..."]' : '%s--%s')).']', $shortcut, $option->getName());
- }
- foreach ($this->getArguments() as $argument) {
- $elements[] = sprintf($argument->isRequired() ? '%s' : '[%s]', $argument->getName().($argument->isArray() ? '1' : ''));
- if ($argument->isArray()) {
- $elements[] = sprintf('... [%sN]', $argument->getName());
- }
- }
- return implode(' ', $elements);
- }
- public function asText()
- {
- $descriptor = new TextDescriptor();
- $output = new BufferedOutput(BufferedOutput::VERBOSITY_NORMAL, true);
- $descriptor->describe($output, $this, array('raw_output' => true));
- return $output->fetch();
- }
- public function asXml($asDom = false)
- {
- $descriptor = new XmlDescriptor();
- if ($asDom) {
- return $descriptor->getInputDefinitionDocument($this);
- }
- $output = new BufferedOutput();
- $descriptor->describe($output, $this);
- return $output->fetch();
- }
- }
- <?php
- namespace Symfony\Component\Console\Input;
- interface InputInterface
- {
- public function getFirstArgument();
- public function hasParameterOption($values);
- public function getParameterOption($values, $default = false);
- public function bind(InputDefinition $definition);
- public function validate();
- public function getArguments();
- public function getArgument($name);
- public function setArgument($name, $value);
- public function hasArgument($name);
- public function getOptions();
- public function getOption($name);
- public function setOption($name, $value);
- public function hasOption($name);
- public function isInteractive();
- public function setInteractive($interactive);
- }
- <?php
- namespace Symfony\Component\Console\Input;
- class InputOption
- {
- const VALUE_NONE = 1;
- const VALUE_REQUIRED = 2;
- const VALUE_OPTIONAL = 4;
- const VALUE_IS_ARRAY = 8;
- private $name;
- private $shortcut;
- private $mode;
- private $default;
- private $description;
- public function __construct($name, $shortcut = null, $mode = null, $description = '', $default = null)
- {
- if (0 === strpos($name, '--')) {
- $name = substr($name, 2);
- }
- if (empty($name)) {
- throw new \InvalidArgumentException('An option name cannot be empty.');
- }
- if (empty($shortcut)) {
- $shortcut = null;
- }
- if (null !== $shortcut) {
- if (is_array($shortcut)) {
- $shortcut = implode('|', $shortcut);
- }
- $shortcuts = preg_split('{(\|)-?}', ltrim($shortcut, '-'));
- $shortcuts = array_filter($shortcuts);
- $shortcut = implode('|', $shortcuts);
- if (empty($shortcut)) {
- throw new \InvalidArgumentException('An option shortcut cannot be empty.');
- }
- }
- if (null === $mode) {
- $mode = self::VALUE_NONE;
- } elseif (!is_int($mode) || $mode > 15 || $mode < 1) {
- throw new \InvalidArgumentException(sprintf('Option mode "%s" is not valid.', $mode));
- }
- $this->name = $name;
- $this->shortcut = $shortcut;
- $this->mode = $mode;
- $this->description = $description;
- if ($this->isArray() && !$this->acceptValue()) {
- throw new \InvalidArgumentException('Impossible to have an option mode VALUE_IS_ARRAY if the option does not accept a value.');
- }
- $this->setDefault($default);
- }
- public function getShortcut()
- {
- return $this->shortcut;
- }
- public function getName()
- {
- return $this->name;
- }
- public function acceptValue()
- {
- return $this->isValueRequired() || $this->isValueOptional();
- }
- public function isValueRequired()
- {
- return self::VALUE_REQUIRED === (self::VALUE_REQUIRED & $this->mode);
- }
- public function isValueOptional()
- {
- return self::VALUE_OPTIONAL === (self::VALUE_OPTIONAL & $this->mode);
- }
- public function isArray()
- {
- return self::VALUE_IS_ARRAY === (self::VALUE_IS_ARRAY & $this->mode);
- }
- public function setDefault($default = null)
- {
- if (self::VALUE_NONE === (self::VALUE_NONE & $this->mode) && null !== $default) {
- throw new \LogicException('Cannot set a default value when using InputOption::VALUE_NONE mode.');
- }
- if ($this->isArray()) {
- if (null === $default) {
- $default = array();
- } elseif (!is_array($default)) {
- throw new \LogicException('A default value for an array option must be an array.');
- }
- }
- $this->default = $this->acceptValue() ? $default : false;
- }
- public function getDefault()
- {
- return $this->default;
- }
- public function getDescription()
- {
- return $this->description;
- }
- public function equals(InputOption $option)
- {
- return $option->getName() === $this->getName()
- && $option->getShortcut() === $this->getShortcut()
- && $option->getDefault() === $this->getDefault()
- && $option->isArray() === $this->isArray()
- && $option->isValueRequired() === $this->isValueRequired()
- && $option->isValueOptional() === $this->isValueOptional()
- ;
- }
- }
- <?php
- namespace Symfony\Component\Console\Input;
- class StringInput extends ArgvInput
- {
- const REGEX_STRING = '([^\s]+?)(?:\s|(?<!\\\\)"|(?<!\\\\)\'|$)';
- const REGEX_QUOTED_STRING = '(?:"([^"\\\\]*(?:\\\\.[^"\\\\]*)*)"|\'([^\'\\\\]*(?:\\\\.[^\'\\\\]*)*)\')';
- public function __construct($input, InputDefinition $definition = null)
- {
- parent::__construct(array(), null);
- $this->setTokens($this->tokenize($input));
- if (null !== $definition) {
- $this->bind($definition);
- }
- }
- private function tokenize($input)
- {
- $tokens = array();
- $length = strlen($input);
- $cursor = 0;
- while ($cursor < $length) {
- if (preg_match('/\s+/A', $input, $match, null, $cursor)) {
- } elseif (preg_match('/([^="\'\s]+?)(=?)('.self::REGEX_QUOTED_STRING.'+)/A', $input, $match, null, $cursor)) {
- $tokens[] = $match[1].$match[2].stripcslashes(str_replace(array('"\'', '\'"', '\'\'', '""'), '', substr($match[3], 1, strlen($match[3]) - 2)));
- } elseif (preg_match('/'.self::REGEX_QUOTED_STRING.'/A', $input, $match, null, $cursor)) {
- $tokens[] = stripcslashes(substr($match[0], 1, strlen($match[0]) - 2));
- } elseif (preg_match('/'.self::REGEX_STRING.'/A', $input, $match, null, $cursor)) {
- $tokens[] = stripcslashes($match[1]);
- } else {
- throw new \InvalidArgumentException(sprintf('Unable to parse input near "... %s ..."', substr($input, $cursor, 10)));
- }
- $cursor += strlen($match[0]);
- }
- return $tokens;
- }
- }
- Copyright (c) 2004-2015 Fabien Potencier
- Permission is hereby granted, free of charge, to any person obtaining a copy
- of this software and associated documentation files (the "Software"), to deal
- in the Software without restriction, including without limitation the rights
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- copies of the Software, and to permit persons to whom the Software is furnished
- to do so, subject to the following conditions:
- The above copyright notice and this permission notice shall be included in all
- copies or substantial portions of the Software.
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- THE SOFTWARE.
- <?php
- namespace Symfony\Component\Console\Logger;
- use Psr\Log\AbstractLogger;
- use Psr\Log\InvalidArgumentException;
- use Psr\Log\LogLevel;
- use Symfony\Component\Console\Output\OutputInterface;
- use Symfony\Component\Console\Output\ConsoleOutputInterface;
- class ConsoleLogger extends AbstractLogger
- {
- const INFO = 'info';
- const ERROR = 'error';
- private $output;
- private $verbosityLevelMap = array(
- LogLevel::EMERGENCY => OutputInterface::VERBOSITY_NORMAL,
- LogLevel::ALERT => OutputInterface::VERBOSITY_NORMAL,
- LogLevel::CRITICAL => OutputInterface::VERBOSITY_NORMAL,
- LogLevel::ERROR => OutputInterface::VERBOSITY_NORMAL,
- LogLevel::WARNING => OutputInterface::VERBOSITY_NORMAL,
- LogLevel::NOTICE => OutputInterface::VERBOSITY_VERBOSE,
- LogLevel::INFO => OutputInterface::VERBOSITY_VERY_VERBOSE,
- LogLevel::DEBUG => OutputInterface::VERBOSITY_DEBUG,
- );
- private $formatLevelMap = array(
- LogLevel::EMERGENCY => self::ERROR,
- LogLevel::ALERT => self::ERROR,
- LogLevel::CRITICAL => self::ERROR,
- LogLevel::ERROR => self::ERROR,
- LogLevel::WARNING => self::INFO,
- LogLevel::NOTICE => self::INFO,
- LogLevel::INFO => self::INFO,
- LogLevel::DEBUG => self::INFO,
- );
- public function __construct(OutputInterface $output, array $verbosityLevelMap = array(), array $formatLevelMap = array())
- {
- $this->output = $output;
- $this->verbosityLevelMap = $verbosityLevelMap + $this->verbosityLevelMap;
- $this->formatLevelMap = $formatLevelMap + $this->formatLevelMap;
- }
- public function log($level, $message, array $context = array())
- {
- if (!isset($this->verbosityLevelMap[$level])) {
- throw new InvalidArgumentException(sprintf('The log level "%s" does not exist.', $level));
- }
- if ($this->formatLevelMap[$level] === self::ERROR && $this->output instanceof ConsoleOutputInterface) {
- $output = $this->output->getErrorOutput();
- } else {
- $output = $this->output;
- }
- if ($output->getVerbosity() >= $this->verbosityLevelMap[$level]) {
- $output->writeln(sprintf('<%1$s>[%2$s] %3$s</%1$s>', $this->formatLevelMap[$level], $level, $this->interpolate($message, $context)));
- }
- }
- private function interpolate($message, array $context)
- {
- $replace = array();
- foreach ($context as $key => $val) {
- if (!is_array($val) && (!is_object($val) || method_exists($val, '__toString'))) {
- $replace[sprintf('{%s}', $key)] = $val;
- }
- }
- return strtr($message, $replace);
- }
- }
- <?php
- namespace Symfony\Component\Console\Output;
- class BufferedOutput extends Output
- {
- private $buffer = '';
- public function fetch()
- {
- $content = $this->buffer;
- $this->buffer = '';
- return $content;
- }
- protected function doWrite($message, $newline)
- {
- $this->buffer .= $message;
- if ($newline) {
- $this->buffer .= "\n";
- }
- }
- }
- <?php
- namespace Symfony\Component\Console\Output;
- use Symfony\Component\Console\Formatter\OutputFormatterInterface;
- class ConsoleOutput extends StreamOutput implements ConsoleOutputInterface
- {
- private $stderr;
- public function __construct($verbosity = self::VERBOSITY_NORMAL, $decorated = null, OutputFormatterInterface $formatter = null)
- {
- $outputStream = 'php://stdout';
- if (!$this->hasStdoutSupport()) {
- $outputStream = 'php://output';
- }
- parent::__construct(fopen($outputStream, 'w'), $verbosity, $decorated, $formatter);
- $this->stderr = new StreamOutput(fopen('php://stderr', 'w'), $verbosity, $decorated, $this->getFormatter());
- }
- public function setDecorated($decorated)
- {
- parent::setDecorated($decorated);
- $this->stderr->setDecorated($decorated);
- }
- public function setFormatter(OutputFormatterInterface $formatter)
- {
- parent::setFormatter($formatter);
- $this->stderr->setFormatter($formatter);
- }
- public function setVerbosity($level)
- {
- parent::setVerbosity($level);
- $this->stderr->setVerbosity($level);
- }
- public function getErrorOutput()
- {
- return $this->stderr;
- }
- public function setErrorOutput(OutputInterface $error)
- {
- $this->stderr = $error;
- }
- protected function hasStdoutSupport()
- {
- return ('OS400' != php_uname('s'));
- }
- }
- <?php
- namespace Symfony\Component\Console\Output;
- interface ConsoleOutputInterface extends OutputInterface
- {
- public function getErrorOutput();
- public function setErrorOutput(OutputInterface $error);
- }
- <?php
- namespace Symfony\Component\Console\Output;
- use Symfony\Component\Console\Formatter\OutputFormatter;
- use Symfony\Component\Console\Formatter\OutputFormatterInterface;
- class NullOutput implements OutputInterface
- {
- public function setFormatter(OutputFormatterInterface $formatter)
- {
- }
- public function getFormatter()
- {
- return new OutputFormatter();
- }
- public function setDecorated($decorated)
- {
- }
- public function isDecorated()
- {
- return false;
- }
- public function setVerbosity($level)
- {
- }
- public function getVerbosity()
- {
- return self::VERBOSITY_QUIET;
- }
- public function isQuiet()
- {
- return true;
- }
- public function isVerbose()
- {
- return false;
- }
- public function isVeryVerbose()
- {
- return false;
- }
- public function isDebug()
- {
- return false;
- }
- public function writeln($messages, $type = self::OUTPUT_NORMAL)
- {
- }
- public function write($messages, $newline = false, $type = self::OUTPUT_NORMAL)
- {
- }
- }
- <?php
- namespace Symfony\Component\Console\Output;
- use Symfony\Component\Console\Formatter\OutputFormatterInterface;
- use Symfony\Component\Console\Formatter\OutputFormatter;
- abstract class Output implements OutputInterface
- {
- private $verbosity;
- private $formatter;
- public function __construct($verbosity = self::VERBOSITY_NORMAL, $decorated = false, OutputFormatterInterface $formatter = null)
- {
- $this->verbosity = null === $verbosity ? self::VERBOSITY_NORMAL : $verbosity;
- $this->formatter = $formatter ?: new OutputFormatter();
- $this->formatter->setDecorated($decorated);
- }
- public function setFormatter(OutputFormatterInterface $formatter)
- {
- $this->formatter = $formatter;
- }
- public function getFormatter()
- {
- return $this->formatter;
- }
- public function setDecorated($decorated)
- {
- $this->formatter->setDecorated($decorated);
- }
- public function isDecorated()
- {
- return $this->formatter->isDecorated();
- }
- public function setVerbosity($level)
- {
- $this->verbosity = (int) $level;
- }
- public function getVerbosity()
- {
- return $this->verbosity;
- }
- public function isQuiet()
- {
- return self::VERBOSITY_QUIET === $this->verbosity;
- }
- public function isVerbose()
- {
- return self::VERBOSITY_VERBOSE <= $this->verbosity;
- }
- public function isVeryVerbose()
- {
- return self::VERBOSITY_VERY_VERBOSE <= $this->verbosity;
- }
- public function isDebug()
- {
- return self::VERBOSITY_DEBUG <= $this->verbosity;
- }
- public function writeln($messages, $type = self::OUTPUT_NORMAL)
- {
- $this->write($messages, true, $type);
- }
- public function write($messages, $newline = false, $type = self::OUTPUT_NORMAL)
- {
- if (self::VERBOSITY_QUIET === $this->verbosity) {
- return;
- }
- $messages = (array) $messages;
- foreach ($messages as $message) {
- switch ($type) {
- case OutputInterface::OUTPUT_NORMAL:
- $message = $this->formatter->format($message);
- break;
- case OutputInterface::OUTPUT_RAW:
- break;
- case OutputInterface::OUTPUT_PLAIN:
- $message = strip_tags($this->formatter->format($message));
- break;
- default:
- throw new \InvalidArgumentException(sprintf('Unknown output type given (%s)', $type));
- }
- $this->doWrite($message, $newline);
- }
- }
- abstract protected function doWrite($message, $newline);
- }
- <?php
- namespace Symfony\Component\Console\Output;
- use Symfony\Component\Console\Formatter\OutputFormatterInterface;
- interface OutputInterface
- {
- const VERBOSITY_QUIET = 0;
- const VERBOSITY_NORMAL = 1;
- const VERBOSITY_VERBOSE = 2;
- const VERBOSITY_VERY_VERBOSE = 3;
- const VERBOSITY_DEBUG = 4;
- const OUTPUT_NORMAL = 0;
- const OUTPUT_RAW = 1;
- const OUTPUT_PLAIN = 2;
- public function write($messages, $newline = false, $type = self::OUTPUT_NORMAL);
- public function writeln($messages, $type = self::OUTPUT_NORMAL);
- public function setVerbosity($level);
- public function getVerbosity();
- public function setDecorated($decorated);
- public function isDecorated();
- public function setFormatter(OutputFormatterInterface $formatter);
- public function getFormatter();
- }
- <?php
- namespace Symfony\Component\Console\Output;
- use Symfony\Component\Console\Formatter\OutputFormatterInterface;
- class StreamOutput extends Output
- {
- private $stream;
- public function __construct($stream, $verbosity = self::VERBOSITY_NORMAL, $decorated = null, OutputFormatterInterface $formatter = null)
- {
- if (!is_resource($stream) || 'stream' !== get_resource_type($stream)) {
- throw new \InvalidArgumentException('The StreamOutput class needs a stream as its first argument.');
- }
- $this->stream = $stream;
- if (null === $decorated) {
- $decorated = $this->hasColorSupport();
- }
- parent::__construct($verbosity, $decorated, $formatter);
- }
- public function getStream()
- {
- return $this->stream;
- }
- protected function doWrite($message, $newline)
- {
- if (false === @fwrite($this->stream, $message.($newline ? PHP_EOL : ''))) {
- throw new \RuntimeException('Unable to write output.');
- }
- fflush($this->stream);
- }
- protected function hasColorSupport()
- {
- if (DIRECTORY_SEPARATOR == '\\') {
- return false !== getenv('ANSICON') || 'ON' === getenv('ConEmuANSI');
- }
- return function_exists('posix_isatty') && @posix_isatty($this->stream);
- }
- }
- <?php
- namespace Symfony\Component\Console\Question;
- class ChoiceQuestion extends Question
- {
- private $choices;
- private $multiselect = false;
- private $prompt = ' > ';
- private $errorMessage = 'Value "%s" is invalid';
- public function __construct($question, array $choices, $default = null)
- {
- parent::__construct($question, $default);
- $this->choices = $choices;
- $this->setValidator($this->getDefaultValidator());
- $this->setAutocompleterValues(array_keys($choices));
- }
- public function getChoices()
- {
- return $this->choices;
- }
- public function setMultiselect($multiselect)
- {
- $this->multiselect = $multiselect;
- $this->setValidator($this->getDefaultValidator());
- return $this;
- }
- public function getPrompt()
- {
- return $this->prompt;
- }
- public function setPrompt($prompt)
- {
- $this->prompt = $prompt;
- return $this;
- }
- public function setErrorMessage($errorMessage)
- {
- $this->errorMessage = $errorMessage;
- $this->setValidator($this->getDefaultValidator());
- return $this;
- }
- private function getDefaultValidator()
- {
- $choices = $this->choices;
- $errorMessage = $this->errorMessage;
- $multiselect = $this->multiselect;
- return function ($selected) use ($choices, $errorMessage, $multiselect) {
- $selectedChoices = str_replace(' ', '', $selected);
- if ($multiselect) {
- if (!preg_match('/^[a-zA-Z0-9_-]+(?:,[a-zA-Z0-9_-]+)*$/', $selectedChoices, $matches)) {
- throw new \InvalidArgumentException(sprintf($errorMessage, $selected));
- }
- $selectedChoices = explode(',', $selectedChoices);
- } else {
- $selectedChoices = array($selected);
- }
- $multiselectChoices = array();
- foreach ($selectedChoices as $value) {
- if (empty($choices[$value])) {
- throw new \InvalidArgumentException(sprintf($errorMessage, $value));
- }
- array_push($multiselectChoices, $choices[$value]);
- }
- if ($multiselect) {
- return $multiselectChoices;
- }
- return $choices[$selected];
- };
- }
- }
- <?php
- namespace Symfony\Component\Console\Question;
- class ConfirmationQuestion extends Question
- {
- public function __construct($question, $default = true)
- {
- parent::__construct($question, (bool) $default);
- $this->setNormalizer($this->getDefaultNormalizer());
- }
- private function getDefaultNormalizer()
- {
- $default = $this->getDefault();
- return function ($answer) use ($default) {
- if (is_bool($answer)) {
- return $answer;
- }
- if (false === $default) {
- return $answer && 'y' === strtolower($answer[0]);
- }
- return !$answer || 'y' === strtolower($answer[0]);
- };
- }
- }
- <?php
- namespace Symfony\Component\Console\Question;
- class Question
- {
- private $question;
- private $attempts;
- private $hidden = false;
- private $hiddenFallback = true;
- private $autocompleterValues;
- private $validator;
- private $default;
- private $normalizer;
- public function __construct($question, $default = null)
- {
- $this->question = $question;
- $this->default = $default;
- }
- public function getQuestion()
- {
- return $this->question;
- }
- public function getDefault()
- {
- return $this->default;
- }
- public function isHidden()
- {
- return $this->hidden;
- }
- public function setHidden($hidden)
- {
- if ($this->autocompleterValues) {
- throw new \LogicException('A hidden question cannot use the autocompleter.');
- }
- $this->hidden = (bool) $hidden;
- return $this;
- }
- public function isHiddenFallback()
- {
- return $this->hiddenFallback;
- }
- public function setHiddenFallback($fallback)
- {
- $this->hiddenFallback = (bool) $fallback;
- return $this;
- }
- public function getAutocompleterValues()
- {
- return $this->autocompleterValues;
- }
- public function setAutocompleterValues($values)
- {
- if (null !== $values && !is_array($values)) {
- if (!$values instanceof \Traversable || $values instanceof \Countable) {
- throw new \InvalidArgumentException('Autocompleter values can be either an array, `null` or an object implementing both `Countable` and `Traversable` interfaces.');
- }
- }
- if ($this->hidden) {
- throw new \LogicException('A hidden question cannot use the autocompleter.');
- }
- $this->autocompleterValues = $values;
- return $this;
- }
- public function setValidator($validator)
- {
- $this->validator = $validator;
- return $this;
- }
- public function getValidator()
- {
- return $this->validator;
- }
- public function setMaxAttempts($attempts)
- {
- if (null !== $attempts && $attempts < 1) {
- throw new \InvalidArgumentException('Maximum number of attempts must be a positive value.');
- }
- $this->attempts = $attempts;
- return $this;
- }
- public function getMaxAttempts()
- {
- return $this->attempts;
- }
- public function setNormalizer($normalizer)
- {
- $this->normalizer = $normalizer;
- return $this;
- }
- public function getNormalizer()
- {
- return $this->normalizer;
- }
- }
- <?php
- namespace Symfony\Component\Console;
- use Symfony\Component\Console\Input\StringInput;
- use Symfony\Component\Console\Output\ConsoleOutput;
- use Symfony\Component\Process\ProcessBuilder;
- use Symfony\Component\Process\PhpExecutableFinder;
- class Shell
- {
- private $application;
- private $history;
- private $output;
- private $hasReadline;
- private $processIsolation = false;
- public function __construct(Application $application)
- {
- $this->hasReadline = function_exists('readline');
- $this->application = $application;
- $this->history = getenv('HOME').'/.history_'.$application->getName();
- $this->output = new ConsoleOutput();
- }
- public function run()
- {
- $this->application->setAutoExit(false);
- $this->application->setCatchExceptions(true);
- if ($this->hasReadline) {
- readline_read_history($this->history);
- readline_completion_function(array($this, 'autocompleter'));
- }
- $this->output->writeln($this->getHeader());
- $php = null;
- if ($this->processIsolation) {
- $finder = new PhpExecutableFinder();
- $php = $finder->find();
- $this->output->writeln(<<<EOF
- <info>Running with process isolation, you should consider this:</info>
- * each command is executed as separate process,
- * commands don't support interactivity, all params must be passed explicitly,
- * commands output is not colorized.
- EOF
- );
- }
- while (true) {
- $command = $this->readline();
- if (false === $command) {
- $this->output->writeln("\n");
- break;
- }
- if ($this->hasReadline) {
- readline_add_history($command);
- readline_write_history($this->history);
- }
- if ($this->processIsolation) {
- $pb = new ProcessBuilder();
- $process = $pb
- ->add($php)
- ->add($_SERVER['argv'][0])
- ->add($command)
- ->inheritEnvironmentVariables(true)
- ->getProcess()
- ;
- $output = $this->output;
- $process->run(function ($type, $data) use ($output) {
- $output->writeln($data);
- });
- $ret = $process->getExitCode();
- } else {
- $ret = $this->application->run(new StringInput($command), $this->output);
- }
- if (0 !== $ret) {
- $this->output->writeln(sprintf('<error>The command terminated with an error status (%s)</error>', $ret));
- }
- }
- }
- protected function getHeader()
- {
- return <<<EOF
- Welcome to the <info>{$this->application->getName()}</info> shell (<comment>{$this->application->getVersion()}</comment>).
- At the prompt, type <comment>help</comment> for some help,
- or <comment>list</comment> to get a list of available commands.
- To exit the shell, type <comment>^D</comment>.
- EOF;
- }
- protected function getPrompt()
- {
- return $this->output->getFormatter()->format($this->application->getName().' > ');
- }
- protected function getOutput()
- {
- return $this->output;
- }
- protected function getApplication()
- {
- return $this->application;
- }
- private function autocompleter($text)
- {
- $info = readline_info();
- $text = substr($info['line_buffer'], 0, $info['end']);
- if ($info['point'] !== $info['end']) {
- return true;
- }
- if (false === strpos($text, ' ') || !$text) {
- return array_keys($this->application->all());
- }
- try {
- $command = $this->application->find(substr($text, 0, strpos($text, ' ')));
- } catch (\Exception $e) {
- return true;
- }
- $list = array('--help');
- foreach ($command->getDefinition()->getOptions() as $option) {
- $list[] = '--'.$option->getName();
- }
- return $list;
- }
- private function readline()
- {
- if ($this->hasReadline) {
- $line = readline($this->getPrompt());
- } else {
- $this->output->write($this->getPrompt());
- $line = fgets(STDIN, 1024);
- $line = (!$line && strlen($line) == 0) ? false : rtrim($line);
- }
- return $line;
- }
- public function getProcessIsolation()
- {
- return $this->processIsolation;
- }
- public function setProcessIsolation($processIsolation)
- {
- $this->processIsolation = (bool) $processIsolation;
- if ($this->processIsolation && !class_exists('Symfony\\Component\\Process\\Process')) {
- throw new \RuntimeException('Unable to isolate processes as the Symfony Process Component is not installed.');
- }
- }
- }
- <?php
- namespace Symfony\Component\Console\Tester;
- use Symfony\Component\Console\Application;
- use Symfony\Component\Console\Input\ArrayInput;
- use Symfony\Component\Console\Input\InputInterface;
- use Symfony\Component\Console\Output\OutputInterface;
- use Symfony\Component\Console\Output\StreamOutput;
- class ApplicationTester
- {
- private $application;
- private $input;
- private $output;
- private $statusCode;
- public function __construct(Application $application)
- {
- $this->application = $application;
- }
- public function run(array $input, $options = array())
- {
- $this->input = new ArrayInput($input);
- if (isset($options['interactive'])) {
- $this->input->setInteractive($options['interactive']);
- }
- $this->output = new StreamOutput(fopen('php://memory', 'w', false));
- if (isset($options['decorated'])) {
- $this->output->setDecorated($options['decorated']);
- }
- if (isset($options['verbosity'])) {
- $this->output->setVerbosity($options['verbosity']);
- }
- return $this->statusCode = $this->application->run($this->input, $this->output);
- }
- public function getDisplay($normalize = false)
- {
- rewind($this->output->getStream());
- $display = stream_get_contents($this->output->getStream());
- if ($normalize) {
- $display = str_replace(PHP_EOL, "\n", $display);
- }
- return $display;
- }
- public function getInput()
- {
- return $this->input;
- }
- public function getOutput()
- {
- return $this->output;
- }
- public function getStatusCode()
- {
- return $this->statusCode;
- }
- }
- <?php
- namespace Symfony\Component\Console\Tester;
- use Symfony\Component\Console\Command\Command;
- use Symfony\Component\Console\Input\ArrayInput;
- use Symfony\Component\Console\Output\StreamOutput;
- use Symfony\Component\Console\Input\InputInterface;
- use Symfony\Component\Console\Output\OutputInterface;
- class CommandTester
- {
- private $command;
- private $input;
- private $output;
- private $statusCode;
- public function __construct(Command $command)
- {
- $this->command = $command;
- }
- public function execute(array $input, array $options = array())
- {
-
- if (!isset($input['command'])
- && (null !== $application = $this->command->getApplication())
- && $application->getDefinition()->hasArgument('command')
- ) {
- $input['command'] = $this->command->getName();
- }
- $this->input = new ArrayInput($input);
- if (isset($options['interactive'])) {
- $this->input->setInteractive($options['interactive']);
- }
- $this->output = new StreamOutput(fopen('php://memory', 'w', false));
- if (isset($options['decorated'])) {
- $this->output->setDecorated($options['decorated']);
- }
- if (isset($options['verbosity'])) {
- $this->output->setVerbosity($options['verbosity']);
- }
- return $this->statusCode = $this->command->run($this->input, $this->output);
- }
- public function getDisplay($normalize = false)
- {
- rewind($this->output->getStream());
- $display = stream_get_contents($this->output->getStream());
- if ($normalize) {
- $display = str_replace(PHP_EOL, "\n", $display);
- }
- return $display;
- }
- public function getInput()
- {
- return $this->input;
- }
- public function getOutput()
- {
- return $this->output;
- }
- public function getStatusCode()
- {
- return $this->statusCode;
- }
- }
- <?php
- namespace Symfony\Component\Finder\Adapter;
- abstract class AbstractAdapter implements AdapterInterface
- {
- protected $followLinks = false;
- protected $mode = 0;
- protected $minDepth = 0;
- protected $maxDepth = PHP_INT_MAX;
- protected $exclude = array();
- protected $names = array();
- protected $notNames = array();
- protected $contains = array();
- protected $notContains = array();
- protected $sizes = array();
- protected $dates = array();
- protected $filters = array();
- protected $sort = false;
- protected $paths = array();
- protected $notPaths = array();
- protected $ignoreUnreadableDirs = false;
- private static $areSupported = array();
- public function isSupported()
- {
- $name = $this->getName();
- if (!array_key_exists($name, self::$areSupported)) {
- self::$areSupported[$name] = $this->canBeUsed();
- }
- return self::$areSupported[$name];
- }
- public function setFollowLinks($followLinks)
- {
- $this->followLinks = $followLinks;
- return $this;
- }
- public function setMode($mode)
- {
- $this->mode = $mode;
- return $this;
- }
- public function setDepths(array $depths)
- {
- $this->minDepth = 0;
- $this->maxDepth = PHP_INT_MAX;
- foreach ($depths as $comparator) {
- switch ($comparator->getOperator()) {
- case '>':
- $this->minDepth = $comparator->getTarget() + 1;
- break;
- case '>=':
- $this->minDepth = $comparator->getTarget();
- break;
- case '<':
- $this->maxDepth = $comparator->getTarget() - 1;
- break;
- case '<=':
- $this->maxDepth = $comparator->getTarget();
- break;
- default:
- $this->minDepth = $this->maxDepth = $comparator->getTarget();
- }
- }
- return $this;
- }
- public function setExclude(array $exclude)
- {
- $this->exclude = $exclude;
- return $this;
- }
- public function setNames(array $names)
- {
- $this->names = $names;
- return $this;
- }
- public function setNotNames(array $notNames)
- {
- $this->notNames = $notNames;
- return $this;
- }
- public function setContains(array $contains)
- {
- $this->contains = $contains;
- return $this;
- }
- public function setNotContains(array $notContains)
- {
- $this->notContains = $notContains;
- return $this;
- }
- public function setSizes(array $sizes)
- {
- $this->sizes = $sizes;
- return $this;
- }
- public function setDates(array $dates)
- {
- $this->dates = $dates;
- return $this;
- }
- public function setFilters(array $filters)
- {
- $this->filters = $filters;
- return $this;
- }
- public function setSort($sort)
- {
- $this->sort = $sort;
- return $this;
- }
- public function setPath(array $paths)
- {
- $this->paths = $paths;
- return $this;
- }
- public function setNotPath(array $notPaths)
- {
- $this->notPaths = $notPaths;
- return $this;
- }
- public function ignoreUnreadableDirs($ignore = true)
- {
- $this->ignoreUnreadableDirs = (bool) $ignore;
- return $this;
- }
- abstract protected function canBeUsed();
- }
- <?php
- namespace Symfony\Component\Finder\Adapter;
- use Symfony\Component\Finder\Exception\AccessDeniedException;
- use Symfony\Component\Finder\Iterator;
- use Symfony\Component\Finder\Shell\Shell;
- use Symfony\Component\Finder\Expression\Expression;
- use Symfony\Component\Finder\Shell\Command;
- use Symfony\Component\Finder\Comparator\NumberComparator;
- use Symfony\Component\Finder\Comparator\DateComparator;
- abstract class AbstractFindAdapter extends AbstractAdapter
- {
- protected $shell;
- public function __construct()
- {
- $this->shell = new Shell();
- }
- public function searchInDirectory($dir)
- {
- $dir = realpath($dir);
- if (Iterator\FileTypeFilterIterator::ONLY_DIRECTORIES === $this->mode && ($this->contains || $this->notContains)) {
- return new Iterator\FilePathsIterator(array(), $dir);
- }
- $command = Command::create();
- $find = $this->buildFindCommand($command, $dir);
- if ($this->followLinks) {
- $find->add('-follow');
- }
- $find->add('-mindepth')->add($this->minDepth + 1);
- if (PHP_INT_MAX !== $this->maxDepth) {
- $find->add('-maxdepth')->add($this->maxDepth + 1);
- }
- if (Iterator\FileTypeFilterIterator::ONLY_DIRECTORIES === $this->mode) {
- $find->add('-type d');
- } elseif (Iterator\FileTypeFilterIterator::ONLY_FILES === $this->mode) {
- $find->add('-type f');
- }
- $this->buildNamesFiltering($find, $this->names);
- $this->buildNamesFiltering($find, $this->notNames, true);
- $this->buildPathsFiltering($find, $dir, $this->paths);
- $this->buildPathsFiltering($find, $dir, $this->notPaths, true);
- $this->buildSizesFiltering($find, $this->sizes);
- $this->buildDatesFiltering($find, $this->dates);
- $useGrep = $this->shell->testCommand('grep') && $this->shell->testCommand('xargs');
- $useSort = is_int($this->sort) && $this->shell->testCommand('sort') && $this->shell->testCommand('cut');
- if ($useGrep && ($this->contains || $this->notContains)) {
- $grep = $command->ins('grep');
- $this->buildContentFiltering($grep, $this->contains);
- $this->buildContentFiltering($grep, $this->notContains, true);
- }
- if ($useSort) {
- $this->buildSorting($command, $this->sort);
- }
- $command->setErrorHandler(
- $this->ignoreUnreadableDirs
- ? function ($stderr) { return; }
- : function ($stderr) { throw new AccessDeniedException($stderr); }
- );
- $paths = $this->shell->testCommand('uniq') ? $command->add('| uniq')->execute() : array_unique($command->execute());
- $iterator = new Iterator\FilePathsIterator($paths, $dir);
- if ($this->exclude) {
- $iterator = new Iterator\ExcludeDirectoryFilterIterator($iterator, $this->exclude);
- }
- if (!$useGrep && ($this->contains || $this->notContains)) {
- $iterator = new Iterator\FilecontentFilterIterator($iterator, $this->contains, $this->notContains);
- }
- if ($this->filters) {
- $iterator = new Iterator\CustomFilterIterator($iterator, $this->filters);
- }
- if (!$useSort && $this->sort) {
- $iteratorAggregate = new Iterator\SortableIterator($iterator, $this->sort);
- $iterator = $iteratorAggregate->getIterator();
- }
- return $iterator;
- }
- protected function canBeUsed()
- {
- return $this->shell->testCommand('find');
- }
- protected function buildFindCommand(Command $command, $dir)
- {
- return $command
- ->ins('find')
- ->add('find ')
- ->arg($dir)
- ->add('-noleaf');
- }
- private function buildNamesFiltering(Command $command, array $names, $not = false)
- {
- if (0 === count($names)) {
- return;
- }
- $command->add($not ? '-not' : null)->cmd('(');
- foreach ($names as $i => $name) {
- $expr = Expression::create($name);
- if ($expr->isGlob() && $expr->getGlob()->isExpandable()) {
- $expr = Expression::create($expr->getGlob()->toRegex(false));
- }
-
-
- if ($expr->isRegex()) {
- $regex = $expr->getRegex();
- $regex->prepend($regex->hasStartFlag() ? '/' : '/[^/]*')
- ->setStartFlag(false)
- ->setStartJoker(true)
- ->replaceJokers('[^/]');
- if (!$regex->hasEndFlag() || $regex->hasEndJoker()) {
- $regex->setEndJoker(false)->append('[^/]*');
- }
- }
- $command
- ->add($i > 0 ? '-or' : null)
- ->add($expr->isRegex()
- ? ($expr->isCaseSensitive() ? '-regex' : '-iregex')
- : ($expr->isCaseSensitive() ? '-name' : '-iname')
- )
- ->arg($expr->renderPattern());
- }
- $command->cmd(')');
- }
- private function buildPathsFiltering(Command $command, $dir, array $paths, $not = false)
- {
- if (0 === count($paths)) {
- return;
- }
- $command->add($not ? '-not' : null)->cmd('(');
- foreach ($paths as $i => $path) {
- $expr = Expression::create($path);
- if ($expr->isGlob() && $expr->getGlob()->isExpandable()) {
- $expr = Expression::create($expr->getGlob()->toRegex(false));
- }
- if ($expr->isRegex()) {
- $regex = $expr->getRegex();
- $regex->prepend($regex->hasStartFlag() ? preg_quote($dir).DIRECTORY_SEPARATOR : '.*')->setEndJoker(!$regex->hasEndFlag());
- } else {
- $expr->prepend('*')->append('*');
- }
- $command
- ->add($i > 0 ? '-or' : null)
- ->add($expr->isRegex()
- ? ($expr->isCaseSensitive() ? '-regex' : '-iregex')
- : ($expr->isCaseSensitive() ? '-path' : '-ipath')
- )
- ->arg($expr->renderPattern());
- }
- $command->cmd(')');
- }
- private function buildSizesFiltering(Command $command, array $sizes)
- {
- foreach ($sizes as $i => $size) {
- $command->add($i > 0 ? '-and' : null);
- switch ($size->getOperator()) {
- case '<=':
- $command->add('-size -'.($size->getTarget() + 1).'c');
- break;
- case '>=':
- $command->add('-size +'.($size->getTarget() - 1).'c');
- break;
- case '>':
- $command->add('-size +'.$size->getTarget().'c');
- break;
- case '!=':
- $command->add('-size -'.$size->getTarget().'c');
- $command->add('-size +'.$size->getTarget().'c');
- break;
- case '<':
- default:
- $command->add('-size -'.$size->getTarget().'c');
- }
- }
- }
- private function buildDatesFiltering(Command $command, array $dates)
- {
- foreach ($dates as $i => $date) {
- $command->add($i > 0 ? '-and' : null);
- $mins = (int) round((time()-$date->getTarget()) / 60);
- if (0 > $mins) {
- $command->add(' -mmin -0');
- return;
- }
- switch ($date->getOperator()) {
- case '<=':
- $command->add('-mmin +'.($mins - 1));
- break;
- case '>=':
- $command->add('-mmin -'.($mins + 1));
- break;
- case '>':
- $command->add('-mmin -'.$mins);
- break;
- case '!=':
- $command->add('-mmin +'.$mins.' -or -mmin -'.$mins);
- break;
- case '<':
- default:
- $command->add('-mmin +'.$mins);
- }
- }
- }
- private function buildSorting(Command $command, $sort)
- {
- $this->buildFormatSorting($command, $sort);
- }
- abstract protected function buildFormatSorting(Command $command, $sort);
- abstract protected function buildContentFiltering(Command $command, array $contains, $not = false);
- }
- <?php
- namespace Symfony\Component\Finder\Adapter;
- interface AdapterInterface
- {
- public function setFollowLinks($followLinks);
- public function setMode($mode);
- public function setExclude(array $exclude);
- public function setDepths(array $depths);
- public function setNames(array $names);
- public function setNotNames(array $notNames);
- public function setContains(array $contains);
- public function setNotContains(array $notContains);
- public function setSizes(array $sizes);
- public function setDates(array $dates);
- public function setFilters(array $filters);
- public function setSort($sort);
- public function setPath(array $paths);
- public function setNotPath(array $notPaths);
- public function ignoreUnreadableDirs($ignore = true);
- public function searchInDirectory($dir);
- public function isSupported();
- public function getName();
- }
- <?php
- namespace Symfony\Component\Finder\Adapter;
- use Symfony\Component\Finder\Shell\Shell;
- use Symfony\Component\Finder\Shell\Command;
- use Symfony\Component\Finder\Iterator\SortableIterator;
- use Symfony\Component\Finder\Expression\Expression;
- class BsdFindAdapter extends AbstractFindAdapter
- {
- public function getName()
- {
- return 'bsd_find';
- }
- protected function canBeUsed()
- {
- return in_array($this->shell->getType(), array(Shell::TYPE_BSD, Shell::TYPE_DARWIN)) && parent::canBeUsed();
- }
- protected function buildFormatSorting(Command $command, $sort)
- {
- switch ($sort) {
- case SortableIterator::SORT_BY_NAME:
- $command->ins('sort')->add('| sort');
- return;
- case SortableIterator::SORT_BY_TYPE:
- $format = '%HT';
- break;
- case SortableIterator::SORT_BY_ACCESSED_TIME:
- $format = '%a';
- break;
- case SortableIterator::SORT_BY_CHANGED_TIME:
- $format = '%c';
- break;
- case SortableIterator::SORT_BY_MODIFIED_TIME:
- $format = '%m';
- break;
- default:
- throw new \InvalidArgumentException(sprintf('Unknown sort options: %s.', $sort));
- }
- $command
- ->add('-print0 | xargs -0 stat -f')
- ->arg($format.'%t%N')
- ->add('| sort | cut -f 2');
- }
- protected function buildFindCommand(Command $command, $dir)
- {
- parent::buildFindCommand($command, $dir)->addAtIndex('-E', 1);
- return $command;
- }
- protected function buildContentFiltering(Command $command, array $contains, $not = false)
- {
- foreach ($contains as $contain) {
- $expr = Expression::create($contain);
- $command
- ->add('| grep -v \'^$\'')
- ->add('| xargs -I{} grep -I')
- ->add($expr->isCaseSensitive() ? null : '-i')
- ->add($not ? '-L' : '-l')
- ->add('-Ee')->arg($expr->renderPattern())
- ->add('{}')
- ;
- }
- }
- }
- <?php
- namespace Symfony\Component\Finder\Adapter;
- use Symfony\Component\Finder\Shell\Shell;
- use Symfony\Component\Finder\Shell\Command;
- use Symfony\Component\Finder\Iterator\SortableIterator;
- use Symfony\Component\Finder\Expression\Expression;
- class GnuFindAdapter extends AbstractFindAdapter
- {
- public function getName()
- {
- return 'gnu_find';
- }
- protected function buildFormatSorting(Command $command, $sort)
- {
- switch ($sort) {
- case SortableIterator::SORT_BY_NAME:
- $command->ins('sort')->add('| sort');
- return;
- case SortableIterator::SORT_BY_TYPE:
- $format = '%y';
- break;
- case SortableIterator::SORT_BY_ACCESSED_TIME:
- $format = '%A@';
- break;
- case SortableIterator::SORT_BY_CHANGED_TIME:
- $format = '%C@';
- break;
- case SortableIterator::SORT_BY_MODIFIED_TIME:
- $format = '%T@';
- break;
- default:
- throw new \InvalidArgumentException(sprintf('Unknown sort options: %s.', $sort));
- }
- $command
- ->get('find')
- ->add('-printf')
- ->arg($format.' %h/%f\\n')
- ->add('| sort | cut')
- ->arg('-d ')
- ->arg('-f2-')
- ;
- }
- protected function canBeUsed()
- {
- return $this->shell->getType() === Shell::TYPE_UNIX && parent::canBeUsed();
- }
- protected function buildFindCommand(Command $command, $dir)
- {
- return parent::buildFindCommand($command, $dir)->add('-regextype posix-extended');
- }
- protected function buildContentFiltering(Command $command, array $contains, $not = false)
- {
- foreach ($contains as $contain) {
- $expr = Expression::create($contain);
- $command
- ->add('| xargs -I{} -r grep -I')
- ->add($expr->isCaseSensitive() ? null : '-i')
- ->add($not ? '-L' : '-l')
- ->add('-Ee')->arg($expr->renderPattern())
- ->add('{}')
- ;
- }
- }
- }
- <?php
- namespace Symfony\Component\Finder\Adapter;
- use Symfony\Component\Finder\Iterator;
- class PhpAdapter extends AbstractAdapter
- {
- public function searchInDirectory($dir)
- {
- $flags = \RecursiveDirectoryIterator::SKIP_DOTS;
- if ($this->followLinks) {
- $flags |= \RecursiveDirectoryIterator::FOLLOW_SYMLINKS;
- }
- $iterator = new \RecursiveIteratorIterator(
- new Iterator\RecursiveDirectoryIterator($dir, $flags, $this->ignoreUnreadableDirs),
- \RecursiveIteratorIterator::SELF_FIRST
- );
- if ($this->minDepth > 0 || $this->maxDepth < PHP_INT_MAX) {
- $iterator = new Iterator\DepthRangeFilterIterator($iterator, $this->minDepth, $this->maxDepth);
- }
- if ($this->mode) {
- $iterator = new Iterator\FileTypeFilterIterator($iterator, $this->mode);
- }
- if ($this->exclude) {
- $iterator = new Iterator\ExcludeDirectoryFilterIterator($iterator, $this->exclude);
- }
- if ($this->names || $this->notNames) {
- $iterator = new Iterator\FilenameFilterIterator($iterator, $this->names, $this->notNames);
- }
- if ($this->contains || $this->notContains) {
- $iterator = new Iterator\FilecontentFilterIterator($iterator, $this->contains, $this->notContains);
- }
- if ($this->sizes) {
- $iterator = new Iterator\SizeRangeFilterIterator($iterator, $this->sizes);
- }
- if ($this->dates) {
- $iterator = new Iterator\DateRangeFilterIterator($iterator, $this->dates);
- }
- if ($this->filters) {
- $iterator = new Iterator\CustomFilterIterator($iterator, $this->filters);
- }
- if ($this->sort) {
- $iteratorAggregate = new Iterator\SortableIterator($iterator, $this->sort);
- $iterator = $iteratorAggregate->getIterator();
- }
- if ($this->paths || $this->notPaths) {
- $iterator = new Iterator\PathFilterIterator($iterator, $this->paths, $this->notPaths);
- }
- return $iterator;
- }
- public function getName()
- {
- return 'php';
- }
- protected function canBeUsed()
- {
- return true;
- }
- }
- <?php
- namespace Symfony\Component\Finder\Comparator;
- class Comparator
- {
- private $target;
- private $operator = '==';
- public function getTarget()
- {
- return $this->target;
- }
- public function setTarget($target)
- {
- $this->target = $target;
- }
- public function getOperator()
- {
- return $this->operator;
- }
- public function setOperator($operator)
- {
- if (!$operator) {
- $operator = '==';
- }
- if (!in_array($operator, array('>', '<', '>=', '<=', '==', '!='))) {
- throw new \InvalidArgumentException(sprintf('Invalid operator "%s".', $operator));
- }
- $this->operator = $operator;
- }
- public function test($test)
- {
- switch ($this->operator) {
- case '>':
- return $test > $this->target;
- case '>=':
- return $test >= $this->target;
- case '<':
- return $test < $this->target;
- case '<=':
- return $test <= $this->target;
- case '!=':
- return $test != $this->target;
- }
- return $test == $this->target;
- }
- }
- <?php
- namespace Symfony\Component\Finder\Comparator;
- class DateComparator extends Comparator
- {
- public function __construct($test)
- {
- if (!preg_match('#^\s*(==|!=|[<>]=?|after|since|before|until)?\s*(.+?)\s*$#i', $test, $matches)) {
- throw new \InvalidArgumentException(sprintf('Don\'t understand "%s" as a date test.', $test));
- }
- try {
- $date = new \DateTime($matches[2]);
- $target = $date->format('U');
- } catch (\Exception $e) {
- throw new \InvalidArgumentException(sprintf('"%s" is not a valid date.', $matches[2]));
- }
- $operator = isset($matches[1]) ? $matches[1] : '==';
- if ('since' === $operator || 'after' === $operator) {
- $operator = '>';
- }
- if ('until' === $operator || 'before' === $operator) {
- $operator = '<';
- }
- $this->setOperator($operator);
- $this->setTarget($target);
- }
- }
- <?php
- namespace Symfony\Component\Finder\Comparator;
- class NumberComparator extends Comparator
- {
- public function __construct($test)
- {
- if (!preg_match('#^\s*(==|!=|[<>]=?)?\s*([0-9\.]+)\s*([kmg]i?)?\s*$#i', $test, $matches)) {
- throw new \InvalidArgumentException(sprintf('Don\'t understand "%s" as a number test.', $test));
- }
- $target = $matches[2];
- if (!is_numeric($target)) {
- throw new \InvalidArgumentException(sprintf('Invalid number "%s".', $target));
- }
- if (isset($matches[3])) {
- switch (strtolower($matches[3])) {
- case 'k':
- $target *= 1000;
- break;
- case 'ki':
- $target *= 1024;
- break;
- case 'm':
- $target *= 1000000;
- break;
- case 'mi':
- $target *= 1024*1024;
- break;
- case 'g':
- $target *= 1000000000;
- break;
- case 'gi':
- $target *= 1024*1024*1024;
- break;
- }
- }
- $this->setTarget($target);
- $this->setOperator(isset($matches[1]) ? $matches[1] : '==');
- }
- }
- <?php
- namespace Symfony\Component\Finder\Exception;
- class AccessDeniedException extends \UnexpectedValueException
- {
- }
- <?php
- namespace Symfony\Component\Finder\Exception;
- use Symfony\Component\Finder\Adapter\AdapterInterface;
- class AdapterFailureException extends \RuntimeException implements ExceptionInterface
- {
- private $adapter;
- public function __construct(AdapterInterface $adapter, $message = null, \Exception $previous = null)
- {
- $this->adapter = $adapter;
- parent::__construct($message ?: 'Search failed with "'.$adapter->getName().'" adapter.', $previous);
- }
- public function getAdapter()
- {
- return $this->adapter;
- }
- }
- <?php
- namespace Symfony\Component\Finder\Exception;
- interface ExceptionInterface
- {
- public function getAdapter();
- }
- <?php
- namespace Symfony\Component\Finder\Exception;
- class OperationNotPermitedException extends AdapterFailureException
- {
- }
- <?php
- namespace Symfony\Component\Finder\Exception;
- use Symfony\Component\Finder\Adapter\AdapterInterface;
- use Symfony\Component\Finder\Shell\Command;
- class ShellCommandFailureException extends AdapterFailureException
- {
- private $command;
- public function __construct(AdapterInterface $adapter, Command $command, \Exception $previous = null)
- {
- $this->command = $command;
- parent::__construct($adapter, 'Shell command failed: "'.$command->join().'".', $previous);
- }
- public function getCommand()
- {
- return $this->command;
- }
- }
- <?php
- namespace Symfony\Component\Finder\Expression;
- class Expression implements ValueInterface
- {
- const TYPE_REGEX = 1;
- const TYPE_GLOB = 2;
- private $value;
- public static function create($expr)
- {
- return new self($expr);
- }
- public function __construct($expr)
- {
- try {
- $this->value = Regex::create($expr);
- } catch (\InvalidArgumentException $e) {
- $this->value = new Glob($expr);
- }
- }
- public function __toString()
- {
- return $this->render();
- }
- public function render()
- {
- return $this->value->render();
- }
- public function renderPattern()
- {
- return $this->value->renderPattern();
- }
- public function isCaseSensitive()
- {
- return $this->value->isCaseSensitive();
- }
- public function getType()
- {
- return $this->value->getType();
- }
- public function prepend($expr)
- {
- $this->value->prepend($expr);
- return $this;
- }
- public function append($expr)
- {
- $this->value->append($expr);
- return $this;
- }
- public function isRegex()
- {
- return self::TYPE_REGEX === $this->value->getType();
- }
- public function isGlob()
- {
- return self::TYPE_GLOB === $this->value->getType();
- }
- public function getGlob()
- {
- if (self::TYPE_GLOB !== $this->value->getType()) {
- throw new \LogicException('Regex can\'t be transformed to glob.');
- }
- return $this->value;
- }
- public function getRegex()
- {
- return self::TYPE_REGEX === $this->value->getType() ? $this->value : $this->value->toRegex();
- }
- }
- <?php
- namespace Symfony\Component\Finder\Expression;
- class Glob implements ValueInterface
- {
- private $pattern;
- public function __construct($pattern)
- {
- $this->pattern = $pattern;
- }
- public function render()
- {
- return $this->pattern;
- }
- public function renderPattern()
- {
- return $this->pattern;
- }
- public function getType()
- {
- return Expression::TYPE_GLOB;
- }
- public function isCaseSensitive()
- {
- return true;
- }
- public function prepend($expr)
- {
- $this->pattern = $expr.$this->pattern;
- return $this;
- }
- public function append($expr)
- {
- $this->pattern .= $expr;
- return $this;
- }
- public function isExpandable()
- {
- return false !== strpos($this->pattern, '{')
- && false !== strpos($this->pattern, '}');
- }
- public function toRegex($strictLeadingDot = true, $strictWildcardSlash = true)
- {
- $firstByte = true;
- $escaping = false;
- $inCurlies = 0;
- $regex = '';
- $sizeGlob = strlen($this->pattern);
- for ($i = 0; $i < $sizeGlob; $i++) {
- $car = $this->pattern[$i];
- if ($firstByte) {
- if ($strictLeadingDot && '.' !== $car) {
- $regex .= '(?=[^\.])';
- }
- $firstByte = false;
- }
- if ('/' === $car) {
- $firstByte = true;
- }
- if ('.' === $car || '(' === $car || ')' === $car || '|' === $car || '+' === $car || '^' === $car || '$' === $car) {
- $regex .= "\\$car";
- } elseif ('*' === $car) {
- $regex .= $escaping ? '\\*' : ($strictWildcardSlash ? '[^/]*' : '.*');
- } elseif ('?' === $car) {
- $regex .= $escaping ? '\\?' : ($strictWildcardSlash ? '[^/]' : '.');
- } elseif ('{' === $car) {
- $regex .= $escaping ? '\\{' : '(';
- if (!$escaping) {
- ++$inCurlies;
- }
- } elseif ('}' === $car && $inCurlies) {
- $regex .= $escaping ? '}' : ')';
- if (!$escaping) {
- --$inCurlies;
- }
- } elseif (',' === $car && $inCurlies) {
- $regex .= $escaping ? ',' : '|';
- } elseif ('\\' === $car) {
- if ($escaping) {
- $regex .= '\\\\';
- $escaping = false;
- } else {
- $escaping = true;
- }
- continue;
- } else {
- $regex .= $car;
- }
- $escaping = false;
- }
- return new Regex('^'.$regex.'$');
- }
- }
- <?php
- namespace Symfony\Component\Finder\Expression;
- class Regex implements ValueInterface
- {
- const START_FLAG = '^';
- const END_FLAG = '$';
- const BOUNDARY = '~';
- const JOKER = '.*';
- const ESCAPING = '\\';
- private $pattern;
- private $options;
- private $startFlag;
- private $endFlag;
- private $startJoker;
- private $endJoker;
- public static function create($expr)
- {
- if (preg_match('/^(.{3,}?)([imsxuADU]*)$/', $expr, $m)) {
- $start = substr($m[1], 0, 1);
- $end = substr($m[1], -1);
- if (
- ($start === $end && !preg_match('/[*?[:alnum:] \\\\]/', $start))
- || ($start === '{' && $end === '}')
- || ($start === '(' && $end === ')')
- ) {
- return new self(substr($m[1], 1, -1), $m[2], $end);
- }
- }
- throw new \InvalidArgumentException('Given expression is not a regex.');
- }
- public function __construct($pattern, $options = '', $delimiter = null)
- {
- if (null !== $delimiter) {
- $pattern = str_replace('\\'.$delimiter, $delimiter, $pattern);
- }
- $this->parsePattern($pattern);
- $this->options = $options;
- }
- public function __toString()
- {
- return $this->render();
- }
- public function render()
- {
- return self::BOUNDARY
- .$this->renderPattern()
- .self::BOUNDARY
- .$this->options;
- }
- public function renderPattern()
- {
- return ($this->startFlag ? self::START_FLAG : '')
- .($this->startJoker ? self::JOKER : '')
- .str_replace(self::BOUNDARY, '\\'.self::BOUNDARY, $this->pattern)
- .($this->endJoker ? self::JOKER : '')
- .($this->endFlag ? self::END_FLAG : '');
- }
- public function isCaseSensitive()
- {
- return !$this->hasOption('i');
- }
- public function getType()
- {
- return Expression::TYPE_REGEX;
- }
- public function prepend($expr)
- {
- $this->pattern = $expr.$this->pattern;
- return $this;
- }
- public function append($expr)
- {
- $this->pattern .= $expr;
- return $this;
- }
- public function hasOption($option)
- {
- return false !== strpos($this->options, $option);
- }
- public function addOption($option)
- {
- if (!$this->hasOption($option)) {
- $this->options .= $option;
- }
- return $this;
- }
- public function removeOption($option)
- {
- $this->options = str_replace($option, '', $this->options);
- return $this;
- }
- public function setStartFlag($startFlag)
- {
- $this->startFlag = $startFlag;
- return $this;
- }
- public function hasStartFlag()
- {
- return $this->startFlag;
- }
- public function setEndFlag($endFlag)
- {
- $this->endFlag = (bool) $endFlag;
- return $this;
- }
- public function hasEndFlag()
- {
- return $this->endFlag;
- }
- public function setStartJoker($startJoker)
- {
- $this->startJoker = $startJoker;
- return $this;
- }
- public function hasStartJoker()
- {
- return $this->startJoker;
- }
- public function setEndJoker($endJoker)
- {
- $this->endJoker = (bool) $endJoker;
- return $this;
- }
- public function hasEndJoker()
- {
- return $this->endJoker;
- }
- public function replaceJokers($replacement)
- {
- $replace = function ($subject) use ($replacement) {
- $subject = $subject[0];
- $replace = 0 === substr_count($subject, '\\') % 2;
- return $replace ? str_replace('.', $replacement, $subject) : $subject;
- };
- $this->pattern = preg_replace_callback('~[\\\\]*\\.~', $replace, $this->pattern);
- return $this;
- }
- private function parsePattern($pattern)
- {
- if ($this->startFlag = self::START_FLAG === substr($pattern, 0, 1)) {
- $pattern = substr($pattern, 1);
- }
- if ($this->startJoker = self::JOKER === substr($pattern, 0, 2)) {
- $pattern = substr($pattern, 2);
- }
- if ($this->endFlag = (self::END_FLAG === substr($pattern, -1) && self::ESCAPING !== substr($pattern, -2, -1))) {
- $pattern = substr($pattern, 0, -1);
- }
- if ($this->endJoker = (self::JOKER === substr($pattern, -2) && self::ESCAPING !== substr($pattern, -3, -2))) {
- $pattern = substr($pattern, 0, -2);
- }
- $this->pattern = $pattern;
- }
- }
- <?php
- namespace Symfony\Component\Finder\Expression;
- interface ValueInterface
- {
- public function render();
- public function renderPattern();
- public function isCaseSensitive();
- public function getType();
- public function prepend($expr);
- public function append($expr);
- }
- <?php
- namespace Symfony\Component\Finder;
- use Symfony\Component\Finder\Adapter\AdapterInterface;
- use Symfony\Component\Finder\Adapter\GnuFindAdapter;
- use Symfony\Component\Finder\Adapter\BsdFindAdapter;
- use Symfony\Component\Finder\Adapter\PhpAdapter;
- use Symfony\Component\Finder\Comparator\DateComparator;
- use Symfony\Component\Finder\Comparator\NumberComparator;
- use Symfony\Component\Finder\Exception\ExceptionInterface;
- use Symfony\Component\Finder\Iterator\CustomFilterIterator;
- use Symfony\Component\Finder\Iterator\DateRangeFilterIterator;
- use Symfony\Component\Finder\Iterator\DepthRangeFilterIterator;
- use Symfony\Component\Finder\Iterator\ExcludeDirectoryFilterIterator;
- use Symfony\Component\Finder\Iterator\FilecontentFilterIterator;
- use Symfony\Component\Finder\Iterator\FilenameFilterIterator;
- use Symfony\Component\Finder\Iterator\SizeRangeFilterIterator;
- use Symfony\Component\Finder\Iterator\SortableIterator;
- class Finder implements \IteratorAggregate, \Countable
- {
- const IGNORE_VCS_FILES = 1;
- const IGNORE_DOT_FILES = 2;
- private $mode = 0;
- private $names = array();
- private $notNames = array();
- private $exclude = array();
- private $filters = array();
- private $depths = array();
- private $sizes = array();
- private $followLinks = false;
- private $sort = false;
- private $ignore = 0;
- private $dirs = array();
- private $dates = array();
- private $iterators = array();
- private $contains = array();
- private $notContains = array();
- private $adapters = array();
- private $paths = array();
- private $notPaths = array();
- private $ignoreUnreadableDirs = false;
- private static $vcsPatterns = array('.svn', '_svn', 'CVS', '_darcs', '.arch-params', '.monotone', '.bzr', '.git', '.hg');
- public function __construct()
- {
- $this->ignore = static::IGNORE_VCS_FILES | static::IGNORE_DOT_FILES;
- $this
- ->addAdapter(new GnuFindAdapter())
- ->addAdapter(new BsdFindAdapter())
- ->addAdapter(new PhpAdapter(), -50)
- ->setAdapter('php')
- ;
- }
- public static function create()
- {
- return new static();
- }
- public function addAdapter(AdapterInterface $adapter, $priority = 0)
- {
- $this->adapters[$adapter->getName()] = array(
- 'adapter' => $adapter,
- 'priority' => $priority,
- 'selected' => false,
- );
- return $this->sortAdapters();
- }
- public function useBestAdapter()
- {
- $this->resetAdapterSelection();
- return $this->sortAdapters();
- }
- public function setAdapter($name)
- {
- if (!isset($this->adapters[$name])) {
- throw new \InvalidArgumentException(sprintf('Adapter "%s" does not exist.', $name));
- }
- $this->resetAdapterSelection();
- $this->adapters[$name]['selected'] = true;
- return $this->sortAdapters();
- }
- public function removeAdapters()
- {
- $this->adapters = array();
- return $this;
- }
- public function getAdapters()
- {
- return array_values(array_map(function (array $adapter) {
- return $adapter['adapter'];
- }, $this->adapters));
- }
- public function directories()
- {
- $this->mode = Iterator\FileTypeFilterIterator::ONLY_DIRECTORIES;
- return $this;
- }
- public function files()
- {
- $this->mode = Iterator\FileTypeFilterIterator::ONLY_FILES;
- return $this;
- }
- public function depth($level)
- {
- $this->depths[] = new Comparator\NumberComparator($level);
- return $this;
- }
- public function date($date)
- {
- $this->dates[] = new Comparator\DateComparator($date);
- return $this;
- }
- public function name($pattern)
- {
- $this->names[] = $pattern;
- return $this;
- }
- public function notName($pattern)
- {
- $this->notNames[] = $pattern;
- return $this;
- }
- public function contains($pattern)
- {
- $this->contains[] = $pattern;
- return $this;
- }
- public function notContains($pattern)
- {
- $this->notContains[] = $pattern;
- return $this;
- }
- public function path($pattern)
- {
- $this->paths[] = $pattern;
- return $this;
- }
- public function notPath($pattern)
- {
- $this->notPaths[] = $pattern;
- return $this;
- }
- public function size($size)
- {
- $this->sizes[] = new Comparator\NumberComparator($size);
- return $this;
- }
- public function exclude($dirs)
- {
- $this->exclude = array_merge($this->exclude, (array) $dirs);
- return $this;
- }
- public function ignoreDotFiles($ignoreDotFiles)
- {
- if ($ignoreDotFiles) {
- $this->ignore = $this->ignore | static::IGNORE_DOT_FILES;
- } else {
- $this->ignore = $this->ignore & ~static::IGNORE_DOT_FILES;
- }
- return $this;
- }
- public function ignoreVCS($ignoreVCS)
- {
- if ($ignoreVCS) {
- $this->ignore = $this->ignore | static::IGNORE_VCS_FILES;
- } else {
- $this->ignore = $this->ignore & ~static::IGNORE_VCS_FILES;
- }
- return $this;
- }
- public static function addVCSPattern($pattern)
- {
- foreach ((array) $pattern as $p) {
- self::$vcsPatterns[] = $p;
- }
- self::$vcsPatterns = array_unique(self::$vcsPatterns);
- }
- public function sort(\Closure $closure)
- {
- $this->sort = $closure;
- return $this;
- }
- public function sortByName()
- {
- $this->sort = Iterator\SortableIterator::SORT_BY_NAME;
- return $this;
- }
- public function sortByType()
- {
- $this->sort = Iterator\SortableIterator::SORT_BY_TYPE;
- return $this;
- }
- public function sortByAccessedTime()
- {
- $this->sort = Iterator\SortableIterator::SORT_BY_ACCESSED_TIME;
- return $this;
- }
- public function sortByChangedTime()
- {
- $this->sort = Iterator\SortableIterator::SORT_BY_CHANGED_TIME;
- return $this;
- }
- public function sortByModifiedTime()
- {
- $this->sort = Iterator\SortableIterator::SORT_BY_MODIFIED_TIME;
- return $this;
- }
- public function filter(\Closure $closure)
- {
- $this->filters[] = $closure;
- return $this;
- }
- public function followLinks()
- {
- $this->followLinks = true;
- return $this;
- }
- public function ignoreUnreadableDirs($ignore = true)
- {
- $this->ignoreUnreadableDirs = (bool) $ignore;
- return $this;
- }
- public function in($dirs)
- {
- $resolvedDirs = array();
- foreach ((array) $dirs as $dir) {
- if (is_dir($dir)) {
- $resolvedDirs[] = $dir;
- } elseif ($glob = glob($dir, GLOB_BRACE | GLOB_ONLYDIR)) {
- $resolvedDirs = array_merge($resolvedDirs, $glob);
- } else {
- throw new \InvalidArgumentException(sprintf('The "%s" directory does not exist.', $dir));
- }
- }
- $this->dirs = array_merge($this->dirs, $resolvedDirs);
- return $this;
- }
- public function getIterator()
- {
- if (0 === count($this->dirs) && 0 === count($this->iterators)) {
- throw new \LogicException('You must call one of in() or append() methods before iterating over a Finder.');
- }
- if (1 === count($this->dirs) && 0 === count($this->iterators)) {
- return $this->searchInDirectory($this->dirs[0]);
- }
- $iterator = new \AppendIterator();
- foreach ($this->dirs as $dir) {
- $iterator->append($this->searchInDirectory($dir));
- }
- foreach ($this->iterators as $it) {
- $iterator->append($it);
- }
- return $iterator;
- }
- public function append($iterator)
- {
- if ($iterator instanceof \IteratorAggregate) {
- $this->iterators[] = $iterator->getIterator();
- } elseif ($iterator instanceof \Iterator) {
- $this->iterators[] = $iterator;
- } elseif ($iterator instanceof \Traversable || is_array($iterator)) {
- $it = new \ArrayIterator();
- foreach ($iterator as $file) {
- $it->append($file instanceof \SplFileInfo ? $file : new \SplFileInfo($file));
- }
- $this->iterators[] = $it;
- } else {
- throw new \InvalidArgumentException('Finder::append() method wrong argument type.');
- }
- return $this;
- }
- public function count()
- {
- return iterator_count($this->getIterator());
- }
- private function sortAdapters()
- {
- uasort($this->adapters, function (array $a, array $b) {
- if ($a['selected'] || $b['selected']) {
- return $a['selected'] ? -1 : 1;
- }
- return $a['priority'] > $b['priority'] ? -1 : 1;
- });
- return $this;
- }
- private function searchInDirectory($dir)
- {
- if (static::IGNORE_VCS_FILES === (static::IGNORE_VCS_FILES & $this->ignore)) {
- $this->exclude = array_merge($this->exclude, self::$vcsPatterns);
- }
- if (static::IGNORE_DOT_FILES === (static::IGNORE_DOT_FILES & $this->ignore)) {
- $this->notPaths[] = '#(^|/)\..+(/|$)#';
- }
- foreach ($this->adapters as $adapter) {
- if ($adapter['adapter']->isSupported()) {
- try {
- return $this
- ->buildAdapter($adapter['adapter'])
- ->searchInDirectory($dir);
- } catch (ExceptionInterface $e) {
- }
- }
- }
- throw new \RuntimeException('No supported adapter found.');
- }
- private function buildAdapter(AdapterInterface $adapter)
- {
- return $adapter
- ->setFollowLinks($this->followLinks)
- ->setDepths($this->depths)
- ->setMode($this->mode)
- ->setExclude($this->exclude)
- ->setNames($this->names)
- ->setNotNames($this->notNames)
- ->setContains($this->contains)
- ->setNotContains($this->notContains)
- ->setSizes($this->sizes)
- ->setDates($this->dates)
- ->setFilters($this->filters)
- ->setSort($this->sort)
- ->setPath($this->paths)
- ->setNotPath($this->notPaths)
- ->ignoreUnreadableDirs($this->ignoreUnreadableDirs);
- }
- private function resetAdapterSelection()
- {
- $this->adapters = array_map(function (array $properties) {
- $properties['selected'] = false;
- return $properties;
- }, $this->adapters);
- }
- }
- <?php
- namespace Symfony\Component\Finder;
- class Glob
- {
- public static function toRegex($glob, $strictLeadingDot = true, $strictWildcardSlash = true)
- {
- $firstByte = true;
- $escaping = false;
- $inCurlies = 0;
- $regex = '';
- $sizeGlob = strlen($glob);
- for ($i = 0; $i < $sizeGlob; $i++) {
- $car = $glob[$i];
- if ($firstByte) {
- if ($strictLeadingDot && '.' !== $car) {
- $regex .= '(?=[^\.])';
- }
- $firstByte = false;
- }
- if ('/' === $car) {
- $firstByte = true;
- }
- if ('.' === $car || '(' === $car || ')' === $car || '|' === $car || '+' === $car || '^' === $car || '$' === $car) {
- $regex .= "\\$car";
- } elseif ('*' === $car) {
- $regex .= $escaping ? '\\*' : ($strictWildcardSlash ? '[^/]*' : '.*');
- } elseif ('?' === $car) {
- $regex .= $escaping ? '\\?' : ($strictWildcardSlash ? '[^/]' : '.');
- } elseif ('{' === $car) {
- $regex .= $escaping ? '\\{' : '(';
- if (!$escaping) {
- ++$inCurlies;
- }
- } elseif ('}' === $car && $inCurlies) {
- $regex .= $escaping ? '}' : ')';
- if (!$escaping) {
- --$inCurlies;
- }
- } elseif (',' === $car && $inCurlies) {
- $regex .= $escaping ? ',' : '|';
- } elseif ('\\' === $car) {
- if ($escaping) {
- $regex .= '\\\\';
- $escaping = false;
- } else {
- $escaping = true;
- }
- continue;
- } else {
- $regex .= $car;
- }
- $escaping = false;
- }
- return '#^'.$regex.'$#';
- }
- }
- <?php
- namespace Symfony\Component\Finder\Iterator;
- class CustomFilterIterator extends FilterIterator
- {
- private $filters = array();
- public function __construct(\Iterator $iterator, array $filters)
- {
- foreach ($filters as $filter) {
- if (!is_callable($filter)) {
- throw new \InvalidArgumentException('Invalid PHP callback.');
- }
- }
- $this->filters = $filters;
- parent::__construct($iterator);
- }
- public function accept()
- {
- $fileinfo = $this->current();
- foreach ($this->filters as $filter) {
- if (false === call_user_func($filter, $fileinfo)) {
- return false;
- }
- }
- return true;
- }
- }
- <?php
- namespace Symfony\Component\Finder\Iterator;
- use Symfony\Component\Finder\Comparator\DateComparator;
- class DateRangeFilterIterator extends FilterIterator
- {
- private $comparators = array();
- public function __construct(\Iterator $iterator, array $comparators)
- {
- $this->comparators = $comparators;
- parent::__construct($iterator);
- }
- public function accept()
- {
- $fileinfo = $this->current();
- if (!file_exists($fileinfo->getRealPath())) {
- return false;
- }
- $filedate = $fileinfo->getMTime();
- foreach ($this->comparators as $compare) {
- if (!$compare->test($filedate)) {
- return false;
- }
- }
- return true;
- }
- }
- <?php
- namespace Symfony\Component\Finder\Iterator;
- class DepthRangeFilterIterator extends FilterIterator
- {
- private $minDepth = 0;
- public function __construct(\RecursiveIteratorIterator $iterator, $minDepth = 0, $maxDepth = PHP_INT_MAX)
- {
- $this->minDepth = $minDepth;
- $iterator->setMaxDepth(PHP_INT_MAX === $maxDepth ? -1 : $maxDepth);
- parent::__construct($iterator);
- }
- public function accept()
- {
- return $this->getInnerIterator()->getDepth() >= $this->minDepth;
- }
- }
- <?php
- namespace Symfony\Component\Finder\Iterator;
- class ExcludeDirectoryFilterIterator extends FilterIterator
- {
- private $patterns = array();
- public function __construct(\Iterator $iterator, array $directories)
- {
- foreach ($directories as $directory) {
- $this->patterns[] = '#(^|/)'.preg_quote($directory, '#').'(/|$)#';
- }
- parent::__construct($iterator);
- }
- public function accept()
- {
- $path = $this->isDir() ? $this->current()->getRelativePathname() : $this->current()->getRelativePath();
- $path = strtr($path, '\\', '/');
- foreach ($this->patterns as $pattern) {
- if (preg_match($pattern, $path)) {
- return false;
- }
- }
- return true;
- }
- }
- <?php
- namespace Symfony\Component\Finder\Iterator;
- class FilecontentFilterIterator extends MultiplePcreFilterIterator
- {
- public function accept()
- {
- if (!$this->matchRegexps && !$this->noMatchRegexps) {
- return true;
- }
- $fileinfo = $this->current();
- if ($fileinfo->isDir() || !$fileinfo->isReadable()) {
- return false;
- }
- $content = $fileinfo->getContents();
- if (!$content) {
- return false;
- }
- foreach ($this->noMatchRegexps as $regex) {
- if (preg_match($regex, $content)) {
- return false;
- }
- }
- $match = true;
- if ($this->matchRegexps) {
- $match = false;
- foreach ($this->matchRegexps as $regex) {
- if (preg_match($regex, $content)) {
- return true;
- }
- }
- }
- return $match;
- }
- protected function toRegex($str)
- {
- return $this->isRegex($str) ? $str : '/'.preg_quote($str, '/').'/';
- }
- }
- <?php
- namespace Symfony\Component\Finder\Iterator;
- use Symfony\Component\Finder\Expression\Expression;
- class FilenameFilterIterator extends MultiplePcreFilterIterator
- {
- public function accept()
- {
- $filename = $this->current()->getFilename();
- foreach ($this->noMatchRegexps as $regex) {
- if (preg_match($regex, $filename)) {
- return false;
- }
- }
- $match = true;
- if ($this->matchRegexps) {
- $match = false;
- foreach ($this->matchRegexps as $regex) {
- if (preg_match($regex, $filename)) {
- return true;
- }
- }
- }
- return $match;
- }
- protected function toRegex($str)
- {
- return Expression::create($str)->getRegex()->render();
- }
- }
- <?php
- namespace Symfony\Component\Finder\Iterator;
- use Symfony\Component\Finder\SplFileInfo;
- class FilePathsIterator extends \ArrayIterator
- {
- private $baseDir;
- private $baseDirLength;
- private $subPath;
- private $subPathname;
- private $current;
- public function __construct(array $paths, $baseDir)
- {
- $this->baseDir = $baseDir;
- $this->baseDirLength = strlen($baseDir);
- parent::__construct($paths);
- }
- public function __call($name, array $arguments)
- {
- return call_user_func_array(array($this->current(), $name), $arguments);
- }
- public function current()
- {
- return $this->current;
- }
- public function key()
- {
- return $this->current->getPathname();
- }
- public function next()
- {
- parent::next();
- $this->buildProperties();
- }
- public function rewind()
- {
- parent::rewind();
- $this->buildProperties();
- }
- public function getSubPath()
- {
- return $this->subPath;
- }
- public function getSubPathname()
- {
- return $this->subPathname;
- }
- private function buildProperties()
- {
- $absolutePath = parent::current();
- if ($this->baseDir === substr($absolutePath, 0, $this->baseDirLength)) {
- $this->subPathname = ltrim(substr($absolutePath, $this->baseDirLength), '/\\');
- $dir = dirname($this->subPathname);
- $this->subPath = '.' === $dir ? '' : $dir;
- } else {
- $this->subPath = $this->subPathname = '';
- }
- $this->current = new SplFileInfo(parent::current(), $this->subPath, $this->subPathname);
- }
- }
- <?php
- namespace Symfony\Component\Finder\Iterator;
- class FileTypeFilterIterator extends FilterIterator
- {
- const ONLY_FILES = 1;
- const ONLY_DIRECTORIES = 2;
- private $mode;
- public function __construct(\Iterator $iterator, $mode)
- {
- $this->mode = $mode;
- parent::__construct($iterator);
- }
- public function accept()
- {
- $fileinfo = $this->current();
- if (self::ONLY_DIRECTORIES === (self::ONLY_DIRECTORIES & $this->mode) && $fileinfo->isFile()) {
- return false;
- } elseif (self::ONLY_FILES === (self::ONLY_FILES & $this->mode) && $fileinfo->isDir()) {
- return false;
- }
- return true;
- }
- }
- <?php
- namespace Symfony\Component\Finder\Iterator;
- abstract class FilterIterator extends \FilterIterator
- {
- public function rewind()
- {
- $iterator = $this;
- while ($iterator instanceof \OuterIterator) {
- $innerIterator = $iterator->getInnerIterator();
- if ($innerIterator instanceof RecursiveDirectoryIterator) {
- if ($innerIterator->isRewindable()) {
- $innerIterator->next();
- $innerIterator->rewind();
- }
- } elseif ($iterator->getInnerIterator() instanceof \FilesystemIterator) {
- $iterator->getInnerIterator()->next();
- $iterator->getInnerIterator()->rewind();
- }
- $iterator = $iterator->getInnerIterator();
- }
- parent::rewind();
- }
- }
- <?php
- namespace Symfony\Component\Finder\Iterator;
- use Symfony\Component\Finder\Expression\Expression;
- abstract class MultiplePcreFilterIterator extends FilterIterator
- {
- protected $matchRegexps = array();
- protected $noMatchRegexps = array();
- public function __construct(\Iterator $iterator, array $matchPatterns, array $noMatchPatterns)
- {
- foreach ($matchPatterns as $pattern) {
- $this->matchRegexps[] = $this->toRegex($pattern);
- }
- foreach ($noMatchPatterns as $pattern) {
- $this->noMatchRegexps[] = $this->toRegex($pattern);
- }
- parent::__construct($iterator);
- }
- protected function isRegex($str)
- {
- return Expression::create($str)->isRegex();
- }
- abstract protected function toRegex($str);
- }
- <?php
- namespace Symfony\Component\Finder\Iterator;
- class PathFilterIterator extends MultiplePcreFilterIterator
- {
- public function accept()
- {
- $filename = $this->current()->getRelativePathname();
- if ('\\' === DIRECTORY_SEPARATOR) {
- $filename = strtr($filename, '\\', '/');
- }
- foreach ($this->noMatchRegexps as $regex) {
- if (preg_match($regex, $filename)) {
- return false;
- }
- }
- $match = true;
- if ($this->matchRegexps) {
- $match = false;
- foreach ($this->matchRegexps as $regex) {
- if (preg_match($regex, $filename)) {
- return true;
- }
- }
- }
- return $match;
- }
- protected function toRegex($str)
- {
- return $this->isRegex($str) ? $str : '/'.preg_quote($str, '/').'/';
- }
- }
- <?php
- namespace Symfony\Component\Finder\Iterator;
- use Symfony\Component\Finder\Exception\AccessDeniedException;
- use Symfony\Component\Finder\SplFileInfo;
- class RecursiveDirectoryIterator extends \RecursiveDirectoryIterator
- {
- private $ignoreUnreadableDirs;
- private $rewindable;
- public function __construct($path, $flags, $ignoreUnreadableDirs = false)
- {
- if ($flags & (self::CURRENT_AS_PATHNAME | self::CURRENT_AS_SELF)) {
- throw new \RuntimeException('This iterator only support returning current as fileinfo.');
- }
- parent::__construct($path, $flags);
- $this->ignoreUnreadableDirs = $ignoreUnreadableDirs;
- }
- public function current()
- {
- return new SplFileInfo(parent::current()->getPathname(), $this->getSubPath(), $this->getSubPathname());
- }
- public function getChildren()
- {
- try {
- $children = parent::getChildren();
- if ($children instanceof self) {
- $children->ignoreUnreadableDirs = $this->ignoreUnreadableDirs;
- }
- return $children;
- } catch (\UnexpectedValueException $e) {
- if ($this->ignoreUnreadableDirs) {
- return new \RecursiveArrayIterator(array());
- } else {
- throw new AccessDeniedException($e->getMessage(), $e->getCode(), $e);
- }
- }
- }
- public function rewind()
- {
- if (false === $this->isRewindable()) {
- return;
- }
- parent::next();
- parent::rewind();
- }
- public function isRewindable()
- {
- if (null !== $this->rewindable) {
- return $this->rewindable;
- }
- if (false !== $stream = @opendir($this->getPath())) {
- $infos = stream_get_meta_data($stream);
- closedir($stream);
- if ($infos['seekable']) {
- return $this->rewindable = true;
- }
- }
- return $this->rewindable = false;
- }
- }
- <?php
- namespace Symfony\Component\Finder\Iterator;
- use Symfony\Component\Finder\Comparator\NumberComparator;
- class SizeRangeFilterIterator extends FilterIterator
- {
- private $comparators = array();
- public function __construct(\Iterator $iterator, array $comparators)
- {
- $this->comparators = $comparators;
- parent::__construct($iterator);
- }
- public function accept()
- {
- $fileinfo = $this->current();
- if (!$fileinfo->isFile()) {
- return true;
- }
- $filesize = $fileinfo->getSize();
- foreach ($this->comparators as $compare) {
- if (!$compare->test($filesize)) {
- return false;
- }
- }
- return true;
- }
- }
- <?php
- namespace Symfony\Component\Finder\Iterator;
- class SortableIterator implements \IteratorAggregate
- {
- const SORT_BY_NAME = 1;
- const SORT_BY_TYPE = 2;
- const SORT_BY_ACCESSED_TIME = 3;
- const SORT_BY_CHANGED_TIME = 4;
- const SORT_BY_MODIFIED_TIME = 5;
- private $iterator;
- private $sort;
- public function __construct(\Traversable $iterator, $sort)
- {
- $this->iterator = $iterator;
- if (self::SORT_BY_NAME === $sort) {
- $this->sort = function ($a, $b) {
- return strcmp($a->getRealpath(), $b->getRealpath());
- };
- } elseif (self::SORT_BY_TYPE === $sort) {
- $this->sort = function ($a, $b) {
- if ($a->isDir() && $b->isFile()) {
- return -1;
- } elseif ($a->isFile() && $b->isDir()) {
- return 1;
- }
- return strcmp($a->getRealpath(), $b->getRealpath());
- };
- } elseif (self::SORT_BY_ACCESSED_TIME === $sort) {
- $this->sort = function ($a, $b) {
- return ($a->getATime() - $b->getATime());
- };
- } elseif (self::SORT_BY_CHANGED_TIME === $sort) {
- $this->sort = function ($a, $b) {
- return ($a->getCTime() - $b->getCTime());
- };
- } elseif (self::SORT_BY_MODIFIED_TIME === $sort) {
- $this->sort = function ($a, $b) {
- return ($a->getMTime() - $b->getMTime());
- };
- } elseif (is_callable($sort)) {
- $this->sort = $sort;
- } else {
- throw new \InvalidArgumentException('The SortableIterator takes a PHP callable or a valid built-in sort algorithm as an argument.');
- }
- }
- public function getIterator()
- {
- $array = iterator_to_array($this->iterator, true);
- uasort($array, $this->sort);
- return new \ArrayIterator($array);
- }
- }
- Copyright (c) 2004-2015 Fabien Potencier
- Permission is hereby granted, free of charge, to any person obtaining a copy
- of this software and associated documentation files (the "Software"), to deal
- in the Software without restriction, including without limitation the rights
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- copies of the Software, and to permit persons to whom the Software is furnished
- to do so, subject to the following conditions:
- The above copyright notice and this permission notice shall be included in all
- copies or substantial portions of the Software.
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- THE SOFTWARE.
- <?php
- namespace Symfony\Component\Finder\Shell;
- class Command
- {
- private $parent;
- private $bits = array();
- private $labels = array();
- private $errorHandler;
- public function __construct(Command $parent = null)
- {
- $this->parent = $parent;
- }
- public function __toString()
- {
- return $this->join();
- }
- public static function create(Command $parent = null)
- {
- return new self($parent);
- }
- public static function escape($input)
- {
- return escapeshellcmd($input);
- }
- public static function quote($input)
- {
- return escapeshellarg($input);
- }
- public function add($bit)
- {
- $this->bits[] = $bit;
- return $this;
- }
- public function top($bit)
- {
- array_unshift($this->bits, $bit);
- foreach ($this->labels as $label => $index) {
- $this->labels[$label] += 1;
- }
- return $this;
- }
- public function arg($arg)
- {
- $this->bits[] = self::quote($arg);
- return $this;
- }
- public function cmd($esc)
- {
- $this->bits[] = self::escape($esc);
- return $this;
- }
- public function ins($label)
- {
- if (isset($this->labels[$label])) {
- throw new \RuntimeException(sprintf('Label "%s" already exists.', $label));
- }
- $this->bits[] = self::create($this);
- $this->labels[$label] = count($this->bits)-1;
- return $this->bits[$this->labels[$label]];
- }
- public function get($label)
- {
- if (!isset($this->labels[$label])) {
- throw new \RuntimeException(sprintf('Label "%s" does not exist.', $label));
- }
- return $this->bits[$this->labels[$label]];
- }
- public function end()
- {
- if (null === $this->parent) {
- throw new \RuntimeException('Calling end on root command doesn\'t make sense.');
- }
- return $this->parent;
- }
- public function length()
- {
- return count($this->bits);
- }
- public function setErrorHandler(\Closure $errorHandler)
- {
- $this->errorHandler = $errorHandler;
- return $this;
- }
- public function getErrorHandler()
- {
- return $this->errorHandler;
- }
- public function execute()
- {
- if (null === $errorHandler = $this->errorHandler) {
- exec($this->join(), $output);
- } else {
- $process = proc_open($this->join(), array(0 => array('pipe', 'r'), 1 => array('pipe', 'w'), 2 => array('pipe', 'w')), $pipes);
- $output = preg_split('~(\r\n|\r|\n)~', stream_get_contents($pipes[1]), -1, PREG_SPLIT_NO_EMPTY);
- if ($error = stream_get_contents($pipes[2])) {
- $errorHandler($error);
- }
- proc_close($process);
- }
- return $output ?: array();
- }
- public function join()
- {
- return implode(' ', array_filter(
- array_map(function ($bit) {
- return $bit instanceof Command ? $bit->join() : ($bit ?: null);
- }, $this->bits),
- function ($bit) { return null !== $bit; }
- ));
- }
- public function addAtIndex($bit, $index)
- {
- array_splice($this->bits, $index, 0, $bit);
- return $this;
- }
- }
- <?php
- namespace Symfony\Component\Finder\Shell;
- class Shell
- {
- const TYPE_UNIX = 1;
- const TYPE_DARWIN = 2;
- const TYPE_CYGWIN = 3;
- const TYPE_WINDOWS = 4;
- const TYPE_BSD = 5;
- private $type;
- public function getType()
- {
- if (null === $this->type) {
- $this->type = $this->guessType();
- }
- return $this->type;
- }
- public function testCommand($command)
- {
- if (!function_exists('exec')) {
- return false;
- }
- $testCommand = 'which ';
- if (self::TYPE_WINDOWS === $this->type) {
- $testCommand = 'where ';
- }
- $command = escapeshellcmd($command);
- exec($testCommand.$command, $output, $code);
- return 0 === $code && count($output) > 0;
- }
- private function guessType()
- {
- $os = strtolower(PHP_OS);
- if (false !== strpos($os, 'cygwin')) {
- return self::TYPE_CYGWIN;
- }
- if (false !== strpos($os, 'darwin')) {
- return self::TYPE_DARWIN;
- }
- if (false !== strpos($os, 'bsd')) {
- return self::TYPE_BSD;
- }
- if (0 === strpos($os, 'win')) {
- return self::TYPE_WINDOWS;
- }
- return self::TYPE_UNIX;
- }
- }
- <?php
- namespace Symfony\Component\Finder;
- class SplFileInfo extends \SplFileInfo
- {
- private $relativePath;
- private $relativePathname;
- public function __construct($file, $relativePath, $relativePathname)
- {
- parent::__construct($file);
- $this->relativePath = $relativePath;
- $this->relativePathname = $relativePathname;
- }
- public function getRelativePath()
- {
- return $this->relativePath;
- }
- public function getRelativePathname()
- {
- return $this->relativePathname;
- }
- public function getContents()
- {
- $level = error_reporting(0);
- $content = file_get_contents($this->getPathname());
- error_reporting($level);
- if (false === $content) {
- $error = error_get_last();
- throw new \RuntimeException($error['message']);
- }
- return $content;
- }
- }
- <?php
- namespace Symfony\Component\Process\Exception;
- interface ExceptionInterface
- {
- }
- <?php
- namespace Symfony\Component\Process\Exception;
- class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface
- {
- }
- <?php
- namespace Symfony\Component\Process\Exception;
- class LogicException extends \LogicException implements ExceptionInterface
- {
- }
- <?php
- namespace Symfony\Component\Process\Exception;
- use Symfony\Component\Process\Process;
- class ProcessFailedException extends RuntimeException
- {
- private $process;
- public function __construct(Process $process)
- {
- if ($process->isSuccessful()) {
- throw new InvalidArgumentException('Expected a failed process, but the given process was successful.');
- }
- $error = sprintf('The command "%s" failed.'."\nExit Code: %s(%s)",
- $process->getCommandLine(),
- $process->getExitCode(),
- $process->getExitCodeText()
- );
- if (!$process->isOutputDisabled()) {
- $error .= sprintf("\n\nOutput:\n================\n%s\n\nError Output:\n================\n%s",
- $process->getOutput(),
- $process->getErrorOutput()
- );
- }
- parent::__construct($error);
- $this->process = $process;
- }
- public function getProcess()
- {
- return $this->process;
- }
- }
- <?php
- namespace Symfony\Component\Process\Exception;
- use Symfony\Component\Process\Process;
- class ProcessTimedOutException extends RuntimeException
- {
- const TYPE_GENERAL = 1;
- const TYPE_IDLE = 2;
- private $process;
- private $timeoutType;
- public function __construct(Process $process, $timeoutType)
- {
- $this->process = $process;
- $this->timeoutType = $timeoutType;
- parent::__construct(sprintf(
- 'The process "%s" exceeded the timeout of %s seconds.',
- $process->getCommandLine(),
- $this->getExceededTimeout()
- ));
- }
- public function getProcess()
- {
- return $this->process;
- }
- public function isGeneralTimeout()
- {
- return $this->timeoutType === self::TYPE_GENERAL;
- }
- public function isIdleTimeout()
- {
- return $this->timeoutType === self::TYPE_IDLE;
- }
- public function getExceededTimeout()
- {
- switch ($this->timeoutType) {
- case self::TYPE_GENERAL:
- return $this->process->getTimeout();
- case self::TYPE_IDLE:
- return $this->process->getIdleTimeout();
- default:
- throw new \LogicException(sprintf('Unknown timeout type "%d".', $this->timeoutType));
- }
- }
- }
- <?php
- namespace Symfony\Component\Process\Exception;
- class RuntimeException extends \RuntimeException implements ExceptionInterface
- {
- }
- <?php
- namespace Symfony\Component\Process;
- class ExecutableFinder
- {
- private $suffixes = array('.exe', '.bat', '.cmd', '.com');
- public function setSuffixes(array $suffixes)
- {
- $this->suffixes = $suffixes;
- }
- public function addSuffix($suffix)
- {
- $this->suffixes[] = $suffix;
- }
- public function find($name, $default = null, array $extraDirs = array())
- {
- if (ini_get('open_basedir')) {
- $searchPath = explode(PATH_SEPARATOR, ini_get('open_basedir'));
- $dirs = array();
- foreach ($searchPath as $path) {
- if (is_dir($path)) {
- $dirs[] = $path;
- } else {
- if (basename($path) == $name && is_executable($path)) {
- return $path;
- }
- }
- }
- } else {
- $dirs = array_merge(
- explode(PATH_SEPARATOR, getenv('PATH') ?: getenv('Path')),
- $extraDirs
- );
- }
- $suffixes = array('');
- if ('\\' === DIRECTORY_SEPARATOR) {
- $pathExt = getenv('PATHEXT');
- $suffixes = $pathExt ? explode(PATH_SEPARATOR, $pathExt) : $this->suffixes;
- }
- foreach ($suffixes as $suffix) {
- foreach ($dirs as $dir) {
- if (is_file($file = $dir.DIRECTORY_SEPARATOR.$name.$suffix) && ('\\' === DIRECTORY_SEPARATOR || is_executable($file))) {
- return $file;
- }
- }
- }
- return $default;
- }
- }
- Copyright (c) 2004-2015 Fabien Potencier
- Permission is hereby granted, free of charge, to any person obtaining a copy
- of this software and associated documentation files (the "Software"), to deal
- in the Software without restriction, including without limitation the rights
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- copies of the Software, and to permit persons to whom the Software is furnished
- to do so, subject to the following conditions:
- The above copyright notice and this permission notice shall be included in all
- copies or substantial portions of the Software.
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- THE SOFTWARE.
- <?php
- namespace Symfony\Component\Process;
- class PhpExecutableFinder
- {
- private $executableFinder;
- public function __construct()
- {
- $this->executableFinder = new ExecutableFinder();
- }
- public function find($includeArgs = true)
- {
- if (defined('HHVM_VERSION')) {
- return (false !== ($hhvm = getenv('PHP_BINARY')) ? $hhvm : PHP_BINARY).($includeArgs ? ' '.implode(' ', $this->findArguments()) : '');
- }
- if (defined('PHP_BINARY') && PHP_BINARY && in_array(PHP_SAPI, array('cli', 'cli-server')) && is_file(PHP_BINARY)) {
- return PHP_BINARY;
- }
- if ($php = getenv('PHP_PATH')) {
- if (!is_executable($php)) {
- return false;
- }
- return $php;
- }
- if ($php = getenv('PHP_PEAR_PHP_BIN')) {
- if (is_executable($php)) {
- return $php;
- }
- }
- $dirs = array(PHP_BINDIR);
- if ('\\' === DIRECTORY_SEPARATOR) {
- $dirs[] = 'C:\xampp\php\\';
- }
- return $this->executableFinder->find('php', false, $dirs);
- }
- public function findArguments()
- {
- $arguments = array();
- if (defined('HHVM_VERSION')) {
- $arguments[] = '--php';
- }
- return $arguments;
- }
- }
- <?php
- namespace Symfony\Component\Process;
- use Symfony\Component\Process\Exception\RuntimeException;
- class PhpProcess extends Process
- {
- private $executableFinder;
- public function __construct($script, $cwd = null, array $env = array(), $timeout = 60, array $options = array())
- {
- parent::__construct(null, $cwd, $env, $script, $timeout, $options);
- $this->executableFinder = new PhpExecutableFinder();
- }
- public function setPhpBinary($php)
- {
- $this->setCommandLine($php);
- }
- public function start($callback = null)
- {
- if (null === $this->getCommandLine()) {
- if (false === $php = $this->executableFinder->find()) {
- throw new RuntimeException('Unable to find the PHP executable.');
- }
- $this->setCommandLine($php);
- }
- parent::start($callback);
- }
- }
- <?php
- namespace Symfony\Component\Process\Pipes;
- abstract class AbstractPipes implements PipesInterface
- {
- public $pipes = array();
- protected $inputBuffer = '';
- protected $input;
- private $blocked = true;
- public function close()
- {
- foreach ($this->pipes as $pipe) {
- fclose($pipe);
- }
- $this->pipes = array();
- }
- protected function hasSystemCallBeenInterrupted()
- {
- $lastError = error_get_last();
- return isset($lastError['message']) && false !== stripos($lastError['message'], 'interrupted system call');
- }
- protected function unblock()
- {
- if (!$this->blocked) {
- return;
- }
- foreach ($this->pipes as $pipe) {
- stream_set_blocking($pipe, 0);
- }
- if (null !== $this->input) {
- stream_set_blocking($this->input, 0);
- }
- $this->blocked = false;
- }
- }
- <?php
- namespace Symfony\Component\Process\Pipes;
- interface PipesInterface
- {
- const CHUNK_SIZE = 16384;
- public function getDescriptors();
- public function getFiles();
- public function readAndWrite($blocking, $close = false);
- public function areOpen();
- public function close();
- }
- <?php
- namespace Symfony\Component\Process\Pipes;
- use Symfony\Component\Process\Process;
- class UnixPipes extends AbstractPipes
- {
- private $ttyMode;
- private $ptyMode;
- private $disableOutput;
- public function __construct($ttyMode, $ptyMode, $input, $disableOutput)
- {
- $this->ttyMode = (bool) $ttyMode;
- $this->ptyMode = (bool) $ptyMode;
- $this->disableOutput = (bool) $disableOutput;
- if (is_resource($input)) {
- $this->input = $input;
- } else {
- $this->inputBuffer = (string) $input;
- }
- }
- public function __destruct()
- {
- $this->close();
- }
- public function getDescriptors()
- {
- if ($this->disableOutput) {
- $nullstream = fopen('/dev/null', 'c');
- return array(
- array('pipe', 'r'),
- $nullstream,
- $nullstream,
- );
- }
- if ($this->ttyMode) {
- return array(
- array('file', '/dev/tty', 'r'),
- array('file', '/dev/tty', 'w'),
- array('file', '/dev/tty', 'w'),
- );
- }
- if ($this->ptyMode && Process::isPtySupported()) {
- return array(
- array('pty'),
- array('pty'),
- array('pty'),
- );
- }
- return array(
- array('pipe', 'r'),
- array('pipe', 'w'),
- array('pipe', 'w'),
- );
- }
- public function getFiles()
- {
- return array();
- }
- public function readAndWrite($blocking, $close = false)
- {
-
- if (1 === count($this->pipes) && array(0) === array_keys($this->pipes)) {
- fclose($this->pipes[0]);
- unset($this->pipes[0]);
- }
- if (empty($this->pipes)) {
- return array();
- }
- $this->unblock();
- $read = array();
- if (null !== $this->input) {
-
- $r = array_merge($this->pipes, array('input' => $this->input));
- } else {
- $r = $this->pipes;
- }
- unset($r[0]);
- $w = isset($this->pipes[0]) ? array($this->pipes[0]) : null;
- $e = null;
- if (false === $n = @stream_select($r, $w, $e, 0, $blocking ? Process::TIMEOUT_PRECISION * 1E6 : 0)) {
-
- if (!$this->hasSystemCallBeenInterrupted()) {
- $this->pipes = array();
- }
- return $read;
- }
- if (0 === $n) {
- return $read;
- }
- foreach ($r as $pipe) {
-
- $type = (false !== $found = array_search($pipe, $this->pipes)) ? $found : 'input';
- $data = '';
- while ('' !== $dataread = (string) fread($pipe, self::CHUNK_SIZE)) {
- $data .= $dataread;
- }
- if ('' !== $data) {
- if ($type === 'input') {
- $this->inputBuffer .= $data;
- } else {
- $read[$type] = $data;
- }
- }
- if (false === $data || (true === $close && feof($pipe) && '' === $data)) {
- if ($type === 'input') {
-
- $this->input = null;
- } else {
- fclose($this->pipes[$type]);
- unset($this->pipes[$type]);
- }
- }
- }
- if (null !== $w && 0 < count($w)) {
- while (strlen($this->inputBuffer)) {
- $written = fwrite($w[0], $this->inputBuffer, 2 << 18);
- if ($written > 0) {
- $this->inputBuffer = (string) substr($this->inputBuffer, $written);
- } else {
- break;
- }
- }
- }
- if ('' === $this->inputBuffer && null === $this->input && isset($this->pipes[0])) {
- fclose($this->pipes[0]);
- unset($this->pipes[0]);
- }
- return $read;
- }
- public function areOpen()
- {
- return (bool) $this->pipes;
- }
- public static function create(Process $process, $input)
- {
- return new static($process->isTty(), $process->isPty(), $input, $process->isOutputDisabled());
- }
- }
- <?php
- namespace Symfony\Component\Process\Pipes;
- use Symfony\Component\Process\Process;
- use Symfony\Component\Process\Exception\RuntimeException;
- class WindowsPipes extends AbstractPipes
- {
- private $files = array();
- private $fileHandles = array();
- private $readBytes = array(
- Process::STDOUT => 0,
- Process::STDERR => 0,
- );
- private $disableOutput;
- public function __construct($disableOutput, $input)
- {
- $this->disableOutput = (bool) $disableOutput;
- if (!$this->disableOutput) {
-
-
-
- $this->files = array(
- Process::STDOUT => tempnam(sys_get_temp_dir(), 'sf_proc_stdout'),
- Process::STDERR => tempnam(sys_get_temp_dir(), 'sf_proc_stderr'),
- );
- foreach ($this->files as $offset => $file) {
- $this->fileHandles[$offset] = fopen($this->files[$offset], 'rb');
- if (false === $this->fileHandles[$offset]) {
- throw new RuntimeException('A temporary file could not be opened to write the process output to, verify that your TEMP environment variable is writable');
- }
- }
- }
- if (is_resource($input)) {
- $this->input = $input;
- } else {
- $this->inputBuffer = $input;
- }
- }
- public function __destruct()
- {
- $this->close();
- $this->removeFiles();
- }
- public function getDescriptors()
- {
- if ($this->disableOutput) {
- $nullstream = fopen('NUL', 'c');
- return array(
- array('pipe', 'r'),
- $nullstream,
- $nullstream,
- );
- }
-
-
- return array(
- array('pipe', 'r'),
- array('file', 'NUL', 'w'),
- array('file', 'NUL', 'w'),
- );
- }
- public function getFiles()
- {
- return $this->files;
- }
- public function readAndWrite($blocking, $close = false)
- {
- $this->write($blocking, $close);
- $read = array();
- $fh = $this->fileHandles;
- foreach ($fh as $type => $fileHandle) {
- if (0 !== fseek($fileHandle, $this->readBytes[$type])) {
- continue;
- }
- $data = '';
- $dataread = null;
- while (!feof($fileHandle)) {
- if (false !== $dataread = fread($fileHandle, self::CHUNK_SIZE)) {
- $data .= $dataread;
- }
- }
- if (0 < $length = strlen($data)) {
- $this->readBytes[$type] += $length;
- $read[$type] = $data;
- }
- if (false === $dataread || (true === $close && feof($fileHandle) && '' === $data)) {
- fclose($this->fileHandles[$type]);
- unset($this->fileHandles[$type]);
- }
- }
- return $read;
- }
- public function areOpen()
- {
- return (bool) $this->pipes && (bool) $this->fileHandles;
- }
- public function close()
- {
- parent::close();
- foreach ($this->fileHandles as $handle) {
- fclose($handle);
- }
- $this->fileHandles = array();
- }
- public static function create(Process $process, $input)
- {
- return new static($process->isOutputDisabled(), $input);
- }
- private function removeFiles()
- {
- foreach ($this->files as $filename) {
- if (file_exists($filename)) {
- @unlink($filename);
- }
- }
- $this->files = array();
- }
- private function write($blocking, $close)
- {
- if (empty($this->pipes)) {
- return;
- }
- $this->unblock();
- $r = null !== $this->input ? array('input' => $this->input) : null;
- $w = isset($this->pipes[0]) ? array($this->pipes[0]) : null;
- $e = null;
- if (false === $n = @stream_select($r, $w, $e, 0, $blocking ? Process::TIMEOUT_PRECISION * 1E6 : 0)) {
-
- if (!$this->hasSystemCallBeenInterrupted()) {
- $this->pipes = array();
- }
- return;
- }
- if (0 === $n) {
- return;
- }
- if (null !== $w && 0 < count($r)) {
- $data = '';
- while ($dataread = fread($r['input'], self::CHUNK_SIZE)) {
- $data .= $dataread;
- }
- $this->inputBuffer .= $data;
- if (false === $data || (true === $close && feof($r['input']) && '' === $data)) {
-
- $this->input = null;
- }
- }
- if (null !== $w && 0 < count($w)) {
- while (strlen($this->inputBuffer)) {
- $written = fwrite($w[0], $this->inputBuffer, 2 << 18);
- if ($written > 0) {
- $this->inputBuffer = (string) substr($this->inputBuffer, $written);
- } else {
- break;
- }
- }
- }
- if ('' === $this->inputBuffer && null === $this->input && isset($this->pipes[0])) {
- fclose($this->pipes[0]);
- unset($this->pipes[0]);
- }
- }
- }
- <?php
- namespace Symfony\Component\Process;
- use Symfony\Component\Process\Exception\InvalidArgumentException;
- use Symfony\Component\Process\Exception\LogicException;
- use Symfony\Component\Process\Exception\ProcessFailedException;
- use Symfony\Component\Process\Exception\ProcessTimedOutException;
- use Symfony\Component\Process\Exception\RuntimeException;
- use Symfony\Component\Process\Pipes\PipesInterface;
- use Symfony\Component\Process\Pipes\UnixPipes;
- use Symfony\Component\Process\Pipes\WindowsPipes;
- class Process
- {
- const ERR = 'err';
- const OUT = 'out';
- const STATUS_READY = 'ready';
- const STATUS_STARTED = 'started';
- const STATUS_TERMINATED = 'terminated';
- const STDIN = 0;
- const STDOUT = 1;
- const STDERR = 2;
- const TIMEOUT_PRECISION = 0.2;
- private $callback;
- private $commandline;
- private $cwd;
- private $env;
- private $input;
- private $starttime;
- private $lastOutputTime;
- private $timeout;
- private $idleTimeout;
- private $options;
- private $exitcode;
- private $fallbackExitcode;
- private $processInformation;
- private $outputDisabled = false;
- private $stdout;
- private $stderr;
- private $enhanceWindowsCompatibility = true;
- private $enhanceSigchildCompatibility;
- private $process;
- private $status = self::STATUS_READY;
- private $incrementalOutputOffset = 0;
- private $incrementalErrorOutputOffset = 0;
- private $tty;
- private $pty;
- private $useFileHandles = false;
- private $processPipes;
- private $latestSignal;
- private static $sigchild;
- public static $exitCodes = array(
- 0 => 'OK',
- 1 => 'General error',
- 2 => 'Misuse of shell builtins',
- 126 => 'Invoked command cannot execute',
- 127 => 'Command not found',
- 128 => 'Invalid exit argument',
- 129 => 'Hangup',
- 130 => 'Interrupt',
- 131 => 'Quit and dump core',
- 132 => 'Illegal instruction',
- 133 => 'Trace/breakpoint trap',
- 134 => 'Process aborted',
- 135 => 'Bus error: "access to undefined portion of memory object"',
- 136 => 'Floating point exception: "erroneous arithmetic operation"',
- 137 => 'Kill (terminate immediately)',
- 138 => 'User-defined 1',
- 139 => 'Segmentation violation',
- 140 => 'User-defined 2',
- 141 => 'Write to pipe with no one reading',
- 142 => 'Signal raised by alarm',
- 143 => 'Termination (request to terminate)',
- 145 => 'Child process terminated, stopped (or continued*)',
- 146 => 'Continue if stopped',
- 147 => 'Stop executing temporarily',
- 148 => 'Terminal stop signal',
- 149 => 'Background process attempting to read from tty ("in")',
- 150 => 'Background process attempting to write to tty ("out")',
- 151 => 'Urgent data available on socket',
- 152 => 'CPU time limit exceeded',
- 153 => 'File size limit exceeded',
- 154 => 'Signal raised by timer counting virtual time: "virtual timer expired"',
- 155 => 'Profiling timer expired',
- 157 => 'Pollable event',
- 159 => 'Bad syscall',
- );
- public function __construct($commandline, $cwd = null, array $env = null, $input = null, $timeout = 60, array $options = array())
- {
- if (!function_exists('proc_open')) {
- throw new RuntimeException('The Process class relies on proc_open, which is not available on your PHP installation.');
- }
- $this->commandline = $commandline;
- $this->cwd = $cwd;
-
-
-
- if (null === $this->cwd && (defined('ZEND_THREAD_SAFE') || '\\' === DIRECTORY_SEPARATOR)) {
- $this->cwd = getcwd();
- }
- if (null !== $env) {
- $this->setEnv($env);
- }
- $this->input = $input;
- $this->setTimeout($timeout);
- $this->useFileHandles = '\\' === DIRECTORY_SEPARATOR;
- $this->pty = false;
- $this->enhanceWindowsCompatibility = true;
- $this->enhanceSigchildCompatibility = '\\' !== DIRECTORY_SEPARATOR && $this->isSigchildEnabled();
- $this->options = array_replace(array('suppress_errors' => true, 'binary_pipes' => true), $options);
- }
- public function __destruct()
- {
- $this->stop();
- }
- public function __clone()
- {
- $this->resetProcessData();
- }
- public function run($callback = null)
- {
- $this->start($callback);
- return $this->wait();
- }
- public function mustRun($callback = null)
- {
- if ($this->isSigchildEnabled() && !$this->enhanceSigchildCompatibility) {
- throw new RuntimeException('This PHP has been compiled with --enable-sigchild. You must use setEnhanceSigchildCompatibility() to use this method.');
- }
- if (0 !== $this->run($callback)) {
- throw new ProcessFailedException($this);
- }
- return $this;
- }
- public function start($callback = null)
- {
- if ($this->isRunning()) {
- throw new RuntimeException('Process is already running');
- }
- if ($this->outputDisabled && null !== $callback) {
- throw new LogicException('Output has been disabled, enable it to allow the use of a callback.');
- }
- $this->resetProcessData();
- $this->starttime = $this->lastOutputTime = microtime(true);
- $this->callback = $this->buildCallback($callback);
- $descriptors = $this->getDescriptors();
- $commandline = $this->commandline;
- if ('\\' === DIRECTORY_SEPARATOR && $this->enhanceWindowsCompatibility) {
- $commandline = 'cmd /V:ON /E:ON /C "('.$commandline.')';
- foreach ($this->processPipes->getFiles() as $offset => $filename) {
- $commandline .= ' '.$offset.'>'.ProcessUtils::escapeArgument($filename);
- }
- $commandline .= '"';
- if (!isset($this->options['bypass_shell'])) {
- $this->options['bypass_shell'] = true;
- }
- }
- $this->process = proc_open($commandline, $descriptors, $this->processPipes->pipes, $this->cwd, $this->env, $this->options);
- if (!is_resource($this->process)) {
- throw new RuntimeException('Unable to launch a new process.');
- }
- $this->status = self::STATUS_STARTED;
- if ($this->tty) {
- return;
- }
- $this->updateStatus(false);
- $this->checkTimeout();
- }
- public function restart($callback = null)
- {
- if ($this->isRunning()) {
- throw new RuntimeException('Process is already running');
- }
- $process = clone $this;
- $process->start($callback);
- return $process;
- }
- public function wait($callback = null)
- {
- $this->requireProcessIsStarted(__FUNCTION__);
- $this->updateStatus(false);
- if (null !== $callback) {
- $this->callback = $this->buildCallback($callback);
- }
- do {
- $this->checkTimeout();
- $running = '\\' === DIRECTORY_SEPARATOR ? $this->isRunning() : $this->processPipes->areOpen();
- $close = '\\' !== DIRECTORY_SEPARATOR || !$running;
- $this->readPipes(true, $close);
- } while ($running);
- while ($this->isRunning()) {
- usleep(1000);
- }
- if ($this->processInformation['signaled'] && $this->processInformation['termsig'] !== $this->latestSignal) {
- throw new RuntimeException(sprintf('The process has been signaled with signal "%s".', $this->processInformation['termsig']));
- }
- return $this->exitcode;
- }
- public function getPid()
- {
- if ($this->isSigchildEnabled()) {
- throw new RuntimeException('This PHP has been compiled with --enable-sigchild. The process identifier can not be retrieved.');
- }
- $this->updateStatus(false);
- return $this->isRunning() ? $this->processInformation['pid'] : null;
- }
- public function signal($signal)
- {
- $this->doSignal($signal, true);
- return $this;
- }
- public function disableOutput()
- {
- if ($this->isRunning()) {
- throw new RuntimeException('Disabling output while the process is running is not possible.');
- }
- if (null !== $this->idleTimeout) {
- throw new LogicException('Output can not be disabled while an idle timeout is set.');
- }
- $this->outputDisabled = true;
- return $this;
- }
- public function enableOutput()
- {
- if ($this->isRunning()) {
- throw new RuntimeException('Enabling output while the process is running is not possible.');
- }
- $this->outputDisabled = false;
- return $this;
- }
- public function isOutputDisabled()
- {
- return $this->outputDisabled;
- }
- public function getOutput()
- {
- if ($this->outputDisabled) {
- throw new LogicException('Output has been disabled.');
- }
- $this->requireProcessIsStarted(__FUNCTION__);
- $this->readPipes(false, '\\' === DIRECTORY_SEPARATOR ? !$this->processInformation['running'] : true);
- return $this->stdout;
- }
- public function getIncrementalOutput()
- {
- $this->requireProcessIsStarted(__FUNCTION__);
- $data = $this->getOutput();
- $latest = substr($data, $this->incrementalOutputOffset);
- if (false === $latest) {
- return '';
- }
- $this->incrementalOutputOffset = strlen($data);
- return $latest;
- }
- public function clearOutput()
- {
- $this->stdout = '';
- $this->incrementalOutputOffset = 0;
- return $this;
- }
- public function getErrorOutput()
- {
- if ($this->outputDisabled) {
- throw new LogicException('Output has been disabled.');
- }
- $this->requireProcessIsStarted(__FUNCTION__);
- $this->readPipes(false, '\\' === DIRECTORY_SEPARATOR ? !$this->processInformation['running'] : true);
- return $this->stderr;
- }
- public function getIncrementalErrorOutput()
- {
- $this->requireProcessIsStarted(__FUNCTION__);
- $data = $this->getErrorOutput();
- $latest = substr($data, $this->incrementalErrorOutputOffset);
- if (false === $latest) {
- return '';
- }
- $this->incrementalErrorOutputOffset = strlen($data);
- return $latest;
- }
- public function clearErrorOutput()
- {
- $this->stderr = '';
- $this->incrementalErrorOutputOffset = 0;
- return $this;
- }
- public function getExitCode()
- {
- if ($this->isSigchildEnabled() && !$this->enhanceSigchildCompatibility) {
- throw new RuntimeException('This PHP has been compiled with --enable-sigchild. You must use setEnhanceSigchildCompatibility() to use this method.');
- }
- $this->updateStatus(false);
- return $this->exitcode;
- }
- public function getExitCodeText()
- {
- if (null === $exitcode = $this->getExitCode()) {
- return;
- }
- return isset(self::$exitCodes[$exitcode]) ? self::$exitCodes[$exitcode] : 'Unknown error';
- }
- public function isSuccessful()
- {
- return 0 === $this->getExitCode();
- }
- public function hasBeenSignaled()
- {
- $this->requireProcessIsTerminated(__FUNCTION__);
- if ($this->isSigchildEnabled()) {
- throw new RuntimeException('This PHP has been compiled with --enable-sigchild. Term signal can not be retrieved.');
- }
- $this->updateStatus(false);
- return $this->processInformation['signaled'];
- }
- public function getTermSignal()
- {
- $this->requireProcessIsTerminated(__FUNCTION__);
- if ($this->isSigchildEnabled()) {
- throw new RuntimeException('This PHP has been compiled with --enable-sigchild. Term signal can not be retrieved.');
- }
- $this->updateStatus(false);
- return $this->processInformation['termsig'];
- }
- public function hasBeenStopped()
- {
- $this->requireProcessIsTerminated(__FUNCTION__);
- $this->updateStatus(false);
- return $this->processInformation['stopped'];
- }
- public function getStopSignal()
- {
- $this->requireProcessIsTerminated(__FUNCTION__);
- $this->updateStatus(false);
- return $this->processInformation['stopsig'];
- }
- public function isRunning()
- {
- if (self::STATUS_STARTED !== $this->status) {
- return false;
- }
- $this->updateStatus(false);
- return $this->processInformation['running'];
- }
- public function isStarted()
- {
- return $this->status != self::STATUS_READY;
- }
- public function isTerminated()
- {
- $this->updateStatus(false);
- return $this->status == self::STATUS_TERMINATED;
- }
- public function getStatus()
- {
- $this->updateStatus(false);
- return $this->status;
- }
- public function stop($timeout = 10, $signal = null)
- {
- $timeoutMicro = microtime(true) + $timeout;
- if ($this->isRunning()) {
- if ('\\' === DIRECTORY_SEPARATOR && !$this->isSigchildEnabled()) {
- exec(sprintf("taskkill /F /T /PID %d 2>&1", $this->getPid()), $output, $exitCode);
- if ($exitCode > 0) {
- throw new RuntimeException('Unable to kill the process');
- }
- }
- $this->doSignal(15, false);
- do {
- usleep(1000);
- } while ($this->isRunning() && microtime(true) < $timeoutMicro);
- if ($this->isRunning() && !$this->isSigchildEnabled()) {
- if (null !== $signal || defined('SIGKILL')) {
-
-
-
- $this->doSignal($signal ?: SIGKILL, false);
- }
- }
- }
- $this->updateStatus(false);
- if ($this->processInformation['running']) {
- $this->close();
- }
- return $this->exitcode;
- }
- public function addOutput($line)
- {
- $this->lastOutputTime = microtime(true);
- $this->stdout .= $line;
- }
- public function addErrorOutput($line)
- {
- $this->lastOutputTime = microtime(true);
- $this->stderr .= $line;
- }
- public function getCommandLine()
- {
- return $this->commandline;
- }
- public function setCommandLine($commandline)
- {
- $this->commandline = $commandline;
- return $this;
- }
- public function getTimeout()
- {
- return $this->timeout;
- }
- public function getIdleTimeout()
- {
- return $this->idleTimeout;
- }
- public function setTimeout($timeout)
- {
- $this->timeout = $this->validateTimeout($timeout);
- return $this;
- }
- public function setIdleTimeout($timeout)
- {
- if (null !== $timeout && $this->outputDisabled) {
- throw new LogicException('Idle timeout can not be set while the output is disabled.');
- }
- $this->idleTimeout = $this->validateTimeout($timeout);
- return $this;
- }
- public function setTty($tty)
- {
- if ('\\' === DIRECTORY_SEPARATOR && $tty) {
- throw new RuntimeException('TTY mode is not supported on Windows platform.');
- }
- $this->tty = (bool) $tty;
- return $this;
- }
- public function isTty()
- {
- return $this->tty;
- }
- public function setPty($bool)
- {
- $this->pty = (bool) $bool;
- return $this;
- }
- public function isPty()
- {
- return $this->pty;
- }
- public function getWorkingDirectory()
- {
- if (null === $this->cwd) {
-
- return getcwd() ?: null;
- }
- return $this->cwd;
- }
- public function setWorkingDirectory($cwd)
- {
- $this->cwd = $cwd;
- return $this;
- }
- public function getEnv()
- {
- return $this->env;
- }
- public function setEnv(array $env)
- {
- $env = array_filter($env, function ($value) {
- return !is_array($value);
- });
- $this->env = array();
- foreach ($env as $key => $value) {
- $this->env[(binary) $key] = (binary) $value;
- }
- return $this;
- }
- public function getStdin()
- {
- return $this->getInput();
- }
- public function getInput()
- {
- return $this->input;
- }
- public function setStdin($stdin)
- {
- return $this->setInput($stdin);
- }
- public function setInput($input)
- {
- if ($this->isRunning()) {
- throw new LogicException('Input can not be set while the process is running.');
- }
- $this->input = ProcessUtils::validateInput(sprintf('%s::%s', __CLASS__, __FUNCTION__), $input);
- return $this;
- }
- public function getOptions()
- {
- return $this->options;
- }
- public function setOptions(array $options)
- {
- $this->options = $options;
- return $this;
- }
- public function getEnhanceWindowsCompatibility()
- {
- return $this->enhanceWindowsCompatibility;
- }
- public function setEnhanceWindowsCompatibility($enhance)
- {
- $this->enhanceWindowsCompatibility = (bool) $enhance;
- return $this;
- }
- public function getEnhanceSigchildCompatibility()
- {
- return $this->enhanceSigchildCompatibility;
- }
- public function setEnhanceSigchildCompatibility($enhance)
- {
- $this->enhanceSigchildCompatibility = (bool) $enhance;
- return $this;
- }
- public function checkTimeout()
- {
- if ($this->status !== self::STATUS_STARTED) {
- return;
- }
- if (null !== $this->timeout && $this->timeout < microtime(true) - $this->starttime) {
- $this->stop(0);
- throw new ProcessTimedOutException($this, ProcessTimedOutException::TYPE_GENERAL);
- }
- if (null !== $this->idleTimeout && $this->idleTimeout < microtime(true) - $this->lastOutputTime) {
- $this->stop(0);
- throw new ProcessTimedOutException($this, ProcessTimedOutException::TYPE_IDLE);
- }
- }
- public static function isPtySupported()
- {
- static $result;
- if (null !== $result) {
- return $result;
- }
- if ('\\' === DIRECTORY_SEPARATOR) {
- return $result = false;
- }
- $proc = @proc_open('echo 1', array(array('pty'), array('pty'), array('pty')), $pipes);
- if (is_resource($proc)) {
- proc_close($proc);
- return $result = true;
- }
- return $result = false;
- }
- private function getDescriptors()
- {
- if ('\\' === DIRECTORY_SEPARATOR) {
- $this->processPipes = WindowsPipes::create($this, $this->input);
- } else {
- $this->processPipes = UnixPipes::create($this, $this->input);
- }
- $descriptors = $this->processPipes->getDescriptors($this->outputDisabled);
- if (!$this->useFileHandles && $this->enhanceSigchildCompatibility && $this->isSigchildEnabled()) {
- $descriptors = array_merge($descriptors, array(array('pipe', 'w')));
- $this->commandline = '('.$this->commandline.') 3>/dev/null; code=$?; echo $code >&3; exit $code';
- }
- return $descriptors;
- }
- protected function buildCallback($callback)
- {
- $that = $this;
- $out = self::OUT;
- $callback = function ($type, $data) use ($that, $callback, $out) {
- if ($out == $type) {
- $that->addOutput($data);
- } else {
- $that->addErrorOutput($data);
- }
- if (null !== $callback) {
- call_user_func($callback, $type, $data);
- }
- };
- return $callback;
- }
- protected function updateStatus($blocking)
- {
- if (self::STATUS_STARTED !== $this->status) {
- return;
- }
- $this->processInformation = proc_get_status($this->process);
- $this->captureExitCode();
- $this->readPipes($blocking, '\\' === DIRECTORY_SEPARATOR ? !$this->processInformation['running'] : true);
- if (!$this->processInformation['running']) {
- $this->close();
- }
- }
- protected function isSigchildEnabled()
- {
- if (null !== self::$sigchild) {
- return self::$sigchild;
- }
- if (!function_exists('phpinfo')) {
- return self::$sigchild = false;
- }
- ob_start();
- phpinfo(INFO_GENERAL);
- return self::$sigchild = false !== strpos(ob_get_clean(), '--enable-sigchild');
- }
- private function validateTimeout($timeout)
- {
- $timeout = (float) $timeout;
- if (0.0 === $timeout) {
- $timeout = null;
- } elseif ($timeout < 0) {
- throw new InvalidArgumentException('The timeout value must be a valid positive integer or float number.');
- }
- return $timeout;
- }
- private function readPipes($blocking, $close)
- {
- $result = $this->processPipes->readAndWrite($blocking, $close);
- $callback = $this->callback;
- foreach ($result as $type => $data) {
- if (3 == $type) {
- $this->fallbackExitcode = (int) $data;
- } else {
- $callback($type === self::STDOUT ? self::OUT : self::ERR, $data);
- }
- }
- }
- private function captureExitCode()
- {
- if (isset($this->processInformation['exitcode']) && -1 != $this->processInformation['exitcode']) {
- $this->exitcode = $this->processInformation['exitcode'];
- }
- }
- private function close()
- {
- $this->processPipes->close();
- if (is_resource($this->process)) {
- $exitcode = proc_close($this->process);
- } else {
- $exitcode = -1;
- }
- $this->exitcode = -1 !== $exitcode ? $exitcode : (null !== $this->exitcode ? $this->exitcode : -1);
- $this->status = self::STATUS_TERMINATED;
- if (-1 === $this->exitcode && null !== $this->fallbackExitcode) {
- $this->exitcode = $this->fallbackExitcode;
- } elseif (-1 === $this->exitcode && $this->processInformation['signaled'] && 0 < $this->processInformation['termsig']) {
- $this->exitcode = 128 + $this->processInformation['termsig'];
- }
- return $this->exitcode;
- }
- private function resetProcessData()
- {
- $this->starttime = null;
- $this->callback = null;
- $this->exitcode = null;
- $this->fallbackExitcode = null;
- $this->processInformation = null;
- $this->stdout = null;
- $this->stderr = null;
- $this->process = null;
- $this->latestSignal = null;
- $this->status = self::STATUS_READY;
- $this->incrementalOutputOffset = 0;
- $this->incrementalErrorOutputOffset = 0;
- }
- private function doSignal($signal, $throwException)
- {
- if (!$this->isRunning()) {
- if ($throwException) {
- throw new LogicException('Can not send signal on a non running process.');
- }
- return false;
- }
- if ($this->isSigchildEnabled()) {
- if ($throwException) {
- throw new RuntimeException('This PHP has been compiled with --enable-sigchild. The process can not be signaled.');
- }
- return false;
- }
- if (true !== @proc_terminate($this->process, $signal)) {
- if ($throwException) {
- throw new RuntimeException(sprintf('Error while sending signal `%s`.', $signal));
- }
- return false;
- }
- $this->latestSignal = $signal;
- return true;
- }
- private function requireProcessIsStarted($functionName)
- {
- if (!$this->isStarted()) {
- throw new LogicException(sprintf('Process must be started before calling %s.', $functionName));
- }
- }
- private function requireProcessIsTerminated($functionName)
- {
- if (!$this->isTerminated()) {
- throw new LogicException(sprintf('Process must be terminated before calling %s.', $functionName));
- }
- }
- }
- <?php
- namespace Symfony\Component\Process;
- use Symfony\Component\Process\Exception\InvalidArgumentException;
- use Symfony\Component\Process\Exception\LogicException;
- class ProcessBuilder
- {
- private $arguments;
- private $cwd;
- private $env = array();
- private $input;
- private $timeout = 60;
- private $options = array();
- private $inheritEnv = true;
- private $prefix = array();
- private $outputDisabled = false;
- public function __construct(array $arguments = array())
- {
- $this->arguments = $arguments;
- }
- public static function create(array $arguments = array())
- {
- return new static($arguments);
- }
- public function add($argument)
- {
- $this->arguments[] = $argument;
- return $this;
- }
- public function setPrefix($prefix)
- {
- $this->prefix = is_array($prefix) ? $prefix : array($prefix);
- return $this;
- }
- public function setArguments(array $arguments)
- {
- $this->arguments = $arguments;
- return $this;
- }
- public function setWorkingDirectory($cwd)
- {
- $this->cwd = $cwd;
- return $this;
- }
- public function inheritEnvironmentVariables($inheritEnv = true)
- {
- $this->inheritEnv = $inheritEnv;
- return $this;
- }
- public function setEnv($name, $value)
- {
- $this->env[$name] = $value;
- return $this;
- }
- public function addEnvironmentVariables(array $variables)
- {
- $this->env = array_replace($this->env, $variables);
- return $this;
- }
- public function setInput($input)
- {
- $this->input = ProcessUtils::validateInput(sprintf('%s::%s', __CLASS__, __FUNCTION__), $input);
- return $this;
- }
- public function setTimeout($timeout)
- {
- if (null === $timeout) {
- $this->timeout = null;
- return $this;
- }
- $timeout = (float) $timeout;
- if ($timeout < 0) {
- throw new InvalidArgumentException('The timeout value must be a valid positive integer or float number.');
- }
- $this->timeout = $timeout;
- return $this;
- }
- public function setOption($name, $value)
- {
- $this->options[$name] = $value;
- return $this;
- }
- public function disableOutput()
- {
- $this->outputDisabled = true;
- return $this;
- }
- public function enableOutput()
- {
- $this->outputDisabled = false;
- return $this;
- }
- public function getProcess()
- {
- if (0 === count($this->prefix) && 0 === count($this->arguments)) {
- throw new LogicException('You must add() command arguments before calling getProcess().');
- }
- $options = $this->options;
- $arguments = array_merge($this->prefix, $this->arguments);
- $script = implode(' ', array_map(array(__NAMESPACE__.'\\ProcessUtils', 'escapeArgument'), $arguments));
- if ($this->inheritEnv) {
- $env = array_replace($_ENV, $_SERVER, $this->env);
- } else {
- $env = $this->env;
- }
- $process = new Process($script, $this->cwd, $env, $this->input, $this->timeout, $options);
- if ($this->outputDisabled) {
- $process->disableOutput();
- }
- return $process;
- }
- }
- <?php
- namespace Symfony\Component\Process;
- use Symfony\Component\Process\Exception\InvalidArgumentException;
- class ProcessUtils
- {
- private function __construct()
- {
- }
- public static function escapeArgument($argument)
- {
-
-
-
- if ('\\' === DIRECTORY_SEPARATOR) {
- if ('' === $argument) {
- return escapeshellarg($argument);
- }
- $escapedArgument = '';
- $quote = false;
- foreach (preg_split('/(")/i', $argument, -1, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE) as $part) {
- if ('"' === $part) {
- $escapedArgument .= '\\"';
- } elseif (self::isSurroundedBy($part, '%')) {
- $escapedArgument .= '^%"'.substr($part, 1, -1).'"^%';
- } else {
- if ('\\' === substr($part, -1)) {
- $part .= '\\';
- }
- $quote = true;
- $escapedArgument .= $part;
- }
- }
- if ($quote) {
- $escapedArgument = '"'.$escapedArgument.'"';
- }
- return $escapedArgument;
- }
- return escapeshellarg($argument);
- }
- public static function validateInput($caller, $input)
- {
- if (null !== $input) {
- if (is_resource($input)) {
- return $input;
- }
- if (is_scalar($input)) {
- return (string) $input;
- }
- if (is_object($input) && method_exists($input, '__toString')) {
- return (string) $input;
- }
- throw new InvalidArgumentException(sprintf('%s only accepts strings or stream resources.', $caller));
- }
- return $input;
- }
- private static function isSurroundedBy($arg, $char)
- {
- return 2 < strlen($arg) && $char === $arg[0] && $char === $arg[strlen($arg) - 1];
- }
- }
- <?php
- namespace Symfony\Component\Yaml;
- class Dumper
- {
- protected $indentation = 4;
- public function setIndentation($num)
- {
- $this->indentation = (int) $num;
- }
- public function dump($input, $inline = 0, $indent = 0, $exceptionOnInvalidType = false, $objectSupport = false)
- {
- $output = '';
- $prefix = $indent ? str_repeat(' ', $indent) : '';
- if ($inline <= 0 || !is_array($input) || empty($input)) {
- $output .= $prefix.Inline::dump($input, $exceptionOnInvalidType, $objectSupport);
- } else {
- $isAHash = array_keys($input) !== range(0, count($input) - 1);
- foreach ($input as $key => $value) {
- $willBeInlined = $inline - 1 <= 0 || !is_array($value) || empty($value);
- $output .= sprintf('%s%s%s%s',
- $prefix,
- $isAHash ? Inline::dump($key, $exceptionOnInvalidType, $objectSupport).':' : '-',
- $willBeInlined ? ' ' : "\n",
- $this->dump($value, $inline - 1, $willBeInlined ? 0 : $indent + $this->indentation, $exceptionOnInvalidType, $objectSupport)
- ).($willBeInlined ? "\n" : '');
- }
- }
- return $output;
- }
- }
- <?php
- namespace Symfony\Component\Yaml;
- class Escaper
- {
- const REGEX_CHARACTER_TO_ESCAPE = "[\\x00-\\x1f]|\xc2\x85|\xc2\xa0|\xe2\x80\xa8|\xe2\x80\xa9";
-
-
-
- private static $escapees = array('\\', '\\\\', '\\"', '"',
- "\x00", "\x01", "\x02", "\x03", "\x04", "\x05", "\x06", "\x07",
- "\x08", "\x09", "\x0a", "\x0b", "\x0c", "\x0d", "\x0e", "\x0f",
- "\x10", "\x11", "\x12", "\x13", "\x14", "\x15", "\x16", "\x17",
- "\x18", "\x19", "\x1a", "\x1b", "\x1c", "\x1d", "\x1e", "\x1f",
- "\xc2\x85", "\xc2\xa0", "\xe2\x80\xa8", "\xe2\x80\xa9",);
- private static $escaped = array('\\\\', '\\"', '\\\\', '\\"',
- "\\0", "\\x01", "\\x02", "\\x03", "\\x04", "\\x05", "\\x06", "\\a",
- "\\b", "\\t", "\\n", "\\v", "\\f", "\\r", "\\x0e", "\\x0f",
- "\\x10", "\\x11", "\\x12", "\\x13", "\\x14", "\\x15", "\\x16", "\\x17",
- "\\x18", "\\x19", "\\x1a", "\\e", "\\x1c", "\\x1d", "\\x1e", "\\x1f",
- "\\N", "\\_", "\\L", "\\P",);
- public static function requiresDoubleQuoting($value)
- {
- return preg_match('/'.self::REGEX_CHARACTER_TO_ESCAPE.'/u', $value);
- }
- public static function escapeWithDoubleQuotes($value)
- {
- return sprintf('"%s"', str_replace(self::$escapees, self::$escaped, $value));
- }
- public static function requiresSingleQuoting($value)
- {
-
- if (in_array(strtolower($value), array('null', '~', 'true', 'false', 'y', 'n', 'yes', 'no', 'on', 'off'))) {
- return true;
- }
-
- return preg_match('/[ \s \' " \: \{ \} \[ \] , & \* \# \?] | \A[ \- ? | < > = ! % @ ` ]/x', $value);
- }
- public static function escapeWithSingleQuotes($value)
- {
- return sprintf("'%s'", str_replace('\'', '\'\'', $value));
- }
- }
- <?php
- namespace Symfony\Component\Yaml\Exception;
- class DumpException extends RuntimeException
- {
- }
- <?php
- namespace Symfony\Component\Yaml\Exception;
- interface ExceptionInterface
- {
- }
- <?php
- namespace Symfony\Component\Yaml\Exception;
- class ParseException extends RuntimeException
- {
- private $parsedFile;
- private $parsedLine;
- private $snippet;
- private $rawMessage;
- public function __construct($message, $parsedLine = -1, $snippet = null, $parsedFile = null, \Exception $previous = null)
- {
- $this->parsedFile = $parsedFile;
- $this->parsedLine = $parsedLine;
- $this->snippet = $snippet;
- $this->rawMessage = $message;
- $this->updateRepr();
- parent::__construct($this->message, 0, $previous);
- }
- public function getSnippet()
- {
- return $this->snippet;
- }
- public function setSnippet($snippet)
- {
- $this->snippet = $snippet;
- $this->updateRepr();
- }
- public function getParsedFile()
- {
- return $this->parsedFile;
- }
- public function setParsedFile($parsedFile)
- {
- $this->parsedFile = $parsedFile;
- $this->updateRepr();
- }
- public function getParsedLine()
- {
- return $this->parsedLine;
- }
- public function setParsedLine($parsedLine)
- {
- $this->parsedLine = $parsedLine;
- $this->updateRepr();
- }
- private function updateRepr()
- {
- $this->message = $this->rawMessage;
- $dot = false;
- if ('.' === substr($this->message, -1)) {
- $this->message = substr($this->message, 0, -1);
- $dot = true;
- }
- if (null !== $this->parsedFile) {
- if (PHP_VERSION_ID >= 50400) {
- $jsonOptions = JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE;
- } else {
- $jsonOptions = 0;
- }
- $this->message .= sprintf(' in %s', json_encode($this->parsedFile, $jsonOptions));
- }
- if ($this->parsedLine >= 0) {
- $this->message .= sprintf(' at line %d', $this->parsedLine);
- }
- if ($this->snippet) {
- $this->message .= sprintf(' (near "%s")', $this->snippet);
- }
- if ($dot) {
- $this->message .= '.';
- }
- }
- }
- <?php
- namespace Symfony\Component\Yaml\Exception;
- class RuntimeException extends \RuntimeException implements ExceptionInterface
- {
- }
- <?php
- namespace Symfony\Component\Yaml;
- use Symfony\Component\Yaml\Exception\ParseException;
- use Symfony\Component\Yaml\Exception\DumpException;
- class Inline
- {
- const REGEX_QUOTED_STRING = '(?:"([^"\\\\]*(?:\\\\.[^"\\\\]*)*)"|\'([^\']*(?:\'\'[^\']*)*)\')';
- private static $exceptionOnInvalidType = false;
- private static $objectSupport = false;
- private static $objectForMap = false;
- public static function parse($value, $exceptionOnInvalidType = false, $objectSupport = false, $objectForMap = false, $references = array())
- {
- self::$exceptionOnInvalidType = $exceptionOnInvalidType;
- self::$objectSupport = $objectSupport;
- self::$objectForMap = $objectForMap;
- $value = trim($value);
- if (0 == strlen($value)) {
- return '';
- }
- if (function_exists('mb_internal_encoding') && ((int) ini_get('mbstring.func_overload')) & 2) {
- $mbEncoding = mb_internal_encoding();
- mb_internal_encoding('ASCII');
- }
- $i = 0;
- switch ($value[0]) {
- case '[':
- $result = self::parseSequence($value, $i, $references);
- ++$i;
- break;
- case '{':
- $result = self::parseMapping($value, $i, $references);
- ++$i;
- break;
- default:
- $result = self::parseScalar($value, null, array('"', "'"), $i, true, $references);
- }
- if (preg_replace('/\s+#.*$/A', '', substr($value, $i))) {
- throw new ParseException(sprintf('Unexpected characters near "%s".', substr($value, $i)));
- }
- if (isset($mbEncoding)) {
- mb_internal_encoding($mbEncoding);
- }
- return $result;
- }
- public static function dump($value, $exceptionOnInvalidType = false, $objectSupport = false)
- {
- switch (true) {
- case is_resource($value):
- if ($exceptionOnInvalidType) {
- throw new DumpException(sprintf('Unable to dump PHP resources in a YAML file ("%s").', get_resource_type($value)));
- }
- return 'null';
- case is_object($value):
- if ($objectSupport) {
- return '!!php/object:'.serialize($value);
- }
- if ($exceptionOnInvalidType) {
- throw new DumpException('Object support when dumping a YAML file has been disabled.');
- }
- return 'null';
- case is_array($value):
- return self::dumpArray($value, $exceptionOnInvalidType, $objectSupport);
- case null === $value:
- return 'null';
- case true === $value:
- return 'true';
- case false === $value:
- return 'false';
- case ctype_digit($value):
- return is_string($value) ? "'$value'" : (int) $value;
- case is_numeric($value):
- $locale = setlocale(LC_NUMERIC, 0);
- if (false !== $locale) {
- setlocale(LC_NUMERIC, 'C');
- }
- if (is_float($value)) {
- $repr = strval($value);
- if (is_infinite($value)) {
- $repr = str_ireplace('INF', '.Inf', $repr);
- } elseif (floor($value) == $value && $repr == $value) {
- $repr = '!!float '.$repr;
- }
- } else {
- $repr = is_string($value) ? "'$value'" : strval($value);
- }
- if (false !== $locale) {
- setlocale(LC_NUMERIC, $locale);
- }
- return $repr;
- case '' == $value:
- return "''";
- case Escaper::requiresDoubleQuoting($value):
- return Escaper::escapeWithDoubleQuotes($value);
- case Escaper::requiresSingleQuoting($value):
- case preg_match(self::getTimestampRegex(), $value):
- return Escaper::escapeWithSingleQuotes($value);
- default:
- return $value;
- }
- }
- private static function dumpArray($value, $exceptionOnInvalidType, $objectSupport)
- {
- $keys = array_keys($value);
- if ((1 == count($keys) && '0' == $keys[0])
- || (count($keys) > 1 && array_reduce($keys, function ($v, $w) { return (int) $v + $w; }, 0) == count($keys) * (count($keys) - 1) / 2)
- ) {
- $output = array();
- foreach ($value as $val) {
- $output[] = self::dump($val, $exceptionOnInvalidType, $objectSupport);
- }
- return sprintf('[%s]', implode(', ', $output));
- }
- $output = array();
- foreach ($value as $key => $val) {
- $output[] = sprintf('%s: %s', self::dump($key, $exceptionOnInvalidType, $objectSupport), self::dump($val, $exceptionOnInvalidType, $objectSupport));
- }
- return sprintf('{ %s }', implode(', ', $output));
- }
- public static function parseScalar($scalar, $delimiters = null, $stringDelimiters = array('"', "'"), &$i = 0, $evaluate = true, $references = array())
- {
- if (in_array($scalar[$i], $stringDelimiters)) {
- $output = self::parseQuotedScalar($scalar, $i);
- if (null !== $delimiters) {
- $tmp = ltrim(substr($scalar, $i), ' ');
- if (!in_array($tmp[0], $delimiters)) {
- throw new ParseException(sprintf('Unexpected characters (%s).', substr($scalar, $i)));
- }
- }
- } else {
- if (!$delimiters) {
- $output = substr($scalar, $i);
- $i += strlen($output);
- if (false !== $strpos = strpos($output, ' #')) {
- $output = rtrim(substr($output, 0, $strpos));
- }
- } elseif (preg_match('/^(.+?)('.implode('|', $delimiters).')/', substr($scalar, $i), $match)) {
- $output = $match[1];
- $i += strlen($output);
- } else {
- throw new ParseException(sprintf('Malformed inline YAML string (%s).', $scalar));
- }
- if ($evaluate) {
- $output = self::evaluateScalar($output, $references);
- }
- }
- return $output;
- }
- private static function parseQuotedScalar($scalar, &$i)
- {
- if (!preg_match('/'.self::REGEX_QUOTED_STRING.'/Au', substr($scalar, $i), $match)) {
- throw new ParseException(sprintf('Malformed inline YAML string (%s).', substr($scalar, $i)));
- }
- $output = substr($match[0], 1, strlen($match[0]) - 2);
- $unescaper = new Unescaper();
- if ('"' == $scalar[$i]) {
- $output = $unescaper->unescapeDoubleQuotedString($output);
- } else {
- $output = $unescaper->unescapeSingleQuotedString($output);
- }
- $i += strlen($match[0]);
- return $output;
- }
- private static function parseSequence($sequence, &$i = 0, $references = array())
- {
- $output = array();
- $len = strlen($sequence);
- $i += 1;
- while ($i < $len) {
- switch ($sequence[$i]) {
- case '[':
- $output[] = self::parseSequence($sequence, $i, $references);
- break;
- case '{':
- $output[] = self::parseMapping($sequence, $i, $references);
- break;
- case ']':
- return $output;
- case ',':
- case ' ':
- break;
- default:
- $isQuoted = in_array($sequence[$i], array('"', "'"));
- $value = self::parseScalar($sequence, array(',', ']'), array('"', "'"), $i, true, $references);
- if (!is_array($value) && !$isQuoted && false !== strpos($value, ': ')) {
- try {
- $pos = 0;
- $value = self::parseMapping('{'.$value.'}', $pos, $references);
- } catch (\InvalidArgumentException $e) {
- }
- }
- $output[] = $value;
- --$i;
- }
- ++$i;
- }
- throw new ParseException(sprintf('Malformed inline YAML string %s', $sequence));
- }
- private static function parseMapping($mapping, &$i = 0, $references = array())
- {
- $output = array();
- $len = strlen($mapping);
- $i += 1;
- while ($i < $len) {
- switch ($mapping[$i]) {
- case ' ':
- case ',':
- ++$i;
- continue 2;
- case '}':
- if (self::$objectForMap) {
- return (object) $output;
- }
- return $output;
- }
- $key = self::parseScalar($mapping, array(':', ' '), array('"', "'"), $i, false);
- $done = false;
- while ($i < $len) {
- switch ($mapping[$i]) {
- case '[':
- $value = self::parseSequence($mapping, $i, $references);
-
-
- if (!isset($output[$key])) {
- $output[$key] = $value;
- }
- $done = true;
- break;
- case '{':
- $value = self::parseMapping($mapping, $i, $references);
-
-
- if (!isset($output[$key])) {
- $output[$key] = $value;
- }
- $done = true;
- break;
- case ':':
- case ' ':
- break;
- default:
- $value = self::parseScalar($mapping, array(',', '}'), array('"', "'"), $i, true, $references);
-
-
- if (!isset($output[$key])) {
- $output[$key] = $value;
- }
- $done = true;
- --$i;
- }
- ++$i;
- if ($done) {
- continue 2;
- }
- }
- }
- throw new ParseException(sprintf('Malformed inline YAML string %s', $mapping));
- }
- private static function evaluateScalar($scalar, $references = array())
- {
- $scalar = trim($scalar);
- $scalarLower = strtolower($scalar);
- if (0 === strpos($scalar, '*')) {
- if (false !== $pos = strpos($scalar, '#')) {
- $value = substr($scalar, 1, $pos - 2);
- } else {
- $value = substr($scalar, 1);
- }
- if (false === $value || '' === $value) {
- throw new ParseException('A reference must contain at least one character.');
- }
- if (!array_key_exists($value, $references)) {
- throw new ParseException(sprintf('Reference "%s" does not exist.', $value));
- }
- return $references[$value];
- }
- switch (true) {
- case 'null' === $scalarLower:
- case '' === $scalar:
- case '~' === $scalar:
- return;
- case 'true' === $scalarLower:
- return true;
- case 'false' === $scalarLower:
- return false;
- case $scalar[0] === '+' || $scalar[0] === '-' || $scalar[0] === '.' || $scalar[0] === '!' || is_numeric($scalar[0]):
- switch (true) {
- case 0 === strpos($scalar, '!str'):
- return (string) substr($scalar, 5);
- case 0 === strpos($scalar, '! '):
- return intval(self::parseScalar(substr($scalar, 2)));
- case 0 === strpos($scalar, '!!php/object:'):
- if (self::$objectSupport) {
- return unserialize(substr($scalar, 13));
- }
- if (self::$exceptionOnInvalidType) {
- throw new ParseException('Object support when parsing a YAML file has been disabled.');
- }
- return;
- case 0 === strpos($scalar, '!!float '):
- return (float) substr($scalar, 8);
- case ctype_digit($scalar):
- $raw = $scalar;
- $cast = intval($scalar);
- return '0' == $scalar[0] ? octdec($scalar) : (((string) $raw == (string) $cast) ? $cast : $raw);
- case '-' === $scalar[0] && ctype_digit(substr($scalar, 1)):
- $raw = $scalar;
- $cast = intval($scalar);
- return '0' == $scalar[1] ? octdec($scalar) : (((string) $raw == (string) $cast) ? $cast : $raw);
- case is_numeric($scalar):
- return '0x' == $scalar[0].$scalar[1] ? hexdec($scalar) : floatval($scalar);
- case '.inf' === $scalarLower:
- case '.nan' === $scalarLower:
- return -log(0);
- case '-.inf' === $scalarLower:
- return log(0);
- case preg_match('/^(-|\+)?[0-9,]+(\.[0-9]+)?$/', $scalar):
- return floatval(str_replace(',', '', $scalar));
- case preg_match(self::getTimestampRegex(), $scalar):
- return strtotime($scalar);
- }
- default:
- return (string) $scalar;
- }
- }
- private static function getTimestampRegex()
- {
- return <<<EOF
- ~^
- (?P<year>[0-9][0-9][0-9][0-9])
- -(?P<month>[0-9][0-9]?)
- -(?P<day>[0-9][0-9]?)
- (?:(?:[Tt]|[ \t]+)
- (?P<hour>[0-9][0-9]?)
- :(?P<minute>[0-9][0-9])
- :(?P<second>[0-9][0-9])
- (?:\.(?P<fraction>[0-9]*))?
- (?:[ \t]*(?P<tz>Z|(?P<tz_sign>[-+])(?P<tz_hour>[0-9][0-9]?)
- (?::(?P<tz_minute>[0-9][0-9]))?))?)?
- $~x
- EOF;
- }
- }
- Copyright (c) 2004-2015 Fabien Potencier
- Permission is hereby granted, free of charge, to any person obtaining a copy
- of this software and associated documentation files (the "Software"), to deal
- in the Software without restriction, including without limitation the rights
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- copies of the Software, and to permit persons to whom the Software is furnished
- to do so, subject to the following conditions:
- The above copyright notice and this permission notice shall be included in all
- copies or substantial portions of the Software.
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- THE SOFTWARE.
- <?php
- namespace Symfony\Component\Yaml;
- use Symfony\Component\Yaml\Exception\ParseException;
- class Parser
- {
- const FOLDED_SCALAR_PATTERN = '(?P<separator>\||>)(?P<modifiers>\+|\-|\d+|\+\d+|\-\d+|\d+\+|\d+\-)?(?P<comments> +#.*)?';
- private $offset = 0;
- private $lines = array();
- private $currentLineNb = -1;
- private $currentLine = '';
- private $refs = array();
- public function __construct($offset = 0)
- {
- $this->offset = $offset;
- }
- public function parse($value, $exceptionOnInvalidType = false, $objectSupport = false, $objectForMap = false)
- {
- $this->currentLineNb = -1;
- $this->currentLine = '';
- $this->lines = explode("\n", $this->cleanup($value));
- if (!preg_match('//u', $value)) {
- throw new ParseException('The YAML value does not appear to be valid UTF-8.');
- }
- if (function_exists('mb_internal_encoding') && ((int) ini_get('mbstring.func_overload')) & 2) {
- $mbEncoding = mb_internal_encoding();
- mb_internal_encoding('UTF-8');
- }
- $data = array();
- $context = null;
- $allowOverwrite = false;
- while ($this->moveToNextLine()) {
- if ($this->isCurrentLineEmpty()) {
- continue;
- }
- if ("\t" === $this->currentLine[0]) {
- throw new ParseException('A YAML file cannot contain tabs as indentation.', $this->getRealCurrentLineNb() + 1, $this->currentLine);
- }
- $isRef = $mergeNode = false;
- if (preg_match('#^\-((?P<leadspaces>\s+)(?P<value>.+?))?\s*$#u', $this->currentLine, $values)) {
- if ($context && 'mapping' == $context) {
- throw new ParseException('You cannot define a sequence item when in a mapping');
- }
- $context = 'sequence';
- if (isset($values['value']) && preg_match('#^&(?P<ref>[^ ]+) *(?P<value>.*)#u', $values['value'], $matches)) {
- $isRef = $matches['ref'];
- $values['value'] = $matches['value'];
- }
- if (!isset($values['value']) || '' == trim($values['value'], ' ') || 0 === strpos(ltrim($values['value'], ' '), '#')) {
- $c = $this->getRealCurrentLineNb() + 1;
- $parser = new Parser($c);
- $parser->refs = & $this->refs;
- $data[] = $parser->parse($this->getNextEmbedBlock(null, true), $exceptionOnInvalidType, $objectSupport, $objectForMap);
- } else {
- if (isset($values['leadspaces'])
- && preg_match('#^(?P<key>'.Inline::REGEX_QUOTED_STRING.'|[^ \'"\{\[].*?) *\:(\s+(?P<value>.+?))?\s*$#u', $values['value'], $matches)
- ) {
- $c = $this->getRealCurrentLineNb();
- $parser = new Parser($c);
- $parser->refs = & $this->refs;
- $block = $values['value'];
- if ($this->isNextLineIndented()) {
- $block .= "\n".$this->getNextEmbedBlock($this->getCurrentLineIndentation() + strlen($values['leadspaces']) + 1);
- }
- $data[] = $parser->parse($block, $exceptionOnInvalidType, $objectSupport, $objectForMap);
- } else {
- $data[] = $this->parseValue($values['value'], $exceptionOnInvalidType, $objectSupport, $objectForMap);
- }
- }
- } elseif (preg_match('#^(?P<key>'.Inline::REGEX_QUOTED_STRING.'|[^ \'"\[\{].*?) *\:(\s+(?P<value>.+?))?\s*$#u', $this->currentLine, $values) && (false === strpos($values['key'], ' #') || in_array($values['key'][0], array('"', "'")))) {
- if ($context && 'sequence' == $context) {
- throw new ParseException('You cannot define a mapping item when in a sequence');
- }
- $context = 'mapping';
- Inline::parse(null, $exceptionOnInvalidType, $objectSupport, $objectForMap, $this->refs);
- try {
- $key = Inline::parseScalar($values['key']);
- } catch (ParseException $e) {
- $e->setParsedLine($this->getRealCurrentLineNb() + 1);
- $e->setSnippet($this->currentLine);
- throw $e;
- }
- if ('<<' === $key) {
- $mergeNode = true;
- $allowOverwrite = true;
- if (isset($values['value']) && 0 === strpos($values['value'], '*')) {
- $refName = substr($values['value'], 1);
- if (!array_key_exists($refName, $this->refs)) {
- throw new ParseException(sprintf('Reference "%s" does not exist.', $refName), $this->getRealCurrentLineNb() + 1, $this->currentLine);
- }
- $refValue = $this->refs[$refName];
- if (!is_array($refValue)) {
- throw new ParseException('YAML merge keys used with a scalar value instead of an array.', $this->getRealCurrentLineNb() + 1, $this->currentLine);
- }
- foreach ($refValue as $key => $value) {
- if (!isset($data[$key])) {
- $data[$key] = $value;
- }
- }
- } else {
- if (isset($values['value']) && $values['value'] !== '') {
- $value = $values['value'];
- } else {
- $value = $this->getNextEmbedBlock();
- }
- $c = $this->getRealCurrentLineNb() + 1;
- $parser = new Parser($c);
- $parser->refs = & $this->refs;
- $parsed = $parser->parse($value, $exceptionOnInvalidType, $objectSupport, $objectForMap);
- if (!is_array($parsed)) {
- throw new ParseException('YAML merge keys used with a scalar value instead of an array.', $this->getRealCurrentLineNb() + 1, $this->currentLine);
- }
- if (isset($parsed[0])) {
-
-
- foreach ($parsed as $parsedItem) {
- if (!is_array($parsedItem)) {
- throw new ParseException('Merge items must be arrays.', $this->getRealCurrentLineNb() + 1, $parsedItem);
- }
- foreach ($parsedItem as $key => $value) {
- if (!isset($data[$key])) {
- $data[$key] = $value;
- }
- }
- }
- } else {
-
- foreach ($parsed as $key => $value) {
- if (!isset($data[$key])) {
- $data[$key] = $value;
- }
- }
- }
- }
- } elseif (isset($values['value']) && preg_match('#^&(?P<ref>[^ ]+) *(?P<value>.*)#u', $values['value'], $matches)) {
- $isRef = $matches['ref'];
- $values['value'] = $matches['value'];
- }
- if ($mergeNode) {
- } elseif (!isset($values['value']) || '' == trim($values['value'], ' ') || 0 === strpos(ltrim($values['value'], ' '), '#')) {
-
- if (!$this->isNextLineIndented() && !$this->isNextLineUnIndentedCollection()) {
-
- if ($allowOverwrite || !isset($data[$key])) {
- $data[$key] = null;
- }
- } else {
- $c = $this->getRealCurrentLineNb() + 1;
- $parser = new Parser($c);
- $parser->refs = & $this->refs;
- $value = $parser->parse($this->getNextEmbedBlock(), $exceptionOnInvalidType, $objectSupport, $objectForMap);
-
- if ($allowOverwrite || !isset($data[$key])) {
- $data[$key] = $value;
- }
- }
- } else {
- $value = $this->parseValue($values['value'], $exceptionOnInvalidType, $objectSupport, $objectForMap);
-
- if ($allowOverwrite || !isset($data[$key])) {
- $data[$key] = $value;
- }
- }
- } else {
- if ('---' === $this->currentLine) {
- throw new ParseException('Multiple documents are not supported.');
- }
- $lineCount = count($this->lines);
- if (1 === $lineCount || (2 === $lineCount && empty($this->lines[1]))) {
- try {
- $value = Inline::parse($this->lines[0], $exceptionOnInvalidType, $objectSupport, $objectForMap, $this->refs);
- } catch (ParseException $e) {
- $e->setParsedLine($this->getRealCurrentLineNb() + 1);
- $e->setSnippet($this->currentLine);
- throw $e;
- }
- if (is_array($value)) {
- $first = reset($value);
- if (is_string($first) && 0 === strpos($first, '*')) {
- $data = array();
- foreach ($value as $alias) {
- $data[] = $this->refs[substr($alias, 1)];
- }
- $value = $data;
- }
- }
- if (isset($mbEncoding)) {
- mb_internal_encoding($mbEncoding);
- }
- return $value;
- }
- switch (preg_last_error()) {
- case PREG_INTERNAL_ERROR:
- $error = 'Internal PCRE error.';
- break;
- case PREG_BACKTRACK_LIMIT_ERROR:
- $error = 'pcre.backtrack_limit reached.';
- break;
- case PREG_RECURSION_LIMIT_ERROR:
- $error = 'pcre.recursion_limit reached.';
- break;
- case PREG_BAD_UTF8_ERROR:
- $error = 'Malformed UTF-8 data.';
- break;
- case PREG_BAD_UTF8_OFFSET_ERROR:
- $error = 'Offset doesn\'t correspond to the begin of a valid UTF-8 code point.';
- break;
- default:
- $error = 'Unable to parse.';
- }
- throw new ParseException($error, $this->getRealCurrentLineNb() + 1, $this->currentLine);
- }
- if ($isRef) {
- $this->refs[$isRef] = end($data);
- }
- }
- if (isset($mbEncoding)) {
- mb_internal_encoding($mbEncoding);
- }
- return empty($data) ? null : $data;
- }
- private function getRealCurrentLineNb()
- {
- return $this->currentLineNb + $this->offset;
- }
- private function getCurrentLineIndentation()
- {
- return strlen($this->currentLine) - strlen(ltrim($this->currentLine, ' '));
- }
- private function getNextEmbedBlock($indentation = null, $inSequence = false)
- {
- $oldLineIndentation = $this->getCurrentLineIndentation();
- if (!$this->moveToNextLine()) {
- return;
- }
- if (null === $indentation) {
- $newIndent = $this->getCurrentLineIndentation();
- $unindentedEmbedBlock = $this->isStringUnIndentedCollectionItem($this->currentLine);
- if (!$this->isCurrentLineEmpty() && 0 === $newIndent && !$unindentedEmbedBlock) {
- throw new ParseException('Indentation problem.', $this->getRealCurrentLineNb() + 1, $this->currentLine);
- }
- } else {
- $newIndent = $indentation;
- }
- $data = array();
- if ($this->getCurrentLineIndentation() >= $newIndent) {
- $data[] = substr($this->currentLine, $newIndent);
- } else {
- $this->moveToPreviousLine();
- return;
- }
- if ($inSequence && $oldLineIndentation === $newIndent && '-' === $data[0][0]) {
-
- $this->moveToPreviousLine();
- return;
- }
- $isItUnindentedCollection = $this->isStringUnIndentedCollectionItem($this->currentLine);
- $removeCommentsPattern = '~'.self::FOLDED_SCALAR_PATTERN.'$~';
- $removeComments = !preg_match($removeCommentsPattern, $this->currentLine);
- while ($this->moveToNextLine()) {
- $indent = $this->getCurrentLineIndentation();
- if ($indent === $newIndent) {
- $removeComments = !preg_match($removeCommentsPattern, $this->currentLine);
- }
- if ($isItUnindentedCollection && !$this->isStringUnIndentedCollectionItem($this->currentLine) && $newIndent === $indent) {
- $this->moveToPreviousLine();
- break;
- }
- if ($this->isCurrentLineBlank()) {
- $data[] = substr($this->currentLine, $newIndent);
- continue;
- }
- if ($removeComments && $this->isCurrentLineComment()) {
- continue;
- }
- if ($indent >= $newIndent) {
- $data[] = substr($this->currentLine, $newIndent);
- } elseif (0 == $indent) {
- $this->moveToPreviousLine();
- break;
- } else {
- throw new ParseException('Indentation problem.', $this->getRealCurrentLineNb() + 1, $this->currentLine);
- }
- }
- return implode("\n", $data);
- }
- private function moveToNextLine()
- {
- if ($this->currentLineNb >= count($this->lines) - 1) {
- return false;
- }
- $this->currentLine = $this->lines[++$this->currentLineNb];
- return true;
- }
- private function moveToPreviousLine()
- {
- $this->currentLine = $this->lines[--$this->currentLineNb];
- }
- private function parseValue($value, $exceptionOnInvalidType, $objectSupport, $objectForMap)
- {
- if (0 === strpos($value, '*')) {
- if (false !== $pos = strpos($value, '#')) {
- $value = substr($value, 1, $pos - 2);
- } else {
- $value = substr($value, 1);
- }
- if (!array_key_exists($value, $this->refs)) {
- throw new ParseException(sprintf('Reference "%s" does not exist.', $value), $this->currentLine);
- }
- return $this->refs[$value];
- }
- if (preg_match('/^'.self::FOLDED_SCALAR_PATTERN.'$/', $value, $matches)) {
- $modifiers = isset($matches['modifiers']) ? $matches['modifiers'] : '';
- return $this->parseFoldedScalar($matches['separator'], preg_replace('#\d+#', '', $modifiers), intval(abs($modifiers)));
- }
- try {
- return Inline::parse($value, $exceptionOnInvalidType, $objectSupport, $objectForMap, $this->refs);
- } catch (ParseException $e) {
- $e->setParsedLine($this->getRealCurrentLineNb() + 1);
- $e->setSnippet($this->currentLine);
- throw $e;
- }
- }
- private function parseFoldedScalar($separator, $indicator = '', $indentation = 0)
- {
- $notEOF = $this->moveToNextLine();
- if (!$notEOF) {
- return '';
- }
- $isCurrentLineBlank = $this->isCurrentLineBlank();
- $text = '';
- while ($notEOF && $isCurrentLineBlank) {
- if ($notEOF = $this->moveToNextLine()) {
- $text .= "\n";
- $isCurrentLineBlank = $this->isCurrentLineBlank();
- }
- }
- if (0 === $indentation) {
- if (preg_match('/^ +/', $this->currentLine, $matches)) {
- $indentation = strlen($matches[0]);
- }
- }
- if ($indentation > 0) {
- $pattern = sprintf('/^ {%d}(.*)$/', $indentation);
- while (
- $notEOF && (
- $isCurrentLineBlank ||
- preg_match($pattern, $this->currentLine, $matches)
- )
- ) {
- if ($isCurrentLineBlank) {
- $text .= substr($this->currentLine, $indentation);
- } else {
- $text .= $matches[1];
- }
- if ($notEOF = $this->moveToNextLine()) {
- $text .= "\n";
- $isCurrentLineBlank = $this->isCurrentLineBlank();
- }
- }
- } elseif ($notEOF) {
- $text .= "\n";
- }
- if ($notEOF) {
- $this->moveToPreviousLine();
- }
- if ('>' === $separator) {
- preg_match('/(\n*)$/', $text, $matches);
- $text = preg_replace('/(?<!\n)\n(?!\n)/', ' ', rtrim($text, "\n"));
- $text .= $matches[1];
- }
- if ('' === $indicator) {
- $text = preg_replace('/\n+$/s', "\n", $text);
- } elseif ('-' === $indicator) {
- $text = preg_replace('/\n+$/s', '', $text);
- }
- return $text;
- }
- private function isNextLineIndented()
- {
- $currentIndentation = $this->getCurrentLineIndentation();
- $EOF = !$this->moveToNextLine();
- while (!$EOF && $this->isCurrentLineEmpty()) {
- $EOF = !$this->moveToNextLine();
- }
- if ($EOF) {
- return false;
- }
- $ret = false;
- if ($this->getCurrentLineIndentation() > $currentIndentation) {
- $ret = true;
- }
- $this->moveToPreviousLine();
- return $ret;
- }
- private function isCurrentLineEmpty()
- {
- return $this->isCurrentLineBlank() || $this->isCurrentLineComment();
- }
- private function isCurrentLineBlank()
- {
- return '' == trim($this->currentLine, ' ');
- }
- private function isCurrentLineComment()
- {
- $ltrimmedLine = ltrim($this->currentLine, ' ');
- return $ltrimmedLine[0] === '#';
- }
- private function cleanup($value)
- {
- $value = str_replace(array("\r\n", "\r"), "\n", $value);
- $count = 0;
- $value = preg_replace('#^\%YAML[: ][\d\.]+.*\n#u', '', $value, -1, $count);
- $this->offset += $count;
- $trimmedValue = preg_replace('#^(\#.*?\n)+#s', '', $value, -1, $count);
- if ($count == 1) {
- $this->offset += substr_count($value, "\n") - substr_count($trimmedValue, "\n");
- $value = $trimmedValue;
- }
- $trimmedValue = preg_replace('#^\-\-\-.*?\n#s', '', $value, -1, $count);
- if ($count == 1) {
- $this->offset += substr_count($value, "\n") - substr_count($trimmedValue, "\n");
- $value = $trimmedValue;
- $value = preg_replace('#\.\.\.\s*$#s', '', $value);
- }
- return $value;
- }
- private function isNextLineUnIndentedCollection()
- {
- $currentIndentation = $this->getCurrentLineIndentation();
- $notEOF = $this->moveToNextLine();
- while ($notEOF && $this->isCurrentLineEmpty()) {
- $notEOF = $this->moveToNextLine();
- }
- if (false === $notEOF) {
- return false;
- }
- $ret = false;
- if (
- $this->getCurrentLineIndentation() == $currentIndentation
- &&
- $this->isStringUnIndentedCollectionItem($this->currentLine)
- ) {
- $ret = true;
- }
- $this->moveToPreviousLine();
- return $ret;
- }
- private function isStringUnIndentedCollectionItem()
- {
- return (0 === strpos($this->currentLine, '- '));
- }
- }
- <?php
- namespace Symfony\Component\Yaml;
- class Unescaper
- {
-
-
- const ENCODING = 'UTF-8';
-
- const REGEX_ESCAPED_CHARACTER = "\\\\([0abt\tnvfre \\\"\\/\\\\N_LP]|x[0-9a-fA-F]{2}|u[0-9a-fA-F]{4}|U[0-9a-fA-F]{8})";
- public function unescapeSingleQuotedString($value)
- {
- return str_replace('\'\'', '\'', $value);
- }
- public function unescapeDoubleQuotedString($value)
- {
- $self = $this;
- $callback = function ($match) use ($self) {
- return $self->unescapeCharacter($match[0]);
- };
- return preg_replace_callback('/'.self::REGEX_ESCAPED_CHARACTER.'/u', $callback, $value);
- }
- public function unescapeCharacter($value)
- {
- switch ($value{1}) {
- case '0':
- return "\x0";
- case 'a':
- return "\x7";
- case 'b':
- return "\x8";
- case 't':
- return "\t";
- case "\t":
- return "\t";
- case 'n':
- return "\n";
- case 'v':
- return "\xB";
- case 'f':
- return "\xC";
- case 'r':
- return "\r";
- case 'e':
- return "\x1B";
- case ' ':
- return ' ';
- case '"':
- return '"';
- case '/':
- return '/';
- case '\\':
- return '\\';
- case 'N':
- return "\xC2\x85";
- case '_':
- return "\xC2\xA0";
- case 'L':
- return "\xE2\x80\xA8";
- case 'P':
- return "\xE2\x80\xA9";
- case 'x':
- return self::utf8chr(hexdec(substr($value, 2, 2)));
- case 'u':
- return self::utf8chr(hexdec(substr($value, 2, 4)));
- case 'U':
- return self::utf8chr(hexdec(substr($value, 2, 8)));
- }
- }
- private static function utf8chr($c)
- {
- if (0x80 > $c %= 0x200000) {
- return chr($c);
- }
- if (0x800 > $c) {
- return chr(0xC0 | $c >> 6).chr(0x80 | $c & 0x3F);
- }
- if (0x10000 > $c) {
- return chr(0xE0 | $c >> 12).chr(0x80 | $c >> 6 & 0x3F).chr(0x80 | $c & 0x3F);
- }
- return chr(0xF0 | $c >> 18).chr(0x80 | $c >> 12 & 0x3F).chr(0x80 | $c >> 6 & 0x3F).chr(0x80 | $c & 0x3F);
- }
- }
- <?php
- namespace Symfony\Component\Yaml;
- use Symfony\Component\Yaml\Exception\ParseException;
- class Yaml
- {
- public static function parse($input, $exceptionOnInvalidType = false, $objectSupport = false)
- {
- $file = '';
- if (strpos($input, "\n") === false && is_file($input)) {
- if (false === is_readable($input)) {
- throw new ParseException(sprintf('Unable to parse "%s" as the file is not readable.', $input));
- }
- $file = $input;
- $input = file_get_contents($file);
- }
- $yaml = new Parser();
- try {
- return $yaml->parse($input, $exceptionOnInvalidType, $objectSupport);
- } catch (ParseException $e) {
- if ($file) {
- $e->setParsedFile($file);
- }
- throw $e;
- }
- }
- public static function dump($array, $inline = 2, $indent = 4, $exceptionOnInvalidType = false, $objectSupport = false)
- {
- $yaml = new Dumper();
- $yaml->setIndentation($indent);
- return $yaml->dump($array, $inline, 0, $exceptionOnInvalidType, $objectSupport);
- }
- }
- Copyright (c) 2011 Jordi Boggiano
- Permission is hereby granted, free of charge, to any person obtaining a copy
- of this software and associated documentation files (the "Software"), to deal
- in the Software without restriction, including without limitation the rights
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- copies of the Software, and to permit persons to whom the Software is furnished
- to do so, subject to the following conditions:
- The above copyright notice and this permission notice shall be included in all
- copies or substantial portions of the Software.
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- THE SOFTWARE.
- <?php
- namespace Seld\JsonLint;
- use stdClass;
- class JsonParser
- {
- const DETECT_KEY_CONFLICTS = 1;
- const ALLOW_DUPLICATE_KEYS = 2;
- const PARSE_TO_ASSOC = 4;
- private $lexer;
- private $flags;
- private $stack;
- private $vstack;
- private $lstack;
- private $symbols = array(
- 'error' => 2,
- 'JSONString' => 3,
- 'STRING' => 4,
- 'JSONNumber' => 5,
- 'NUMBER' => 6,
- 'JSONNullLiteral' => 7,
- 'NULL' => 8,
- 'JSONBooleanLiteral' => 9,
- 'TRUE' => 10,
- 'FALSE' => 11,
- 'JSONText' => 12,
- 'JSONValue' => 13,
- 'EOF' => 14,
- 'JSONObject' => 15,
- 'JSONArray' => 16,
- '{' => 17,
- '}' => 18,
- 'JSONMemberList' => 19,
- 'JSONMember' => 20,
- ':' => 21,
- ',' => 22,
- '[' => 23,
- ']' => 24,
- 'JSONElementList' => 25,
- '$accept' => 0,
- '$end' => 1,
- );
- private $terminals_ = array(
- 2 => "error",
- 4 => "STRING",
- 6 => "NUMBER",
- 8 => "NULL",
- 10 => "TRUE",
- 11 => "FALSE",
- 14 => "EOF",
- 17 => "{",
- 18 => "}",
- 21 => ":",
- 22 => ",",
- 23 => "[",
- 24 => "]",
- );
- private $productions_ = array(
- 0,
- array(3, 1),
- array(5, 1),
- array(7, 1),
- array(9, 1),
- array(9, 1),
- array(12, 2),
- array(13, 1),
- array(13, 1),
- array(13, 1),
- array(13, 1),
- array(13, 1),
- array(13, 1),
- array(15, 2),
- array(15, 3),
- array(20, 3),
- array(19, 1),
- array(19, 3),
- array(16, 2),
- array(16, 3),
- array(25, 1),
- array(25, 3)
- );
- private $table = array(array(3 => 5, 4 => array(1,12), 5 => 6, 6 => array(1,13), 7 => 3, 8 => array(1,9), 9 => 4, 10 => array(1,10), 11 => array(1,11), 12 => 1, 13 => 2, 15 => 7, 16 => 8, 17 => array(1,14), 23 => array(1,15)), array( 1 => array(3)), array( 14 => array(1,16)), array( 14 => array(2,7), 18 => array(2,7), 22 => array(2,7), 24 => array(2,7)), array( 14 => array(2,8), 18 => array(2,8), 22 => array(2,8), 24 => array(2,8)), array( 14 => array(2,9), 18 => array(2,9), 22 => array(2,9), 24 => array(2,9)), array( 14 => array(2,10), 18 => array(2,10), 22 => array(2,10), 24 => array(2,10)), array( 14 => array(2,11), 18 => array(2,11), 22 => array(2,11), 24 => array(2,11)), array( 14 => array(2,12), 18 => array(2,12), 22 => array(2,12), 24 => array(2,12)), array( 14 => array(2,3), 18 => array(2,3), 22 => array(2,3), 24 => array(2,3)), array( 14 => array(2,4), 18 => array(2,4), 22 => array(2,4), 24 => array(2,4)), array( 14 => array(2,5), 18 => array(2,5), 22 => array(2,5), 24 => array(2,5)), array( 14 => array(2,1), 18 => array(2,1), 21 => array(2,1), 22 => array(2,1), 24 => array(2,1)), array( 14 => array(2,2), 18 => array(2,2), 22 => array(2,2), 24 => array(2,2)), array( 3 => 20, 4 => array(1,12), 18 => array(1,17), 19 => 18, 20 => 19 ), array( 3 => 5, 4 => array(1,12), 5 => 6, 6 => array(1,13), 7 => 3, 8 => array(1,9), 9 => 4, 10 => array(1,10), 11 => array(1,11), 13 => 23, 15 => 7, 16 => 8, 17 => array(1,14), 23 => array(1,15), 24 => array(1,21), 25 => 22 ), array( 1 => array(2,6)), array( 14 => array(2,13), 18 => array(2,13), 22 => array(2,13), 24 => array(2,13)), array( 18 => array(1,24), 22 => array(1,25)), array( 18 => array(2,16), 22 => array(2,16)), array( 21 => array(1,26)), array( 14 => array(2,18), 18 => array(2,18), 22 => array(2,18), 24 => array(2,18)), array( 22 => array(1,28), 24 => array(1,27)), array( 22 => array(2,20), 24 => array(2,20)), array( 14 => array(2,14), 18 => array(2,14), 22 => array(2,14), 24 => array(2,14)), array( 3 => 20, 4 => array(1,12), 20 => 29 ), array( 3 => 5, 4 => array(1,12), 5 => 6, 6 => array(1,13), 7 => 3, 8 => array(1,9), 9 => 4, 10 => array(1,10), 11 => array(1,11), 13 => 30, 15 => 7, 16 => 8, 17 => array(1,14), 23 => array(1,15)), array( 14 => array(2,19), 18 => array(2,19), 22 => array(2,19), 24 => array(2,19)), array( 3 => 5, 4 => array(1,12), 5 => 6, 6 => array(1,13), 7 => 3, 8 => array(1,9), 9 => 4, 10 => array(1,10), 11 => array(1,11), 13 => 31, 15 => 7, 16 => 8, 17 => array(1,14), 23 => array(1,15)), array( 18 => array(2,17), 22 => array(2,17)), array( 18 => array(2,15), 22 => array(2,15)), array( 22 => array(2,21), 24 => array(2,21)),
- );
- private $defaultActions = array(
- 16 => array(2, 6)
- );
- public function lint($input)
- {
- try {
- $this->parse($input);
- } catch (ParsingException $e) {
- return $e;
- }
- }
- public function parse($input, $flags = 0)
- {
- $this->failOnBOM($input);
- $this->flags = $flags;
- $this->stack = array(0);
- $this->vstack = array(null);
- $this->lstack = array();
- $yytext = '';
- $yylineno = 0;
- $yyleng = 0;
- $recovering = 0;
- $TERROR = 2;
- $EOF = 1;
- $this->lexer = new Lexer();
- $this->lexer->setInput($input);
- $yyloc = $this->lexer->yylloc;
- $this->lstack[] = $yyloc;
- $symbol = null;
- $preErrorSymbol = null;
- $state = null;
- $action = null;
- $a = null;
- $r = null;
- $yyval = new stdClass;
- $p = null;
- $len = null;
- $newState = null;
- $expected = null;
- $errStr = null;
- while (true) {
- $state = $this->stack[count($this->stack)-1];
- if (isset($this->defaultActions[$state])) {
- $action = $this->defaultActions[$state];
- } else {
- if ($symbol == null) {
- $symbol = $this->lex();
- }
- $action = isset($this->table[$state][$symbol]) ? $this->table[$state][$symbol] : false;
- }
- if (!$action || !$action[0]) {
- if (!$recovering) {
- $expected = array();
- foreach ($this->table[$state] as $p => $ignore) {
- if (isset($this->terminals_[$p]) && $p > 2) {
- $expected[] = "'" . $this->terminals_[$p] . "'";
- }
- }
- $message = null;
- if (in_array("'STRING'", $expected) && in_array(substr($this->lexer->match, 0, 1), array('"', "'"))) {
- $message = "Invalid string";
- if ("'" === substr($this->lexer->match, 0, 1)) {
- $message .= ", it appears you used single quotes instead of double quotes";
- } elseif (preg_match('{".+?(\\\\[^"bfnrt/\\\\u])}', $this->lexer->getUpcomingInput(), $match)) {
- $message .= ", it appears you have an unescaped backslash at: ".$match[1];
- } elseif (preg_match('{"(?:[^"]+|\\\\")*$}m', $this->lexer->getUpcomingInput())) {
- $message .= ", it appears you forgot to terminated the string, or attempted to write a multiline string which is invalid";
- }
- }
- $errStr = 'Parse error on line ' . ($yylineno+1) . ":\n";
- $errStr .= $this->lexer->showPosition() . "\n";
- if ($message) {
- $errStr .= $message;
- } else {
- $errStr .= (count($expected) > 1) ? "Expected one of: " : "Expected: ";
- $errStr .= implode(', ', $expected);
- }
- if (',' === substr(trim($this->lexer->getPastInput()), -1)) {
- $errStr .= " - It appears you have an extra trailing comma";
- }
- $this->parseError($errStr, array(
- 'text' => $this->lexer->match,
- 'token' => !empty($this->terminals_[$symbol]) ? $this->terminals_[$symbol] : $symbol,
- 'line' => $this->lexer->yylineno,
- 'loc' => $yyloc,
- 'expected' => $expected,
- ));
- }
- if ($recovering == 3) {
- if ($symbol == $EOF) {
- throw new ParsingException($errStr ?: 'Parsing halted.');
- }
- $yyleng = $this->lexer->yyleng;
- $yytext = $this->lexer->yytext;
- $yylineno = $this->lexer->yylineno;
- $yyloc = $this->lexer->yylloc;
- $symbol = $this->lex();
- }
- while (true) {
- if (array_key_exists($TERROR, $this->table[$state])) {
- break;
- }
- if ($state == 0) {
- throw new ParsingException($errStr ?: 'Parsing halted.');
- }
- $this->popStack(1);
- $state = $this->stack[count($this->stack)-1];
- }
- $preErrorSymbol = $symbol;
- $symbol = $TERROR;
- $state = $this->stack[count($this->stack)-1];
- $action = isset($this->table[$state][$TERROR]) ? $this->table[$state][$TERROR] : false;
- $recovering = 3;
- }
- if (is_array($action[0]) && count($action) > 1) {
- throw new ParsingException('Parse Error: multiple actions possible at state: ' . $state . ', token: ' . $symbol);
- }
- switch ($action[0]) {
- case 1:
- $this->stack[] = $symbol;
- $this->vstack[] = $this->lexer->yytext;
- $this->lstack[] = $this->lexer->yylloc;
- $this->stack[] = $action[1];
- $symbol = null;
- if (!$preErrorSymbol) {
- $yyleng = $this->lexer->yyleng;
- $yytext = $this->lexer->yytext;
- $yylineno = $this->lexer->yylineno;
- $yyloc = $this->lexer->yylloc;
- if ($recovering > 0) {
- $recovering--;
- }
- } else {
- $symbol = $preErrorSymbol;
- $preErrorSymbol = null;
- }
- break;
- case 2:
- $len = $this->productions_[$action[1]][1];
- $yyval->token = $this->vstack[count($this->vstack) - $len];
-
- $yyval->store = array(
- 'first_line' => $this->lstack[count($this->lstack) - ($len ?: 1)]['first_line'],
- 'last_line' => $this->lstack[count($this->lstack) - 1]['last_line'],
- 'first_column' => $this->lstack[count($this->lstack) - ($len ?: 1)]['first_column'],
- 'last_column' => $this->lstack[count($this->lstack) - 1]['last_column'],
- );
- $r = $this->performAction($yyval, $yytext, $yyleng, $yylineno, $action[1], $this->vstack, $this->lstack);
- if (!$r instanceof Undefined) {
- return $r;
- }
- if ($len) {
- $this->popStack($len);
- }
- $this->stack[] = $this->productions_[$action[1]][0];
- $this->vstack[] = $yyval->token;
- $this->lstack[] = $yyval->store;
- $newState = $this->table[$this->stack[count($this->stack)-2]][$this->stack[count($this->stack)-1]];
- $this->stack[] = $newState;
- break;
- case 3:
- return true;
- }
- }
- return true;
- }
- protected function parseError($str, $hash)
- {
- throw new ParsingException($str, $hash);
- }
-
-
- private function performAction(stdClass $yyval, $yytext, $yyleng, $yylineno, $yystate, &$tokens)
- {
- $len = count($tokens) - 1;
- switch ($yystate) {
- case 1:
- $yytext = preg_replace_callback('{(?:\\\\["bfnrt/\\\\]|\\\\u[a-fA-F0-9]{4})}', array($this, 'stringInterpolation'), $yytext);
- $yyval->token = $yytext;
- break;
- case 2:
- if (strpos($yytext, 'e') !== false || strpos($yytext, 'E') !== false) {
- $yyval->token = floatval($yytext);
- } else {
- $yyval->token = strpos($yytext, '.') === false ? intval($yytext) : floatval($yytext);
- }
- break;
- case 3:
- $yyval->token = null;
- break;
- case 4:
- $yyval->token = true;
- break;
- case 5:
- $yyval->token = false;
- break;
- case 6:
- return $yyval->token = $tokens[$len-1];
- case 13:
- if ($this->flags & self::PARSE_TO_ASSOC) {
- $yyval->token = array();
- } else {
- $yyval->token = new stdClass;
- }
- break;
- case 14:
- $yyval->token = $tokens[$len-1];
- break;
- case 15:
- $yyval->token = array($tokens[$len-2], $tokens[$len]);
- break;
- case 16:
- $property = $tokens[$len][0] === '' ? '_empty_' : $tokens[$len][0];
- if ($this->flags & self::PARSE_TO_ASSOC) {
- $yyval->token = array();
- $yyval->token[$property] = $tokens[$len][1];
- } else {
- $yyval->token = new stdClass;
- $yyval->token->$property = $tokens[$len][1];
- }
- break;
- case 17:
- if ($this->flags & self::PARSE_TO_ASSOC) {
- $yyval->token =& $tokens[$len-2];
- $key = $tokens[$len][0];
- if (($this->flags & self::DETECT_KEY_CONFLICTS) && isset($tokens[$len-2][$key])) {
- $errStr = 'Parse error on line ' . ($yylineno+1) . ":\n";
- $errStr .= $this->lexer->showPosition() . "\n";
- $errStr .= "Duplicate key: ".$tokens[$len][0];
- throw new ParsingException($errStr);
- } elseif (($this->flags & self::ALLOW_DUPLICATE_KEYS) && isset($tokens[$len-2][$key])) {
- $duplicateCount = 1;
- do {
- $duplicateKey = $key . '.' . $duplicateCount++;
- } while (isset($tokens[$len-2][$duplicateKey]));
- $key = $duplicateKey;
- }
- $tokens[$len-2][$key] = $tokens[$len][1];
- } else {
- $yyval->token = $tokens[$len-2];
- $key = $tokens[$len][0] === '' ? '_empty_' : $tokens[$len][0];
- if (($this->flags & self::DETECT_KEY_CONFLICTS) && isset($tokens[$len-2]->{$key})) {
- $errStr = 'Parse error on line ' . ($yylineno+1) . ":\n";
- $errStr .= $this->lexer->showPosition() . "\n";
- $errStr .= "Duplicate key: ".$tokens[$len][0];
- throw new ParsingException($errStr);
- } elseif (($this->flags & self::ALLOW_DUPLICATE_KEYS) && isset($tokens[$len-2]->{$key})) {
- $duplicateCount = 1;
- do {
- $duplicateKey = $key . '.' . $duplicateCount++;
- } while (isset($tokens[$len-2]->$duplicateKey));
- $key = $duplicateKey;
- }
- $tokens[$len-2]->$key = $tokens[$len][1];
- }
- break;
- case 18:
- $yyval->token = array();
- break;
- case 19:
- $yyval->token = $tokens[$len-1];
- break;
- case 20:
- $yyval->token = array($tokens[$len]);
- break;
- case 21:
- $tokens[$len-2][] = $tokens[$len];
- $yyval->token = $tokens[$len-2];
- break;
- }
- return new Undefined();
- }
- private function stringInterpolation($match)
- {
- switch ($match[0]) {
- case '\\\\':
- return '\\';
- case '\"':
- return '"';
- case '\b':
- return chr(8);
- case '\f':
- return chr(12);
- case '\n':
- return "\n";
- case '\r':
- return "\r";
- case '\t':
- return "\t";
- case '\/':
- return "/";
- default:
- return html_entity_decode('&#x'.ltrim(substr($match[0], 2), '0').';', 0, 'UTF-8');
- }
- }
- private function popStack($n)
- {
- $this->stack = array_slice($this->stack, 0, - (2 * $n));
- $this->vstack = array_slice($this->vstack, 0, - $n);
- $this->lstack = array_slice($this->lstack, 0, - $n);
- }
- private function lex()
- {
- $token = $this->lexer->lex() ?: 1;
-
- if (!is_numeric($token)) {
- $token = isset($this->symbols[$token]) ? $this->symbols[$token] : $token;
- }
- return $token;
- }
- private function failOnBOM($input)
- {
- $bom = "\xEF\xBB\xBF";
- if (substr($input, 0, 3) === $bom) {
- $this->parseError("BOM detected, make sure your input does not include a Unicode Byte-Order-Mark", array());
- }
- }
- }
- <?php
- namespace Seld\JsonLint;
- class Lexer
- {
- private $EOF = 1;
- private $rules = array(
- 0 => '/^\s+/',
- 1 => '/^-?([0-9]|[1-9][0-9]+)(\.[0-9]+)?([eE][+-]?[0-9]+)?\b/',
- 2 => '{^"(?:\\\\["bfnrt/\\\\]|\\\\u[a-fA-F0-9]{4}|[^\0-\x09\x0a-\x1f\\\\"]+)*"}',
- 3 => '/^\{/',
- 4 => '/^\}/',
- 5 => '/^\[/',
- 6 => '/^\]/',
- 7 => '/^,/',
- 8 => '/^:/',
- 9 => '/^true\b/',
- 10 => '/^false\b/',
- 11 => '/^null\b/',
- 12 => '/^$/',
- 13 => '/^./',
- );
- private $conditions = array(
- "INITIAL" => array(
- "rules" => array(0,1,2,3,4,5,6,7,8,9,10,11,12,13),
- "inclusive" => true,
- ),
- );
- private $conditionStack;
- private $input;
- private $more;
- private $done;
- private $matched;
- public $match;
- public $yylineno;
- public $yyleng;
- public $yytext;
- public $yylloc;
- public function lex()
- {
- $r = $this->next();
- if (!$r instanceof Undefined) {
- return $r;
- }
- return $this->lex();
- }
- public function setInput($input)
- {
- $this->input = $input;
- $this->more = false;
- $this->done = false;
- $this->yylineno = $this->yyleng = 0;
- $this->yytext = $this->matched = $this->match = '';
- $this->conditionStack = array('INITIAL');
- $this->yylloc = array('first_line' => 1, 'first_column' => 0, 'last_line' => 1, 'last_column' => 0);
- return $this;
- }
- public function showPosition()
- {
- $pre = str_replace("\n", '', $this->getPastInput());
- $c = str_repeat('-', max(0, strlen($pre) - 1));
- return $pre . str_replace("\n", '', $this->getUpcomingInput()) . "\n" . $c . "^";
- }
- public function getPastInput()
- {
- $past = substr($this->matched, 0, strlen($this->matched) - strlen($this->match));
- return (strlen($past) > 20 ? '...' : '') . substr($past, -20);
- }
- public function getUpcomingInput()
- {
- $next = $this->match;
- if (strlen($next) < 20) {
- $next .= substr($this->input, 0, 20 - strlen($next));
- }
- return substr($next, 0, 20) . (strlen($next) > 20 ? '...' : '');
- }
- protected function parseError($str, $hash)
- {
- throw new \Exception($str);
- }
- private function next()
- {
- if ($this->done) {
- return $this->EOF;
- }
- if (!$this->input) {
- $this->done = true;
- }
- $token = null;
- $match = null;
- $col = null;
- $lines = null;
- if (!$this->more) {
- $this->yytext = '';
- $this->match = '';
- }
- $rules = $this->getCurrentRules();
- $rulesLen = count($rules);
- for ($i=0; $i < $rulesLen; $i++) {
- if (preg_match($this->rules[$rules[$i]], $this->input, $match)) {
- preg_match_all('/\n.*/', $match[0], $lines);
- $lines = $lines[0];
- if ($lines) {
- $this->yylineno += count($lines);
- }
- $this->yylloc = array(
- 'first_line' => $this->yylloc['last_line'],
- 'last_line' => $this->yylineno+1,
- 'first_column' => $this->yylloc['last_column'],
- 'last_column' => $lines ? strlen($lines[count($lines) - 1]) - 1 : $this->yylloc['last_column'] + strlen($match[0]),
- );
- $this->yytext .= $match[0];
- $this->match .= $match[0];
- $this->yyleng = strlen($this->yytext);
- $this->more = false;
- $this->input = substr($this->input, strlen($match[0]));
- $this->matched .= $match[0];
- $token = $this->performAction($rules[$i], $this->conditionStack[count($this->conditionStack)-1]);
- if ($token) {
- return $token;
- }
- return new Undefined();
- }
- }
- if ($this->input === "") {
- return $this->EOF;
- }
- $this->parseError(
- 'Lexical error on line ' . ($this->yylineno+1) . ". Unrecognized text.\n" . $this->showPosition(),
- array(
- 'text' => "",
- 'token' => null,
- 'line' => $this->yylineno,
- )
- );
- }
- private function getCurrentRules()
- {
- return $this->conditions[$this->conditionStack[count($this->conditionStack)-1]]['rules'];
- }
- private function performAction($avoiding_name_collisions, $YY_START)
- {
- switch ($avoiding_name_collisions) {
- case 0:
- break;
- case 1:
- return 6;
- break;
- case 2:
- $this->yytext = substr($this->yytext, 1, $this->yyleng-2);
- return 4;
- case 3:
- return 17;
- case 4:
- return 18;
- case 5:
- return 23;
- case 6:
- return 24;
- case 7:
- return 22;
- case 8:
- return 21;
- case 9:
- return 10;
- case 10:
- return 11;
- case 11:
- return 8;
- case 12:
- return 14;
- case 13:
- return 'INVALID';
- }
- }
- }
- <?php
- namespace Seld\JsonLint;
- class ParsingException extends \Exception
- {
- protected $details;
- public function __construct($message, $details = array())
- {
- $this->details = $details;
- parent::__construct($message);
- }
- public function getDetails()
- {
- return $this->details;
- }
- }
- <?php
- namespace Seld\JsonLint;
- class Undefined
- {
- }
- Copyright (c) 2008, Gradua Networks
- Author: Bruno Prieto Reis
- All rights reserved.
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions are met:
- * Redistributions of source code must retain the above copyright notice, this
- list of conditions and the following disclaimer.
- * Redistributions in binary form must reproduce the above copyright notice,
- this list of conditions and the following disclaimer in the documentation
- and/or other materials provided with the distribution.
- * Neither the name of the Gradua Networks nor the names of its contributors
- may be used to endorse or promote products derived from this software
- without specific prior written permission.
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
- FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
- CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- <?php
- namespace JsonSchema\Constraints;
- class Collection extends Constraint
- {
- public function check($value, $schema = null, $path = null, $i = null)
- {
- if (isset($schema->minItems) && count($value) < $schema->minItems) {
- $this->addError($path, "There must be a minimum of " . $schema->minItems . " in the array");
- }
- if (isset($schema->maxItems) && count($value) > $schema->maxItems) {
- $this->addError($path, "There must be a maximum of " . $schema->maxItems . " in the array");
- }
- if (isset($schema->uniqueItems)) {
- $unique = $value;
- if (is_array($value) && count($value)) {
- $unique = array_map(function($e) { return var_export($e, true); }, $value);
- }
- if (count(array_unique($unique)) != count($value)) {
- $this->addError($path, "There are no duplicates allowed in the array");
- }
- }
- if (isset($schema->items)) {
- $this->validateItems($value, $schema, $path, $i);
- }
- }
- protected function validateItems($value, $schema = null, $path = null, $i = null)
- {
- if (is_object($schema->items)) {
- foreach ($value as $k => $v) {
- $initErrors = $this->getErrors();
- $this->checkUndefined($v, $schema->items, $path, $k);
- if (count($initErrors) < count($this->getErrors()) && (isset($schema->additionalItems) && $schema->additionalItems !== false)) {
- $secondErrors = $this->getErrors();
- $this->checkUndefined($v, $schema->additionalItems, $path, $k);
- }
- if (isset($secondErrors) && count($secondErrors) < count($this->getErrors())) {
- $this->errors = $secondErrors;
- } else if (isset($secondErrors) && count($secondErrors) === count($this->getErrors())) {
- $this->errors = $initErrors;
- }
- }
- } else {
- foreach ($value as $k => $v) {
- if (array_key_exists($k, $schema->items)) {
- $this->checkUndefined($v, $schema->items[$k], $path, $k);
- } else {
- if (property_exists($schema, 'additionalItems')) {
- if ($schema->additionalItems !== false) {
- $this->checkUndefined($v, $schema->additionalItems, $path, $k);
- } else {
- $this->addError(
- $path, 'The item ' . $i . '[' . $k . '] is not defined and the definition does not allow additional items');
- }
- } else {
- $this->checkUndefined($v, new \stdClass(), $path, $k);
- }
- }
- }
- if(count($value) > 0) {
- for ($k = count($value); $k < count($schema->items); $k++) {
- $this->checkUndefined(new Undefined(), $schema->items[$k], $path, $k);
- }
- }
- }
- }
- }<?php
- namespace JsonSchema\Constraints;
- use JsonSchema\Uri\UriRetriever;
- abstract class Constraint implements ConstraintInterface
- {
- protected $checkMode = self::CHECK_MODE_NORMAL;
- protected $uriRetriever;
- protected $errors = array();
- protected $inlineSchemaProperty = '$schema';
- const CHECK_MODE_NORMAL = 1;
- const CHECK_MODE_TYPE_CAST = 2;
- public function __construct($checkMode = self::CHECK_MODE_NORMAL, UriRetriever $uriRetriever = null)
- {
- $this->checkMode = $checkMode;
- $this->uriRetriever = $uriRetriever;
- }
- public function getUriRetriever()
- {
- if (is_null($this->uriRetriever))
- {
- $this->setUriRetriever(new UriRetriever);
- }
- return $this->uriRetriever;
- }
- public function setUriRetriever(UriRetriever $uriRetriever)
- {
- $this->uriRetriever = $uriRetriever;
- }
- public function addError($path, $message)
- {
- $this->errors[] = array(
- 'property' => $path,
- 'message' => $message
- );
- }
- public function addErrors(array $errors)
- {
- $this->errors = array_merge($this->errors, $errors);
- }
- public function getErrors()
- {
- return $this->errors;
- }
- public function isValid()
- {
- return !$this->getErrors();
- }
- public function reset()
- {
- $this->errors = array();
- }
- protected function incrementPath($path, $i)
- {
- if ($path !== '') {
- if (is_int($i)) {
- $path .= '[' . $i . ']';
- } elseif ($i == '') {
- $path .= '';
- } else {
- $path .= '.' . $i;
- }
- } else {
- $path = $i;
- }
- return $path;
- }
- protected function checkArray($value, $schema = null, $path = null, $i = null)
- {
- $validator = new Collection($this->checkMode, $this->uriRetriever);
- $validator->check($value, $schema, $path, $i);
- $this->addErrors($validator->getErrors());
- }
- protected function checkObject($value, $schema = null, $path = null, $i = null, $patternProperties = null)
- {
- $validator = new Object($this->checkMode, $this->uriRetriever);
- $validator->check($value, $schema, $path, $i, $patternProperties);
- $this->addErrors($validator->getErrors());
- }
- protected function checkType($value, $schema = null, $path = null, $i = null)
- {
- $validator = new Type($this->checkMode, $this->uriRetriever);
- $validator->check($value, $schema, $path, $i);
- $this->addErrors($validator->getErrors());
- }
- protected function checkUndefined($value, $schema = null, $path = null, $i = null)
- {
- $validator = new Undefined($this->checkMode, $this->uriRetriever);
- $validator->check($value, $schema, $path, $i);
- $this->addErrors($validator->getErrors());
- }
- protected function checkString($value, $schema = null, $path = null, $i = null)
- {
- $validator = new String($this->checkMode, $this->uriRetriever);
- $validator->check($value, $schema, $path, $i);
- $this->addErrors($validator->getErrors());
- }
- protected function checkNumber($value, $schema = null, $path = null, $i = null)
- {
- $validator = new Number($this->checkMode, $this->uriRetriever);
- $validator->check($value, $schema, $path, $i);
- $this->addErrors($validator->getErrors());
- }
- protected function checkEnum($value, $schema = null, $path = null, $i = null)
- {
- $validator = new Enum($this->checkMode, $this->uriRetriever);
- $validator->check($value, $schema, $path, $i);
- $this->addErrors($validator->getErrors());
- }
- protected function checkFormat($value, $schema = null, $path = null, $i = null)
- {
- $validator = new Format($this->checkMode, $this->uriRetriever);
- $validator->check($value, $schema, $path, $i);
- $this->addErrors($validator->getErrors());
- }
- protected function retrieveUri($uri)
- {
- if (null === $this->uriRetriever) {
- $this->setUriRetriever(new UriRetriever);
- }
- $jsonSchema = $this->uriRetriever->retrieve($uri);
- return $jsonSchema;
- }
- }
- <?php
- namespace JsonSchema\Constraints;
- interface ConstraintInterface
- {
- public function getErrors();
- public function addErrors(array $errors);
- public function addError($path, $message);
- public function isValid();
- public function check($value, $schema = null, $path = null, $i = null);
- }<?php
- namespace JsonSchema\Constraints;
- class Enum extends Constraint
- {
- public function check($element, $schema = null, $path = null, $i = null)
- {
- if ($element instanceof Undefined && (!isset($schema->required) || !$schema->required)) {
- return;
- }
- foreach ($schema->enum as $enum) {
- if ((gettype($element) === gettype($enum)) && ($element == $enum)) {
- return;
- }
- }
- $this->addError($path, "does not have a value in the enumeration " . print_r($schema->enum, true));
- }
- }<?php
- namespace JsonSchema\Constraints;
- class Format extends Constraint
- {
- public function check($element, $schema = null, $path = null, $i = null)
- {
- if (!isset($schema->format)) {
- return;
- }
- switch ($schema->format) {
- case 'date':
- if (!$date = $this->validateDateTime($element, 'Y-m-d')) {
- $this->addError($path, sprintf('Invalid date %s, expected format YYYY-MM-DD', json_encode($element)));
- }
- break;
- case 'time':
- if (!$this->validateDateTime($element, 'H:i:s')) {
- $this->addError($path, sprintf('Invalid time %s, expected format hh:mm:ss', json_encode($element)));
- }
- break;
- case 'date-time':
- if (!$this->validateDateTime($element, 'Y-m-d\TH:i:s\Z') &&
- !$this->validateDateTime($element, 'Y-m-d\TH:i:s.u\Z') &&
- !$this->validateDateTime($element, 'Y-m-d\TH:i:sP') &&
- !$this->validateDateTime($element, 'Y-m-d\TH:i:sO')
- ) {
- $this->addError($path, sprintf('Invalid date-time %s, expected format YYYY-MM-DDThh:mm:ssZ or YYYY-MM-DDThh:mm:ss+hh:mm', json_encode($element)));
- }
- break;
- case 'utc-millisec':
- if (!$this->validateDateTime($element, 'U')) {
- $this->addError($path, sprintf('Invalid time %s, expected integer of milliseconds since Epoch', json_encode($element)));
- }
- break;
- case 'regex':
- if (!$this->validateRegex($element)) {
- $this->addError($path, 'Invalid regex format ' . $element);
- }
- break;
- case 'color':
- if (!$this->validateColor($element)) {
- $this->addError($path, "Invalid color");
- }
- break;
- case 'style':
- if (!$this->validateStyle($element)) {
- $this->addError($path, "Invalid style");
- }
- break;
- case 'phone':
- if (!$this->validatePhone($element)) {
- $this->addError($path, "Invalid phone number");
- }
- break;
- case 'uri':
- if (null === filter_var($element, FILTER_VALIDATE_URL, FILTER_NULL_ON_FAILURE)) {
- $this->addError($path, "Invalid URL format");
- }
- break;
- case 'email':
- if (null === filter_var($element, FILTER_VALIDATE_EMAIL, FILTER_NULL_ON_FAILURE)) {
- $this->addError($path, "Invalid email");
- }
- break;
- case 'ip-address':
- case 'ipv4':
- if (null === filter_var($element, FILTER_VALIDATE_IP, FILTER_NULL_ON_FAILURE | FILTER_FLAG_IPV4)) {
- $this->addError($path, "Invalid IP address");
- }
- break;
- case 'ipv6':
- if (null === filter_var($element, FILTER_VALIDATE_IP, FILTER_NULL_ON_FAILURE | FILTER_FLAG_IPV6)) {
- $this->addError($path, "Invalid IP address");
- }
- break;
- case 'host-name':
- case 'hostname':
- if (!$this->validateHostname($element)) {
- $this->addError($path, "Invalid hostname");
- }
- break;
- default:
- $this->addError($path, "Unknown format: " . json_encode($schema->format));
- break;
- }
- }
- protected function validateDateTime($datetime, $format)
- {
- $dt = \DateTime::createFromFormat($format, $datetime);
- if (!$dt) {
- return false;
- }
- return $datetime === $dt->format($format);
- }
- protected function validateRegex($regex)
- {
- return false !== @preg_match('/' . $regex . '/', '');
- }
- protected function validateColor($color)
- {
- if (in_array(strtolower($color), array('aqua', 'black', 'blue', 'fuchsia',
- 'gray', 'green', 'lime', 'maroon', 'navy', 'olive', 'orange', 'purple',
- 'red', 'silver', 'teal', 'white', 'yellow'))) {
- return true;
- }
- return preg_match('/^#([a-f0-9]{3}|[a-f0-9]{6})$/i', $color);
- }
- protected function validateStyle($style)
- {
- $properties = explode(';', rtrim($style, ';'));
- $invalidEntries = preg_grep('/^\s*[-a-z]+\s*:\s*.+$/i', $properties, PREG_GREP_INVERT);
- return empty($invalidEntries);
- }
- protected function validatePhone($phone)
- {
- return preg_match('/^\+?(\(\d{3}\)|\d{3}) \d{3} \d{4}$/', $phone);
- }
- protected function validateHostname($host)
- {
- return preg_match('/^[_a-z]+\.([_a-z]+\.?)+$/i', $host);
- }
- }
- <?php
- namespace JsonSchema\Constraints;
- class Number extends Constraint
- {
- public function check($element, $schema = null, $path = null, $i = null)
- {
- if (isset($schema->exclusiveMinimum)) {
- if (isset($schema->minimum)) {
- if ($schema->exclusiveMinimum && $element === $schema->minimum) {
- $this->addError($path, "must have a minimum value greater than boundary value of " . $schema->minimum);
- } else if ($element < $schema->minimum) {
- $this->addError($path, "must have a minimum value of " . $schema->minimum);
- }
- } else {
- $this->addError($path, "use of exclusiveMinimum requires presence of minimum");
- }
- } else if (isset($schema->minimum) && $element < $schema->minimum) {
- $this->addError($path, "must have a minimum value of " . $schema->minimum);
- }
- if (isset($schema->exclusiveMaximum)) {
- if (isset($schema->maximum)) {
- if ($schema->exclusiveMaximum && $element === $schema->maximum) {
- $this->addError($path, "must have a maximum value less than boundary value of " . $schema->maximum);
- } else if ($element > $schema->maximum) {
- $this->addError($path, "must have a maximum value of " . $schema->maximum);
- }
- } else {
- $this->addError($path, "use of exclusiveMaximum requires presence of maximum");
- }
- } else if (isset($schema->maximum) && $element > $schema->maximum) {
- $this->addError($path, "must have a maximum value of " . $schema->maximum);
- }
- if (isset($schema->divisibleBy) && $this->fmod($element, $schema->divisibleBy) != 0) {
- $this->addError($path, "is not divisible by " . $schema->divisibleBy);
- }
- if (isset($schema->multipleOf) && $this->fmod($element, $schema->multipleOf) != 0) {
- $this->addError($path, "must be a multiple of " . $schema->multipleOf);
- }
- $this->checkFormat($element, $schema, $path, $i);
- }
- private function fmod($number1, $number2)
- {
- $modulus = fmod($number1, $number2);
- $precision = abs(0.0000000001);
- $diff = (float)($modulus - $number2);
- if (-$precision < $diff && $diff < $precision) {
- return 0.0;
- }
- $decimals1 = mb_strpos($number1, ".") ? mb_strlen($number1) - mb_strpos($number1, ".") - 1 : 0;
- $decimals2 = mb_strpos($number2, ".") ? mb_strlen($number2) - mb_strpos($number2, ".") - 1 : 0;
- return (float)round($modulus, max($decimals1, $decimals2));
- }
- }
- <?php
- namespace JsonSchema\Constraints;
- class Object extends Constraint
- {
- function check($element, $definition = null, $path = null, $additionalProp = null, $patternProperties = null)
- {
- if ($element instanceof Undefined) {
- return;
- }
- $matches = array();
- if ($patternProperties) {
- $matches = $this->validatePatternProperties($element, $path, $patternProperties);
- }
- if ($definition) {
- $this->validateDefinition($element, $definition, $path);
- }
- $this->validateElement($element, $matches, $definition, $path, $additionalProp);
- }
- public function validatePatternProperties($element, $path, $patternProperties)
- {
- $matches = array();
- foreach ($patternProperties as $pregex => $schema) {
- if (@preg_match('/'. $pregex . '/', '') === false) {
- $this->addError($path, 'The pattern "' . $pregex . '" is invalid');
- continue;
- }
- foreach ($element as $i => $value) {
- if (preg_match('/' . $pregex . '/', $i)) {
- $matches[] = $i;
- $this->checkUndefined($value, $schema ? : new \stdClass(), $path, $i);
- }
- }
- }
- return $matches;
- }
- public function validateElement($element, $matches, $objectDefinition = null, $path = null, $additionalProp = null)
- {
- foreach ($element as $i => $value) {
- $property = $this->getProperty($element, $i, new Undefined());
- $definition = $this->getProperty($objectDefinition, $i);
- if (!in_array($i, $matches) && $additionalProp === false && $this->inlineSchemaProperty !== $i && !$definition) {
- $this->addError($path, "The property " . $i . " is not defined and the definition does not allow additional properties");
- }
- if (!in_array($i, $matches) && $additionalProp && !$definition) {
- if ($additionalProp === true) {
- $this->checkUndefined($value, null, $path, $i);
- } else {
- $this->checkUndefined($value, $additionalProp, $path, $i);
- }
- }
- $require = $this->getProperty($definition, 'requires');
- if ($require && !$this->getProperty($element, $require)) {
- $this->addError($path, "the presence of the property " . $i . " requires that " . $require . " also be present");
- }
- if (!$definition) {
- $this->checkUndefined($value, new \stdClass(), $path, $i);
- }
- }
- }
- public function validateDefinition($element, $objectDefinition = null, $path = null)
- {
- foreach ($objectDefinition as $i => $value) {
- $property = $this->getProperty($element, $i, new Undefined());
- $definition = $this->getProperty($objectDefinition, $i);
- $this->checkUndefined($property, $definition, $path, $i);
- }
- }
- protected function getProperty($element, $property, $fallback = null)
- {
- if (is_array($element) ) {
- return array_key_exists($property, $element) ? $element[$property] : $fallback;
- } elseif (is_object($element)) {
- return property_exists($element, $property) ? $element->$property : $fallback;
- }
- return $fallback;
- }
- }<?php
- namespace JsonSchema\Constraints;
- use JsonSchema\Exception\InvalidArgumentException;
- class Schema extends Constraint
- {
- public function check($element, $schema = null, $path = null, $i = null)
- {
- if ($schema !== null) {
- $this->checkUndefined($element, $schema, '', '');
- } elseif (property_exists($element, $this->inlineSchemaProperty)) {
- $this->checkUndefined($element, $element->{$this->inlineSchemaProperty}, '', '');
- } else {
- throw new InvalidArgumentException('no schema found to verify against');
- }
- }
- }<?php
- namespace JsonSchema\Constraints;
- class String extends Constraint
- {
- public function check($element, $schema = null, $path = null, $i = null)
- {
- if (isset($schema->maxLength) && $this->strlen($element) > $schema->maxLength) {
- $this->addError($path, "must be at most " . $schema->maxLength . " characters long");
- }
- if (isset($schema->minLength) && $this->strlen($element) < $schema->minLength) {
- $this->addError($path, "must be at least " . $schema->minLength . " characters long");
- }
- if (isset($schema->pattern) && !preg_match('#' . str_replace('#', '\\#', $schema->pattern) . '#', $element)) {
- $this->addError($path, "does not match the regex pattern " . $schema->pattern);
- }
- $this->checkFormat($element, $schema, $path, $i);
- }
- private function strlen($string)
- {
- if (extension_loaded('mbstring')) {
- return mb_strlen($string, mb_detect_encoding($string));
- } else {
- return strlen($string);
- }
- }
- }
- <?php
- namespace JsonSchema\Constraints;
- use JsonSchema\Exception\InvalidArgumentException;
- use UnexpectedValueException as StandardUnexpectedValueException;
- class Type extends Constraint
- {
- static $wording = array(
- 'integer' => 'an integer',
- 'number' => 'a number',
- 'boolean' => 'a boolean',
- 'object' => 'an object',
- 'array' => 'an array',
- 'string' => 'a string',
- 'null' => 'a null',
- 'any' => NULL,
- 0 => NULL,
- );
- public function check($value = null, $schema = null, $path = null, $i = null)
- {
- $type = isset($schema->type) ? $schema->type : null;
- $isValid = true;
- if (is_array($type)) {
- $validatedOneType = false;
- $errors = array();
- foreach ($type as $tp) {
- $validator = new Type($this->checkMode);
- $subSchema = new \stdClass();
- $subSchema->type = $tp;
- $validator->check($value, $subSchema, $path, null);
- $error = $validator->getErrors();
- if (!count($error)) {
- $validatedOneType = true;
- break;
- }
- $errors = $error;
- }
- if (!$validatedOneType) {
- return $this->addErrors($errors);
- }
- } elseif (is_object($type)) {
- $this->checkUndefined($value, $type, $path);
- } else {
- $isValid = $this->validateType($value, $type);
- }
- if ($isValid === false) {
- if (!isset(self::$wording[$type])) {
- throw new StandardUnexpectedValueException(
- sprintf(
- "No wording for %s available, expected wordings are: [%s]",
- var_export($type, true),
- implode(', ', array_filter(self::$wording)))
- );
- }
- $this->addError($path, gettype($value) . " value found, but " . self::$wording[$type] . " is required");
- }
- }
- protected function validateType($value, $type)
- {
- if (!$type) {
- return true;
- }
- if ('integer' === $type) {
- return is_int($value);
- }
- if ('number' === $type) {
- return is_numeric($value) && !is_string($value);
- }
- if ('boolean' === $type) {
- return is_bool($value);
- }
- if ('object' === $type) {
- return is_object($value);
- }
- if ('array' === $type) {
- return is_array($value);
- }
- if ('string' === $type) {
- return is_string($value);
- }
- if ('null' === $type) {
- return is_null($value);
- }
- if ('any' === $type) {
- return true;
- }
- throw new InvalidArgumentException((is_object($value) ? 'object' : $value) . ' is an invalid type for ' . $type);
- }
- }<?php
- namespace JsonSchema\Constraints;
- use JsonSchema\Exception\InvalidArgumentException;
- use JsonSchema\Uri\UriResolver;
- class Undefined extends Constraint
- {
- public function check($value, $schema = null, $path = null, $i = null)
- {
- if (is_null($schema)) {
- return;
- }
- if (!is_object($schema)) {
- throw new InvalidArgumentException(
- 'Given schema must be an object in ' . $path
- . ' but is a ' . gettype($schema)
- );
- }
- $i = is_null($i) ? "" : $i;
- $path = $this->incrementPath($path, $i);
- $this->validateCommonProperties($value, $schema, $path);
- $this->validateOfProperties($value, $schema, $path);
- $this->validateTypes($value, $schema, $path, $i);
- }
- public function validateTypes($value, $schema = null, $path = null, $i = null)
- {
- if (is_array($value)) {
- $this->checkArray($value, $schema, $path, $i);
- }
- if (is_object($value) && (isset($schema->properties) || isset($schema->patternProperties))) {
- $this->checkObject(
- $value,
- isset($schema->properties) ? $schema->properties : null,
- $path,
- isset($schema->additionalProperties) ? $schema->additionalProperties : null,
- isset($schema->patternProperties) ? $schema->patternProperties : null
- );
- }
- if (is_string($value)) {
- $this->checkString($value, $schema, $path, $i);
- }
- if (is_numeric($value)) {
- $this->checkNumber($value, $schema, $path, $i);
- }
- if (isset($schema->enum)) {
- $this->checkEnum($value, $schema, $path, $i);
- }
- }
- protected function validateCommonProperties($value, $schema = null, $path = null, $i = "")
- {
- if (isset($schema->extends)) {
- if (is_string($schema->extends)) {
- $schema->extends = $this->validateUri($schema, $schema->extends);
- }
- if (is_array($schema->extends)) {
- foreach ($schema->extends as $extends) {
- $this->checkUndefined($value, $extends, $path, $i);
- }
- } else {
- $this->checkUndefined($value, $schema->extends, $path, $i);
- }
- }
- if (is_object($value)) {
- if (!($value instanceof Undefined) && isset($schema->required) && is_array($schema->required) ) {
- foreach ($schema->required as $required) {
- if (!property_exists($value, $required)) {
- $this->addError($path, "the property " . $required . " is required");
- }
- }
- } else if (isset($schema->required) && !is_array($schema->required)) {
- if ( $schema->required && $value instanceof Undefined) {
- $this->addError($path, "is missing and it is required");
- }
- }
- }
- if (!($value instanceof Undefined)) {
- $this->checkType($value, $schema, $path);
- }
- if (isset($schema->disallow)) {
- $initErrors = $this->getErrors();
- $typeSchema = new \stdClass();
- $typeSchema->type = $schema->disallow;
- $this->checkType($value, $typeSchema, $path);
- if (count($this->getErrors()) == count($initErrors)) {
- $this->addError($path, "disallowed value was matched");
- } else {
- $this->errors = $initErrors;
- }
- }
- if (isset($schema->not)) {
- $initErrors = $this->getErrors();
- $this->checkUndefined($value, $schema->not, $path, $i);
- if (count($this->getErrors()) == count($initErrors)) {
- $this->addError($path, "matched a schema which it should not");
- } else {
- $this->errors = $initErrors;
- }
- }
- if (is_object($value)) {
- if (isset($schema->minProperties)) {
- if (count(get_object_vars($value)) < $schema->minProperties) {
- $this->addError($path, "must contain a minimum of " . $schema->minProperties . " properties");
- }
- }
- if (isset($schema->maxProperties)) {
- if (count(get_object_vars($value)) > $schema->maxProperties) {
- $this->addError($path, "must contain no more than " . $schema->maxProperties . " properties");
- }
- }
- }
- if (is_object($value) && isset($schema->dependencies)) {
- $this->validateDependencies($value, $schema->dependencies, $path);
- }
- }
- protected function validateOfProperties($value, $schema, $path, $i = "")
- {
- if ($value instanceof Undefined) {
- return;
- }
- if (isset($schema->allOf)) {
- $isValid = true;
- foreach ($schema->allOf as $allOf) {
- $initErrors = $this->getErrors();
- $this->checkUndefined($value, $allOf, $path, $i);
- $isValid = $isValid && (count($this->getErrors()) == count($initErrors));
- }
- if (!$isValid) {
- $this->addError($path, "failed to match all schemas");
- }
- }
- if (isset($schema->anyOf)) {
- $isValid = false;
- $startErrors = $this->getErrors();
- foreach ($schema->anyOf as $anyOf) {
- $initErrors = $this->getErrors();
- $this->checkUndefined($value, $anyOf, $path, $i);
- if ($isValid = (count($this->getErrors()) == count($initErrors))) {
- break;
- }
- }
- if (!$isValid) {
- $this->addError($path, "failed to match at least one schema");
- } else {
- $this->errors = $startErrors;
- }
- }
- if (isset($schema->oneOf)) {
- $allErrors = array();
- $matchedSchemas = 0;
- $startErrors = $this->getErrors();
- foreach ($schema->oneOf as $oneOf) {
- $this->errors = array();
- $this->checkUndefined($value, $oneOf, $path, $i);
- if (count($this->getErrors()) == 0) {
- $matchedSchemas++;
- }
- $allErrors = array_merge($allErrors, array_values($this->getErrors()));
- }
- if ($matchedSchemas !== 1) {
- $this->addErrors(
- array_merge(
- $allErrors,
- array(array(
- 'property' => $path,
- 'message' => "failed to match exactly one schema"
- ),),
- $startErrors
- )
- );
- } else {
- $this->errors = $startErrors;
- }
- }
- }
- protected function validateDependencies($value, $dependencies, $path, $i = "")
- {
- foreach ($dependencies as $key => $dependency) {
- if (property_exists($value, $key)) {
- if (is_string($dependency)) {
- if (!property_exists($value, $dependency)) {
- $this->addError($path, "$key depends on $dependency and $dependency is missing");
- }
- } else if (is_array($dependency)) {
- foreach ($dependency as $d) {
- if (!property_exists($value, $d)) {
- $this->addError($path, "$key depends on $d and $d is missing");
- }
- }
- } else if (is_object($dependency)) {
- $this->checkUndefined($value, $dependency, $path, $i);
- }
- }
- }
- }
- protected function validateUri($schema, $schemaUri = null)
- {
- $resolver = new UriResolver();
- $retriever = $this->getUriRetriever();
- $jsonSchema = null;
- if ($resolver->isValid($schemaUri)) {
- $schemaId = property_exists($schema, 'id') ? $schema->id : null;
- $jsonSchema = $retriever->retrieve($schemaId, $schemaUri);
- }
- return $jsonSchema;
- }
- }
- <?php
- namespace JsonSchema\Exception;
- class InvalidArgumentException extends \InvalidArgumentException
- {
- }<?php
- namespace JsonSchema\Exception;
- class InvalidSchemaMediaTypeException extends \RuntimeException
- {
- }<?php
- namespace JsonSchema\Exception;
- class InvalidSourceUriException extends InvalidArgumentException
- {
- }
- <?php
- namespace JsonSchema\Exception;
- class JsonDecodingException extends \RuntimeException
- {
- public function __construct($code = JSON_ERROR_NONE, \Exception $previous = null)
- {
- switch ($code) {
- case JSON_ERROR_DEPTH:
- $message = 'The maximum stack depth has been exceeded';
- break;
- case JSON_ERROR_STATE_MISMATCH:
- $message = 'Invalid or malformed JSON';
- break;
- case JSON_ERROR_CTRL_CHAR:
- $message = 'Control character error, possibly incorrectly encoded';
- break;
- case JSON_ERROR_UTF8:
- $message = 'Malformed UTF-8 characters, possibly incorrectly encoded';
- break;
- case JSON_ERROR_SYNTAX:
- $message = 'JSON syntax is malformed';
- break;
- default:
- $message = 'Syntax error';
- }
- parent::__construct($message, $code, $previous);
- }
- }<?php
- namespace JsonSchema\Exception;
- class ResourceNotFoundException extends \RuntimeException
- {
- }<?php
- namespace JsonSchema\Exception;
- class UriResolverException extends \RuntimeException
- {
- }<?php
- namespace JsonSchema;
- use JsonSchema\Uri\Retrievers\UriRetrieverInterface;
- use JsonSchema\Uri\UriRetriever;
- class RefResolver
- {
- protected static $depth = 0;
- public static $maxDepth = 7;
- protected $uriRetriever = null;
- public function __construct($retriever = null)
- {
- $this->uriRetriever = $retriever;
- }
- public function fetchRef($ref, $sourceUri)
- {
- $retriever = $this->getUriRetriever();
- $jsonSchema = $retriever->retrieve($ref, $sourceUri);
- $this->resolve($jsonSchema);
- return $jsonSchema;
- }
- public function getUriRetriever()
- {
- if (is_null($this->uriRetriever)) {
- $this->setUriRetriever(new UriRetriever);
- }
- return $this->uriRetriever;
- }
- public function resolve($schema, $sourceUri = null)
- {
- if (self::$depth > self::$maxDepth) {
- return;
- }
- ++self::$depth;
- if (! is_object($schema)) {
- --self::$depth;
- return;
- }
- if (null === $sourceUri && ! empty($schema->id)) {
- $sourceUri = $schema->id;
- }
- $this->resolveRef($schema, $sourceUri);
-
- foreach (array('additionalItems', 'additionalProperties', 'extends', 'items') as $propertyName) {
- $this->resolveProperty($schema, $propertyName, $sourceUri);
- }
-
-
- foreach (array('disallow', 'extends', 'items', 'type', 'allOf', 'anyOf', 'oneOf') as $propertyName) {
- $this->resolveArrayOfSchemas($schema, $propertyName, $sourceUri);
- }
- foreach (array('dependencies', 'patternProperties', 'properties') as $propertyName) {
- $this->resolveObjectOfSchemas($schema, $propertyName, $sourceUri);
- }
- --self::$depth;
- }
- public function resolveArrayOfSchemas($schema, $propertyName, $sourceUri)
- {
- if (! isset($schema->$propertyName) || ! is_array($schema->$propertyName)) {
- return;
- }
- foreach ($schema->$propertyName as $possiblySchema) {
- $this->resolve($possiblySchema, $sourceUri);
- }
- }
- public function resolveObjectOfSchemas($schema, $propertyName, $sourceUri)
- {
- if (! isset($schema->$propertyName) || ! is_object($schema->$propertyName)) {
- return;
- }
- foreach (get_object_vars($schema->$propertyName) as $possiblySchema) {
- $this->resolve($possiblySchema, $sourceUri);
- }
- }
- public function resolveProperty($schema, $propertyName, $sourceUri)
- {
- if (! isset($schema->$propertyName)) {
- return;
- }
- $this->resolve($schema->$propertyName, $sourceUri);
- }
- public function resolveRef($schema, $sourceUri)
- {
- $ref = '$ref';
- if (empty($schema->$ref)) {
- return;
- }
- $refSchema = $this->fetchRef($schema->$ref, $sourceUri);
- unset($schema->$ref);
- foreach (get_object_vars($refSchema) as $prop => $value) {
- $schema->$prop = $value;
- }
- }
- public function setUriRetriever(UriRetriever $retriever)
- {
- $this->uriRetriever = $retriever;
- return $this;
- }
- }
- <?php
- namespace JsonSchema\Uri\Retrievers;
- abstract class AbstractRetriever implements UriRetrieverInterface
- {
- protected $contentType;
- public function getContentType()
- {
- return $this->contentType;
- }
- }
- <?php
- namespace JsonSchema\Uri\Retrievers;
- use JsonSchema\Validator;
- class Curl extends AbstractRetriever
- {
- protected $messageBody;
- public function __construct()
- {
- if (!function_exists('curl_init')) {
- throw new \RuntimeException("cURL not installed");
- }
- }
- public function retrieve($uri)
- {
- $ch = curl_init();
- curl_setopt($ch, CURLOPT_URL, $uri);
- curl_setopt($ch, CURLOPT_HEADER, true);
- curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
- curl_setopt($ch, CURLOPT_HTTPHEADER, array('Accept: ' . Validator::SCHEMA_MEDIA_TYPE));
- $response = curl_exec($ch);
- if (false === $response) {
- throw new \JsonSchema\Exception\ResourceNotFoundException('JSON schema not found');
- }
- $this->fetchMessageBody($response);
- $this->fetchContentType($response);
- curl_close($ch);
- return $this->messageBody;
- }
- private function fetchMessageBody($response)
- {
- preg_match("/(?:\r\n){2}(.*)$/ms", $response, $match);
- $this->messageBody = $match[1];
- }
- protected function fetchContentType($response)
- {
- if (0 < preg_match("/Content-Type:(\V*)/ims", $response, $match)) {
- $this->contentType = trim($match[1]);
- return true;
- }
- return false;
- }
- }<?php
- namespace JsonSchema\Uri\Retrievers;
- use JsonSchema\Exception\ResourceNotFoundException;
- use JsonSchema\Validator;
- class FileGetContents extends AbstractRetriever
- {
- protected $messageBody;
- public function retrieve($uri)
- {
- $context = stream_context_create(array(
- 'http' => array(
- 'method' => 'GET',
- 'header' => "Accept: " . Validator::SCHEMA_MEDIA_TYPE
- )));
- $response = file_get_contents($uri);
- if (false === $response) {
- throw new ResourceNotFoundException('JSON schema not found at ' . $uri);
- }
- if ($response == ''
- && substr($uri, 0, 7) == 'file://' && substr($uri, -1) == '/'
- ) {
- throw new ResourceNotFoundException('JSON schema not found at ' . $uri);
- }
- $this->messageBody = $response;
- if (! empty($http_response_header)) {
- $this->fetchContentType($http_response_header);
- } else {
- $this->contentType = null;
- }
- return $this->messageBody;
- }
- private function fetchContentType(array $headers)
- {
- foreach ($headers as $header) {
- if ($this->contentType = self::getContentTypeMatchInHeader($header)) {
- return true;
- }
- }
- return false;
- }
- protected static function getContentTypeMatchInHeader($header)
- {
- if (0 < preg_match("/Content-Type:(\V*)/ims", $header, $match)) {
- return trim($match[1]);
- }
- }
- }
- <?php
- namespace JsonSchema\Uri\Retrievers;
- use JsonSchema\Validator;
- use JsonSchema\Uri\Retrievers\UriRetrieverInterface;
- class PredefinedArray extends AbstractRetriever
- {
- private $schemas;
- public function __construct(array $schemas, $contentType = Validator::SCHEMA_MEDIA_TYPE)
- {
- $this->schemas = $schemas;
- $this->contentType = $contentType;
- }
- public function retrieve($uri)
- {
- if (!array_key_exists($uri, $this->schemas)) {
- throw new \JsonSchema\Exception\ResourceNotFoundException(sprintf(
- 'The JSON schema "%s" was not found.',
- $uri
- ));
- }
- return $this->schemas[$uri];
- }
- }<?php
- namespace JsonSchema\Uri\Retrievers;
- interface UriRetrieverInterface
- {
- public function retrieve($uri);
- public function getContentType();
- }<?php
- namespace JsonSchema\Uri;
- use JsonSchema\Exception\UriResolverException;
- class UriResolver
- {
- public function parse($uri)
- {
- preg_match('|^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?|', $uri, $match);
- $components = array();
- if (5 < count($match)) {
- $components = array(
- 'scheme' => $match[2],
- 'authority' => $match[4],
- 'path' => $match[5]
- );
- }
- if (7 < count($match)) {
- $components['query'] = $match[7];
- }
- if (9 < count($match)) {
- $components['fragment'] = $match[9];
- }
- return $components;
- }
- public function generate(array $components)
- {
- $uri = $components['scheme'] . '://'
- . $components['authority']
- . $components['path'];
- if (array_key_exists('query', $components)) {
- $uri .= $components['query'];
- }
- if (array_key_exists('fragment', $components)) {
- $uri .= '#' . $components['fragment'];
- }
- return $uri;
- }
- public function resolve($uri, $baseUri = null)
- {
- if ($uri == '') {
- return $baseUri;
- }
- $components = $this->parse($uri);
- $path = $components['path'];
- if (! empty($components['scheme'])) {
- return $uri;
- }
- $baseComponents = $this->parse($baseUri);
- $basePath = $baseComponents['path'];
- $baseComponents['path'] = self::combineRelativePathWithBasePath($path, $basePath);
- if (isset($components['fragment'])) {
- $baseComponents['fragment'] = $components['fragment'];
- }
- return $this->generate($baseComponents);
- }
- public static function combineRelativePathWithBasePath($relativePath, $basePath)
- {
- $relativePath = self::normalizePath($relativePath);
- if ($relativePath == '') {
- return $basePath;
- }
- if ($relativePath{0} == '/') {
- return $relativePath;
- }
- $basePathSegments = self::getPathSegments($basePath);
- preg_match('|^/?(\.\./(?:\./)*)*|', $relativePath, $match);
- $numLevelUp = strlen($match[0]) /3 + 1;
- if ($numLevelUp >= count($basePathSegments)) {
- throw new UriResolverException(sprintf("Unable to resolve URI '%s' from base '%s'", $relativePath, $basePath));
- }
- $basePathSegments = array_slice($basePathSegments, 0, -$numLevelUp);
- $path = preg_replace('|^/?(\.\./(\./)*)*|', '', $relativePath);
- return implode('/', $basePathSegments) . '/' . $path;
- }
- private static function normalizePath($path)
- {
- $path = preg_replace('|((?<!\.)\./)*|', '', $path);
- $path = preg_replace('|//|', '/', $path);
- return $path;
- }
- private static function getPathSegments($path) {
- return explode('/', $path);
- }
- public function isValid($uri)
- {
- $components = $this->parse($uri);
- return !empty($components);
- }
- }
- <?php
- namespace JsonSchema\Uri;
- use JsonSchema\Uri\Retrievers\FileGetContents;
- use JsonSchema\Uri\Retrievers\UriRetrieverInterface;
- use JsonSchema\Validator;
- use JsonSchema\Exception\InvalidSchemaMediaTypeException;
- use JsonSchema\Exception\JsonDecodingException;
- class UriRetriever
- {
- protected $uriRetriever = null;
- public function confirmMediaType($uriRetriever, $uri)
- {
- $contentType = $uriRetriever->getContentType();
- if (is_null($contentType)) {
- return;
- }
- if (Validator::SCHEMA_MEDIA_TYPE === $contentType) {
- return;
- }
- if (substr($uri, 0, 23) == 'http://json-schema.org/') {
- return true;
- }
- throw new InvalidSchemaMediaTypeException(sprintf('Media type %s expected', Validator::SCHEMA_MEDIA_TYPE));
- }
- public function getUriRetriever()
- {
- if (is_null($this->uriRetriever)) {
- $this->setUriRetriever(new FileGetContents);
- }
- return $this->uriRetriever;
- }
- public function resolvePointer($jsonSchema, $uri)
- {
- $resolver = new UriResolver();
- $parsed = $resolver->parse($uri);
- if (empty($parsed['fragment'])) {
- return $jsonSchema;
- }
- $path = explode('/', $parsed['fragment']);
- while ($path) {
- $pathElement = array_shift($path);
- if (! empty($pathElement)) {
- $pathElement = str_replace('~1', '/', $pathElement);
- $pathElement = str_replace('~0', '~', $pathElement);
- if (! empty($jsonSchema->$pathElement)) {
- $jsonSchema = $jsonSchema->$pathElement;
- } else {
- throw new \JsonSchema\Exception\ResourceNotFoundException(
- 'Fragment "' . $parsed['fragment'] . '" not found'
- . ' in ' . $uri
- );
- }
- if (! is_object($jsonSchema)) {
- throw new \JsonSchema\Exception\ResourceNotFoundException(
- 'Fragment part "' . $pathElement . '" is no object '
- . ' in ' . $uri
- );
- }
- }
- }
- return $jsonSchema;
- }
- public function retrieve($uri, $baseUri = null)
- {
- $resolver = new UriResolver();
- $resolvedUri = $fetchUri = $resolver->resolve($uri, $baseUri);
- $arParts = $resolver->parse($resolvedUri);
- if (isset($arParts['fragment'])) {
- unset($arParts['fragment']);
- $fetchUri = $resolver->generate($arParts);
- }
- $jsonSchema = $this->loadSchema($fetchUri);
- $jsonSchema = $this->resolvePointer($jsonSchema, $resolvedUri);
- $jsonSchema->id = $resolvedUri;
- return $jsonSchema;
- }
- protected function loadSchema($fetchUri)
- {
- if (isset($this->schemaCache[$fetchUri])) {
- return $this->schemaCache[$fetchUri];
- }
- $uriRetriever = $this->getUriRetriever();
- $contents = $this->uriRetriever->retrieve($fetchUri);
- $this->confirmMediaType($uriRetriever, $fetchUri);
- $jsonSchema = json_decode($contents);
- if (JSON_ERROR_NONE < $error = json_last_error()) {
- throw new JsonDecodingException($error);
- }
- $this->schemaCache[$fetchUri] = $jsonSchema;
- return $jsonSchema;
- }
- public function setUriRetriever(UriRetrieverInterface $uriRetriever)
- {
- $this->uriRetriever = $uriRetriever;
- return $this;
- }
- public function parse($uri)
- {
- preg_match('|^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?|', $uri, $match);
- $components = array();
- if (5 < count($match)) {
- $components = array(
- 'scheme' => $match[2],
- 'authority' => $match[4],
- 'path' => $match[5]
- );
- }
- if (7 < count($match)) {
- $components['query'] = $match[7];
- }
- if (9 < count($match)) {
- $components['fragment'] = $match[9];
- }
- return $components;
- }
- public function generate(array $components)
- {
- $uri = $components['scheme'] . '://'
- . $components['authority']
- . $components['path'];
- if (array_key_exists('query', $components)) {
- $uri .= $components['query'];
- }
- if (array_key_exists('fragment', $components)) {
- $uri .= $components['fragment'];
- }
- return $uri;
- }
- public function resolve($uri, $baseUri = null)
- {
- $components = $this->parse($uri);
- $path = $components['path'];
- if ((array_key_exists('scheme', $components)) && ('http' === $components['scheme'])) {
- return $uri;
- }
- $baseComponents = $this->parse($baseUri);
- $basePath = $baseComponents['path'];
- $baseComponents['path'] = self::combineRelativePathWithBasePath($path, $basePath);
- return $this->generate($baseComponents);
- }
- private static function combineRelativePathWithBasePath($relativePath, $basePath)
- {
- $relativePath = self::normalizePath($relativePath);
- $basePathSegments = self::getPathSegments($basePath);
- preg_match('|^/?(\.\./(?:\./)*)*|', $relativePath, $match);
- $numLevelUp = strlen($match[0]) /3 + 1;
- if ($numLevelUp >= count($basePathSegments)) {
- throw new \JsonSchema\Exception\UriResolverException(sprintf("Unable to resolve URI '%s' from base '%s'", $relativePath, $basePath));
- }
- $basePathSegments = array_slice($basePathSegments, 0, -$numLevelUp);
- $path = preg_replace('|^/?(\.\./(\./)*)*|', '', $relativePath);
- return implode('/', $basePathSegments) . '/' . $path;
- }
- private static function normalizePath($path)
- {
- $path = preg_replace('|((?<!\.)\./)*|', '', $path);
- $path = preg_replace('|//|', '/', $path);
- return $path;
- }
- private static function getPathSegments($path)
- {
- return explode('/', $path);
- }
- public function isValid($uri)
- {
- $components = $this->parse($uri);
- return !empty($components);
- }
- }
- <?php
- namespace JsonSchema;
- use JsonSchema\Constraints\Schema;
- use JsonSchema\Constraints\Constraint;
- use JsonSchema\Exception\InvalidSchemaMediaTypeException;
- use JsonSchema\Exception\JsonDecodingException;
- use JsonSchema\Uri\Retrievers\UriRetrieverInterface;
- class Validator extends Constraint
- {
- const SCHEMA_MEDIA_TYPE = 'application/schema+json';
- public function check($value, $schema = null, $path = null, $i = null)
- {
- $validator = new Schema($this->checkMode, $this->uriRetriever);
- $validator->check($value, $schema);
- $this->addErrors(array_unique($validator->getErrors(), SORT_REGULAR));
- }
- }
- <?php
- require_once __DIR__ . '/composer' . '/autoload_real.php';
- return ComposerAutoloaderInite50dadd7af3a60367a2353872e1658c3::getLoader();
- <?php
- $vendorDir = dirname(dirname(__FILE__));
- $baseDir = dirname($vendorDir);
- return array(
- 'phpDocumentor' => array($vendorDir . '/phpdocumentor/reflection-docblock/src'),
- 'Symfony\\Component\\Yaml\\' => array($vendorDir . '/symfony/yaml'),
- 'Symfony\\Component\\Process\\' => array($vendorDir . '/symfony/process'),
- 'Symfony\\Component\\Finder\\' => array($vendorDir . '/symfony/finder'),
- 'Symfony\\Component\\Console\\' => array($vendorDir . '/symfony/console'),
- 'Prophecy\\' => array($vendorDir . '/phpspec/prophecy/src'),
- 'JsonSchema' => array($vendorDir . '/justinrainbow/json-schema/src'),
- 'Doctrine\\Instantiator\\' => array($vendorDir . '/doctrine/instantiator/src'),
- 'Composer\\Test' => array($baseDir . '/tests'),
- 'Composer' => array($baseDir . '/src'),
- );
- <?php
- $vendorDir = dirname(dirname(__FILE__));
- $baseDir = dirname($vendorDir);
- return array(
- 'Seld\\JsonLint\\' => array($vendorDir . '/seld/jsonlint/src/Seld/JsonLint'),
- );
- <?php
- $vendorDir = dirname(dirname(__FILE__));
- $baseDir = dirname($vendorDir);
- return array(
- 'File_Iterator' => $vendorDir . '/phpunit/php-file-iterator/File/Iterator.php',
- 'File_Iterator_Facade' => $vendorDir . '/phpunit/php-file-iterator/File/Iterator/Facade.php',
- 'File_Iterator_Factory' => $vendorDir . '/phpunit/php-file-iterator/File/Iterator/Factory.php',
- 'PHPUnit_Exception' => $vendorDir . '/phpunit/phpunit/src/Exception.php',
- 'PHPUnit_Extensions_GroupTestSuite' => $vendorDir . '/phpunit/phpunit/src/Extensions/GroupTestSuite.php',
- 'PHPUnit_Extensions_PhptTestCase' => $vendorDir . '/phpunit/phpunit/src/Extensions/PhptTestCase.php',
- 'PHPUnit_Extensions_PhptTestSuite' => $vendorDir . '/phpunit/phpunit/src/Extensions/PhptTestSuite.php',
- 'PHPUnit_Extensions_RepeatedTest' => $vendorDir . '/phpunit/phpunit/src/Extensions/RepeatedTest.php',
- 'PHPUnit_Extensions_TestDecorator' => $vendorDir . '/phpunit/phpunit/src/Extensions/TestDecorator.php',
- 'PHPUnit_Extensions_TicketListener' => $vendorDir . '/phpunit/phpunit/src/Extensions/TicketListener.php',
- 'PHPUnit_Framework_Assert' => $vendorDir . '/phpunit/phpunit/src/Framework/Assert.php',
- 'PHPUnit_Framework_AssertionFailedError' => $vendorDir . '/phpunit/phpunit/src/Framework/AssertionFailedError.php',
- 'PHPUnit_Framework_BaseTestListener' => $vendorDir . '/phpunit/phpunit/src/Framework/BaseTestListener.php',
- 'PHPUnit_Framework_CodeCoverageException' => $vendorDir . '/phpunit/phpunit/src/Framework/CodeCoverageException.php',
- 'PHPUnit_Framework_Constraint' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint.php',
- 'PHPUnit_Framework_Constraint_And' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/And.php',
- 'PHPUnit_Framework_Constraint_ArrayHasKey' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/ArrayHasKey.php',
- 'PHPUnit_Framework_Constraint_ArraySubset' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/ArraySubset.php',
- 'PHPUnit_Framework_Constraint_Attribute' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Attribute.php',
- 'PHPUnit_Framework_Constraint_Callback' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Callback.php',
- 'PHPUnit_Framework_Constraint_ClassHasAttribute' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/ClassHasAttribute.php',
- 'PHPUnit_Framework_Constraint_ClassHasStaticAttribute' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/ClassHasStaticAttribute.php',
- 'PHPUnit_Framework_Constraint_Composite' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Composite.php',
- 'PHPUnit_Framework_Constraint_Count' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Count.php',
- 'PHPUnit_Framework_Constraint_Exception' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Exception.php',
- 'PHPUnit_Framework_Constraint_ExceptionCode' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/ExceptionCode.php',
- 'PHPUnit_Framework_Constraint_ExceptionMessage' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/ExceptionMessage.php',
- 'PHPUnit_Framework_Constraint_ExceptionMessageRegExp' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/ExceptionMessageRegExp.php',
- 'PHPUnit_Framework_Constraint_FileExists' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/FileExists.php',
- 'PHPUnit_Framework_Constraint_GreaterThan' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/GreaterThan.php',
- 'PHPUnit_Framework_Constraint_IsAnything' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/IsAnything.php',
- 'PHPUnit_Framework_Constraint_IsEmpty' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/IsEmpty.php',
- 'PHPUnit_Framework_Constraint_IsEqual' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/IsEqual.php',
- 'PHPUnit_Framework_Constraint_IsFalse' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/IsFalse.php',
- 'PHPUnit_Framework_Constraint_IsIdentical' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/IsIdentical.php',
- 'PHPUnit_Framework_Constraint_IsInstanceOf' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/IsInstanceOf.php',
- 'PHPUnit_Framework_Constraint_IsJson' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/IsJson.php',
- 'PHPUnit_Framework_Constraint_IsNull' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/IsNull.php',
- 'PHPUnit_Framework_Constraint_IsTrue' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/IsTrue.php',
- 'PHPUnit_Framework_Constraint_IsType' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/IsType.php',
- 'PHPUnit_Framework_Constraint_JsonMatches' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/JsonMatches.php',
- 'PHPUnit_Framework_Constraint_JsonMatches_ErrorMessageProvider' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/JsonMatches/ErrorMessageProvider.php',
- 'PHPUnit_Framework_Constraint_LessThan' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/LessThan.php',
- 'PHPUnit_Framework_Constraint_Not' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Not.php',
- 'PHPUnit_Framework_Constraint_ObjectHasAttribute' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/ObjectHasAttribute.php',
- 'PHPUnit_Framework_Constraint_Or' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Or.php',
- 'PHPUnit_Framework_Constraint_PCREMatch' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/PCREMatch.php',
- 'PHPUnit_Framework_Constraint_SameSize' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/SameSize.php',
- 'PHPUnit_Framework_Constraint_StringContains' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/StringContains.php',
- 'PHPUnit_Framework_Constraint_StringEndsWith' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/StringEndsWith.php',
- 'PHPUnit_Framework_Constraint_StringMatches' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/StringMatches.php',
- 'PHPUnit_Framework_Constraint_StringStartsWith' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/StringStartsWith.php',
- 'PHPUnit_Framework_Constraint_TraversableContains' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/TraversableContains.php',
- 'PHPUnit_Framework_Constraint_TraversableContainsOnly' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/TraversableContainsOnly.php',
- 'PHPUnit_Framework_Constraint_Xor' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Xor.php',
- 'PHPUnit_Framework_Error' => $vendorDir . '/phpunit/phpunit/src/Framework/Error.php',
- 'PHPUnit_Framework_Error_Deprecated' => $vendorDir . '/phpunit/phpunit/src/Framework/Error/Deprecated.php',
- 'PHPUnit_Framework_Error_Notice' => $vendorDir . '/phpunit/phpunit/src/Framework/Error/Notice.php',
- 'PHPUnit_Framework_Error_Warning' => $vendorDir . '/phpunit/phpunit/src/Framework/Error/Warning.php',
- 'PHPUnit_Framework_Exception' => $vendorDir . '/phpunit/phpunit/src/Framework/Exception.php',
- 'PHPUnit_Framework_ExceptionWrapper' => $vendorDir . '/phpunit/phpunit/src/Framework/ExceptionWrapper.php',
- 'PHPUnit_Framework_ExpectationFailedException' => $vendorDir . '/phpunit/phpunit/src/Framework/ExpectationFailedException.php',
- 'PHPUnit_Framework_IncompleteTest' => $vendorDir . '/phpunit/phpunit/src/Framework/IncompleteTest.php',
- 'PHPUnit_Framework_IncompleteTestCase' => $vendorDir . '/phpunit/phpunit/src/Framework/IncompleteTestCase.php',
- 'PHPUnit_Framework_IncompleteTestError' => $vendorDir . '/phpunit/phpunit/src/Framework/IncompleteTestError.php',
- 'PHPUnit_Framework_InvalidCoversTargetError' => $vendorDir . '/phpunit/phpunit/src/Framework/InvalidCoversTargetError.php',
- 'PHPUnit_Framework_InvalidCoversTargetException' => $vendorDir . '/phpunit/phpunit/src/Framework/InvalidCoversTargetException.php',
- 'PHPUnit_Framework_MockObject_BadMethodCallException' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Exception/BadMethodCallException.php',
- 'PHPUnit_Framework_MockObject_Builder_Identity' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Builder/Identity.php',
- 'PHPUnit_Framework_MockObject_Builder_InvocationMocker' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Builder/InvocationMocker.php',
- 'PHPUnit_Framework_MockObject_Builder_Match' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Builder/Match.php',
- 'PHPUnit_Framework_MockObject_Builder_MethodNameMatch' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Builder/MethodNameMatch.php',
- 'PHPUnit_Framework_MockObject_Builder_Namespace' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Builder/Namespace.php',
- 'PHPUnit_Framework_MockObject_Builder_ParametersMatch' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Builder/ParametersMatch.php',
- 'PHPUnit_Framework_MockObject_Builder_Stub' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Builder/Stub.php',
- 'PHPUnit_Framework_MockObject_Exception' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Exception/Exception.php',
- 'PHPUnit_Framework_MockObject_Generator' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Generator.php',
- 'PHPUnit_Framework_MockObject_Invocation' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Invocation.php',
- 'PHPUnit_Framework_MockObject_InvocationMocker' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/InvocationMocker.php',
- 'PHPUnit_Framework_MockObject_Invocation_Object' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Invocation/Object.php',
- 'PHPUnit_Framework_MockObject_Invocation_Static' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Invocation/Static.php',
- 'PHPUnit_Framework_MockObject_Invokable' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Invokable.php',
- 'PHPUnit_Framework_MockObject_Matcher' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Matcher.php',
- 'PHPUnit_Framework_MockObject_Matcher_AnyInvokedCount' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Matcher/AnyInvokedCount.php',
- 'PHPUnit_Framework_MockObject_Matcher_AnyParameters' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Matcher/AnyParameters.php',
- 'PHPUnit_Framework_MockObject_Matcher_ConsecutiveParameters' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Matcher/ConsecutiveParameters.php',
- 'PHPUnit_Framework_MockObject_Matcher_Invocation' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Matcher/Invocation.php',
- 'PHPUnit_Framework_MockObject_Matcher_InvokedAtIndex' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Matcher/InvokedAtIndex.php',
- 'PHPUnit_Framework_MockObject_Matcher_InvokedAtLeastCount' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Matcher/InvokedAtLeastCount.php',
- 'PHPUnit_Framework_MockObject_Matcher_InvokedAtLeastOnce' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Matcher/InvokedAtLeastOnce.php',
- 'PHPUnit_Framework_MockObject_Matcher_InvokedAtMostCount' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Matcher/InvokedAtMostCount.php',
- 'PHPUnit_Framework_MockObject_Matcher_InvokedCount' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Matcher/InvokedCount.php',
- 'PHPUnit_Framework_MockObject_Matcher_InvokedRecorder' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Matcher/InvokedRecorder.php',
- 'PHPUnit_Framework_MockObject_Matcher_MethodName' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Matcher/MethodName.php',
- 'PHPUnit_Framework_MockObject_Matcher_Parameters' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Matcher/Parameters.php',
- 'PHPUnit_Framework_MockObject_Matcher_StatelessInvocation' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Matcher/StatelessInvocation.php',
- 'PHPUnit_Framework_MockObject_MockBuilder' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/MockBuilder.php',
- 'PHPUnit_Framework_MockObject_MockObject' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/MockObject.php',
- 'PHPUnit_Framework_MockObject_RuntimeException' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Exception/RuntimeException.php',
- 'PHPUnit_Framework_MockObject_Stub' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Stub.php',
- 'PHPUnit_Framework_MockObject_Stub_ConsecutiveCalls' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Stub/ConsecutiveCalls.php',
- 'PHPUnit_Framework_MockObject_Stub_Exception' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Stub/Exception.php',
- 'PHPUnit_Framework_MockObject_Stub_MatcherCollection' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Stub/MatcherCollection.php',
- 'PHPUnit_Framework_MockObject_Stub_Return' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Stub/Return.php',
- 'PHPUnit_Framework_MockObject_Stub_ReturnArgument' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Stub/ReturnArgument.php',
- 'PHPUnit_Framework_MockObject_Stub_ReturnCallback' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Stub/ReturnCallback.php',
- 'PHPUnit_Framework_MockObject_Stub_ReturnSelf' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Stub/ReturnSelf.php',
- 'PHPUnit_Framework_MockObject_Stub_ReturnValueMap' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Stub/ReturnValueMap.php',
- 'PHPUnit_Framework_MockObject_Verifiable' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Verifiable.php',
- 'PHPUnit_Framework_OutputError' => $vendorDir . '/phpunit/phpunit/src/Framework/OutputError.php',
- 'PHPUnit_Framework_RiskyTest' => $vendorDir . '/phpunit/phpunit/src/Framework/RiskyTest.php',
- 'PHPUnit_Framework_RiskyTestError' => $vendorDir . '/phpunit/phpunit/src/Framework/RiskyTestError.php',
- 'PHPUnit_Framework_SelfDescribing' => $vendorDir . '/phpunit/phpunit/src/Framework/SelfDescribing.php',
- 'PHPUnit_Framework_SkippedTest' => $vendorDir . '/phpunit/phpunit/src/Framework/SkippedTest.php',
- 'PHPUnit_Framework_SkippedTestCase' => $vendorDir . '/phpunit/phpunit/src/Framework/SkippedTestCase.php',
- 'PHPUnit_Framework_SkippedTestError' => $vendorDir . '/phpunit/phpunit/src/Framework/SkippedTestError.php',
- 'PHPUnit_Framework_SkippedTestSuiteError' => $vendorDir . '/phpunit/phpunit/src/Framework/SkippedTestSuiteError.php',
- 'PHPUnit_Framework_SyntheticError' => $vendorDir . '/phpunit/phpunit/src/Framework/SyntheticError.php',
- 'PHPUnit_Framework_Test' => $vendorDir . '/phpunit/phpunit/src/Framework/Test.php',
- 'PHPUnit_Framework_TestCase' => $vendorDir . '/phpunit/phpunit/src/Framework/TestCase.php',
- 'PHPUnit_Framework_TestFailure' => $vendorDir . '/phpunit/phpunit/src/Framework/TestFailure.php',
- 'PHPUnit_Framework_TestListener' => $vendorDir . '/phpunit/phpunit/src/Framework/TestListener.php',
- 'PHPUnit_Framework_TestResult' => $vendorDir . '/phpunit/phpunit/src/Framework/TestResult.php',
- 'PHPUnit_Framework_TestSuite' => $vendorDir . '/phpunit/phpunit/src/Framework/TestSuite.php',
- 'PHPUnit_Framework_TestSuite_DataProvider' => $vendorDir . '/phpunit/phpunit/src/Framework/TestSuite/DataProvider.php',
- 'PHPUnit_Framework_UnintentionallyCoveredCodeError' => $vendorDir . '/phpunit/phpunit/src/Framework/UnintentionallyCoveredCodeError.php',
- 'PHPUnit_Framework_Warning' => $vendorDir . '/phpunit/phpunit/src/Framework/Warning.php',
- 'PHPUnit_Runner_BaseTestRunner' => $vendorDir . '/phpunit/phpunit/src/Runner/BaseTestRunner.php',
- 'PHPUnit_Runner_Exception' => $vendorDir . '/phpunit/phpunit/src/Runner/Exception.php',
- 'PHPUnit_Runner_Filter_Factory' => $vendorDir . '/phpunit/phpunit/src/Runner/Filter/Factory.php',
- 'PHPUnit_Runner_Filter_GroupFilterIterator' => $vendorDir . '/phpunit/phpunit/src/Runner/Filter/Group.php',
- 'PHPUnit_Runner_Filter_Group_Exclude' => $vendorDir . '/phpunit/phpunit/src/Runner/Filter/Group/Exclude.php',
- 'PHPUnit_Runner_Filter_Group_Include' => $vendorDir . '/phpunit/phpunit/src/Runner/Filter/Group/Include.php',
- 'PHPUnit_Runner_Filter_Test' => $vendorDir . '/phpunit/phpunit/src/Runner/Filter/Test.php',
- 'PHPUnit_Runner_StandardTestSuiteLoader' => $vendorDir . '/phpunit/phpunit/src/Runner/StandardTestSuiteLoader.php',
- 'PHPUnit_Runner_TestSuiteLoader' => $vendorDir . '/phpunit/phpunit/src/Runner/TestSuiteLoader.php',
- 'PHPUnit_Runner_Version' => $vendorDir . '/phpunit/phpunit/src/Runner/Version.php',
- 'PHPUnit_TextUI_Command' => $vendorDir . '/phpunit/phpunit/src/TextUI/Command.php',
- 'PHPUnit_TextUI_ResultPrinter' => $vendorDir . '/phpunit/phpunit/src/TextUI/ResultPrinter.php',
- 'PHPUnit_TextUI_TestRunner' => $vendorDir . '/phpunit/phpunit/src/TextUI/TestRunner.php',
- 'PHPUnit_Util_Blacklist' => $vendorDir . '/phpunit/phpunit/src/Util/Blacklist.php',
- 'PHPUnit_Util_Configuration' => $vendorDir . '/phpunit/phpunit/src/Util/Configuration.php',
- 'PHPUnit_Util_ErrorHandler' => $vendorDir . '/phpunit/phpunit/src/Util/ErrorHandler.php',
- 'PHPUnit_Util_Fileloader' => $vendorDir . '/phpunit/phpunit/src/Util/Fileloader.php',
- 'PHPUnit_Util_Filesystem' => $vendorDir . '/phpunit/phpunit/src/Util/Filesystem.php',
- 'PHPUnit_Util_Filter' => $vendorDir . '/phpunit/phpunit/src/Util/Filter.php',
- 'PHPUnit_Util_Getopt' => $vendorDir . '/phpunit/phpunit/src/Util/Getopt.php',
- 'PHPUnit_Util_GlobalState' => $vendorDir . '/phpunit/phpunit/src/Util/GlobalState.php',
- 'PHPUnit_Util_InvalidArgumentHelper' => $vendorDir . '/phpunit/phpunit/src/Util/InvalidArgumentHelper.php',
- 'PHPUnit_Util_Log_JSON' => $vendorDir . '/phpunit/phpunit/src/Util/Log/JSON.php',
- 'PHPUnit_Util_Log_JUnit' => $vendorDir . '/phpunit/phpunit/src/Util/Log/JUnit.php',
- 'PHPUnit_Util_Log_TAP' => $vendorDir . '/phpunit/phpunit/src/Util/Log/TAP.php',
- 'PHPUnit_Util_PHP' => $vendorDir . '/phpunit/phpunit/src/Util/PHP.php',
- 'PHPUnit_Util_PHP_Default' => $vendorDir . '/phpunit/phpunit/src/Util/PHP/Default.php',
- 'PHPUnit_Util_PHP_Windows' => $vendorDir . '/phpunit/phpunit/src/Util/PHP/Windows.php',
- 'PHPUnit_Util_Printer' => $vendorDir . '/phpunit/phpunit/src/Util/Printer.php',
- 'PHPUnit_Util_Regex' => $vendorDir . '/phpunit/phpunit/src/Util/Regex.php',
- 'PHPUnit_Util_String' => $vendorDir . '/phpunit/phpunit/src/Util/String.php',
- 'PHPUnit_Util_Test' => $vendorDir . '/phpunit/phpunit/src/Util/Test.php',
- 'PHPUnit_Util_TestDox_NamePrettifier' => $vendorDir . '/phpunit/phpunit/src/Util/TestDox/NamePrettifier.php',
- 'PHPUnit_Util_TestDox_ResultPrinter' => $vendorDir . '/phpunit/phpunit/src/Util/TestDox/ResultPrinter.php',
- 'PHPUnit_Util_TestDox_ResultPrinter_HTML' => $vendorDir . '/phpunit/phpunit/src/Util/TestDox/ResultPrinter/HTML.php',
- 'PHPUnit_Util_TestDox_ResultPrinter_Text' => $vendorDir . '/phpunit/phpunit/src/Util/TestDox/ResultPrinter/Text.php',
- 'PHPUnit_Util_TestSuiteIterator' => $vendorDir . '/phpunit/phpunit/src/Util/TestSuiteIterator.php',
- 'PHPUnit_Util_Type' => $vendorDir . '/phpunit/phpunit/src/Util/Type.php',
- 'PHPUnit_Util_XML' => $vendorDir . '/phpunit/phpunit/src/Util/XML.php',
- 'PHP_CodeCoverage' => $vendorDir . '/phpunit/php-code-coverage/src/CodeCoverage.php',
- 'PHP_CodeCoverage_Driver' => $vendorDir . '/phpunit/php-code-coverage/src/CodeCoverage/Driver.php',
- 'PHP_CodeCoverage_Driver_HHVM' => $vendorDir . '/phpunit/php-code-coverage/src/CodeCoverage/Driver/HHVM.php',
- 'PHP_CodeCoverage_Driver_Xdebug' => $vendorDir . '/phpunit/php-code-coverage/src/CodeCoverage/Driver/Xdebug.php',
- 'PHP_CodeCoverage_Exception' => $vendorDir . '/phpunit/php-code-coverage/src/CodeCoverage/Exception.php',
- 'PHP_CodeCoverage_Exception_UnintentionallyCoveredCode' => $vendorDir . '/phpunit/php-code-coverage/src/CodeCoverage/Exception/UnintentionallyCoveredCode.php',
- 'PHP_CodeCoverage_Filter' => $vendorDir . '/phpunit/php-code-coverage/src/CodeCoverage/Filter.php',
- 'PHP_CodeCoverage_Report_Clover' => $vendorDir . '/phpunit/php-code-coverage/src/CodeCoverage/Report/Clover.php',
- 'PHP_CodeCoverage_Report_Crap4j' => $vendorDir . '/phpunit/php-code-coverage/src/CodeCoverage/Report/Crap4j.php',
- 'PHP_CodeCoverage_Report_Factory' => $vendorDir . '/phpunit/php-code-coverage/src/CodeCoverage/Report/Factory.php',
- 'PHP_CodeCoverage_Report_HTML' => $vendorDir . '/phpunit/php-code-coverage/src/CodeCoverage/Report/HTML.php',
- 'PHP_CodeCoverage_Report_HTML_Renderer' => $vendorDir . '/phpunit/php-code-coverage/src/CodeCoverage/Report/HTML/Renderer.php',
- 'PHP_CodeCoverage_Report_HTML_Renderer_Dashboard' => $vendorDir . '/phpunit/php-code-coverage/src/CodeCoverage/Report/HTML/Renderer/Dashboard.php',
- 'PHP_CodeCoverage_Report_HTML_Renderer_Directory' => $vendorDir . '/phpunit/php-code-coverage/src/CodeCoverage/Report/HTML/Renderer/Directory.php',
- 'PHP_CodeCoverage_Report_HTML_Renderer_File' => $vendorDir . '/phpunit/php-code-coverage/src/CodeCoverage/Report/HTML/Renderer/File.php',
- 'PHP_CodeCoverage_Report_Node' => $vendorDir . '/phpunit/php-code-coverage/src/CodeCoverage/Report/Node.php',
- 'PHP_CodeCoverage_Report_Node_Directory' => $vendorDir . '/phpunit/php-code-coverage/src/CodeCoverage/Report/Node/Directory.php',
- 'PHP_CodeCoverage_Report_Node_File' => $vendorDir . '/phpunit/php-code-coverage/src/CodeCoverage/Report/Node/File.php',
- 'PHP_CodeCoverage_Report_Node_Iterator' => $vendorDir . '/phpunit/php-code-coverage/src/CodeCoverage/Report/Node/Iterator.php',
- 'PHP_CodeCoverage_Report_PHP' => $vendorDir . '/phpunit/php-code-coverage/src/CodeCoverage/Report/PHP.php',
- 'PHP_CodeCoverage_Report_Text' => $vendorDir . '/phpunit/php-code-coverage/src/CodeCoverage/Report/Text.php',
- 'PHP_CodeCoverage_Report_XML' => $vendorDir . '/phpunit/php-code-coverage/src/CodeCoverage/Report/XML.php',
- 'PHP_CodeCoverage_Report_XML_Directory' => $vendorDir . '/phpunit/php-code-coverage/src/CodeCoverage/Report/XML/Directory.php',
- 'PHP_CodeCoverage_Report_XML_File' => $vendorDir . '/phpunit/php-code-coverage/src/CodeCoverage/Report/XML/File.php',
- 'PHP_CodeCoverage_Report_XML_File_Coverage' => $vendorDir . '/phpunit/php-code-coverage/src/CodeCoverage/Report/XML/File/Coverage.php',
- 'PHP_CodeCoverage_Report_XML_File_Method' => $vendorDir . '/phpunit/php-code-coverage/src/CodeCoverage/Report/XML/File/Method.php',
- 'PHP_CodeCoverage_Report_XML_File_Report' => $vendorDir . '/phpunit/php-code-coverage/src/CodeCoverage/Report/XML/File/Report.php',
- 'PHP_CodeCoverage_Report_XML_File_Unit' => $vendorDir . '/phpunit/php-code-coverage/src/CodeCoverage/Report/XML/File/Unit.php',
- 'PHP_CodeCoverage_Report_XML_Node' => $vendorDir . '/phpunit/php-code-coverage/src/CodeCoverage/Report/XML/Node.php',
- 'PHP_CodeCoverage_Report_XML_Project' => $vendorDir . '/phpunit/php-code-coverage/src/CodeCoverage/Report/XML/Project.php',
- 'PHP_CodeCoverage_Report_XML_Tests' => $vendorDir . '/phpunit/php-code-coverage/src/CodeCoverage/Report/XML/Tests.php',
- 'PHP_CodeCoverage_Report_XML_Totals' => $vendorDir . '/phpunit/php-code-coverage/src/CodeCoverage/Report/XML/Totals.php',
- 'PHP_CodeCoverage_Util' => $vendorDir . '/phpunit/php-code-coverage/src/CodeCoverage/Util.php',
- 'PHP_CodeCoverage_Util_InvalidArgumentHelper' => $vendorDir . '/phpunit/php-code-coverage/src/CodeCoverage/Util/InvalidArgumentHelper.php',
- 'PHP_Timer' => $vendorDir . '/phpunit/php-timer/PHP/Timer.php',
- 'PHP_Token' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_TokenWithScope' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_TokenWithScopeAndVisibility' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_ABSTRACT' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_AMPERSAND' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_AND_EQUAL' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_ARRAY' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_ARRAY_CAST' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_AS' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_AT' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_BACKTICK' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_BAD_CHARACTER' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_BOOLEAN_AND' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_BOOLEAN_OR' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_BOOL_CAST' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_BREAK' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_CALLABLE' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_CARET' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_CASE' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_CATCH' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_CHARACTER' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_CLASS' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_CLASS_C' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_CLASS_NAME_CONSTANT' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_CLONE' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_CLOSE_BRACKET' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_CLOSE_CURLY' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_CLOSE_SQUARE' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_CLOSE_TAG' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_COLON' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_COMMA' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_COMMENT' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_CONCAT_EQUAL' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_CONST' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_CONSTANT_ENCAPSED_STRING' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_CONTINUE' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_CURLY_OPEN' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_DEC' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_DECLARE' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_DEFAULT' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_DIR' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_DIV' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_DIV_EQUAL' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_DNUMBER' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_DO' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_DOC_COMMENT' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_DOLLAR' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_DOLLAR_OPEN_CURLY_BRACES' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_DOT' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_DOUBLE_ARROW' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_DOUBLE_CAST' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_DOUBLE_COLON' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_DOUBLE_QUOTES' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_ECHO' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_ELLIPSIS' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_ELSE' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_ELSEIF' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_EMPTY' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_ENCAPSED_AND_WHITESPACE' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_ENDDECLARE' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_ENDFOR' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_ENDFOREACH' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_ENDIF' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_ENDSWITCH' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_ENDWHILE' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_END_HEREDOC' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_EQUAL' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_EVAL' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_EXCLAMATION_MARK' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_EXIT' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_EXTENDS' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_FILE' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_FINAL' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_FINALLY' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_FOR' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_FOREACH' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_FUNCTION' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_FUNC_C' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_GLOBAL' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_GOTO' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_GT' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_HALT_COMPILER' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_IF' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_IMPLEMENTS' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_INC' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_INCLUDE' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_INCLUDE_ONCE' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_INLINE_HTML' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_INSTANCEOF' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_INSTEADOF' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_INTERFACE' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_INT_CAST' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_ISSET' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_IS_EQUAL' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_IS_GREATER_OR_EQUAL' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_IS_IDENTICAL' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_IS_NOT_EQUAL' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_IS_NOT_IDENTICAL' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_IS_SMALLER_OR_EQUAL' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_Includes' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_LAMBDA_ARROW' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_LAMBDA_CP' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_LAMBDA_OP' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_LINE' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_LIST' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_LNUMBER' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_LOGICAL_AND' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_LOGICAL_OR' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_LOGICAL_XOR' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_LT' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_METHOD_C' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_MINUS' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_MINUS_EQUAL' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_MOD_EQUAL' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_MULT' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_MUL_EQUAL' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_NAMESPACE' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_NEW' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_NS_C' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_NS_SEPARATOR' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_NUM_STRING' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_OBJECT_CAST' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_OBJECT_OPERATOR' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_OPEN_BRACKET' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_OPEN_CURLY' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_OPEN_SQUARE' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_OPEN_TAG' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_OPEN_TAG_WITH_ECHO' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_OR_EQUAL' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_PAAMAYIM_NEKUDOTAYIM' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_PERCENT' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_PIPE' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_PLUS' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_PLUS_EQUAL' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_POW' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_POW_EQUAL' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_PRINT' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_PRIVATE' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_PROTECTED' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_PUBLIC' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_QUESTION_MARK' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_REQUIRE' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_REQUIRE_ONCE' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_RETURN' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_SEMICOLON' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_SHAPE' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_SL' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_SL_EQUAL' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_SR' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_SR_EQUAL' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_START_HEREDOC' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_STATIC' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_STRING' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_STRING_CAST' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_STRING_VARNAME' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_SWITCH' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_Stream' => $vendorDir . '/phpunit/php-token-stream/src/Token/Stream.php',
- 'PHP_Token_Stream_CachingFactory' => $vendorDir . '/phpunit/php-token-stream/src/Token/Stream/CachingFactory.php',
- 'PHP_Token_THROW' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_TILDE' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_TRAIT' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_TRAIT_C' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_TRY' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_TYPE' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_TYPELIST_GT' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_TYPELIST_LT' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_UNSET' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_UNSET_CAST' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_USE' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_VAR' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_VARIABLE' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_WHILE' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_WHITESPACE' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_XOR_EQUAL' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'PHP_Token_YIELD' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
- 'SebastianBergmann\\Comparator\\ArrayComparator' => $vendorDir . '/sebastian/comparator/src/ArrayComparator.php',
- 'SebastianBergmann\\Comparator\\Comparator' => $vendorDir . '/sebastian/comparator/src/Comparator.php',
- 'SebastianBergmann\\Comparator\\ComparisonFailure' => $vendorDir . '/sebastian/comparator/src/ComparisonFailure.php',
- 'SebastianBergmann\\Comparator\\DOMNodeComparator' => $vendorDir . '/sebastian/comparator/src/DOMNodeComparator.php',
- 'SebastianBergmann\\Comparator\\DateTimeComparator' => $vendorDir . '/sebastian/comparator/src/DateTimeComparator.php',
- 'SebastianBergmann\\Comparator\\DoubleComparator' => $vendorDir . '/sebastian/comparator/src/DoubleComparator.php',
- 'SebastianBergmann\\Comparator\\ExceptionComparator' => $vendorDir . '/sebastian/comparator/src/ExceptionComparator.php',
- 'SebastianBergmann\\Comparator\\Factory' => $vendorDir . '/sebastian/comparator/src/Factory.php',
- 'SebastianBergmann\\Comparator\\MockObjectComparator' => $vendorDir . '/sebastian/comparator/src/MockObjectComparator.php',
- 'SebastianBergmann\\Comparator\\NumericComparator' => $vendorDir . '/sebastian/comparator/src/NumericComparator.php',
- 'SebastianBergmann\\Comparator\\ObjectComparator' => $vendorDir . '/sebastian/comparator/src/ObjectComparator.php',
- 'SebastianBergmann\\Comparator\\ResourceComparator' => $vendorDir . '/sebastian/comparator/src/ResourceComparator.php',
- 'SebastianBergmann\\Comparator\\ScalarComparator' => $vendorDir . '/sebastian/comparator/src/ScalarComparator.php',
- 'SebastianBergmann\\Comparator\\SplObjectStorageComparator' => $vendorDir . '/sebastian/comparator/src/SplObjectStorageComparator.php',
- 'SebastianBergmann\\Comparator\\TypeComparator' => $vendorDir . '/sebastian/comparator/src/TypeComparator.php',
- 'SebastianBergmann\\Diff\\Chunk' => $vendorDir . '/sebastian/diff/src/Chunk.php',
- 'SebastianBergmann\\Diff\\Diff' => $vendorDir . '/sebastian/diff/src/Diff.php',
- 'SebastianBergmann\\Diff\\Differ' => $vendorDir . '/sebastian/diff/src/Differ.php',
- 'SebastianBergmann\\Diff\\LCS\\LongestCommonSubsequence' => $vendorDir . '/sebastian/diff/src/LCS/LongestCommonSubsequence.php',
- 'SebastianBergmann\\Diff\\LCS\\MemoryEfficientImplementation' => $vendorDir . '/sebastian/diff/src/LCS/MemoryEfficientLongestCommonSubsequenceImplementation.php',
- 'SebastianBergmann\\Diff\\LCS\\TimeEfficientImplementation' => $vendorDir . '/sebastian/diff/src/LCS/TimeEfficientLongestCommonSubsequenceImplementation.php',
- 'SebastianBergmann\\Diff\\Line' => $vendorDir . '/sebastian/diff/src/Line.php',
- 'SebastianBergmann\\Diff\\Parser' => $vendorDir . '/sebastian/diff/src/Parser.php',
- 'SebastianBergmann\\Environment\\Console' => $vendorDir . '/sebastian/environment/src/Console.php',
- 'SebastianBergmann\\Environment\\Runtime' => $vendorDir . '/sebastian/environment/src/Runtime.php',
- 'SebastianBergmann\\Exporter\\Exporter' => $vendorDir . '/sebastian/exporter/src/Exporter.php',
- 'SebastianBergmann\\GlobalState\\Blacklist' => $vendorDir . '/sebastian/global-state/src/Blacklist.php',
- 'SebastianBergmann\\GlobalState\\Exception' => $vendorDir . '/sebastian/global-state/src/Exception.php',
- 'SebastianBergmann\\GlobalState\\Restorer' => $vendorDir . '/sebastian/global-state/src/Restorer.php',
- 'SebastianBergmann\\GlobalState\\RuntimeException' => $vendorDir . '/sebastian/global-state/src/RuntimeException.php',
- 'SebastianBergmann\\GlobalState\\Snapshot' => $vendorDir . '/sebastian/global-state/src/Snapshot.php',
- 'SebastianBergmann\\RecursionContext\\Context' => $vendorDir . '/sebastian/recursion-context/src/Context.php',
- 'SebastianBergmann\\RecursionContext\\Exception' => $vendorDir . '/sebastian/recursion-context/src/Exception.php',
- 'SebastianBergmann\\RecursionContext\\InvalidArgumentException' => $vendorDir . '/sebastian/recursion-context/src/InvalidArgumentException.php',
- 'SebastianBergmann\\Version' => $vendorDir . '/sebastian/version/src/Version.php',
- 'Text_Template' => $vendorDir . '/phpunit/php-text-template/Text/Template.php',
- );
- <?php
- class ComposerAutoloaderInite50dadd7af3a60367a2353872e1658c3
- {
- private static $loader;
- public static function loadClassLoader($class)
- {
- if ('Composer\Autoload\ClassLoader' === $class) {
- require __DIR__ . '/ClassLoader.php';
- }
- }
- public static function getLoader()
- {
- if (null !== self::$loader) {
- return self::$loader;
- }
- spl_autoload_register(array('ComposerAutoloaderInite50dadd7af3a60367a2353872e1658c3', 'loadClassLoader'), true, true);
- self::$loader = $loader = new \Composer\Autoload\ClassLoader();
- spl_autoload_unregister(array('ComposerAutoloaderInite50dadd7af3a60367a2353872e1658c3', 'loadClassLoader'));
- $includePaths = require __DIR__ . '/include_paths.php';
- array_push($includePaths, get_include_path());
- set_include_path(join(PATH_SEPARATOR, $includePaths));
- $map = require __DIR__ . '/autoload_namespaces.php';
- foreach ($map as $namespace => $path) {
- $loader->set($namespace, $path);
- }
- $map = require __DIR__ . '/autoload_psr4.php';
- foreach ($map as $namespace => $path) {
- $loader->setPsr4($namespace, $path);
- }
- $classMap = require __DIR__ . '/autoload_classmap.php';
- if ($classMap) {
- $loader->addClassMap($classMap);
- }
- $loader->register(true);
- return $loader;
- }
- }
- function composerRequiree50dadd7af3a60367a2353872e1658c3($file)
- {
- require $file;
- }
- <?php
- $vendorDir = dirname(dirname(__FILE__));
- $baseDir = dirname($vendorDir);
- return array(
- $vendorDir . '/phpunit/php-text-template',
- $vendorDir . '/phpunit/php-timer',
- $vendorDir . '/phpunit/php-file-iterator',
- );
- <?php
- namespace Composer\Autoload;
- class ClassLoader
- {
- private $prefixLengthsPsr4 = array();
- private $prefixDirsPsr4 = array();
- private $fallbackDirsPsr4 = array();
- private $prefixesPsr0 = array();
- private $fallbackDirsPsr0 = array();
- private $useIncludePath = false;
- private $classMap = array();
- private $classMapAuthoritative = false;
- public function getPrefixes()
- {
- if (!empty($this->prefixesPsr0)) {
- return call_user_func_array('array_merge', $this->prefixesPsr0);
- }
- return array();
- }
- public function getPrefixesPsr4()
- {
- return $this->prefixDirsPsr4;
- }
- public function getFallbackDirs()
- {
- return $this->fallbackDirsPsr0;
- }
- public function getFallbackDirsPsr4()
- {
- return $this->fallbackDirsPsr4;
- }
- public function getClassMap()
- {
- return $this->classMap;
- }
- public function addClassMap(array $classMap)
- {
- if ($this->classMap) {
- $this->classMap = array_merge($this->classMap, $classMap);
- } else {
- $this->classMap = $classMap;
- }
- }
- public function add($prefix, $paths, $prepend = false)
- {
- if (!$prefix) {
- if ($prepend) {
- $this->fallbackDirsPsr0 = array_merge(
- (array) $paths,
- $this->fallbackDirsPsr0
- );
- } else {
- $this->fallbackDirsPsr0 = array_merge(
- $this->fallbackDirsPsr0,
- (array) $paths
- );
- }
- return;
- }
- $first = $prefix[0];
- if (!isset($this->prefixesPsr0[$first][$prefix])) {
- $this->prefixesPsr0[$first][$prefix] = (array) $paths;
- return;
- }
- if ($prepend) {
- $this->prefixesPsr0[$first][$prefix] = array_merge(
- (array) $paths,
- $this->prefixesPsr0[$first][$prefix]
- );
- } else {
- $this->prefixesPsr0[$first][$prefix] = array_merge(
- $this->prefixesPsr0[$first][$prefix],
- (array) $paths
- );
- }
- }
- public function addPsr4($prefix, $paths, $prepend = false)
- {
- if (!$prefix) {
- if ($prepend) {
- $this->fallbackDirsPsr4 = array_merge(
- (array) $paths,
- $this->fallbackDirsPsr4
- );
- } else {
- $this->fallbackDirsPsr4 = array_merge(
- $this->fallbackDirsPsr4,
- (array) $paths
- );
- }
- } elseif (!isset($this->prefixDirsPsr4[$prefix])) {
- $length = strlen($prefix);
- if ('\\' !== $prefix[$length - 1]) {
- throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
- }
- $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
- $this->prefixDirsPsr4[$prefix] = (array) $paths;
- } elseif ($prepend) {
- $this->prefixDirsPsr4[$prefix] = array_merge(
- (array) $paths,
- $this->prefixDirsPsr4[$prefix]
- );
- } else {
- $this->prefixDirsPsr4[$prefix] = array_merge(
- $this->prefixDirsPsr4[$prefix],
- (array) $paths
- );
- }
- }
- public function set($prefix, $paths)
- {
- if (!$prefix) {
- $this->fallbackDirsPsr0 = (array) $paths;
- } else {
- $this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths;
- }
- }
- public function setPsr4($prefix, $paths)
- {
- if (!$prefix) {
- $this->fallbackDirsPsr4 = (array) $paths;
- } else {
- $length = strlen($prefix);
- if ('\\' !== $prefix[$length - 1]) {
- throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
- }
- $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
- $this->prefixDirsPsr4[$prefix] = (array) $paths;
- }
- }
- public function setUseIncludePath($useIncludePath)
- {
- $this->useIncludePath = $useIncludePath;
- }
- public function getUseIncludePath()
- {
- return $this->useIncludePath;
- }
- public function setClassMapAuthoritative($classMapAuthoritative)
- {
- $this->classMapAuthoritative = $classMapAuthoritative;
- }
- public function isClassMapAuthoritative()
- {
- return $this->classMapAuthoritative;
- }
- public function register($prepend = false)
- {
- spl_autoload_register(array($this, 'loadClass'), true, $prepend);
- }
- public function unregister()
- {
- spl_autoload_unregister(array($this, 'loadClass'));
- }
- public function loadClass($class)
- {
- if ($file = $this->findFile($class)) {
- includeFile($file);
- return true;
- }
- }
- public function findFile($class)
- {
- if ('\\' == $class[0]) {
- $class = substr($class, 1);
- }
- if (isset($this->classMap[$class])) {
- return $this->classMap[$class];
- }
- if ($this->classMapAuthoritative) {
- return false;
- }
- $file = $this->findFileWithExtension($class, '.php');
- if ($file === null && defined('HHVM_VERSION')) {
- $file = $this->findFileWithExtension($class, '.hh');
- }
- if ($file === null) {
- return $this->classMap[$class] = false;
- }
- return $file;
- }
- private function findFileWithExtension($class, $ext)
- {
- $logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext;
- $first = $class[0];
- if (isset($this->prefixLengthsPsr4[$first])) {
- foreach ($this->prefixLengthsPsr4[$first] as $prefix => $length) {
- if (0 === strpos($class, $prefix)) {
- foreach ($this->prefixDirsPsr4[$prefix] as $dir) {
- if (file_exists($file = $dir . DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $length))) {
- return $file;
- }
- }
- }
- }
- }
- foreach ($this->fallbackDirsPsr4 as $dir) {
- if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) {
- return $file;
- }
- }
- if (false !== $pos = strrpos($class, '\\')) {
- $logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1)
- . strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR);
- } else {
- $logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext;
- }
- if (isset($this->prefixesPsr0[$first])) {
- foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) {
- if (0 === strpos($class, $prefix)) {
- foreach ($dirs as $dir) {
- if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
- return $file;
- }
- }
- }
- }
- }
- foreach ($this->fallbackDirsPsr0 as $dir) {
- if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
- return $file;
- }
- }
- if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) {
- return $file;
- }
- }
- }
- function includeFile($file)
- {
- include $file;
- }
- <?php
- if (PHP_SAPI !== 'cli') {
- echo 'Warning: Composer should be invoked via the CLI version of PHP, not the '.PHP_SAPI.' SAPI'.PHP_EOL;
- }
- require __DIR__.'/../src/bootstrap.php';
- use Composer\Console\Application;
- error_reporting(-1);
- if (function_exists('ini_set')) {
- @ini_set('display_errors', 1);
- $memoryInBytes = function ($value) {
- $unit = strtolower(substr($value, -1, 1));
- $value = (int) $value;
- switch($unit) {
- case 'g':
- $value *= 1024;
- // no break (cumulative multiplier)
- case 'm':
- $value *= 1024;
- // no break (cumulative multiplier)
- case 'k':
- $value *= 1024;
- }
- return $value;
- };
- $memoryLimit = trim(ini_get('memory_limit'));
- // Increase memory_limit if it is lower than 512M
- if ($memoryLimit != -1 && $memoryInBytes($memoryLimit) < 512 * 1024 * 1024) {
- @ini_set('memory_limit', '512M');
- }
- unset($memoryInBytes, $memoryLimit);
- }
- // run the command application
- $application = new Application();
- $application->run();
- Copyright (c) 2011 Nils Adermann, Jordi Boggiano
- Permission is hereby granted, free of charge, to any person obtaining a copy
- of this software and associated documentation files (the "Software"), to deal
- in the Software without restriction, including without limitation the rights
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- copies of the Software, and to permit persons to whom the Software is furnished
- to do so, subject to the following conditions:
- The above copyright notice and this permission notice shall be included in all
- copies or substantial portions of the Software.
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- THE SOFTWARE.
- øB®ù”¿ê�Ìçw-¬G�¶Ì*á���GBMB
|