1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011501250135014501550165017501850195020502150225023502450255026502750285029503050315032503350345035503650375038503950405041504250435044504550465047504850495050505150525053505450555056505750585059506050615062506350645065506650675068506950705071507250735074507550765077507850795080508150825083508450855086508750885089509050915092509350945095509650975098509951005101510251035104510551065107510851095110511151125113511451155116511751185119512051215122512351245125512651275128512951305131513251335134513551365137513851395140514151425143514451455146514751485149515051515152515351545155515651575158515951605161516251635164516551665167516851695170517151725173517451755176517751785179518051815182518351845185518651875188518951905191519251935194519551965197519851995200520152025203520452055206520752085209521052115212521352145215521652175218521952205221522252235224522552265227522852295230523152325233523452355236523752385239524052415242524352445245524652475248524952505251525252535254525552565257525852595260526152625263526452655266526752685269527052715272527352745275527652775278527952805281528252835284528552865287528852895290529152925293529452955296529752985299530053015302530353045305530653075308530953105311531253135314531553165317531853195320532153225323532453255326532753285329533053315332533353345335533653375338533953405341534253435344534553465347534853495350535153525353535453555356535753585359536053615362536353645365536653675368536953705371537253735374537553765377537853795380538153825383538453855386538753885389539053915392539353945395539653975398539954005401540254035404540554065407540854095410541154125413541454155416541754185419542054215422542354245425542654275428542954305431543254335434543554365437543854395440544154425443544454455446544754485449545054515452545354545455545654575458545954605461546254635464546554665467546854695470547154725473547454755476547754785479548054815482548354845485548654875488548954905491549254935494549554965497549854995500550155025503550455055506550755085509551055115512551355145515551655175518551955205521552255235524552555265527552855295530553155325533553455355536553755385539554055415542554355445545554655475548554955505551555255535554555555565557555855595560556155625563556455655566556755685569557055715572557355745575557655775578557955805581558255835584558555865587558855895590559155925593559455955596559755985599560056015602560356045605560656075608560956105611561256135614561556165617561856195620562156225623562456255626562756285629563056315632563356345635563656375638563956405641564256435644564556465647564856495650565156525653565456555656565756585659566056615662566356645665566656675668566956705671567256735674567556765677567856795680568156825683568456855686568756885689569056915692569356945695569656975698569957005701570257035704570557065707570857095710571157125713571457155716571757185719572057215722572357245725572657275728572957305731573257335734573557365737573857395740574157425743574457455746574757485749575057515752575357545755575657575758575957605761576257635764576557665767576857695770577157725773577457755776577757785779578057815782578357845785578657875788578957905791579257935794579557965797579857995800580158025803580458055806580758085809581058115812581358145815581658175818581958205821582258235824582558265827582858295830583158325833583458355836583758385839584058415842584358445845584658475848584958505851585258535854585558565857585858595860586158625863586458655866586758685869587058715872587358745875587658775878587958805881588258835884588558865887588858895890589158925893589458955896589758985899590059015902590359045905590659075908590959105911591259135914591559165917591859195920592159225923592459255926592759285929593059315932593359345935593659375938593959405941594259435944594559465947594859495950595159525953595459555956595759585959596059615962596359645965596659675968596959705971597259735974597559765977597859795980598159825983598459855986598759885989599059915992599359945995599659975998599960006001600260036004600560066007600860096010601160126013601460156016601760186019602060216022602360246025602660276028602960306031603260336034603560366037603860396040604160426043604460456046604760486049605060516052605360546055605660576058605960606061606260636064606560666067606860696070607160726073607460756076607760786079608060816082608360846085608660876088608960906091609260936094609560966097609860996100610161026103610461056106610761086109611061116112611361146115611661176118611961206121612261236124612561266127612861296130613161326133613461356136613761386139614061416142614361446145614661476148614961506151615261536154615561566157615861596160616161626163616461656166616761686169617061716172617361746175617661776178617961806181618261836184618561866187618861896190619161926193619461956196619761986199620062016202620362046205620662076208620962106211621262136214621562166217621862196220622162226223622462256226622762286229623062316232623362346235623662376238623962406241624262436244624562466247624862496250625162526253625462556256625762586259626062616262626362646265626662676268626962706271627262736274627562766277627862796280628162826283628462856286628762886289629062916292629362946295629662976298629963006301630263036304630563066307630863096310631163126313631463156316631763186319632063216322632363246325632663276328632963306331633263336334633563366337633863396340634163426343634463456346634763486349635063516352635363546355635663576358635963606361636263636364636563666367636863696370637163726373637463756376637763786379638063816382638363846385638663876388638963906391639263936394639563966397639863996400640164026403640464056406640764086409641064116412641364146415641664176418641964206421642264236424642564266427642864296430643164326433643464356436643764386439644064416442644364446445644664476448644964506451645264536454645564566457645864596460646164626463646464656466646764686469647064716472647364746475647664776478647964806481648264836484648564866487648864896490649164926493649464956496649764986499650065016502650365046505650665076508650965106511651265136514651565166517651865196520652165226523652465256526652765286529653065316532653365346535653665376538653965406541654265436544654565466547654865496550655165526553655465556556655765586559656065616562656365646565656665676568656965706571657265736574657565766577657865796580658165826583658465856586658765886589659065916592659365946595659665976598659966006601660266036604660566066607660866096610661166126613661466156616661766186619662066216622662366246625662666276628662966306631663266336634663566366637663866396640664166426643664466456646664766486649665066516652665366546655665666576658665966606661666266636664666566666667666866696670667166726673667466756676667766786679668066816682668366846685668666876688668966906691669266936694669566966697669866996700670167026703670467056706670767086709671067116712671367146715671667176718671967206721672267236724672567266727672867296730673167326733673467356736673767386739674067416742674367446745674667476748674967506751675267536754675567566757675867596760676167626763676467656766676767686769677067716772677367746775677667776778677967806781678267836784678567866787678867896790679167926793679467956796679767986799680068016802680368046805680668076808680968106811681268136814681568166817681868196820682168226823682468256826682768286829683068316832683368346835683668376838683968406841684268436844684568466847684868496850685168526853685468556856685768586859686068616862686368646865686668676868686968706871687268736874687568766877687868796880688168826883688468856886688768886889689068916892689368946895689668976898689969006901690269036904690569066907690869096910691169126913691469156916691769186919692069216922692369246925692669276928692969306931693269336934693569366937693869396940694169426943694469456946694769486949695069516952695369546955695669576958695969606961696269636964696569666967696869696970697169726973697469756976697769786979698069816982698369846985698669876988698969906991699269936994699569966997699869997000700170027003700470057006700770087009701070117012701370147015701670177018701970207021702270237024702570267027702870297030703170327033703470357036703770387039704070417042704370447045704670477048704970507051705270537054705570567057705870597060706170627063706470657066706770687069707070717072707370747075707670777078707970807081708270837084708570867087708870897090709170927093709470957096709770987099710071017102710371047105710671077108710971107111711271137114711571167117711871197120712171227123712471257126712771287129713071317132713371347135713671377138713971407141714271437144714571467147714871497150715171527153715471557156715771587159716071617162716371647165716671677168716971707171717271737174717571767177717871797180718171827183718471857186718771887189719071917192719371947195719671977198719972007201720272037204720572067207720872097210721172127213721472157216721772187219722072217222722372247225722672277228722972307231723272337234723572367237723872397240724172427243724472457246724772487249725072517252725372547255725672577258725972607261726272637264726572667267726872697270727172727273727472757276727772787279728072817282728372847285728672877288728972907291729272937294729572967297729872997300730173027303730473057306730773087309731073117312731373147315731673177318731973207321732273237324732573267327732873297330733173327333733473357336733773387339734073417342734373447345734673477348734973507351735273537354735573567357735873597360736173627363736473657366736773687369737073717372737373747375737673777378737973807381738273837384738573867387738873897390739173927393739473957396739773987399740074017402740374047405740674077408740974107411741274137414741574167417741874197420742174227423742474257426742774287429743074317432743374347435743674377438743974407441744274437444744574467447744874497450745174527453745474557456745774587459746074617462746374647465746674677468746974707471747274737474747574767477747874797480748174827483748474857486748774887489749074917492749374947495749674977498749975007501750275037504750575067507750875097510751175127513751475157516751775187519752075217522752375247525752675277528752975307531753275337534753575367537753875397540754175427543754475457546754775487549755075517552755375547555755675577558755975607561756275637564756575667567756875697570757175727573757475757576757775787579758075817582758375847585758675877588758975907591759275937594759575967597759875997600760176027603760476057606760776087609761076117612761376147615761676177618761976207621762276237624762576267627762876297630763176327633763476357636763776387639764076417642764376447645764676477648764976507651765276537654765576567657765876597660766176627663766476657666766776687669767076717672767376747675767676777678767976807681768276837684768576867687768876897690769176927693769476957696769776987699770077017702770377047705770677077708770977107711771277137714771577167717771877197720772177227723772477257726772777287729773077317732773377347735773677377738773977407741774277437744774577467747774877497750775177527753775477557756775777587759776077617762776377647765776677677768776977707771777277737774777577767777777877797780778177827783778477857786778777887789779077917792779377947795779677977798779978007801780278037804780578067807780878097810781178127813781478157816781778187819782078217822782378247825782678277828782978307831783278337834783578367837783878397840784178427843784478457846784778487849785078517852785378547855785678577858785978607861786278637864786578667867786878697870787178727873787478757876787778787879788078817882788378847885788678877888788978907891789278937894789578967897789878997900790179027903790479057906790779087909791079117912791379147915791679177918791979207921792279237924792579267927792879297930793179327933793479357936793779387939794079417942794379447945794679477948794979507951795279537954795579567957795879597960796179627963796479657966796779687969797079717972797379747975797679777978797979807981798279837984798579867987798879897990799179927993799479957996799779987999800080018002800380048005800680078008800980108011801280138014801580168017801880198020802180228023802480258026802780288029803080318032803380348035803680378038803980408041804280438044804580468047804880498050805180528053805480558056805780588059806080618062806380648065806680678068806980708071807280738074807580768077807880798080808180828083808480858086808780888089809080918092809380948095809680978098809981008101810281038104810581068107810881098110811181128113811481158116811781188119812081218122812381248125812681278128812981308131813281338134813581368137813881398140814181428143814481458146814781488149815081518152815381548155815681578158815981608161816281638164816581668167816881698170817181728173817481758176817781788179818081818182818381848185818681878188818981908191819281938194819581968197819881998200820182028203820482058206820782088209821082118212821382148215821682178218821982208221822282238224822582268227822882298230823182328233823482358236823782388239824082418242824382448245824682478248824982508251825282538254825582568257825882598260826182628263826482658266826782688269827082718272827382748275827682778278827982808281828282838284828582868287828882898290829182928293829482958296829782988299830083018302830383048305830683078308830983108311831283138314831583168317831883198320832183228323832483258326832783288329833083318332833383348335833683378338833983408341834283438344834583468347834883498350835183528353835483558356835783588359836083618362836383648365836683678368836983708371837283738374837583768377837883798380838183828383838483858386838783888389839083918392839383948395839683978398839984008401840284038404840584068407840884098410841184128413841484158416841784188419842084218422842384248425842684278428842984308431843284338434843584368437843884398440844184428443844484458446844784488449845084518452845384548455845684578458845984608461846284638464846584668467846884698470847184728473847484758476847784788479848084818482848384848485848684878488848984908491849284938494849584968497849884998500850185028503850485058506850785088509851085118512851385148515851685178518851985208521852285238524852585268527852885298530853185328533853485358536853785388539854085418542854385448545854685478548854985508551855285538554855585568557855885598560856185628563856485658566856785688569857085718572857385748575857685778578857985808581858285838584858585868587858885898590859185928593859485958596859785988599860086018602860386048605860686078608860986108611861286138614861586168617861886198620862186228623862486258626862786288629863086318632863386348635863686378638863986408641864286438644864586468647864886498650865186528653865486558656865786588659866086618662866386648665866686678668866986708671867286738674867586768677867886798680868186828683868486858686868786888689869086918692869386948695869686978698869987008701870287038704870587068707870887098710871187128713871487158716871787188719872087218722872387248725872687278728872987308731873287338734873587368737873887398740874187428743874487458746874787488749875087518752875387548755875687578758875987608761876287638764876587668767876887698770877187728773877487758776877787788779878087818782878387848785878687878788878987908791879287938794879587968797879887998800880188028803880488058806880788088809881088118812881388148815881688178818881988208821882288238824882588268827882888298830883188328833883488358836883788388839884088418842884388448845884688478848884988508851885288538854885588568857885888598860886188628863886488658866886788688869887088718872887388748875887688778878887988808881888288838884888588868887888888898890889188928893889488958896889788988899890089018902890389048905890689078908890989108911891289138914891589168917891889198920892189228923892489258926892789288929893089318932893389348935893689378938893989408941894289438944894589468947894889498950895189528953895489558956895789588959896089618962896389648965896689678968896989708971897289738974897589768977897889798980898189828983898489858986898789888989899089918992899389948995899689978998899990009001900290039004900590069007900890099010901190129013901490159016901790189019902090219022902390249025902690279028902990309031903290339034903590369037903890399040904190429043904490459046904790489049905090519052905390549055905690579058905990609061906290639064906590669067906890699070907190729073907490759076907790789079908090819082908390849085908690879088908990909091909290939094909590969097909890999100910191029103910491059106910791089109911091119112911391149115911691179118911991209121912291239124912591269127912891299130913191329133913491359136913791389139914091419142914391449145914691479148914991509151915291539154915591569157915891599160916191629163916491659166916791689169917091719172917391749175917691779178917991809181918291839184918591869187918891899190919191929193919491959196919791989199920092019202920392049205920692079208920992109211921292139214921592169217921892199220922192229223922492259226922792289229923092319232923392349235923692379238923992409241924292439244924592469247924892499250925192529253925492559256925792589259926092619262926392649265926692679268926992709271927292739274927592769277927892799280928192829283928492859286928792889289929092919292929392949295929692979298929993009301930293039304930593069307930893099310931193129313931493159316931793189319932093219322932393249325932693279328932993309331933293339334933593369337933893399340934193429343934493459346934793489349935093519352935393549355935693579358935993609361936293639364936593669367936893699370937193729373937493759376937793789379938093819382938393849385938693879388938993909391939293939394939593969397939893999400940194029403940494059406940794089409941094119412941394149415941694179418941994209421942294239424942594269427942894299430943194329433943494359436943794389439944094419442944394449445944694479448944994509451945294539454945594569457945894599460946194629463946494659466946794689469947094719472947394749475947694779478947994809481948294839484948594869487948894899490949194929493949494959496949794989499950095019502950395049505950695079508950995109511951295139514951595169517951895199520952195229523952495259526952795289529953095319532953395349535953695379538953995409541954295439544954595469547954895499550955195529553955495559556955795589559956095619562956395649565956695679568956995709571957295739574957595769577957895799580958195829583958495859586958795889589959095919592959395949595959695979598959996009601960296039604960596069607960896099610961196129613961496159616961796189619962096219622962396249625962696279628962996309631963296339634963596369637963896399640964196429643964496459646964796489649965096519652965396549655965696579658965996609661966296639664966596669667966896699670967196729673967496759676967796789679968096819682968396849685968696879688968996909691969296939694969596969697969896999700970197029703970497059706970797089709971097119712971397149715971697179718971997209721972297239724972597269727972897299730973197329733973497359736973797389739974097419742974397449745974697479748974997509751975297539754975597569757975897599760976197629763976497659766976797689769977097719772977397749775977697779778977997809781978297839784978597869787978897899790979197929793979497959796979797989799980098019802980398049805980698079808980998109811981298139814981598169817981898199820982198229823982498259826982798289829983098319832983398349835983698379838983998409841984298439844984598469847984898499850985198529853985498559856985798589859986098619862986398649865986698679868986998709871987298739874987598769877987898799880988198829883988498859886988798889889989098919892989398949895989698979898989999009901990299039904990599069907990899099910991199129913991499159916991799189919992099219922992399249925992699279928992999309931993299339934993599369937993899399940994199429943994499459946994799489949995099519952995399549955995699579958995999609961996299639964996599669967996899699970997199729973997499759976997799789979998099819982998399849985998699879988998999909991999299939994999599969997999899991000010001100021000310004100051000610007100081000910010100111001210013100141001510016100171001810019100201002110022100231002410025100261002710028100291003010031100321003310034100351003610037100381003910040100411004210043100441004510046100471004810049100501005110052100531005410055100561005710058100591006010061100621006310064100651006610067100681006910070100711007210073100741007510076100771007810079100801008110082100831008410085100861008710088100891009010091100921009310094100951009610097100981009910100101011010210103101041010510106101071010810109101101011110112101131011410115101161011710118101191012010121101221012310124101251012610127101281012910130101311013210133101341013510136101371013810139101401014110142101431014410145101461014710148101491015010151101521015310154101551015610157101581015910160101611016210163101641016510166101671016810169101701017110172101731017410175101761017710178101791018010181101821018310184101851018610187101881018910190101911019210193101941019510196101971019810199102001020110202102031020410205102061020710208102091021010211102121021310214102151021610217102181021910220102211022210223102241022510226102271022810229102301023110232102331023410235102361023710238102391024010241102421024310244102451024610247102481024910250102511025210253102541025510256102571025810259102601026110262102631026410265102661026710268102691027010271102721027310274102751027610277102781027910280102811028210283102841028510286102871028810289102901029110292102931029410295102961029710298102991030010301103021030310304103051030610307103081030910310103111031210313103141031510316103171031810319103201032110322103231032410325103261032710328103291033010331103321033310334103351033610337103381033910340103411034210343103441034510346103471034810349103501035110352103531035410355103561035710358103591036010361103621036310364103651036610367103681036910370103711037210373103741037510376103771037810379103801038110382103831038410385103861038710388103891039010391103921039310394103951039610397103981039910400104011040210403104041040510406104071040810409104101041110412104131041410415104161041710418104191042010421104221042310424104251042610427104281042910430104311043210433104341043510436104371043810439104401044110442104431044410445104461044710448104491045010451104521045310454104551045610457104581045910460104611046210463104641046510466104671046810469104701047110472104731047410475104761047710478104791048010481104821048310484104851048610487104881048910490104911049210493104941049510496104971049810499105001050110502105031050410505105061050710508105091051010511105121051310514105151051610517105181051910520105211052210523105241052510526105271052810529105301053110532105331053410535105361053710538105391054010541105421054310544105451054610547105481054910550105511055210553105541055510556105571055810559105601056110562105631056410565105661056710568105691057010571105721057310574105751057610577105781057910580105811058210583105841058510586105871058810589105901059110592105931059410595105961059710598105991060010601106021060310604106051060610607106081060910610106111061210613106141061510616106171061810619106201062110622106231062410625106261062710628106291063010631106321063310634106351063610637106381063910640106411064210643106441064510646106471064810649106501065110652106531065410655106561065710658106591066010661106621066310664106651066610667106681066910670106711067210673106741067510676106771067810679106801068110682106831068410685106861068710688106891069010691106921069310694106951069610697106981069910700107011070210703107041070510706107071070810709107101071110712107131071410715107161071710718107191072010721107221072310724107251072610727107281072910730107311073210733107341073510736107371073810739107401074110742107431074410745107461074710748107491075010751107521075310754107551075610757107581075910760107611076210763107641076510766107671076810769107701077110772107731077410775107761077710778107791078010781107821078310784107851078610787107881078910790107911079210793107941079510796107971079810799108001080110802108031080410805108061080710808108091081010811108121081310814108151081610817108181081910820108211082210823108241082510826108271082810829108301083110832108331083410835108361083710838108391084010841108421084310844108451084610847108481084910850108511085210853108541085510856108571085810859108601086110862108631086410865108661086710868108691087010871108721087310874108751087610877108781087910880108811088210883108841088510886108871088810889108901089110892108931089410895108961089710898108991090010901109021090310904109051090610907109081090910910109111091210913109141091510916109171091810919109201092110922109231092410925109261092710928109291093010931109321093310934109351093610937109381093910940109411094210943109441094510946109471094810949109501095110952109531095410955109561095710958109591096010961109621096310964109651096610967109681096910970109711097210973109741097510976109771097810979109801098110982109831098410985109861098710988109891099010991109921099310994109951099610997109981099911000110011100211003110041100511006110071100811009110101101111012110131101411015110161101711018110191102011021110221102311024110251102611027110281102911030110311103211033110341103511036110371103811039110401104111042110431104411045110461104711048110491105011051110521105311054110551105611057110581105911060110611106211063110641106511066110671106811069110701107111072110731107411075110761107711078110791108011081110821108311084110851108611087110881108911090110911109211093110941109511096110971109811099111001110111102111031110411105111061110711108111091111011111111121111311114111151111611117111181111911120111211112211123111241112511126111271112811129111301113111132111331113411135111361113711138111391114011141111421114311144111451114611147111481114911150111511115211153111541115511156111571115811159111601116111162111631116411165111661116711168111691117011171111721117311174111751117611177111781117911180111811118211183111841118511186111871118811189111901119111192111931119411195111961119711198111991120011201112021120311204112051120611207112081120911210112111121211213112141121511216112171121811219112201122111222112231122411225112261122711228112291123011231112321123311234112351123611237112381123911240112411124211243112441124511246112471124811249112501125111252112531125411255112561125711258112591126011261112621126311264112651126611267112681126911270112711127211273112741127511276112771127811279112801128111282112831128411285112861128711288112891129011291112921129311294112951129611297112981129911300113011130211303113041130511306113071130811309113101131111312113131131411315113161131711318113191132011321113221132311324113251132611327113281132911330113311133211333113341133511336113371133811339113401134111342113431134411345113461134711348113491135011351113521135311354113551135611357113581135911360113611136211363113641136511366113671136811369113701137111372113731137411375113761137711378113791138011381113821138311384113851138611387113881138911390113911139211393113941139511396113971139811399114001140111402114031140411405114061140711408114091141011411114121141311414114151141611417114181141911420114211142211423114241142511426114271142811429114301143111432114331143411435114361143711438114391144011441114421144311444114451144611447114481144911450114511145211453114541145511456114571145811459114601146111462114631146411465114661146711468114691147011471114721147311474114751147611477114781147911480114811148211483114841148511486114871148811489114901149111492114931149411495114961149711498114991150011501115021150311504115051150611507115081150911510115111151211513115141151511516115171151811519115201152111522115231152411525115261152711528115291153011531115321153311534115351153611537115381153911540115411154211543115441154511546115471154811549115501155111552115531155411555115561155711558115591156011561115621156311564115651156611567115681156911570115711157211573115741157511576115771157811579115801158111582115831158411585115861158711588115891159011591115921159311594115951159611597115981159911600116011160211603116041160511606116071160811609116101161111612116131161411615116161161711618116191162011621116221162311624116251162611627116281162911630116311163211633116341163511636116371163811639116401164111642116431164411645116461164711648116491165011651116521165311654116551165611657116581165911660116611166211663116641166511666116671166811669116701167111672116731167411675116761167711678116791168011681116821168311684116851168611687116881168911690116911169211693116941169511696116971169811699117001170111702117031170411705117061170711708117091171011711117121171311714117151171611717117181171911720117211172211723117241172511726117271172811729117301173111732117331173411735117361173711738117391174011741117421174311744117451174611747117481174911750117511175211753117541175511756117571175811759117601176111762117631176411765117661176711768117691177011771117721177311774117751177611777117781177911780117811178211783117841178511786117871178811789117901179111792117931179411795117961179711798117991180011801118021180311804118051180611807118081180911810118111181211813118141181511816118171181811819118201182111822118231182411825118261182711828118291183011831118321183311834118351183611837118381183911840118411184211843118441184511846118471184811849118501185111852118531185411855118561185711858118591186011861118621186311864118651186611867118681186911870118711187211873118741187511876118771187811879118801188111882118831188411885118861188711888118891189011891118921189311894118951189611897118981189911900119011190211903119041190511906119071190811909119101191111912119131191411915119161191711918119191192011921119221192311924119251192611927119281192911930119311193211933119341193511936119371193811939119401194111942119431194411945119461194711948119491195011951119521195311954119551195611957119581195911960119611196211963119641196511966119671196811969119701197111972119731197411975119761197711978119791198011981119821198311984119851198611987119881198911990119911199211993119941199511996119971199811999120001200112002120031200412005120061200712008120091201012011120121201312014120151201612017120181201912020120211202212023120241202512026120271202812029120301203112032120331203412035120361203712038120391204012041120421204312044120451204612047120481204912050120511205212053120541205512056120571205812059120601206112062120631206412065120661206712068120691207012071120721207312074120751207612077120781207912080120811208212083120841208512086120871208812089120901209112092120931209412095120961209712098120991210012101121021210312104121051210612107121081210912110121111211212113121141211512116121171211812119121201212112122121231212412125121261212712128121291213012131121321213312134121351213612137121381213912140121411214212143121441214512146121471214812149121501215112152121531215412155121561215712158121591216012161121621216312164121651216612167121681216912170121711217212173121741217512176121771217812179121801218112182121831218412185121861218712188121891219012191121921219312194121951219612197121981219912200122011220212203122041220512206122071220812209122101221112212122131221412215122161221712218122191222012221122221222312224122251222612227122281222912230122311223212233122341223512236122371223812239122401224112242122431224412245122461224712248122491225012251122521225312254122551225612257122581225912260122611226212263122641226512266122671226812269122701227112272122731227412275122761227712278122791228012281122821228312284122851228612287122881228912290122911229212293122941229512296122971229812299123001230112302123031230412305123061230712308123091231012311123121231312314123151231612317123181231912320123211232212323123241232512326123271232812329123301233112332123331233412335123361233712338123391234012341123421234312344123451234612347123481234912350123511235212353123541235512356123571235812359123601236112362123631236412365123661236712368123691237012371123721237312374123751237612377123781237912380123811238212383123841238512386123871238812389123901239112392123931239412395123961239712398123991240012401124021240312404124051240612407124081240912410124111241212413124141241512416124171241812419124201242112422124231242412425124261242712428124291243012431124321243312434124351243612437124381243912440124411244212443124441244512446124471244812449124501245112452124531245412455124561245712458124591246012461124621246312464124651246612467124681246912470124711247212473124741247512476124771247812479124801248112482124831248412485124861248712488124891249012491124921249312494124951249612497124981249912500125011250212503125041250512506125071250812509125101251112512125131251412515125161251712518125191252012521125221252312524125251252612527125281252912530125311253212533125341253512536125371253812539125401254112542125431254412545125461254712548125491255012551125521255312554125551255612557125581255912560125611256212563125641256512566125671256812569125701257112572125731257412575125761257712578125791258012581125821258312584125851258612587125881258912590125911259212593125941259512596125971259812599126001260112602126031260412605126061260712608126091261012611126121261312614126151261612617126181261912620126211262212623126241262512626126271262812629126301263112632126331263412635126361263712638126391264012641126421264312644126451264612647126481264912650126511265212653126541265512656126571265812659126601266112662126631266412665126661266712668126691267012671126721267312674126751267612677126781267912680126811268212683126841268512686126871268812689126901269112692126931269412695126961269712698126991270012701127021270312704127051270612707127081270912710127111271212713127141271512716127171271812719127201272112722127231272412725127261272712728127291273012731127321273312734127351273612737127381273912740127411274212743127441274512746127471274812749127501275112752127531275412755127561275712758127591276012761127621276312764127651276612767127681276912770127711277212773127741277512776127771277812779127801278112782127831278412785127861278712788127891279012791127921279312794127951279612797127981279912800128011280212803128041280512806128071280812809128101281112812128131281412815128161281712818128191282012821128221282312824128251282612827128281282912830128311283212833128341283512836128371283812839128401284112842128431284412845128461284712848128491285012851128521285312854128551285612857128581285912860128611286212863128641286512866128671286812869128701287112872128731287412875128761287712878128791288012881128821288312884128851288612887128881288912890128911289212893128941289512896128971289812899129001290112902129031290412905129061290712908129091291012911129121291312914129151291612917129181291912920129211292212923129241292512926129271292812929129301293112932129331293412935129361293712938129391294012941129421294312944129451294612947129481294912950129511295212953129541295512956129571295812959129601296112962129631296412965129661296712968129691297012971129721297312974129751297612977129781297912980129811298212983129841298512986129871298812989129901299112992129931299412995129961299712998129991300013001130021300313004130051300613007130081300913010130111301213013130141301513016130171301813019130201302113022130231302413025130261302713028130291303013031130321303313034130351303613037130381303913040130411304213043130441304513046130471304813049130501305113052130531305413055130561305713058130591306013061130621306313064130651306613067130681306913070130711307213073130741307513076130771307813079130801308113082130831308413085130861308713088130891309013091130921309313094130951309613097130981309913100131011310213103131041310513106131071310813109131101311113112131131311413115131161311713118131191312013121131221312313124131251312613127131281312913130131311313213133131341313513136131371313813139131401314113142131431314413145131461314713148131491315013151131521315313154131551315613157131581315913160131611316213163131641316513166131671316813169131701317113172131731317413175131761317713178131791318013181131821318313184131851318613187131881318913190131911319213193131941319513196131971319813199132001320113202132031320413205132061320713208132091321013211132121321313214132151321613217132181321913220132211322213223132241322513226132271322813229132301323113232132331323413235132361323713238132391324013241132421324313244132451324613247132481324913250132511325213253132541325513256132571325813259132601326113262132631326413265132661326713268132691327013271132721327313274132751327613277132781327913280132811328213283132841328513286132871328813289132901329113292132931329413295132961329713298132991330013301133021330313304133051330613307133081330913310133111331213313133141331513316133171331813319133201332113322133231332413325133261332713328133291333013331133321333313334133351333613337133381333913340133411334213343133441334513346133471334813349133501335113352133531335413355133561335713358133591336013361133621336313364133651336613367133681336913370133711337213373133741337513376133771337813379133801338113382133831338413385133861338713388133891339013391133921339313394133951339613397133981339913400134011340213403134041340513406134071340813409134101341113412134131341413415134161341713418134191342013421134221342313424134251342613427134281342913430134311343213433134341343513436134371343813439134401344113442134431344413445134461344713448134491345013451134521345313454134551345613457134581345913460134611346213463134641346513466134671346813469134701347113472134731347413475134761347713478134791348013481134821348313484134851348613487134881348913490134911349213493134941349513496134971349813499135001350113502135031350413505135061350713508135091351013511135121351313514135151351613517135181351913520135211352213523135241352513526135271352813529135301353113532135331353413535135361353713538135391354013541135421354313544135451354613547135481354913550135511355213553135541355513556135571355813559135601356113562135631356413565135661356713568135691357013571135721357313574135751357613577135781357913580135811358213583135841358513586135871358813589135901359113592135931359413595135961359713598135991360013601136021360313604136051360613607136081360913610136111361213613136141361513616136171361813619136201362113622136231362413625136261362713628136291363013631136321363313634136351363613637136381363913640136411364213643136441364513646136471364813649136501365113652136531365413655136561365713658136591366013661136621366313664136651366613667136681366913670136711367213673136741367513676136771367813679136801368113682136831368413685136861368713688136891369013691136921369313694136951369613697136981369913700137011370213703137041370513706137071370813709137101371113712137131371413715137161371713718137191372013721137221372313724137251372613727137281372913730137311373213733137341373513736137371373813739137401374113742137431374413745137461374713748137491375013751137521375313754137551375613757137581375913760137611376213763137641376513766137671376813769137701377113772137731377413775137761377713778137791378013781137821378313784137851378613787137881378913790137911379213793137941379513796137971379813799138001380113802138031380413805138061380713808138091381013811138121381313814138151381613817138181381913820138211382213823138241382513826138271382813829138301383113832138331383413835138361383713838138391384013841138421384313844138451384613847138481384913850138511385213853138541385513856138571385813859138601386113862138631386413865138661386713868138691387013871138721387313874138751387613877138781387913880138811388213883138841388513886138871388813889138901389113892138931389413895138961389713898138991390013901139021390313904139051390613907139081390913910139111391213913139141391513916139171391813919139201392113922139231392413925139261392713928139291393013931139321393313934139351393613937139381393913940139411394213943139441394513946139471394813949139501395113952139531395413955139561395713958139591396013961139621396313964139651396613967139681396913970139711397213973139741397513976139771397813979139801398113982139831398413985139861398713988139891399013991139921399313994139951399613997139981399914000140011400214003140041400514006140071400814009140101401114012140131401414015140161401714018140191402014021140221402314024140251402614027140281402914030140311403214033140341403514036140371403814039140401404114042140431404414045140461404714048140491405014051140521405314054140551405614057140581405914060140611406214063140641406514066140671406814069140701407114072140731407414075140761407714078140791408014081140821408314084140851408614087140881408914090140911409214093140941409514096140971409814099141001410114102141031410414105141061410714108141091411014111141121411314114141151411614117141181411914120141211412214123141241412514126141271412814129141301413114132141331413414135141361413714138141391414014141141421414314144141451414614147141481414914150141511415214153141541415514156141571415814159141601416114162141631416414165141661416714168141691417014171141721417314174141751417614177141781417914180141811418214183141841418514186141871418814189141901419114192141931419414195141961419714198141991420014201142021420314204142051420614207142081420914210142111421214213142141421514216142171421814219142201422114222142231422414225142261422714228142291423014231142321423314234142351423614237142381423914240142411424214243142441424514246142471424814249142501425114252142531425414255142561425714258142591426014261142621426314264142651426614267142681426914270142711427214273142741427514276142771427814279142801428114282142831428414285142861428714288142891429014291142921429314294142951429614297142981429914300143011430214303143041430514306143071430814309143101431114312143131431414315143161431714318143191432014321143221432314324143251432614327143281432914330143311433214333143341433514336143371433814339143401434114342143431434414345143461434714348143491435014351143521435314354143551435614357143581435914360143611436214363143641436514366143671436814369143701437114372143731437414375143761437714378143791438014381143821438314384143851438614387143881438914390143911439214393143941439514396143971439814399144001440114402144031440414405144061440714408144091441014411144121441314414144151441614417144181441914420144211442214423144241442514426144271442814429144301443114432144331443414435144361443714438144391444014441144421444314444144451444614447144481444914450144511445214453144541445514456144571445814459144601446114462144631446414465144661446714468144691447014471144721447314474144751447614477144781447914480144811448214483144841448514486144871448814489144901449114492144931449414495144961449714498144991450014501145021450314504145051450614507145081450914510145111451214513145141451514516145171451814519145201452114522145231452414525145261452714528145291453014531145321453314534145351453614537145381453914540145411454214543145441454514546145471454814549145501455114552145531455414555145561455714558145591456014561145621456314564145651456614567145681456914570145711457214573145741457514576145771457814579145801458114582145831458414585145861458714588145891459014591145921459314594145951459614597145981459914600146011460214603146041460514606146071460814609146101461114612146131461414615146161461714618146191462014621146221462314624146251462614627146281462914630146311463214633146341463514636146371463814639146401464114642146431464414645146461464714648146491465014651146521465314654146551465614657146581465914660146611466214663146641466514666146671466814669146701467114672146731467414675146761467714678146791468014681146821468314684146851468614687146881468914690146911469214693146941469514696146971469814699147001470114702147031470414705147061470714708147091471014711147121471314714147151471614717147181471914720147211472214723147241472514726147271472814729147301473114732147331473414735147361473714738147391474014741147421474314744147451474614747147481474914750147511475214753147541475514756147571475814759147601476114762147631476414765147661476714768147691477014771147721477314774147751477614777147781477914780147811478214783147841478514786147871478814789147901479114792147931479414795147961479714798147991480014801148021480314804148051480614807148081480914810148111481214813148141481514816148171481814819148201482114822148231482414825148261482714828148291483014831148321483314834148351483614837148381483914840148411484214843148441484514846148471484814849148501485114852148531485414855148561485714858148591486014861148621486314864148651486614867148681486914870148711487214873148741487514876148771487814879148801488114882148831488414885148861488714888148891489014891148921489314894148951489614897148981489914900149011490214903149041490514906149071490814909149101491114912149131491414915149161491714918149191492014921149221492314924149251492614927149281492914930149311493214933149341493514936149371493814939149401494114942149431494414945149461494714948149491495014951149521495314954149551495614957149581495914960149611496214963149641496514966149671496814969149701497114972149731497414975149761497714978149791498014981149821498314984149851498614987149881498914990149911499214993149941499514996149971499814999150001500115002150031500415005150061500715008150091501015011150121501315014150151501615017150181501915020150211502215023150241502515026150271502815029150301503115032150331503415035150361503715038150391504015041150421504315044150451504615047150481504915050150511505215053150541505515056150571505815059150601506115062150631506415065150661506715068150691507015071150721507315074150751507615077150781507915080150811508215083150841508515086150871508815089150901509115092150931509415095150961509715098150991510015101151021510315104151051510615107151081510915110151111511215113151141511515116151171511815119151201512115122151231512415125151261512715128151291513015131151321513315134151351513615137151381513915140151411514215143151441514515146151471514815149151501515115152151531515415155151561515715158151591516015161151621516315164151651516615167151681516915170151711517215173151741517515176151771517815179151801518115182151831518415185151861518715188151891519015191151921519315194151951519615197151981519915200152011520215203152041520515206152071520815209152101521115212152131521415215152161521715218152191522015221152221522315224152251522615227152281522915230152311523215233152341523515236152371523815239152401524115242152431524415245152461524715248152491525015251152521525315254152551525615257152581525915260152611526215263152641526515266152671526815269152701527115272152731527415275152761527715278152791528015281152821528315284152851528615287152881528915290152911529215293152941529515296152971529815299153001530115302153031530415305153061530715308153091531015311153121531315314153151531615317153181531915320153211532215323153241532515326153271532815329153301533115332153331533415335153361533715338153391534015341153421534315344153451534615347153481534915350153511535215353153541535515356153571535815359153601536115362153631536415365153661536715368153691537015371153721537315374153751537615377153781537915380153811538215383153841538515386153871538815389153901539115392153931539415395153961539715398153991540015401154021540315404154051540615407154081540915410154111541215413154141541515416154171541815419154201542115422154231542415425154261542715428154291543015431154321543315434154351543615437154381543915440154411544215443154441544515446154471544815449154501545115452154531545415455154561545715458154591546015461154621546315464154651546615467154681546915470154711547215473154741547515476154771547815479154801548115482154831548415485154861548715488154891549015491154921549315494154951549615497154981549915500155011550215503155041550515506155071550815509155101551115512155131551415515155161551715518155191552015521155221552315524155251552615527155281552915530155311553215533155341553515536155371553815539155401554115542155431554415545155461554715548155491555015551155521555315554155551555615557155581555915560155611556215563155641556515566155671556815569155701557115572155731557415575155761557715578155791558015581155821558315584155851558615587155881558915590155911559215593155941559515596155971559815599156001560115602156031560415605156061560715608156091561015611156121561315614156151561615617156181561915620156211562215623156241562515626156271562815629156301563115632156331563415635156361563715638156391564015641156421564315644156451564615647156481564915650156511565215653156541565515656156571565815659156601566115662156631566415665156661566715668156691567015671156721567315674156751567615677156781567915680156811568215683156841568515686156871568815689156901569115692156931569415695156961569715698156991570015701157021570315704157051570615707157081570915710157111571215713157141571515716157171571815719157201572115722157231572415725157261572715728157291573015731157321573315734157351573615737157381573915740157411574215743157441574515746157471574815749157501575115752157531575415755157561575715758157591576015761157621576315764157651576615767157681576915770157711577215773157741577515776157771577815779157801578115782157831578415785157861578715788157891579015791157921579315794157951579615797157981579915800158011580215803158041580515806158071580815809158101581115812158131581415815158161581715818158191582015821158221582315824158251582615827158281582915830158311583215833158341583515836158371583815839158401584115842158431584415845158461584715848158491585015851158521585315854158551585615857158581585915860158611586215863158641586515866158671586815869158701587115872158731587415875158761587715878158791588015881158821588315884158851588615887158881588915890158911589215893158941589515896158971589815899159001590115902159031590415905159061590715908159091591015911159121591315914159151591615917159181591915920159211592215923159241592515926159271592815929159301593115932159331593415935159361593715938159391594015941159421594315944159451594615947159481594915950159511595215953159541595515956159571595815959159601596115962159631596415965159661596715968159691597015971159721597315974159751597615977159781597915980159811598215983159841598515986159871598815989159901599115992159931599415995159961599715998159991600016001160021600316004160051600616007160081600916010160111601216013160141601516016160171601816019160201602116022160231602416025160261602716028160291603016031160321603316034160351603616037160381603916040160411604216043160441604516046160471604816049160501605116052160531605416055160561605716058160591606016061160621606316064160651606616067160681606916070160711607216073160741607516076160771607816079160801608116082160831608416085160861608716088160891609016091160921609316094160951609616097160981609916100161011610216103161041610516106161071610816109161101611116112161131611416115161161611716118161191612016121161221612316124161251612616127161281612916130161311613216133161341613516136161371613816139161401614116142161431614416145161461614716148161491615016151161521615316154161551615616157161581615916160161611616216163161641616516166161671616816169161701617116172161731617416175161761617716178161791618016181161821618316184161851618616187161881618916190161911619216193161941619516196161971619816199162001620116202162031620416205162061620716208162091621016211162121621316214162151621616217162181621916220162211622216223162241622516226162271622816229162301623116232162331623416235162361623716238162391624016241162421624316244162451624616247162481624916250162511625216253162541625516256162571625816259162601626116262162631626416265162661626716268162691627016271162721627316274162751627616277162781627916280162811628216283162841628516286162871628816289162901629116292162931629416295162961629716298162991630016301163021630316304163051630616307163081630916310163111631216313163141631516316163171631816319163201632116322163231632416325163261632716328163291633016331163321633316334163351633616337163381633916340163411634216343163441634516346163471634816349163501635116352163531635416355163561635716358163591636016361163621636316364163651636616367163681636916370163711637216373163741637516376163771637816379163801638116382163831638416385163861638716388163891639016391163921639316394163951639616397163981639916400164011640216403164041640516406164071640816409164101641116412164131641416415164161641716418164191642016421164221642316424164251642616427164281642916430164311643216433164341643516436164371643816439164401644116442164431644416445164461644716448164491645016451164521645316454164551645616457164581645916460164611646216463164641646516466164671646816469164701647116472164731647416475164761647716478164791648016481164821648316484164851648616487164881648916490164911649216493164941649516496164971649816499165001650116502165031650416505165061650716508165091651016511165121651316514165151651616517165181651916520165211652216523165241652516526165271652816529165301653116532165331653416535165361653716538165391654016541165421654316544165451654616547165481654916550165511655216553165541655516556165571655816559165601656116562165631656416565165661656716568165691657016571165721657316574165751657616577165781657916580165811658216583165841658516586165871658816589165901659116592165931659416595165961659716598165991660016601166021660316604166051660616607166081660916610166111661216613166141661516616166171661816619166201662116622166231662416625166261662716628166291663016631166321663316634166351663616637166381663916640166411664216643166441664516646166471664816649166501665116652166531665416655166561665716658166591666016661166621666316664166651666616667166681666916670166711667216673166741667516676166771667816679166801668116682166831668416685166861668716688166891669016691166921669316694166951669616697166981669916700167011670216703167041670516706167071670816709167101671116712167131671416715167161671716718167191672016721167221672316724167251672616727167281672916730167311673216733167341673516736167371673816739167401674116742167431674416745167461674716748167491675016751167521675316754167551675616757167581675916760167611676216763167641676516766167671676816769167701677116772167731677416775167761677716778167791678016781167821678316784167851678616787167881678916790167911679216793167941679516796167971679816799168001680116802168031680416805168061680716808168091681016811168121681316814168151681616817168181681916820168211682216823168241682516826168271682816829168301683116832168331683416835168361683716838168391684016841168421684316844168451684616847168481684916850168511685216853168541685516856168571685816859168601686116862168631686416865168661686716868168691687016871168721687316874168751687616877168781687916880168811688216883168841688516886168871688816889168901689116892168931689416895168961689716898168991690016901169021690316904169051690616907169081690916910169111691216913169141691516916169171691816919169201692116922169231692416925169261692716928169291693016931169321693316934169351693616937169381693916940169411694216943169441694516946169471694816949169501695116952169531695416955169561695716958169591696016961169621696316964169651696616967169681696916970169711697216973169741697516976169771697816979169801698116982169831698416985169861698716988169891699016991169921699316994169951699616997169981699917000170011700217003170041700517006170071700817009170101701117012170131701417015170161701717018170191702017021170221702317024170251702617027170281702917030170311703217033170341703517036170371703817039170401704117042170431704417045170461704717048170491705017051170521705317054170551705617057170581705917060170611706217063170641706517066170671706817069170701707117072170731707417075170761707717078170791708017081170821708317084170851708617087170881708917090170911709217093170941709517096170971709817099171001710117102171031710417105171061710717108171091711017111171121711317114171151711617117171181711917120171211712217123171241712517126171271712817129171301713117132171331713417135171361713717138171391714017141171421714317144171451714617147171481714917150171511715217153171541715517156171571715817159171601716117162171631716417165171661716717168171691717017171171721717317174171751717617177171781717917180171811718217183171841718517186171871718817189171901719117192171931719417195171961719717198171991720017201172021720317204172051720617207172081720917210172111721217213172141721517216172171721817219172201722117222172231722417225172261722717228172291723017231172321723317234172351723617237172381723917240172411724217243172441724517246172471724817249172501725117252172531725417255172561725717258172591726017261172621726317264172651726617267172681726917270172711727217273172741727517276172771727817279172801728117282172831728417285172861728717288172891729017291172921729317294172951729617297172981729917300173011730217303173041730517306173071730817309173101731117312173131731417315173161731717318173191732017321173221732317324173251732617327173281732917330173311733217333173341733517336173371733817339173401734117342173431734417345173461734717348173491735017351173521735317354173551735617357173581735917360173611736217363173641736517366173671736817369173701737117372173731737417375173761737717378173791738017381173821738317384173851738617387173881738917390173911739217393173941739517396173971739817399174001740117402174031740417405174061740717408174091741017411174121741317414174151741617417174181741917420174211742217423174241742517426174271742817429174301743117432174331743417435174361743717438174391744017441174421744317444174451744617447174481744917450174511745217453174541745517456174571745817459174601746117462174631746417465174661746717468174691747017471174721747317474174751747617477174781747917480174811748217483174841748517486174871748817489174901749117492174931749417495174961749717498174991750017501175021750317504175051750617507175081750917510175111751217513175141751517516175171751817519175201752117522175231752417525175261752717528175291753017531175321753317534175351753617537175381753917540175411754217543175441754517546175471754817549175501755117552175531755417555175561755717558175591756017561175621756317564175651756617567175681756917570175711757217573175741757517576175771757817579175801758117582175831758417585175861758717588175891759017591175921759317594175951759617597175981759917600176011760217603176041760517606176071760817609176101761117612176131761417615176161761717618176191762017621176221762317624176251762617627176281762917630176311763217633176341763517636176371763817639176401764117642176431764417645176461764717648176491765017651176521765317654176551765617657176581765917660176611766217663176641766517666176671766817669176701767117672176731767417675176761767717678176791768017681176821768317684176851768617687176881768917690176911769217693176941769517696176971769817699177001770117702177031770417705177061770717708177091771017711177121771317714177151771617717177181771917720177211772217723177241772517726177271772817729177301773117732177331773417735177361773717738177391774017741177421774317744177451774617747177481774917750177511775217753177541775517756177571775817759177601776117762177631776417765177661776717768177691777017771177721777317774177751777617777177781777917780177811778217783177841778517786177871778817789177901779117792177931779417795177961779717798177991780017801178021780317804178051780617807178081780917810178111781217813178141781517816178171781817819178201782117822178231782417825178261782717828178291783017831178321783317834178351783617837178381783917840178411784217843178441784517846178471784817849178501785117852178531785417855178561785717858178591786017861178621786317864178651786617867178681786917870178711787217873178741787517876178771787817879178801788117882178831788417885178861788717888178891789017891178921789317894178951789617897178981789917900179011790217903179041790517906179071790817909179101791117912179131791417915179161791717918179191792017921179221792317924179251792617927179281792917930179311793217933179341793517936179371793817939179401794117942179431794417945179461794717948179491795017951179521795317954179551795617957179581795917960179611796217963179641796517966179671796817969179701797117972179731797417975179761797717978179791798017981179821798317984179851798617987179881798917990179911799217993179941799517996179971799817999180001800118002180031800418005180061800718008180091801018011180121801318014180151801618017180181801918020180211802218023180241802518026180271802818029180301803118032180331803418035180361803718038180391804018041180421804318044180451804618047180481804918050180511805218053180541805518056180571805818059180601806118062180631806418065180661806718068180691807018071180721807318074180751807618077180781807918080180811808218083180841808518086180871808818089180901809118092180931809418095180961809718098180991810018101181021810318104181051810618107181081810918110181111811218113181141811518116181171811818119181201812118122181231812418125181261812718128181291813018131181321813318134181351813618137181381813918140181411814218143181441814518146181471814818149181501815118152181531815418155181561815718158181591816018161181621816318164181651816618167181681816918170181711817218173181741817518176181771817818179181801818118182181831818418185181861818718188181891819018191181921819318194181951819618197181981819918200182011820218203182041820518206182071820818209182101821118212182131821418215182161821718218182191822018221182221822318224182251822618227182281822918230182311823218233182341823518236182371823818239182401824118242182431824418245182461824718248182491825018251182521825318254182551825618257182581825918260182611826218263182641826518266182671826818269182701827118272182731827418275182761827718278182791828018281182821828318284182851828618287182881828918290182911829218293182941829518296182971829818299183001830118302183031830418305183061830718308183091831018311183121831318314183151831618317183181831918320183211832218323183241832518326183271832818329183301833118332183331833418335183361833718338183391834018341183421834318344183451834618347183481834918350183511835218353183541835518356183571835818359183601836118362183631836418365183661836718368183691837018371183721837318374183751837618377183781837918380183811838218383183841838518386183871838818389183901839118392183931839418395183961839718398183991840018401184021840318404184051840618407184081840918410184111841218413184141841518416184171841818419184201842118422184231842418425184261842718428184291843018431184321843318434184351843618437184381843918440184411844218443184441844518446184471844818449184501845118452184531845418455184561845718458184591846018461184621846318464184651846618467184681846918470184711847218473184741847518476184771847818479184801848118482184831848418485184861848718488184891849018491184921849318494184951849618497184981849918500185011850218503185041850518506185071850818509185101851118512185131851418515185161851718518185191852018521185221852318524185251852618527185281852918530185311853218533185341853518536185371853818539185401854118542185431854418545185461854718548185491855018551185521855318554185551855618557185581855918560185611856218563185641856518566185671856818569185701857118572185731857418575185761857718578185791858018581185821858318584185851858618587185881858918590185911859218593185941859518596185971859818599186001860118602186031860418605186061860718608186091861018611186121861318614186151861618617186181861918620186211862218623186241862518626186271862818629186301863118632186331863418635186361863718638186391864018641186421864318644186451864618647186481864918650186511865218653186541865518656186571865818659186601866118662186631866418665186661866718668186691867018671186721867318674186751867618677186781867918680186811868218683186841868518686186871868818689186901869118692186931869418695186961869718698186991870018701187021870318704187051870618707187081870918710187111871218713187141871518716187171871818719187201872118722187231872418725187261872718728187291873018731187321873318734187351873618737187381873918740187411874218743187441874518746187471874818749187501875118752187531875418755187561875718758187591876018761187621876318764187651876618767187681876918770187711877218773187741877518776187771877818779187801878118782187831878418785187861878718788187891879018791187921879318794187951879618797187981879918800188011880218803188041880518806188071880818809188101881118812188131881418815188161881718818188191882018821188221882318824188251882618827188281882918830188311883218833188341883518836188371883818839188401884118842188431884418845188461884718848188491885018851188521885318854188551885618857188581885918860188611886218863188641886518866188671886818869188701887118872188731887418875188761887718878188791888018881188821888318884188851888618887188881888918890188911889218893188941889518896188971889818899189001890118902189031890418905189061890718908189091891018911189121891318914189151891618917189181891918920189211892218923189241892518926189271892818929189301893118932189331893418935189361893718938189391894018941189421894318944189451894618947189481894918950189511895218953189541895518956189571895818959189601896118962189631896418965189661896718968189691897018971189721897318974189751897618977189781897918980189811898218983189841898518986189871898818989189901899118992189931899418995189961899718998189991900019001190021900319004190051900619007190081900919010190111901219013190141901519016190171901819019190201902119022190231902419025190261902719028190291903019031190321903319034190351903619037190381903919040190411904219043190441904519046190471904819049190501905119052190531905419055190561905719058190591906019061190621906319064190651906619067190681906919070190711907219073190741907519076190771907819079190801908119082190831908419085190861908719088190891909019091190921909319094190951909619097190981909919100191011910219103191041910519106191071910819109191101911119112191131911419115191161911719118191191912019121191221912319124191251912619127191281912919130191311913219133191341913519136191371913819139191401914119142191431914419145191461914719148191491915019151191521915319154191551915619157191581915919160191611916219163191641916519166191671916819169191701917119172191731917419175191761917719178191791918019181191821918319184191851918619187191881918919190191911919219193191941919519196191971919819199192001920119202192031920419205192061920719208192091921019211192121921319214192151921619217192181921919220192211922219223192241922519226192271922819229192301923119232192331923419235192361923719238192391924019241192421924319244192451924619247192481924919250192511925219253192541925519256192571925819259192601926119262192631926419265192661926719268192691927019271192721927319274192751927619277192781927919280192811928219283192841928519286192871928819289192901929119292192931929419295192961929719298192991930019301193021930319304193051930619307193081930919310193111931219313193141931519316193171931819319193201932119322193231932419325193261932719328193291933019331193321933319334193351933619337193381933919340193411934219343193441934519346193471934819349193501935119352193531935419355193561935719358193591936019361193621936319364193651936619367193681936919370193711937219373193741937519376193771937819379193801938119382193831938419385193861938719388193891939019391193921939319394193951939619397193981939919400194011940219403194041940519406194071940819409194101941119412194131941419415194161941719418194191942019421194221942319424194251942619427194281942919430194311943219433194341943519436194371943819439194401944119442194431944419445194461944719448194491945019451194521945319454194551945619457194581945919460194611946219463194641946519466194671946819469194701947119472194731947419475194761947719478194791948019481194821948319484194851948619487194881948919490194911949219493194941949519496194971949819499195001950119502195031950419505195061950719508195091951019511195121951319514195151951619517195181951919520195211952219523195241952519526195271952819529195301953119532195331953419535195361953719538195391954019541195421954319544195451954619547195481954919550195511955219553195541955519556195571955819559195601956119562195631956419565195661956719568195691957019571195721957319574195751957619577195781957919580195811958219583195841958519586195871958819589195901959119592195931959419595195961959719598195991960019601196021960319604196051960619607196081960919610196111961219613196141961519616196171961819619196201962119622196231962419625196261962719628196291963019631196321963319634196351963619637196381963919640196411964219643196441964519646196471964819649196501965119652196531965419655196561965719658196591966019661196621966319664196651966619667196681966919670196711967219673196741967519676196771967819679196801968119682196831968419685196861968719688196891969019691196921969319694196951969619697196981969919700197011970219703197041970519706197071970819709197101971119712197131971419715197161971719718197191972019721197221972319724197251972619727197281972919730197311973219733197341973519736197371973819739197401974119742197431974419745197461974719748197491975019751197521975319754197551975619757197581975919760197611976219763197641976519766197671976819769197701977119772197731977419775197761977719778197791978019781197821978319784197851978619787197881978919790197911979219793197941979519796197971979819799198001980119802198031980419805198061980719808198091981019811198121981319814198151981619817198181981919820198211982219823198241982519826198271982819829198301983119832198331983419835198361983719838198391984019841198421984319844198451984619847198481984919850198511985219853198541985519856198571985819859198601986119862198631986419865198661986719868198691987019871198721987319874198751987619877198781987919880198811988219883198841988519886198871988819889198901989119892198931989419895198961989719898198991990019901199021990319904199051990619907199081990919910199111991219913199141991519916199171991819919199201992119922199231992419925199261992719928199291993019931199321993319934199351993619937199381993919940199411994219943199441994519946199471994819949199501995119952199531995419955199561995719958199591996019961199621996319964199651996619967199681996919970199711997219973199741997519976199771997819979199801998119982199831998419985199861998719988199891999019991199921999319994199951999619997199981999920000200012000220003200042000520006200072000820009200102001120012200132001420015200162001720018200192002020021200222002320024200252002620027200282002920030200312003220033200342003520036200372003820039200402004120042200432004420045200462004720048200492005020051200522005320054200552005620057200582005920060200612006220063200642006520066200672006820069200702007120072200732007420075200762007720078200792008020081200822008320084200852008620087200882008920090200912009220093200942009520096200972009820099201002010120102201032010420105201062010720108201092011020111201122011320114201152011620117201182011920120201212012220123201242012520126201272012820129201302013120132201332013420135201362013720138201392014020141201422014320144201452014620147201482014920150201512015220153201542015520156201572015820159201602016120162201632016420165201662016720168201692017020171201722017320174201752017620177201782017920180201812018220183201842018520186201872018820189201902019120192201932019420195201962019720198201992020020201202022020320204202052020620207202082020920210202112021220213202142021520216202172021820219202202022120222202232022420225202262022720228202292023020231202322023320234202352023620237202382023920240202412024220243202442024520246202472024820249202502025120252202532025420255202562025720258202592026020261202622026320264202652026620267202682026920270202712027220273202742027520276202772027820279202802028120282202832028420285202862028720288202892029020291202922029320294202952029620297202982029920300203012030220303203042030520306203072030820309203102031120312203132031420315203162031720318203192032020321203222032320324203252032620327203282032920330203312033220333203342033520336203372033820339203402034120342203432034420345203462034720348203492035020351203522035320354203552035620357203582035920360203612036220363203642036520366203672036820369203702037120372203732037420375203762037720378203792038020381203822038320384203852038620387203882038920390203912039220393203942039520396203972039820399204002040120402204032040420405204062040720408204092041020411204122041320414204152041620417204182041920420204212042220423204242042520426204272042820429204302043120432204332043420435204362043720438204392044020441204422044320444204452044620447204482044920450204512045220453204542045520456204572045820459204602046120462204632046420465204662046720468204692047020471204722047320474204752047620477204782047920480204812048220483204842048520486204872048820489204902049120492204932049420495204962049720498204992050020501205022050320504205052050620507205082050920510205112051220513205142051520516205172051820519205202052120522205232052420525205262052720528205292053020531205322053320534205352053620537205382053920540205412054220543205442054520546205472054820549205502055120552205532055420555205562055720558205592056020561205622056320564205652056620567205682056920570205712057220573205742057520576205772057820579205802058120582205832058420585205862058720588205892059020591205922059320594205952059620597205982059920600206012060220603206042060520606206072060820609206102061120612206132061420615206162061720618206192062020621206222062320624206252062620627206282062920630206312063220633206342063520636206372063820639206402064120642206432064420645206462064720648206492065020651206522065320654206552065620657206582065920660206612066220663206642066520666206672066820669206702067120672206732067420675206762067720678206792068020681206822068320684206852068620687206882068920690206912069220693206942069520696206972069820699207002070120702207032070420705207062070720708207092071020711207122071320714207152071620717207182071920720207212072220723207242072520726207272072820729207302073120732207332073420735207362073720738207392074020741207422074320744207452074620747207482074920750207512075220753207542075520756207572075820759207602076120762207632076420765207662076720768207692077020771207722077320774207752077620777207782077920780207812078220783207842078520786207872078820789207902079120792207932079420795207962079720798207992080020801208022080320804208052080620807208082080920810208112081220813208142081520816208172081820819208202082120822208232082420825208262082720828208292083020831208322083320834208352083620837208382083920840208412084220843208442084520846208472084820849208502085120852208532085420855208562085720858208592086020861208622086320864208652086620867208682086920870208712087220873208742087520876208772087820879208802088120882208832088420885208862088720888208892089020891208922089320894208952089620897208982089920900209012090220903209042090520906209072090820909209102091120912209132091420915209162091720918209192092020921209222092320924209252092620927209282092920930209312093220933209342093520936209372093820939209402094120942209432094420945209462094720948209492095020951209522095320954209552095620957209582095920960209612096220963209642096520966209672096820969209702097120972209732097420975209762097720978209792098020981209822098320984209852098620987209882098920990209912099220993209942099520996209972099820999210002100121002210032100421005210062100721008210092101021011210122101321014210152101621017210182101921020210212102221023210242102521026210272102821029210302103121032210332103421035210362103721038210392104021041210422104321044210452104621047210482104921050210512105221053210542105521056210572105821059210602106121062210632106421065210662106721068210692107021071210722107321074210752107621077210782107921080210812108221083210842108521086210872108821089210902109121092210932109421095210962109721098210992110021101211022110321104211052110621107211082110921110211112111221113211142111521116211172111821119211202112121122211232112421125211262112721128211292113021131211322113321134211352113621137211382113921140211412114221143211442114521146211472114821149211502115121152211532115421155211562115721158211592116021161211622116321164211652116621167211682116921170211712117221173211742117521176211772117821179211802118121182211832118421185211862118721188211892119021191211922119321194211952119621197211982119921200212012120221203212042120521206212072120821209212102121121212212132121421215212162121721218212192122021221212222122321224212252122621227212282122921230212312123221233212342123521236212372123821239212402124121242212432124421245212462124721248212492125021251212522125321254212552125621257212582125921260212612126221263212642126521266212672126821269212702127121272212732127421275212762127721278212792128021281212822128321284212852128621287212882128921290212912129221293212942129521296212972129821299213002130121302213032130421305213062130721308213092131021311213122131321314213152131621317213182131921320213212132221323213242132521326213272132821329213302133121332213332133421335213362133721338213392134021341213422134321344213452134621347213482134921350213512135221353213542135521356213572135821359213602136121362213632136421365213662136721368213692137021371213722137321374213752137621377213782137921380213812138221383213842138521386213872138821389213902139121392213932139421395213962139721398213992140021401214022140321404214052140621407214082140921410214112141221413214142141521416214172141821419214202142121422214232142421425214262142721428214292143021431214322143321434214352143621437214382143921440214412144221443214442144521446214472144821449214502145121452214532145421455214562145721458214592146021461214622146321464214652146621467214682146921470214712147221473214742147521476214772147821479214802148121482214832148421485214862148721488214892149021491214922149321494214952149621497214982149921500215012150221503215042150521506215072150821509215102151121512215132151421515215162151721518215192152021521215222152321524215252152621527215282152921530215312153221533215342153521536215372153821539215402154121542215432154421545215462154721548215492155021551215522155321554215552155621557215582155921560215612156221563215642156521566215672156821569215702157121572215732157421575215762157721578215792158021581215822158321584215852158621587215882158921590215912159221593215942159521596215972159821599216002160121602216032160421605216062160721608216092161021611216122161321614216152161621617216182161921620216212162221623216242162521626216272162821629216302163121632216332163421635216362163721638216392164021641216422164321644216452164621647216482164921650216512165221653216542165521656216572165821659216602166121662216632166421665216662166721668216692167021671216722167321674216752167621677216782167921680216812168221683216842168521686216872168821689216902169121692216932169421695216962169721698216992170021701217022170321704217052170621707217082170921710217112171221713217142171521716217172171821719217202172121722217232172421725217262172721728217292173021731217322173321734217352173621737217382173921740217412174221743217442174521746217472174821749217502175121752217532175421755217562175721758217592176021761217622176321764217652176621767217682176921770217712177221773217742177521776217772177821779217802178121782217832178421785217862178721788217892179021791217922179321794217952179621797217982179921800218012180221803218042180521806218072180821809218102181121812218132181421815218162181721818218192182021821218222182321824218252182621827218282182921830218312183221833218342183521836218372183821839218402184121842218432184421845218462184721848218492185021851218522185321854218552185621857218582185921860218612186221863218642186521866218672186821869218702187121872218732187421875218762187721878218792188021881218822188321884218852188621887218882188921890218912189221893218942189521896218972189821899219002190121902219032190421905219062190721908219092191021911219122191321914219152191621917219182191921920219212192221923219242192521926219272192821929219302193121932219332193421935219362193721938219392194021941219422194321944219452194621947219482194921950219512195221953219542195521956219572195821959219602196121962219632196421965219662196721968219692197021971219722197321974219752197621977219782197921980219812198221983219842198521986219872198821989219902199121992219932199421995219962199721998219992200022001220022200322004220052200622007220082200922010220112201222013220142201522016220172201822019220202202122022220232202422025220262202722028220292203022031220322203322034220352203622037220382203922040220412204222043220442204522046220472204822049220502205122052220532205422055220562205722058220592206022061220622206322064220652206622067220682206922070220712207222073220742207522076220772207822079220802208122082220832208422085220862208722088220892209022091220922209322094220952209622097220982209922100221012210222103221042210522106221072210822109221102211122112221132211422115221162211722118221192212022121221222212322124221252212622127221282212922130221312213222133221342213522136221372213822139221402214122142221432214422145221462214722148221492215022151221522215322154221552215622157221582215922160221612216222163221642216522166221672216822169221702217122172221732217422175221762217722178221792218022181221822218322184221852218622187221882218922190221912219222193221942219522196221972219822199222002220122202222032220422205222062220722208222092221022211222122221322214222152221622217222182221922220222212222222223222242222522226222272222822229222302223122232222332223422235222362223722238222392224022241222422224322244222452224622247222482224922250222512225222253222542225522256222572225822259222602226122262222632226422265222662226722268222692227022271222722227322274222752227622277222782227922280222812228222283222842228522286222872228822289222902229122292222932229422295222962229722298222992230022301223022230322304223052230622307223082230922310223112231222313223142231522316223172231822319223202232122322223232232422325223262232722328223292233022331223322233322334223352233622337223382233922340223412234222343223442234522346223472234822349223502235122352223532235422355223562235722358223592236022361223622236322364223652236622367223682236922370223712237222373223742237522376223772237822379223802238122382223832238422385223862238722388223892239022391223922239322394223952239622397223982239922400224012240222403224042240522406224072240822409224102241122412224132241422415224162241722418224192242022421224222242322424224252242622427224282242922430224312243222433224342243522436224372243822439224402244122442224432244422445224462244722448224492245022451224522245322454224552245622457224582245922460224612246222463224642246522466224672246822469224702247122472224732247422475224762247722478224792248022481224822248322484224852248622487224882248922490224912249222493224942249522496224972249822499225002250122502225032250422505225062250722508225092251022511225122251322514225152251622517225182251922520225212252222523225242252522526225272252822529225302253122532225332253422535225362253722538225392254022541225422254322544225452254622547225482254922550225512255222553225542255522556225572255822559225602256122562225632256422565225662256722568225692257022571225722257322574225752257622577225782257922580225812258222583225842258522586225872258822589225902259122592225932259422595225962259722598225992260022601226022260322604226052260622607226082260922610226112261222613226142261522616226172261822619226202262122622226232262422625226262262722628226292263022631226322263322634226352263622637226382263922640226412264222643226442264522646226472264822649226502265122652226532265422655226562265722658226592266022661226622266322664226652266622667226682266922670226712267222673226742267522676226772267822679226802268122682226832268422685226862268722688226892269022691226922269322694226952269622697226982269922700227012270222703227042270522706227072270822709227102271122712227132271422715227162271722718227192272022721227222272322724227252272622727227282272922730227312273222733227342273522736227372273822739227402274122742227432274422745227462274722748227492275022751227522275322754227552275622757227582275922760227612276222763227642276522766227672276822769227702277122772227732277422775227762277722778227792278022781227822278322784227852278622787227882278922790227912279222793227942279522796227972279822799228002280122802228032280422805228062280722808228092281022811228122281322814228152281622817228182281922820228212282222823228242282522826228272282822829228302283122832228332283422835228362283722838228392284022841228422284322844228452284622847228482284922850228512285222853228542285522856228572285822859228602286122862228632286422865228662286722868228692287022871228722287322874228752287622877228782287922880228812288222883228842288522886228872288822889228902289122892228932289422895228962289722898228992290022901229022290322904229052290622907229082290922910229112291222913229142291522916229172291822919229202292122922229232292422925229262292722928229292293022931229322293322934229352293622937229382293922940229412294222943229442294522946229472294822949229502295122952229532295422955229562295722958229592296022961229622296322964229652296622967229682296922970229712297222973229742297522976229772297822979229802298122982229832298422985229862298722988229892299022991229922299322994229952299622997229982299923000230012300223003230042300523006230072300823009230102301123012230132301423015230162301723018230192302023021230222302323024230252302623027230282302923030230312303223033230342303523036230372303823039230402304123042230432304423045230462304723048230492305023051230522305323054230552305623057230582305923060230612306223063230642306523066230672306823069230702307123072230732307423075230762307723078230792308023081230822308323084230852308623087230882308923090230912309223093230942309523096230972309823099231002310123102231032310423105231062310723108231092311023111231122311323114231152311623117231182311923120231212312223123231242312523126231272312823129231302313123132231332313423135231362313723138231392314023141231422314323144231452314623147231482314923150231512315223153231542315523156231572315823159231602316123162231632316423165231662316723168231692317023171231722317323174231752317623177231782317923180231812318223183231842318523186231872318823189231902319123192231932319423195231962319723198231992320023201232022320323204232052320623207232082320923210232112321223213232142321523216232172321823219232202322123222232232322423225232262322723228232292323023231232322323323234232352323623237232382323923240232412324223243232442324523246232472324823249232502325123252232532325423255232562325723258232592326023261232622326323264232652326623267232682326923270232712327223273232742327523276232772327823279232802328123282232832328423285232862328723288232892329023291232922329323294232952329623297232982329923300233012330223303233042330523306233072330823309233102331123312233132331423315233162331723318233192332023321233222332323324233252332623327233282332923330233312333223333233342333523336233372333823339233402334123342233432334423345233462334723348233492335023351233522335323354233552335623357233582335923360233612336223363233642336523366233672336823369233702337123372233732337423375233762337723378233792338023381233822338323384233852338623387233882338923390233912339223393233942339523396233972339823399234002340123402234032340423405234062340723408234092341023411234122341323414234152341623417234182341923420234212342223423234242342523426234272342823429234302343123432234332343423435234362343723438234392344023441234422344323444234452344623447234482344923450234512345223453234542345523456234572345823459234602346123462234632346423465234662346723468234692347023471234722347323474234752347623477234782347923480234812348223483234842348523486234872348823489234902349123492234932349423495234962349723498234992350023501235022350323504235052350623507235082350923510235112351223513235142351523516235172351823519235202352123522235232352423525235262352723528235292353023531235322353323534235352353623537235382353923540235412354223543235442354523546235472354823549235502355123552235532355423555235562355723558235592356023561235622356323564235652356623567235682356923570235712357223573235742357523576235772357823579235802358123582235832358423585235862358723588235892359023591235922359323594235952359623597235982359923600236012360223603236042360523606236072360823609236102361123612236132361423615236162361723618236192362023621236222362323624236252362623627236282362923630236312363223633236342363523636236372363823639236402364123642236432364423645236462364723648236492365023651236522365323654236552365623657236582365923660236612366223663236642366523666236672366823669236702367123672236732367423675236762367723678236792368023681236822368323684236852368623687236882368923690236912369223693236942369523696236972369823699237002370123702237032370423705237062370723708237092371023711237122371323714237152371623717237182371923720237212372223723237242372523726237272372823729237302373123732237332373423735237362373723738237392374023741237422374323744237452374623747237482374923750237512375223753237542375523756237572375823759237602376123762237632376423765237662376723768237692377023771237722377323774237752377623777237782377923780237812378223783237842378523786237872378823789237902379123792237932379423795237962379723798237992380023801238022380323804238052380623807238082380923810238112381223813238142381523816238172381823819238202382123822238232382423825238262382723828238292383023831238322383323834238352383623837238382383923840238412384223843238442384523846238472384823849238502385123852238532385423855238562385723858238592386023861238622386323864238652386623867238682386923870238712387223873238742387523876238772387823879238802388123882238832388423885238862388723888238892389023891238922389323894238952389623897238982389923900239012390223903239042390523906239072390823909239102391123912239132391423915239162391723918239192392023921239222392323924239252392623927239282392923930239312393223933239342393523936239372393823939239402394123942239432394423945239462394723948239492395023951239522395323954239552395623957239582395923960239612396223963239642396523966239672396823969239702397123972239732397423975239762397723978239792398023981239822398323984239852398623987239882398923990239912399223993239942399523996239972399823999240002400124002240032400424005240062400724008240092401024011240122401324014240152401624017240182401924020240212402224023240242402524026240272402824029240302403124032240332403424035240362403724038240392404024041240422404324044240452404624047240482404924050240512405224053240542405524056240572405824059240602406124062240632406424065240662406724068240692407024071240722407324074240752407624077240782407924080240812408224083240842408524086240872408824089240902409124092240932409424095240962409724098240992410024101241022410324104241052410624107241082410924110241112411224113241142411524116241172411824119241202412124122241232412424125241262412724128241292413024131241322413324134241352413624137241382413924140241412414224143241442414524146241472414824149241502415124152241532415424155241562415724158241592416024161241622416324164241652416624167241682416924170241712417224173241742417524176241772417824179241802418124182241832418424185241862418724188241892419024191241922419324194241952419624197241982419924200242012420224203242042420524206242072420824209242102421124212242132421424215242162421724218242192422024221242222422324224242252422624227242282422924230242312423224233242342423524236242372423824239242402424124242242432424424245242462424724248242492425024251242522425324254242552425624257242582425924260242612426224263242642426524266242672426824269242702427124272242732427424275242762427724278242792428024281242822428324284242852428624287242882428924290242912429224293242942429524296242972429824299243002430124302243032430424305243062430724308243092431024311243122431324314243152431624317243182431924320243212432224323243242432524326243272432824329243302433124332243332433424335243362433724338243392434024341243422434324344243452434624347243482434924350243512435224353243542435524356243572435824359243602436124362243632436424365243662436724368243692437024371243722437324374243752437624377243782437924380243812438224383243842438524386243872438824389243902439124392243932439424395243962439724398243992440024401244022440324404244052440624407244082440924410244112441224413244142441524416244172441824419244202442124422244232442424425244262442724428244292443024431244322443324434244352443624437244382443924440244412444224443244442444524446244472444824449244502445124452244532445424455244562445724458244592446024461244622446324464244652446624467244682446924470244712447224473244742447524476244772447824479244802448124482244832448424485244862448724488244892449024491244922449324494244952449624497244982449924500245012450224503245042450524506245072450824509245102451124512245132451424515245162451724518245192452024521245222452324524245252452624527245282452924530245312453224533245342453524536245372453824539245402454124542245432454424545245462454724548245492455024551245522455324554245552455624557245582455924560245612456224563245642456524566245672456824569245702457124572245732457424575245762457724578245792458024581245822458324584245852458624587245882458924590245912459224593245942459524596245972459824599246002460124602246032460424605246062460724608246092461024611246122461324614246152461624617246182461924620246212462224623246242462524626246272462824629246302463124632246332463424635246362463724638246392464024641246422464324644246452464624647246482464924650246512465224653246542465524656246572465824659246602466124662246632466424665246662466724668246692467024671246722467324674246752467624677246782467924680246812468224683246842468524686246872468824689246902469124692246932469424695246962469724698246992470024701247022470324704247052470624707247082470924710247112471224713247142471524716247172471824719247202472124722247232472424725247262472724728247292473024731247322473324734247352473624737247382473924740247412474224743247442474524746247472474824749247502475124752247532475424755247562475724758247592476024761247622476324764247652476624767247682476924770247712477224773247742477524776247772477824779247802478124782247832478424785247862478724788247892479024791247922479324794247952479624797247982479924800248012480224803248042480524806248072480824809248102481124812248132481424815248162481724818248192482024821248222482324824248252482624827248282482924830248312483224833248342483524836248372483824839248402484124842248432484424845248462484724848248492485024851248522485324854248552485624857248582485924860248612486224863248642486524866248672486824869248702487124872248732487424875248762487724878248792488024881248822488324884248852488624887248882488924890248912489224893248942489524896248972489824899249002490124902249032490424905249062490724908249092491024911249122491324914249152491624917249182491924920249212492224923249242492524926249272492824929249302493124932249332493424935249362493724938249392494024941249422494324944249452494624947249482494924950249512495224953249542495524956249572495824959249602496124962249632496424965249662496724968249692497024971249722497324974249752497624977249782497924980249812498224983249842498524986249872498824989249902499124992249932499424995249962499724998249992500025001250022500325004250052500625007250082500925010250112501225013250142501525016250172501825019250202502125022250232502425025250262502725028250292503025031250322503325034250352503625037250382503925040250412504225043250442504525046250472504825049250502505125052250532505425055250562505725058250592506025061250622506325064250652506625067250682506925070250712507225073250742507525076250772507825079250802508125082250832508425085250862508725088250892509025091250922509325094250952509625097250982509925100251012510225103251042510525106251072510825109251102511125112251132511425115251162511725118251192512025121251222512325124251252512625127251282512925130251312513225133251342513525136251372513825139251402514125142251432514425145251462514725148251492515025151251522515325154251552515625157251582515925160251612516225163251642516525166251672516825169251702517125172251732517425175251762517725178251792518025181251822518325184251852518625187251882518925190251912519225193251942519525196251972519825199252002520125202252032520425205252062520725208252092521025211252122521325214252152521625217252182521925220252212522225223252242522525226252272522825229252302523125232252332523425235252362523725238252392524025241252422524325244252452524625247252482524925250252512525225253252542525525256252572525825259252602526125262252632526425265252662526725268252692527025271252722527325274252752527625277252782527925280252812528225283252842528525286252872528825289252902529125292252932529425295252962529725298252992530025301253022530325304253052530625307253082530925310253112531225313253142531525316253172531825319253202532125322253232532425325253262532725328253292533025331253322533325334253352533625337253382533925340253412534225343253442534525346253472534825349253502535125352253532535425355253562535725358253592536025361253622536325364253652536625367253682536925370253712537225373253742537525376253772537825379253802538125382253832538425385253862538725388253892539025391253922539325394253952539625397253982539925400254012540225403254042540525406254072540825409254102541125412254132541425415254162541725418254192542025421254222542325424254252542625427254282542925430254312543225433254342543525436254372543825439254402544125442254432544425445254462544725448254492545025451254522545325454254552545625457254582545925460254612546225463254642546525466254672546825469254702547125472254732547425475254762547725478254792548025481254822548325484254852548625487254882548925490254912549225493254942549525496254972549825499255002550125502255032550425505255062550725508255092551025511255122551325514255152551625517255182551925520255212552225523255242552525526255272552825529255302553125532255332553425535255362553725538255392554025541255422554325544255452554625547255482554925550255512555225553255542555525556255572555825559255602556125562255632556425565255662556725568255692557025571255722557325574255752557625577255782557925580255812558225583255842558525586255872558825589255902559125592255932559425595255962559725598255992560025601256022560325604256052560625607256082560925610256112561225613256142561525616256172561825619256202562125622256232562425625256262562725628256292563025631256322563325634256352563625637256382563925640256412564225643256442564525646256472564825649256502565125652256532565425655256562565725658256592566025661256622566325664256652566625667256682566925670256712567225673256742567525676256772567825679256802568125682256832568425685256862568725688256892569025691256922569325694256952569625697256982569925700257012570225703257042570525706257072570825709257102571125712257132571425715257162571725718257192572025721257222572325724257252572625727257282572925730257312573225733257342573525736257372573825739257402574125742257432574425745257462574725748257492575025751257522575325754257552575625757257582575925760257612576225763257642576525766257672576825769257702577125772257732577425775257762577725778257792578025781257822578325784257852578625787257882578925790257912579225793257942579525796257972579825799258002580125802258032580425805258062580725808258092581025811258122581325814258152581625817258182581925820258212582225823258242582525826258272582825829258302583125832258332583425835258362583725838258392584025841258422584325844258452584625847258482584925850258512585225853258542585525856258572585825859258602586125862258632586425865258662586725868258692587025871258722587325874258752587625877258782587925880258812588225883258842588525886258872588825889258902589125892258932589425895258962589725898258992590025901259022590325904259052590625907259082590925910259112591225913259142591525916259172591825919259202592125922259232592425925259262592725928259292593025931259322593325934259352593625937259382593925940259412594225943259442594525946259472594825949259502595125952259532595425955259562595725958259592596025961259622596325964259652596625967259682596925970259712597225973259742597525976259772597825979259802598125982259832598425985259862598725988259892599025991259922599325994259952599625997259982599926000260012600226003260042600526006260072600826009260102601126012260132601426015260162601726018260192602026021260222602326024260252602626027260282602926030260312603226033260342603526036260372603826039260402604126042260432604426045260462604726048260492605026051260522605326054260552605626057260582605926060260612606226063260642606526066260672606826069260702607126072260732607426075260762607726078260792608026081260822608326084260852608626087260882608926090260912609226093260942609526096260972609826099261002610126102261032610426105261062610726108261092611026111261122611326114261152611626117261182611926120261212612226123261242612526126261272612826129261302613126132261332613426135261362613726138261392614026141261422614326144261452614626147261482614926150261512615226153261542615526156261572615826159261602616126162261632616426165261662616726168261692617026171261722617326174261752617626177261782617926180261812618226183261842618526186261872618826189261902619126192261932619426195261962619726198261992620026201262022620326204262052620626207262082620926210262112621226213262142621526216262172621826219262202622126222262232622426225262262622726228262292623026231262322623326234262352623626237262382623926240262412624226243262442624526246262472624826249262502625126252262532625426255262562625726258262592626026261262622626326264262652626626267262682626926270262712627226273262742627526276262772627826279262802628126282262832628426285262862628726288262892629026291262922629326294262952629626297262982629926300263012630226303263042630526306263072630826309263102631126312263132631426315263162631726318263192632026321263222632326324263252632626327263282632926330263312633226333263342633526336263372633826339263402634126342263432634426345263462634726348263492635026351263522635326354263552635626357263582635926360263612636226363263642636526366263672636826369263702637126372263732637426375263762637726378263792638026381263822638326384263852638626387263882638926390263912639226393263942639526396263972639826399264002640126402264032640426405264062640726408264092641026411264122641326414264152641626417264182641926420264212642226423264242642526426264272642826429264302643126432264332643426435264362643726438264392644026441264422644326444264452644626447264482644926450264512645226453264542645526456264572645826459264602646126462264632646426465264662646726468264692647026471264722647326474264752647626477264782647926480264812648226483264842648526486264872648826489264902649126492264932649426495264962649726498264992650026501265022650326504265052650626507265082650926510265112651226513265142651526516265172651826519265202652126522265232652426525265262652726528265292653026531265322653326534265352653626537265382653926540265412654226543265442654526546265472654826549265502655126552265532655426555265562655726558265592656026561265622656326564265652656626567265682656926570265712657226573265742657526576265772657826579265802658126582265832658426585265862658726588265892659026591265922659326594265952659626597265982659926600266012660226603266042660526606266072660826609266102661126612266132661426615266162661726618266192662026621266222662326624266252662626627266282662926630266312663226633266342663526636266372663826639266402664126642266432664426645266462664726648266492665026651266522665326654266552665626657266582665926660266612666226663266642666526666266672666826669266702667126672266732667426675266762667726678266792668026681266822668326684266852668626687266882668926690266912669226693266942669526696266972669826699267002670126702267032670426705267062670726708267092671026711267122671326714267152671626717267182671926720267212672226723267242672526726267272672826729267302673126732267332673426735267362673726738267392674026741267422674326744267452674626747267482674926750267512675226753267542675526756267572675826759267602676126762267632676426765267662676726768267692677026771267722677326774267752677626777267782677926780267812678226783267842678526786267872678826789267902679126792267932679426795267962679726798267992680026801268022680326804268052680626807268082680926810268112681226813268142681526816268172681826819268202682126822268232682426825268262682726828268292683026831268322683326834268352683626837268382683926840268412684226843268442684526846268472684826849268502685126852268532685426855268562685726858268592686026861268622686326864268652686626867268682686926870268712687226873268742687526876268772687826879268802688126882268832688426885268862688726888268892689026891268922689326894268952689626897268982689926900269012690226903269042690526906269072690826909269102691126912269132691426915269162691726918269192692026921269222692326924269252692626927269282692926930269312693226933269342693526936269372693826939269402694126942269432694426945269462694726948269492695026951269522695326954269552695626957269582695926960269612696226963269642696526966269672696826969269702697126972269732697426975269762697726978269792698026981269822698326984269852698626987269882698926990269912699226993269942699526996269972699826999270002700127002270032700427005270062700727008270092701027011270122701327014270152701627017270182701927020270212702227023270242702527026270272702827029270302703127032270332703427035270362703727038270392704027041270422704327044270452704627047270482704927050270512705227053270542705527056270572705827059270602706127062270632706427065270662706727068270692707027071270722707327074270752707627077270782707927080270812708227083270842708527086270872708827089270902709127092270932709427095270962709727098270992710027101271022710327104271052710627107271082710927110271112711227113271142711527116271172711827119271202712127122271232712427125271262712727128271292713027131271322713327134271352713627137271382713927140271412714227143271442714527146271472714827149271502715127152271532715427155271562715727158271592716027161271622716327164271652716627167271682716927170271712717227173271742717527176271772717827179271802718127182271832718427185271862718727188271892719027191271922719327194271952719627197271982719927200272012720227203272042720527206272072720827209272102721127212272132721427215272162721727218272192722027221272222722327224272252722627227272282722927230272312723227233272342723527236272372723827239272402724127242272432724427245272462724727248272492725027251272522725327254272552725627257272582725927260272612726227263272642726527266272672726827269272702727127272272732727427275272762727727278272792728027281272822728327284272852728627287272882728927290272912729227293272942729527296272972729827299273002730127302273032730427305273062730727308273092731027311273122731327314273152731627317273182731927320273212732227323273242732527326273272732827329273302733127332273332733427335273362733727338273392734027341273422734327344273452734627347273482734927350273512735227353273542735527356273572735827359273602736127362273632736427365273662736727368273692737027371273722737327374273752737627377273782737927380273812738227383273842738527386273872738827389273902739127392273932739427395273962739727398273992740027401274022740327404274052740627407274082740927410274112741227413274142741527416274172741827419274202742127422274232742427425274262742727428274292743027431274322743327434274352743627437274382743927440274412744227443274442744527446274472744827449274502745127452274532745427455274562745727458274592746027461274622746327464274652746627467274682746927470274712747227473274742747527476274772747827479274802748127482274832748427485274862748727488274892749027491274922749327494274952749627497274982749927500275012750227503275042750527506275072750827509275102751127512275132751427515275162751727518275192752027521275222752327524275252752627527275282752927530275312753227533275342753527536275372753827539275402754127542275432754427545275462754727548275492755027551275522755327554275552755627557275582755927560275612756227563275642756527566275672756827569275702757127572275732757427575275762757727578275792758027581275822758327584275852758627587275882758927590275912759227593275942759527596275972759827599276002760127602276032760427605276062760727608276092761027611276122761327614276152761627617276182761927620276212762227623276242762527626276272762827629276302763127632276332763427635276362763727638276392764027641276422764327644276452764627647276482764927650276512765227653276542765527656276572765827659276602766127662276632766427665276662766727668276692767027671276722767327674276752767627677276782767927680276812768227683276842768527686276872768827689276902769127692276932769427695276962769727698276992770027701277022770327704277052770627707277082770927710277112771227713277142771527716277172771827719277202772127722277232772427725277262772727728277292773027731277322773327734277352773627737277382773927740277412774227743277442774527746277472774827749277502775127752277532775427755277562775727758277592776027761277622776327764277652776627767277682776927770277712777227773277742777527776277772777827779277802778127782277832778427785277862778727788277892779027791277922779327794277952779627797277982779927800278012780227803278042780527806278072780827809278102781127812278132781427815278162781727818278192782027821278222782327824278252782627827278282782927830278312783227833278342783527836278372783827839278402784127842278432784427845278462784727848278492785027851278522785327854278552785627857278582785927860278612786227863278642786527866278672786827869278702787127872278732787427875278762787727878278792788027881278822788327884278852788627887278882788927890278912789227893278942789527896278972789827899279002790127902279032790427905279062790727908279092791027911279122791327914279152791627917279182791927920279212792227923279242792527926279272792827929279302793127932279332793427935279362793727938279392794027941279422794327944279452794627947279482794927950279512795227953279542795527956279572795827959279602796127962279632796427965279662796727968279692797027971279722797327974279752797627977279782797927980279812798227983279842798527986279872798827989279902799127992279932799427995279962799727998279992800028001280022800328004280052800628007280082800928010280112801228013280142801528016280172801828019280202802128022280232802428025280262802728028280292803028031280322803328034280352803628037280382803928040280412804228043280442804528046280472804828049280502805128052280532805428055280562805728058280592806028061280622806328064280652806628067280682806928070280712807228073280742807528076280772807828079280802808128082280832808428085280862808728088280892809028091280922809328094280952809628097280982809928100281012810228103281042810528106281072810828109281102811128112281132811428115281162811728118281192812028121281222812328124281252812628127281282812928130281312813228133281342813528136281372813828139281402814128142281432814428145281462814728148281492815028151281522815328154281552815628157281582815928160281612816228163281642816528166281672816828169281702817128172281732817428175281762817728178281792818028181281822818328184281852818628187281882818928190281912819228193281942819528196281972819828199282002820128202282032820428205282062820728208282092821028211282122821328214282152821628217282182821928220282212822228223282242822528226282272822828229282302823128232282332823428235282362823728238282392824028241282422824328244282452824628247282482824928250282512825228253282542825528256282572825828259282602826128262282632826428265282662826728268282692827028271282722827328274282752827628277282782827928280282812828228283282842828528286282872828828289282902829128292282932829428295282962829728298282992830028301283022830328304283052830628307283082830928310283112831228313283142831528316283172831828319283202832128322283232832428325283262832728328283292833028331283322833328334283352833628337283382833928340283412834228343283442834528346283472834828349283502835128352283532835428355283562835728358283592836028361283622836328364283652836628367283682836928370283712837228373283742837528376283772837828379283802838128382283832838428385283862838728388283892839028391283922839328394283952839628397283982839928400284012840228403284042840528406284072840828409284102841128412284132841428415284162841728418284192842028421284222842328424284252842628427284282842928430284312843228433284342843528436284372843828439284402844128442284432844428445284462844728448284492845028451284522845328454284552845628457284582845928460284612846228463284642846528466284672846828469284702847128472284732847428475284762847728478284792848028481284822848328484284852848628487284882848928490284912849228493284942849528496284972849828499285002850128502285032850428505285062850728508285092851028511285122851328514285152851628517285182851928520285212852228523285242852528526285272852828529285302853128532285332853428535285362853728538285392854028541285422854328544285452854628547285482854928550285512855228553285542855528556285572855828559285602856128562285632856428565285662856728568285692857028571285722857328574285752857628577285782857928580285812858228583285842858528586285872858828589285902859128592285932859428595285962859728598285992860028601286022860328604286052860628607286082860928610286112861228613286142861528616286172861828619286202862128622286232862428625286262862728628286292863028631286322863328634286352863628637286382863928640286412864228643286442864528646286472864828649286502865128652286532865428655286562865728658286592866028661286622866328664286652866628667286682866928670286712867228673286742867528676286772867828679286802868128682286832868428685286862868728688286892869028691286922869328694286952869628697286982869928700287012870228703287042870528706287072870828709287102871128712287132871428715287162871728718287192872028721287222872328724287252872628727287282872928730287312873228733287342873528736287372873828739287402874128742287432874428745287462874728748287492875028751287522875328754287552875628757287582875928760287612876228763287642876528766287672876828769287702877128772287732877428775287762877728778287792878028781287822878328784287852878628787287882878928790287912879228793287942879528796287972879828799288002880128802288032880428805288062880728808288092881028811288122881328814288152881628817288182881928820288212882228823288242882528826288272882828829288302883128832288332883428835288362883728838288392884028841288422884328844288452884628847288482884928850288512885228853288542885528856288572885828859288602886128862288632886428865288662886728868288692887028871288722887328874288752887628877288782887928880288812888228883288842888528886288872888828889288902889128892288932889428895288962889728898288992890028901289022890328904289052890628907289082890928910289112891228913289142891528916289172891828919289202892128922289232892428925289262892728928289292893028931289322893328934289352893628937289382893928940289412894228943289442894528946289472894828949289502895128952289532895428955289562895728958289592896028961289622896328964289652896628967289682896928970289712897228973289742897528976289772897828979289802898128982289832898428985289862898728988289892899028991289922899328994289952899628997289982899929000290012900229003290042900529006290072900829009290102901129012290132901429015290162901729018290192902029021290222902329024290252902629027290282902929030290312903229033290342903529036290372903829039290402904129042290432904429045290462904729048290492905029051290522905329054290552905629057290582905929060290612906229063290642906529066290672906829069290702907129072290732907429075290762907729078290792908029081290822908329084290852908629087290882908929090290912909229093290942909529096290972909829099291002910129102291032910429105291062910729108291092911029111291122911329114291152911629117291182911929120291212912229123291242912529126291272912829129291302913129132291332913429135291362913729138291392914029141291422914329144291452914629147291482914929150291512915229153291542915529156291572915829159291602916129162291632916429165291662916729168291692917029171291722917329174291752917629177291782917929180291812918229183291842918529186291872918829189291902919129192291932919429195291962919729198291992920029201292022920329204292052920629207292082920929210292112921229213292142921529216292172921829219292202922129222292232922429225292262922729228292292923029231292322923329234292352923629237292382923929240292412924229243292442924529246292472924829249292502925129252292532925429255292562925729258292592926029261292622926329264292652926629267292682926929270292712927229273292742927529276292772927829279292802928129282292832928429285292862928729288292892929029291292922929329294292952929629297292982929929300293012930229303293042930529306293072930829309293102931129312293132931429315293162931729318293192932029321293222932329324293252932629327293282932929330293312933229333293342933529336293372933829339293402934129342293432934429345293462934729348293492935029351293522935329354293552935629357293582935929360293612936229363293642936529366293672936829369293702937129372293732937429375293762937729378293792938029381293822938329384293852938629387293882938929390293912939229393293942939529396293972939829399294002940129402294032940429405294062940729408294092941029411294122941329414294152941629417294182941929420294212942229423294242942529426294272942829429294302943129432294332943429435294362943729438294392944029441294422944329444294452944629447294482944929450294512945229453294542945529456294572945829459294602946129462294632946429465294662946729468294692947029471294722947329474294752947629477294782947929480294812948229483294842948529486294872948829489294902949129492294932949429495294962949729498294992950029501295022950329504295052950629507295082950929510295112951229513295142951529516295172951829519295202952129522295232952429525295262952729528295292953029531295322953329534295352953629537295382953929540295412954229543295442954529546295472954829549295502955129552295532955429555295562955729558295592956029561295622956329564295652956629567295682956929570295712957229573295742957529576295772957829579295802958129582295832958429585295862958729588295892959029591295922959329594295952959629597295982959929600296012960229603296042960529606296072960829609296102961129612296132961429615296162961729618296192962029621296222962329624296252962629627296282962929630296312963229633296342963529636296372963829639296402964129642296432964429645296462964729648296492965029651296522965329654296552965629657296582965929660296612966229663296642966529666296672966829669296702967129672296732967429675296762967729678296792968029681296822968329684296852968629687296882968929690296912969229693296942969529696296972969829699297002970129702297032970429705297062970729708297092971029711297122971329714297152971629717297182971929720297212972229723297242972529726297272972829729297302973129732297332973429735297362973729738297392974029741297422974329744297452974629747297482974929750297512975229753297542975529756297572975829759297602976129762297632976429765297662976729768297692977029771297722977329774297752977629777297782977929780297812978229783297842978529786297872978829789297902979129792297932979429795297962979729798297992980029801298022980329804298052980629807298082980929810298112981229813298142981529816298172981829819298202982129822298232982429825298262982729828298292983029831298322983329834298352983629837298382983929840298412984229843298442984529846298472984829849298502985129852298532985429855298562985729858298592986029861298622986329864298652986629867298682986929870298712987229873298742987529876298772987829879298802988129882298832988429885298862988729888298892989029891298922989329894298952989629897298982989929900299012990229903299042990529906299072990829909299102991129912299132991429915299162991729918299192992029921299222992329924299252992629927299282992929930299312993229933299342993529936299372993829939299402994129942299432994429945299462994729948299492995029951299522995329954299552995629957299582995929960299612996229963299642996529966299672996829969299702997129972299732997429975299762997729978299792998029981299822998329984299852998629987299882998929990299912999229993299942999529996299972999829999300003000130002300033000430005300063000730008300093001030011300123001330014300153001630017300183001930020300213002230023300243002530026300273002830029300303003130032300333003430035300363003730038300393004030041300423004330044300453004630047300483004930050300513005230053300543005530056300573005830059300603006130062300633006430065300663006730068300693007030071300723007330074300753007630077300783007930080300813008230083300843008530086300873008830089300903009130092300933009430095300963009730098300993010030101301023010330104301053010630107301083010930110301113011230113301143011530116301173011830119301203012130122301233012430125301263012730128301293013030131301323013330134301353013630137301383013930140301413014230143301443014530146301473014830149301503015130152301533015430155301563015730158301593016030161301623016330164301653016630167301683016930170301713017230173301743017530176301773017830179301803018130182301833018430185301863018730188301893019030191301923019330194301953019630197301983019930200302013020230203302043020530206302073020830209302103021130212302133021430215302163021730218302193022030221302223022330224302253022630227302283022930230302313023230233302343023530236302373023830239302403024130242302433024430245302463024730248302493025030251302523025330254302553025630257302583025930260302613026230263302643026530266302673026830269302703027130272302733027430275302763027730278302793028030281302823028330284302853028630287302883028930290302913029230293302943029530296302973029830299303003030130302303033030430305303063030730308303093031030311303123031330314303153031630317303183031930320303213032230323303243032530326303273032830329303303033130332303333033430335303363033730338303393034030341303423034330344303453034630347303483034930350303513035230353303543035530356303573035830359303603036130362303633036430365303663036730368303693037030371303723037330374303753037630377303783037930380303813038230383303843038530386303873038830389303903039130392303933039430395303963039730398303993040030401304023040330404304053040630407304083040930410304113041230413304143041530416304173041830419304203042130422304233042430425304263042730428304293043030431304323043330434304353043630437304383043930440304413044230443304443044530446304473044830449304503045130452304533045430455304563045730458304593046030461304623046330464304653046630467304683046930470304713047230473304743047530476304773047830479304803048130482304833048430485304863048730488304893049030491304923049330494304953049630497304983049930500305013050230503305043050530506305073050830509305103051130512305133051430515305163051730518305193052030521305223052330524305253052630527305283052930530305313053230533305343053530536305373053830539305403054130542305433054430545305463054730548305493055030551305523055330554305553055630557305583055930560305613056230563305643056530566305673056830569305703057130572305733057430575305763057730578305793058030581305823058330584305853058630587305883058930590305913059230593305943059530596305973059830599306003060130602306033060430605306063060730608306093061030611306123061330614306153061630617306183061930620306213062230623306243062530626306273062830629306303063130632306333063430635306363063730638306393064030641306423064330644306453064630647306483064930650306513065230653306543065530656306573065830659306603066130662306633066430665306663066730668306693067030671306723067330674306753067630677306783067930680306813068230683306843068530686306873068830689306903069130692306933069430695306963069730698306993070030701307023070330704307053070630707307083070930710307113071230713307143071530716307173071830719307203072130722307233072430725307263072730728307293073030731307323073330734307353073630737307383073930740307413074230743307443074530746307473074830749307503075130752307533075430755307563075730758307593076030761307623076330764307653076630767307683076930770307713077230773307743077530776307773077830779307803078130782307833078430785307863078730788307893079030791307923079330794307953079630797307983079930800308013080230803308043080530806308073080830809308103081130812308133081430815308163081730818308193082030821308223082330824308253082630827308283082930830308313083230833308343083530836308373083830839308403084130842308433084430845308463084730848308493085030851308523085330854308553085630857308583085930860308613086230863308643086530866308673086830869308703087130872308733087430875308763087730878308793088030881308823088330884308853088630887308883088930890308913089230893308943089530896308973089830899309003090130902309033090430905309063090730908309093091030911309123091330914309153091630917309183091930920309213092230923309243092530926309273092830929309303093130932309333093430935309363093730938309393094030941309423094330944309453094630947309483094930950309513095230953309543095530956309573095830959309603096130962309633096430965309663096730968309693097030971309723097330974309753097630977309783097930980309813098230983309843098530986309873098830989309903099130992309933099430995309963099730998309993100031001310023100331004310053100631007310083100931010310113101231013310143101531016310173101831019310203102131022310233102431025310263102731028310293103031031310323103331034310353103631037310383103931040310413104231043310443104531046310473104831049310503105131052310533105431055310563105731058310593106031061310623106331064310653106631067310683106931070310713107231073310743107531076310773107831079310803108131082310833108431085310863108731088310893109031091310923109331094310953109631097310983109931100311013110231103311043110531106311073110831109311103111131112311133111431115311163111731118311193112031121311223112331124311253112631127311283112931130311313113231133311343113531136311373113831139311403114131142311433114431145311463114731148311493115031151311523115331154311553115631157311583115931160311613116231163311643116531166311673116831169311703117131172311733117431175311763117731178311793118031181311823118331184311853118631187311883118931190311913119231193311943119531196311973119831199312003120131202312033120431205312063120731208312093121031211312123121331214312153121631217312183121931220312213122231223312243122531226312273122831229312303123131232312333123431235312363123731238312393124031241312423124331244312453124631247312483124931250312513125231253312543125531256312573125831259312603126131262312633126431265312663126731268312693127031271312723127331274312753127631277312783127931280312813128231283312843128531286312873128831289312903129131292312933129431295312963129731298312993130031301313023130331304313053130631307313083130931310313113131231313313143131531316313173131831319313203132131322313233132431325313263132731328313293133031331313323133331334313353133631337313383133931340313413134231343313443134531346313473134831349313503135131352313533135431355313563135731358313593136031361313623136331364313653136631367313683136931370313713137231373313743137531376313773137831379313803138131382313833138431385313863138731388313893139031391313923139331394313953139631397313983139931400314013140231403314043140531406314073140831409314103141131412314133141431415314163141731418314193142031421314223142331424314253142631427314283142931430314313143231433314343143531436314373143831439314403144131442314433144431445314463144731448314493145031451314523145331454314553145631457314583145931460314613146231463314643146531466314673146831469314703147131472314733147431475314763147731478314793148031481314823148331484314853148631487314883148931490314913149231493314943149531496314973149831499315003150131502315033150431505315063150731508315093151031511315123151331514315153151631517315183151931520315213152231523315243152531526315273152831529315303153131532315333153431535315363153731538315393154031541315423154331544315453154631547315483154931550315513155231553315543155531556315573155831559315603156131562315633156431565315663156731568315693157031571315723157331574315753157631577315783157931580315813158231583315843158531586315873158831589315903159131592315933159431595315963159731598315993160031601316023160331604316053160631607316083160931610316113161231613316143161531616316173161831619316203162131622316233162431625316263162731628316293163031631316323163331634316353163631637316383163931640316413164231643316443164531646316473164831649316503165131652316533165431655316563165731658316593166031661316623166331664316653166631667316683166931670316713167231673316743167531676316773167831679316803168131682316833168431685316863168731688316893169031691316923169331694316953169631697316983169931700317013170231703317043170531706317073170831709317103171131712317133171431715317163171731718317193172031721317223172331724317253172631727317283172931730317313173231733317343173531736317373173831739317403174131742317433174431745317463174731748317493175031751317523175331754317553175631757317583175931760317613176231763317643176531766317673176831769317703177131772317733177431775317763177731778317793178031781317823178331784317853178631787317883178931790317913179231793317943179531796317973179831799318003180131802318033180431805318063180731808318093181031811318123181331814318153181631817318183181931820318213182231823318243182531826318273182831829318303183131832318333183431835318363183731838318393184031841318423184331844318453184631847318483184931850318513185231853318543185531856318573185831859318603186131862318633186431865318663186731868318693187031871318723187331874318753187631877318783187931880318813188231883318843188531886318873188831889318903189131892318933189431895318963189731898318993190031901319023190331904319053190631907319083190931910319113191231913319143191531916319173191831919319203192131922319233192431925319263192731928319293193031931319323193331934319353193631937319383193931940319413194231943319443194531946319473194831949319503195131952319533195431955319563195731958319593196031961319623196331964319653196631967319683196931970319713197231973319743197531976319773197831979319803198131982319833198431985319863198731988319893199031991319923199331994319953199631997319983199932000320013200232003320043200532006320073200832009320103201132012320133201432015320163201732018320193202032021320223202332024320253202632027320283202932030320313203232033320343203532036320373203832039320403204132042320433204432045320463204732048320493205032051320523205332054320553205632057320583205932060320613206232063320643206532066320673206832069320703207132072320733207432075320763207732078320793208032081320823208332084320853208632087320883208932090320913209232093320943209532096320973209832099321003210132102321033210432105321063210732108321093211032111321123211332114321153211632117321183211932120321213212232123321243212532126321273212832129321303213132132321333213432135321363213732138321393214032141321423214332144321453214632147321483214932150321513215232153321543215532156321573215832159321603216132162321633216432165321663216732168321693217032171321723217332174321753217632177321783217932180321813218232183321843218532186321873218832189321903219132192321933219432195321963219732198321993220032201322023220332204322053220632207322083220932210322113221232213322143221532216322173221832219322203222132222322233222432225322263222732228322293223032231322323223332234322353223632237322383223932240322413224232243322443224532246322473224832249322503225132252322533225432255322563225732258322593226032261322623226332264322653226632267322683226932270322713227232273322743227532276322773227832279322803228132282322833228432285322863228732288322893229032291322923229332294322953229632297322983229932300323013230232303323043230532306323073230832309323103231132312323133231432315323163231732318323193232032321323223232332324323253232632327323283232932330323313233232333323343233532336323373233832339323403234132342323433234432345323463234732348323493235032351323523235332354323553235632357323583235932360323613236232363323643236532366323673236832369323703237132372323733237432375323763237732378323793238032381323823238332384323853238632387323883238932390323913239232393323943239532396323973239832399324003240132402324033240432405324063240732408324093241032411324123241332414324153241632417324183241932420324213242232423324243242532426324273242832429324303243132432324333243432435324363243732438324393244032441324423244332444324453244632447324483244932450324513245232453324543245532456324573245832459324603246132462324633246432465324663246732468324693247032471324723247332474324753247632477324783247932480324813248232483324843248532486324873248832489324903249132492324933249432495324963249732498324993250032501325023250332504325053250632507325083250932510325113251232513325143251532516325173251832519325203252132522325233252432525325263252732528325293253032531325323253332534325353253632537325383253932540325413254232543325443254532546325473254832549325503255132552325533255432555325563255732558325593256032561325623256332564325653256632567325683256932570325713257232573325743257532576325773257832579325803258132582325833258432585325863258732588325893259032591325923259332594325953259632597325983259932600326013260232603326043260532606326073260832609326103261132612326133261432615326163261732618326193262032621326223262332624326253262632627326283262932630326313263232633326343263532636326373263832639326403264132642326433264432645326463264732648326493265032651326523265332654326553265632657326583265932660326613266232663326643266532666326673266832669326703267132672326733267432675326763267732678326793268032681326823268332684326853268632687326883268932690326913269232693326943269532696326973269832699327003270132702327033270432705327063270732708327093271032711327123271332714327153271632717327183271932720327213272232723327243272532726327273272832729327303273132732327333273432735327363273732738327393274032741327423274332744327453274632747327483274932750327513275232753327543275532756327573275832759327603276132762327633276432765327663276732768327693277032771327723277332774327753277632777327783277932780327813278232783327843278532786327873278832789327903279132792327933279432795327963279732798327993280032801328023280332804328053280632807328083280932810328113281232813328143281532816328173281832819328203282132822328233282432825328263282732828328293283032831328323283332834328353283632837328383283932840328413284232843328443284532846328473284832849328503285132852328533285432855328563285732858328593286032861328623286332864328653286632867328683286932870328713287232873328743287532876328773287832879328803288132882328833288432885328863288732888328893289032891328923289332894328953289632897328983289932900329013290232903329043290532906329073290832909329103291132912329133291432915329163291732918329193292032921329223292332924329253292632927329283292932930329313293232933329343293532936329373293832939329403294132942329433294432945329463294732948329493295032951329523295332954329553295632957329583295932960329613296232963329643296532966329673296832969329703297132972329733297432975329763297732978329793298032981329823298332984329853298632987329883298932990329913299232993329943299532996329973299832999330003300133002330033300433005330063300733008330093301033011330123301333014330153301633017330183301933020330213302233023330243302533026330273302833029330303303133032330333303433035330363303733038330393304033041330423304333044330453304633047330483304933050330513305233053330543305533056330573305833059330603306133062330633306433065330663306733068330693307033071330723307333074330753307633077330783307933080330813308233083330843308533086330873308833089330903309133092330933309433095330963309733098330993310033101331023310333104331053310633107331083310933110331113311233113331143311533116331173311833119331203312133122331233312433125331263312733128331293313033131331323313333134331353313633137331383313933140331413314233143331443314533146331473314833149331503315133152331533315433155331563315733158331593316033161331623316333164331653316633167331683316933170331713317233173331743317533176331773317833179331803318133182331833318433185331863318733188331893319033191331923319333194331953319633197331983319933200332013320233203332043320533206332073320833209332103321133212332133321433215332163321733218332193322033221332223322333224332253322633227332283322933230332313323233233332343323533236332373323833239332403324133242332433324433245332463324733248332493325033251332523325333254332553325633257332583325933260332613326233263332643326533266332673326833269332703327133272332733327433275332763327733278332793328033281332823328333284332853328633287332883328933290332913329233293332943329533296332973329833299333003330133302333033330433305333063330733308333093331033311333123331333314333153331633317333183331933320333213332233323333243332533326333273332833329333303333133332333333333433335333363333733338333393334033341333423334333344333453334633347333483334933350333513335233353333543335533356333573335833359333603336133362333633336433365333663336733368333693337033371333723337333374333753337633377333783337933380333813338233383333843338533386333873338833389333903339133392333933339433395333963339733398333993340033401334023340333404334053340633407334083340933410334113341233413334143341533416334173341833419334203342133422334233342433425334263342733428334293343033431334323343333434334353343633437334383343933440334413344233443334443344533446334473344833449334503345133452334533345433455334563345733458334593346033461334623346333464334653346633467334683346933470334713347233473334743347533476334773347833479334803348133482334833348433485334863348733488334893349033491334923349333494334953349633497334983349933500335013350233503335043350533506335073350833509335103351133512335133351433515335163351733518335193352033521335223352333524335253352633527335283352933530335313353233533335343353533536335373353833539335403354133542335433354433545335463354733548335493355033551335523355333554335553355633557335583355933560335613356233563335643356533566335673356833569335703357133572335733357433575335763357733578335793358033581335823358333584335853358633587335883358933590335913359233593335943359533596335973359833599336003360133602336033360433605336063360733608336093361033611336123361333614336153361633617336183361933620336213362233623336243362533626336273362833629336303363133632336333363433635336363363733638336393364033641336423364333644336453364633647336483364933650336513365233653336543365533656336573365833659336603366133662336633366433665336663366733668336693367033671336723367333674336753367633677336783367933680336813368233683336843368533686336873368833689336903369133692336933369433695336963369733698336993370033701337023370333704337053370633707337083370933710337113371233713337143371533716337173371833719337203372133722337233372433725337263372733728337293373033731337323373333734337353373633737337383373933740337413374233743337443374533746337473374833749337503375133752337533375433755337563375733758337593376033761337623376333764337653376633767337683376933770337713377233773337743377533776337773377833779337803378133782337833378433785337863378733788337893379033791337923379333794337953379633797337983379933800338013380233803338043380533806338073380833809338103381133812338133381433815338163381733818338193382033821338223382333824338253382633827338283382933830338313383233833338343383533836338373383833839338403384133842338433384433845338463384733848338493385033851338523385333854338553385633857338583385933860338613386233863338643386533866338673386833869338703387133872338733387433875338763387733878338793388033881338823388333884338853388633887338883388933890338913389233893338943389533896338973389833899339003390133902339033390433905339063390733908339093391033911339123391333914339153391633917339183391933920339213392233923339243392533926339273392833929339303393133932339333393433935339363393733938339393394033941339423394333944339453394633947339483394933950339513395233953339543395533956339573395833959339603396133962339633396433965339663396733968339693397033971339723397333974339753397633977339783397933980339813398233983339843398533986339873398833989339903399133992339933399433995339963399733998339993400034001340023400334004340053400634007340083400934010340113401234013340143401534016340173401834019340203402134022340233402434025340263402734028340293403034031340323403334034340353403634037340383403934040340413404234043340443404534046340473404834049340503405134052340533405434055340563405734058340593406034061340623406334064340653406634067340683406934070340713407234073340743407534076340773407834079340803408134082340833408434085340863408734088340893409034091340923409334094340953409634097340983409934100341013410234103341043410534106341073410834109341103411134112341133411434115341163411734118341193412034121341223412334124341253412634127341283412934130341313413234133341343413534136341373413834139341403414134142341433414434145341463414734148341493415034151341523415334154341553415634157341583415934160341613416234163341643416534166341673416834169341703417134172341733417434175341763417734178341793418034181341823418334184341853418634187341883418934190341913419234193341943419534196341973419834199342003420134202342033420434205342063420734208342093421034211342123421334214342153421634217342183421934220342213422234223342243422534226342273422834229342303423134232342333423434235342363423734238342393424034241342423424334244342453424634247342483424934250342513425234253342543425534256342573425834259342603426134262342633426434265342663426734268342693427034271342723427334274342753427634277342783427934280342813428234283342843428534286342873428834289342903429134292342933429434295342963429734298342993430034301343023430334304343053430634307343083430934310343113431234313343143431534316343173431834319343203432134322343233432434325343263432734328343293433034331343323433334334343353433634337343383433934340343413434234343343443434534346343473434834349343503435134352343533435434355343563435734358343593436034361343623436334364343653436634367343683436934370343713437234373343743437534376343773437834379343803438134382343833438434385343863438734388343893439034391343923439334394343953439634397343983439934400344013440234403344043440534406344073440834409344103441134412344133441434415344163441734418344193442034421344223442334424344253442634427344283442934430344313443234433344343443534436344373443834439344403444134442344433444434445344463444734448344493445034451344523445334454344553445634457344583445934460344613446234463344643446534466344673446834469344703447134472344733447434475344763447734478344793448034481344823448334484344853448634487344883448934490344913449234493344943449534496344973449834499345003450134502345033450434505345063450734508345093451034511345123451334514345153451634517345183451934520345213452234523345243452534526345273452834529345303453134532345333453434535345363453734538345393454034541345423454334544345453454634547345483454934550345513455234553345543455534556345573455834559345603456134562345633456434565345663456734568345693457034571345723457334574345753457634577345783457934580345813458234583345843458534586345873458834589345903459134592345933459434595345963459734598345993460034601346023460334604346053460634607346083460934610346113461234613346143461534616346173461834619346203462134622346233462434625346263462734628346293463034631346323463334634346353463634637346383463934640346413464234643346443464534646346473464834649346503465134652346533465434655346563465734658346593466034661346623466334664346653466634667346683466934670346713467234673346743467534676346773467834679346803468134682346833468434685346863468734688346893469034691346923469334694346953469634697346983469934700347013470234703347043470534706347073470834709347103471134712347133471434715347163471734718347193472034721347223472334724347253472634727347283472934730347313473234733347343473534736347373473834739347403474134742347433474434745347463474734748347493475034751347523475334754347553475634757347583475934760347613476234763347643476534766347673476834769347703477134772347733477434775347763477734778347793478034781347823478334784347853478634787347883478934790347913479234793347943479534796347973479834799348003480134802348033480434805348063480734808348093481034811348123481334814348153481634817348183481934820348213482234823348243482534826348273482834829348303483134832348333483434835348363483734838348393484034841348423484334844348453484634847348483484934850348513485234853348543485534856348573485834859348603486134862348633486434865348663486734868348693487034871348723487334874348753487634877348783487934880348813488234883348843488534886348873488834889348903489134892348933489434895348963489734898348993490034901349023490334904349053490634907349083490934910349113491234913349143491534916349173491834919349203492134922349233492434925349263492734928349293493034931349323493334934349353493634937349383493934940349413494234943349443494534946349473494834949349503495134952349533495434955349563495734958349593496034961349623496334964349653496634967349683496934970349713497234973349743497534976349773497834979349803498134982349833498434985349863498734988349893499034991349923499334994349953499634997349983499935000350013500235003350043500535006350073500835009350103501135012350133501435015350163501735018350193502035021350223502335024350253502635027350283502935030350313503235033350343503535036350373503835039350403504135042350433504435045350463504735048350493505035051350523505335054350553505635057350583505935060350613506235063350643506535066350673506835069350703507135072350733507435075350763507735078350793508035081350823508335084350853508635087350883508935090350913509235093350943509535096350973509835099351003510135102351033510435105351063510735108351093511035111351123511335114351153511635117351183511935120351213512235123351243512535126351273512835129351303513135132351333513435135351363513735138351393514035141351423514335144351453514635147351483514935150351513515235153351543515535156351573515835159351603516135162351633516435165351663516735168351693517035171351723517335174351753517635177351783517935180351813518235183351843518535186351873518835189351903519135192351933519435195351963519735198351993520035201352023520335204352053520635207352083520935210352113521235213352143521535216352173521835219352203522135222352233522435225352263522735228352293523035231352323523335234352353523635237352383523935240352413524235243352443524535246352473524835249352503525135252352533525435255352563525735258352593526035261352623526335264352653526635267352683526935270352713527235273352743527535276352773527835279352803528135282352833528435285352863528735288352893529035291352923529335294352953529635297352983529935300353013530235303353043530535306353073530835309353103531135312353133531435315353163531735318353193532035321353223532335324353253532635327353283532935330353313533235333353343533535336353373533835339353403534135342353433534435345353463534735348353493535035351353523535335354353553535635357353583535935360353613536235363353643536535366353673536835369353703537135372353733537435375353763537735378353793538035381353823538335384353853538635387353883538935390353913539235393353943539535396353973539835399354003540135402354033540435405354063540735408354093541035411354123541335414354153541635417354183541935420354213542235423354243542535426354273542835429354303543135432354333543435435354363543735438354393544035441354423544335444354453544635447354483544935450354513545235453354543545535456354573545835459354603546135462354633546435465354663546735468354693547035471354723547335474354753547635477354783547935480354813548235483354843548535486354873548835489354903549135492354933549435495354963549735498354993550035501355023550335504355053550635507355083550935510355113551235513355143551535516355173551835519355203552135522355233552435525355263552735528355293553035531355323553335534355353553635537355383553935540355413554235543355443554535546355473554835549355503555135552355533555435555355563555735558355593556035561355623556335564355653556635567355683556935570355713557235573355743557535576355773557835579355803558135582355833558435585355863558735588355893559035591355923559335594355953559635597355983559935600356013560235603356043560535606356073560835609356103561135612356133561435615356163561735618356193562035621356223562335624356253562635627356283562935630356313563235633356343563535636356373563835639356403564135642356433564435645356463564735648356493565035651356523565335654356553565635657356583565935660356613566235663356643566535666356673566835669356703567135672356733567435675356763567735678356793568035681356823568335684356853568635687356883568935690356913569235693356943569535696356973569835699357003570135702357033570435705357063570735708357093571035711357123571335714357153571635717357183571935720357213572235723357243572535726357273572835729357303573135732357333573435735357363573735738357393574035741357423574335744357453574635747357483574935750357513575235753357543575535756357573575835759357603576135762357633576435765357663576735768357693577035771357723577335774357753577635777357783577935780357813578235783357843578535786357873578835789357903579135792357933579435795357963579735798357993580035801358023580335804358053580635807358083580935810358113581235813358143581535816358173581835819358203582135822358233582435825358263582735828358293583035831358323583335834358353583635837358383583935840358413584235843358443584535846358473584835849358503585135852358533585435855358563585735858358593586035861358623586335864358653586635867358683586935870358713587235873358743587535876358773587835879358803588135882358833588435885358863588735888358893589035891358923589335894358953589635897358983589935900359013590235903359043590535906359073590835909359103591135912359133591435915359163591735918359193592035921359223592335924359253592635927359283592935930359313593235933359343593535936359373593835939359403594135942359433594435945359463594735948359493595035951359523595335954359553595635957359583595935960359613596235963359643596535966359673596835969359703597135972359733597435975359763597735978359793598035981359823598335984359853598635987359883598935990359913599235993359943599535996359973599835999360003600136002360033600436005360063600736008360093601036011360123601336014360153601636017360183601936020360213602236023360243602536026360273602836029360303603136032360333603436035360363603736038360393604036041360423604336044360453604636047360483604936050360513605236053360543605536056360573605836059360603606136062360633606436065360663606736068360693607036071360723607336074360753607636077360783607936080360813608236083360843608536086360873608836089360903609136092360933609436095360963609736098360993610036101361023610336104361053610636107361083610936110361113611236113361143611536116361173611836119361203612136122361233612436125361263612736128361293613036131361323613336134361353613636137361383613936140361413614236143361443614536146361473614836149361503615136152361533615436155361563615736158361593616036161361623616336164361653616636167361683616936170361713617236173361743617536176361773617836179361803618136182361833618436185361863618736188361893619036191361923619336194361953619636197361983619936200362013620236203362043620536206362073620836209362103621136212362133621436215362163621736218362193622036221362223622336224362253622636227362283622936230362313623236233362343623536236362373623836239362403624136242362433624436245362463624736248362493625036251362523625336254362553625636257362583625936260362613626236263362643626536266362673626836269362703627136272362733627436275362763627736278362793628036281362823628336284362853628636287362883628936290362913629236293362943629536296362973629836299363003630136302363033630436305363063630736308363093631036311363123631336314363153631636317363183631936320363213632236323363243632536326363273632836329363303633136332363333633436335363363633736338363393634036341363423634336344363453634636347363483634936350363513635236353363543635536356363573635836359363603636136362363633636436365363663636736368363693637036371363723637336374363753637636377363783637936380363813638236383363843638536386363873638836389363903639136392363933639436395363963639736398363993640036401364023640336404364053640636407364083640936410364113641236413364143641536416364173641836419364203642136422364233642436425364263642736428364293643036431364323643336434364353643636437364383643936440364413644236443364443644536446364473644836449364503645136452364533645436455364563645736458364593646036461364623646336464364653646636467364683646936470364713647236473364743647536476364773647836479364803648136482364833648436485364863648736488364893649036491364923649336494364953649636497364983649936500365013650236503365043650536506365073650836509365103651136512365133651436515365163651736518365193652036521365223652336524365253652636527365283652936530365313653236533365343653536536365373653836539365403654136542365433654436545365463654736548365493655036551365523655336554365553655636557365583655936560365613656236563365643656536566365673656836569365703657136572365733657436575365763657736578365793658036581365823658336584365853658636587365883658936590365913659236593365943659536596365973659836599366003660136602366033660436605366063660736608366093661036611366123661336614366153661636617366183661936620366213662236623366243662536626366273662836629366303663136632366333663436635366363663736638366393664036641366423664336644366453664636647366483664936650366513665236653366543665536656366573665836659366603666136662366633666436665366663666736668366693667036671366723667336674366753667636677366783667936680366813668236683366843668536686366873668836689366903669136692366933669436695366963669736698366993670036701367023670336704367053670636707367083670936710367113671236713367143671536716367173671836719367203672136722367233672436725367263672736728367293673036731367323673336734367353673636737367383673936740367413674236743367443674536746367473674836749367503675136752367533675436755367563675736758367593676036761367623676336764367653676636767367683676936770367713677236773367743677536776367773677836779367803678136782367833678436785367863678736788367893679036791367923679336794367953679636797367983679936800368013680236803368043680536806368073680836809368103681136812368133681436815368163681736818368193682036821368223682336824368253682636827368283682936830368313683236833368343683536836368373683836839368403684136842368433684436845368463684736848368493685036851368523685336854368553685636857368583685936860368613686236863368643686536866368673686836869368703687136872368733687436875368763687736878368793688036881368823688336884368853688636887368883688936890368913689236893368943689536896368973689836899369003690136902369033690436905369063690736908369093691036911369123691336914369153691636917369183691936920369213692236923369243692536926369273692836929369303693136932369333693436935369363693736938369393694036941369423694336944369453694636947369483694936950369513695236953369543695536956369573695836959369603696136962369633696436965369663696736968369693697036971369723697336974369753697636977369783697936980369813698236983369843698536986369873698836989369903699136992369933699436995369963699736998369993700037001370023700337004370053700637007370083700937010370113701237013370143701537016370173701837019370203702137022370233702437025370263702737028370293703037031370323703337034370353703637037370383703937040370413704237043370443704537046370473704837049370503705137052370533705437055370563705737058370593706037061370623706337064370653706637067370683706937070370713707237073370743707537076370773707837079370803708137082370833708437085370863708737088370893709037091370923709337094370953709637097370983709937100371013710237103371043710537106371073710837109371103711137112371133711437115371163711737118371193712037121371223712337124371253712637127371283712937130371313713237133371343713537136371373713837139371403714137142371433714437145371463714737148371493715037151371523715337154371553715637157371583715937160371613716237163371643716537166371673716837169371703717137172371733717437175371763717737178371793718037181371823718337184371853718637187371883718937190371913719237193371943719537196371973719837199372003720137202372033720437205372063720737208372093721037211372123721337214372153721637217372183721937220372213722237223372243722537226372273722837229372303723137232372333723437235372363723737238372393724037241372423724337244372453724637247372483724937250372513725237253372543725537256372573725837259372603726137262372633726437265372663726737268372693727037271372723727337274372753727637277372783727937280372813728237283372843728537286372873728837289372903729137292372933729437295372963729737298372993730037301373023730337304373053730637307373083730937310373113731237313373143731537316373173731837319373203732137322373233732437325373263732737328373293733037331373323733337334373353733637337373383733937340373413734237343373443734537346373473734837349373503735137352373533735437355373563735737358373593736037361373623736337364373653736637367373683736937370373713737237373373743737537376373773737837379373803738137382373833738437385373863738737388373893739037391373923739337394373953739637397373983739937400374013740237403374043740537406374073740837409374103741137412374133741437415374163741737418374193742037421374223742337424374253742637427374283742937430374313743237433374343743537436374373743837439374403744137442374433744437445374463744737448374493745037451374523745337454374553745637457374583745937460374613746237463374643746537466374673746837469374703747137472374733747437475374763747737478374793748037481374823748337484374853748637487374883748937490374913749237493374943749537496374973749837499375003750137502375033750437505375063750737508375093751037511375123751337514375153751637517375183751937520375213752237523375243752537526375273752837529375303753137532375333753437535375363753737538375393754037541375423754337544375453754637547375483754937550375513755237553375543755537556375573755837559375603756137562375633756437565375663756737568375693757037571375723757337574375753757637577375783757937580375813758237583375843758537586375873758837589375903759137592375933759437595375963759737598375993760037601376023760337604376053760637607376083760937610376113761237613376143761537616376173761837619376203762137622376233762437625376263762737628376293763037631376323763337634376353763637637376383763937640376413764237643376443764537646376473764837649376503765137652376533765437655376563765737658376593766037661376623766337664376653766637667376683766937670376713767237673376743767537676376773767837679376803768137682376833768437685376863768737688376893769037691376923769337694376953769637697376983769937700377013770237703377043770537706377073770837709377103771137712377133771437715377163771737718377193772037721377223772337724377253772637727377283772937730377313773237733377343773537736377373773837739377403774137742377433774437745377463774737748377493775037751377523775337754377553775637757377583775937760377613776237763377643776537766377673776837769377703777137772377733777437775377763777737778377793778037781377823778337784377853778637787377883778937790377913779237793377943779537796377973779837799378003780137802378033780437805378063780737808378093781037811378123781337814378153781637817378183781937820378213782237823378243782537826378273782837829378303783137832378333783437835378363783737838378393784037841378423784337844378453784637847378483784937850378513785237853378543785537856378573785837859378603786137862378633786437865378663786737868378693787037871378723787337874378753787637877378783787937880378813788237883378843788537886378873788837889378903789137892378933789437895378963789737898378993790037901379023790337904379053790637907379083790937910379113791237913379143791537916379173791837919379203792137922379233792437925379263792737928379293793037931379323793337934379353793637937379383793937940379413794237943379443794537946379473794837949379503795137952379533795437955379563795737958379593796037961379623796337964379653796637967379683796937970379713797237973379743797537976379773797837979379803798137982379833798437985379863798737988379893799037991379923799337994379953799637997379983799938000380013800238003380043800538006380073800838009380103801138012380133801438015380163801738018380193802038021380223802338024380253802638027380283802938030380313803238033380343803538036380373803838039380403804138042380433804438045380463804738048380493805038051380523805338054380553805638057380583805938060380613806238063380643806538066380673806838069380703807138072380733807438075380763807738078380793808038081380823808338084380853808638087380883808938090380913809238093380943809538096380973809838099381003810138102381033810438105381063810738108381093811038111381123811338114381153811638117381183811938120381213812238123381243812538126381273812838129381303813138132381333813438135381363813738138381393814038141381423814338144381453814638147381483814938150381513815238153381543815538156381573815838159381603816138162381633816438165381663816738168381693817038171381723817338174381753817638177381783817938180381813818238183381843818538186381873818838189381903819138192381933819438195381963819738198381993820038201382023820338204382053820638207382083820938210382113821238213382143821538216382173821838219382203822138222382233822438225382263822738228382293823038231382323823338234382353823638237382383823938240382413824238243382443824538246382473824838249382503825138252382533825438255382563825738258382593826038261382623826338264382653826638267382683826938270382713827238273382743827538276382773827838279382803828138282382833828438285382863828738288382893829038291382923829338294382953829638297382983829938300383013830238303383043830538306383073830838309383103831138312383133831438315383163831738318383193832038321383223832338324383253832638327383283832938330383313833238333383343833538336383373833838339383403834138342383433834438345383463834738348383493835038351383523835338354383553835638357383583835938360383613836238363383643836538366383673836838369383703837138372383733837438375383763837738378383793838038381383823838338384383853838638387383883838938390383913839238393383943839538396383973839838399384003840138402384033840438405384063840738408384093841038411384123841338414384153841638417384183841938420384213842238423384243842538426384273842838429384303843138432384333843438435384363843738438384393844038441384423844338444384453844638447384483844938450384513845238453384543845538456384573845838459384603846138462384633846438465384663846738468384693847038471384723847338474384753847638477384783847938480384813848238483384843848538486384873848838489384903849138492384933849438495384963849738498384993850038501385023850338504385053850638507385083850938510385113851238513385143851538516385173851838519385203852138522385233852438525385263852738528385293853038531385323853338534385353853638537385383853938540385413854238543385443854538546385473854838549385503855138552385533855438555385563855738558385593856038561385623856338564385653856638567385683856938570385713857238573385743857538576385773857838579385803858138582385833858438585385863858738588385893859038591385923859338594385953859638597385983859938600386013860238603386043860538606386073860838609386103861138612386133861438615386163861738618386193862038621386223862338624386253862638627386283862938630386313863238633386343863538636386373863838639386403864138642386433864438645386463864738648386493865038651386523865338654386553865638657386583865938660386613866238663386643866538666386673866838669386703867138672386733867438675386763867738678386793868038681386823868338684386853868638687386883868938690386913869238693386943869538696386973869838699387003870138702387033870438705387063870738708387093871038711387123871338714387153871638717387183871938720387213872238723387243872538726387273872838729387303873138732387333873438735387363873738738387393874038741387423874338744387453874638747387483874938750387513875238753387543875538756387573875838759387603876138762387633876438765387663876738768387693877038771387723877338774387753877638777387783877938780387813878238783387843878538786387873878838789387903879138792387933879438795387963879738798387993880038801388023880338804388053880638807388083880938810388113881238813388143881538816388173881838819388203882138822388233882438825388263882738828388293883038831388323883338834388353883638837388383883938840388413884238843388443884538846388473884838849388503885138852388533885438855388563885738858388593886038861388623886338864388653886638867388683886938870388713887238873388743887538876388773887838879388803888138882388833888438885388863888738888388893889038891388923889338894388953889638897388983889938900389013890238903389043890538906389073890838909389103891138912389133891438915389163891738918389193892038921389223892338924389253892638927389283892938930389313893238933389343893538936389373893838939389403894138942389433894438945389463894738948389493895038951389523895338954389553895638957389583895938960389613896238963389643896538966389673896838969389703897138972389733897438975389763897738978389793898038981389823898338984389853898638987389883898938990389913899238993389943899538996389973899838999390003900139002390033900439005390063900739008390093901039011390123901339014390153901639017390183901939020390213902239023390243902539026390273902839029390303903139032390333903439035390363903739038390393904039041390423904339044390453904639047390483904939050390513905239053390543905539056390573905839059390603906139062390633906439065390663906739068390693907039071390723907339074390753907639077390783907939080390813908239083390843908539086390873908839089390903909139092390933909439095390963909739098390993910039101391023910339104391053910639107391083910939110391113911239113391143911539116391173911839119391203912139122391233912439125391263912739128391293913039131391323913339134391353913639137391383913939140391413914239143391443914539146391473914839149391503915139152391533915439155391563915739158391593916039161391623916339164391653916639167391683916939170391713917239173391743917539176391773917839179391803918139182391833918439185391863918739188391893919039191391923919339194391953919639197391983919939200392013920239203392043920539206392073920839209392103921139212392133921439215392163921739218392193922039221392223922339224392253922639227392283922939230392313923239233392343923539236392373923839239392403924139242392433924439245392463924739248392493925039251392523925339254392553925639257392583925939260392613926239263392643926539266392673926839269392703927139272392733927439275392763927739278392793928039281392823928339284392853928639287392883928939290392913929239293392943929539296392973929839299393003930139302393033930439305393063930739308393093931039311393123931339314393153931639317393183931939320393213932239323393243932539326393273932839329393303933139332393333933439335393363933739338393393934039341393423934339344393453934639347393483934939350393513935239353393543935539356393573935839359393603936139362393633936439365393663936739368393693937039371393723937339374393753937639377393783937939380393813938239383393843938539386393873938839389393903939139392393933939439395393963939739398393993940039401394023940339404394053940639407394083940939410394113941239413394143941539416394173941839419394203942139422394233942439425394263942739428394293943039431394323943339434394353943639437394383943939440394413944239443394443944539446394473944839449394503945139452394533945439455394563945739458394593946039461394623946339464394653946639467394683946939470394713947239473394743947539476394773947839479394803948139482394833948439485394863948739488394893949039491394923949339494394953949639497394983949939500395013950239503395043950539506395073950839509395103951139512395133951439515395163951739518395193952039521395223952339524395253952639527395283952939530395313953239533395343953539536395373953839539395403954139542395433954439545395463954739548395493955039551395523955339554395553955639557395583955939560395613956239563395643956539566395673956839569395703957139572395733957439575395763957739578395793958039581395823958339584395853958639587395883958939590395913959239593395943959539596395973959839599396003960139602396033960439605396063960739608396093961039611396123961339614396153961639617396183961939620396213962239623396243962539626396273962839629396303963139632396333963439635396363963739638396393964039641396423964339644396453964639647396483964939650396513965239653396543965539656396573965839659396603966139662396633966439665396663966739668396693967039671396723967339674396753967639677396783967939680396813968239683396843968539686396873968839689396903969139692396933969439695396963969739698396993970039701397023970339704397053970639707397083970939710397113971239713397143971539716397173971839719397203972139722397233972439725397263972739728397293973039731397323973339734397353973639737397383973939740397413974239743397443974539746397473974839749397503975139752397533975439755397563975739758397593976039761397623976339764397653976639767397683976939770397713977239773397743977539776397773977839779397803978139782397833978439785397863978739788397893979039791397923979339794397953979639797397983979939800398013980239803398043980539806398073980839809398103981139812398133981439815398163981739818398193982039821398223982339824398253982639827398283982939830398313983239833398343983539836398373983839839398403984139842398433984439845398463984739848398493985039851398523985339854398553985639857398583985939860398613986239863398643986539866398673986839869398703987139872398733987439875398763987739878398793988039881398823988339884398853988639887398883988939890398913989239893398943989539896398973989839899399003990139902399033990439905399063990739908399093991039911399123991339914399153991639917399183991939920399213992239923399243992539926399273992839929399303993139932399333993439935399363993739938399393994039941399423994339944399453994639947399483994939950399513995239953399543995539956399573995839959399603996139962399633996439965399663996739968399693997039971399723997339974399753997639977399783997939980399813998239983399843998539986399873998839989399903999139992399933999439995399963999739998399994000040001400024000340004400054000640007400084000940010400114001240013400144001540016400174001840019400204002140022400234002440025400264002740028400294003040031400324003340034400354003640037400384003940040400414004240043400444004540046400474004840049400504005140052400534005440055400564005740058400594006040061400624006340064400654006640067400684006940070400714007240073400744007540076400774007840079400804008140082400834008440085400864008740088400894009040091400924009340094400954009640097400984009940100401014010240103401044010540106401074010840109401104011140112401134011440115401164011740118401194012040121401224012340124401254012640127401284012940130401314013240133401344013540136401374013840139401404014140142401434014440145401464014740148401494015040151401524015340154401554015640157401584015940160401614016240163401644016540166401674016840169401704017140172401734017440175401764017740178401794018040181401824018340184401854018640187401884018940190401914019240193401944019540196401974019840199402004020140202402034020440205402064020740208402094021040211402124021340214402154021640217402184021940220402214022240223402244022540226402274022840229402304023140232402334023440235402364023740238402394024040241402424024340244402454024640247402484024940250402514025240253402544025540256402574025840259402604026140262402634026440265402664026740268402694027040271402724027340274402754027640277402784027940280402814028240283402844028540286402874028840289402904029140292402934029440295402964029740298402994030040301403024030340304403054030640307403084030940310403114031240313403144031540316403174031840319403204032140322403234032440325403264032740328403294033040331403324033340334403354033640337403384033940340403414034240343403444034540346403474034840349403504035140352403534035440355403564035740358403594036040361403624036340364403654036640367403684036940370403714037240373403744037540376403774037840379403804038140382403834038440385403864038740388403894039040391403924039340394403954039640397403984039940400404014040240403404044040540406404074040840409404104041140412404134041440415404164041740418404194042040421404224042340424404254042640427404284042940430404314043240433404344043540436404374043840439404404044140442404434044440445404464044740448404494045040451404524045340454404554045640457404584045940460404614046240463404644046540466404674046840469404704047140472404734047440475404764047740478404794048040481404824048340484404854048640487404884048940490404914049240493404944049540496404974049840499405004050140502405034050440505405064050740508405094051040511405124051340514405154051640517405184051940520405214052240523405244052540526405274052840529405304053140532405334053440535405364053740538405394054040541405424054340544405454054640547405484054940550405514055240553405544055540556405574055840559405604056140562405634056440565405664056740568405694057040571405724057340574405754057640577405784057940580405814058240583405844058540586405874058840589405904059140592405934059440595405964059740598405994060040601406024060340604406054060640607406084060940610406114061240613406144061540616406174061840619406204062140622406234062440625406264062740628406294063040631406324063340634406354063640637406384063940640406414064240643406444064540646406474064840649406504065140652406534065440655406564065740658406594066040661406624066340664406654066640667406684066940670406714067240673406744067540676406774067840679406804068140682406834068440685406864068740688406894069040691406924069340694406954069640697406984069940700407014070240703407044070540706407074070840709407104071140712407134071440715407164071740718407194072040721407224072340724407254072640727407284072940730407314073240733407344073540736407374073840739407404074140742407434074440745407464074740748407494075040751407524075340754407554075640757407584075940760407614076240763407644076540766407674076840769407704077140772407734077440775407764077740778407794078040781407824078340784407854078640787407884078940790407914079240793407944079540796407974079840799408004080140802408034080440805408064080740808408094081040811408124081340814408154081640817408184081940820408214082240823408244082540826408274082840829408304083140832408334083440835408364083740838408394084040841408424084340844408454084640847408484084940850408514085240853408544085540856408574085840859408604086140862408634086440865408664086740868408694087040871408724087340874408754087640877408784087940880408814088240883408844088540886408874088840889408904089140892408934089440895408964089740898408994090040901409024090340904409054090640907409084090940910409114091240913409144091540916409174091840919409204092140922409234092440925409264092740928409294093040931409324093340934409354093640937409384093940940409414094240943409444094540946409474094840949409504095140952409534095440955409564095740958409594096040961409624096340964409654096640967409684096940970409714097240973409744097540976409774097840979409804098140982409834098440985409864098740988409894099040991409924099340994409954099640997409984099941000410014100241003410044100541006410074100841009410104101141012410134101441015410164101741018410194102041021410224102341024410254102641027410284102941030410314103241033410344103541036410374103841039410404104141042410434104441045410464104741048410494105041051410524105341054410554105641057410584105941060410614106241063410644106541066410674106841069410704107141072410734107441075410764107741078410794108041081410824108341084410854108641087410884108941090410914109241093410944109541096410974109841099411004110141102411034110441105411064110741108411094111041111411124111341114411154111641117411184111941120411214112241123411244112541126411274112841129411304113141132411334113441135411364113741138411394114041141411424114341144411454114641147411484114941150411514115241153411544115541156411574115841159411604116141162411634116441165411664116741168411694117041171411724117341174411754117641177411784117941180411814118241183411844118541186411874118841189411904119141192411934119441195411964119741198411994120041201412024120341204412054120641207412084120941210412114121241213412144121541216412174121841219412204122141222412234122441225412264122741228412294123041231412324123341234412354123641237412384123941240412414124241243412444124541246412474124841249412504125141252412534125441255412564125741258412594126041261412624126341264412654126641267412684126941270412714127241273412744127541276412774127841279412804128141282412834128441285412864128741288412894129041291412924129341294412954129641297412984129941300413014130241303413044130541306413074130841309413104131141312413134131441315413164131741318413194132041321413224132341324413254132641327413284132941330413314133241333413344133541336413374133841339413404134141342413434134441345413464134741348413494135041351413524135341354413554135641357413584135941360413614136241363413644136541366413674136841369413704137141372413734137441375413764137741378413794138041381413824138341384413854138641387413884138941390413914139241393413944139541396413974139841399414004140141402414034140441405414064140741408414094141041411414124141341414414154141641417414184141941420414214142241423414244142541426414274142841429414304143141432414334143441435414364143741438414394144041441414424144341444414454144641447414484144941450414514145241453414544145541456414574145841459414604146141462414634146441465414664146741468414694147041471414724147341474414754147641477414784147941480414814148241483414844148541486414874148841489414904149141492414934149441495414964149741498414994150041501415024150341504415054150641507415084150941510415114151241513415144151541516415174151841519415204152141522415234152441525415264152741528415294153041531415324153341534415354153641537415384153941540415414154241543415444154541546415474154841549415504155141552415534155441555415564155741558415594156041561415624156341564415654156641567415684156941570415714157241573415744157541576415774157841579415804158141582415834158441585415864158741588415894159041591415924159341594415954159641597415984159941600416014160241603416044160541606416074160841609416104161141612416134161441615416164161741618416194162041621416224162341624416254162641627416284162941630416314163241633416344163541636416374163841639416404164141642416434164441645416464164741648416494165041651416524165341654416554165641657416584165941660416614166241663416644166541666416674166841669416704167141672416734167441675416764167741678416794168041681416824168341684416854168641687416884168941690416914169241693416944169541696416974169841699417004170141702417034170441705417064170741708417094171041711417124171341714417154171641717417184171941720417214172241723417244172541726417274172841729417304173141732417334173441735417364173741738417394174041741417424174341744417454174641747417484174941750417514175241753417544175541756417574175841759417604176141762417634176441765417664176741768417694177041771417724177341774417754177641777417784177941780417814178241783417844178541786417874178841789417904179141792417934179441795417964179741798417994180041801418024180341804418054180641807418084180941810418114181241813418144181541816418174181841819418204182141822418234182441825418264182741828418294183041831418324183341834418354183641837418384183941840418414184241843418444184541846418474184841849418504185141852418534185441855418564185741858418594186041861418624186341864418654186641867418684186941870418714187241873418744187541876418774187841879418804188141882418834188441885418864188741888418894189041891418924189341894418954189641897418984189941900419014190241903419044190541906419074190841909419104191141912419134191441915419164191741918419194192041921419224192341924419254192641927419284192941930419314193241933419344193541936419374193841939419404194141942419434194441945419464194741948419494195041951419524195341954419554195641957419584195941960419614196241963419644196541966419674196841969419704197141972419734197441975419764197741978419794198041981419824198341984419854198641987419884198941990419914199241993419944199541996419974199841999420004200142002420034200442005420064200742008420094201042011420124201342014420154201642017420184201942020420214202242023420244202542026420274202842029420304203142032420334203442035420364203742038420394204042041420424204342044420454204642047420484204942050420514205242053420544205542056420574205842059420604206142062420634206442065420664206742068420694207042071420724207342074420754207642077420784207942080420814208242083420844208542086420874208842089420904209142092420934209442095420964209742098420994210042101421024210342104421054210642107421084210942110421114211242113421144211542116421174211842119421204212142122421234212442125421264212742128421294213042131421324213342134421354213642137421384213942140421414214242143421444214542146421474214842149421504215142152421534215442155421564215742158421594216042161421624216342164421654216642167421684216942170421714217242173421744217542176421774217842179421804218142182421834218442185421864218742188421894219042191421924219342194421954219642197421984219942200422014220242203422044220542206422074220842209422104221142212422134221442215422164221742218422194222042221422224222342224422254222642227422284222942230422314223242233422344223542236422374223842239422404224142242422434224442245422464224742248422494225042251422524225342254422554225642257422584225942260422614226242263422644226542266422674226842269422704227142272422734227442275422764227742278422794228042281422824228342284422854228642287422884228942290422914229242293422944229542296422974229842299423004230142302423034230442305423064230742308423094231042311423124231342314423154231642317423184231942320423214232242323423244232542326423274232842329423304233142332423334233442335423364233742338423394234042341423424234342344423454234642347423484234942350423514235242353423544235542356423574235842359423604236142362423634236442365423664236742368423694237042371423724237342374423754237642377423784237942380423814238242383423844238542386423874238842389423904239142392423934239442395423964239742398423994240042401424024240342404424054240642407424084240942410424114241242413424144241542416424174241842419424204242142422424234242442425424264242742428424294243042431424324243342434424354243642437424384243942440424414244242443424444244542446424474244842449424504245142452424534245442455424564245742458424594246042461424624246342464424654246642467424684246942470424714247242473424744247542476424774247842479424804248142482424834248442485424864248742488424894249042491424924249342494424954249642497424984249942500425014250242503425044250542506425074250842509425104251142512425134251442515425164251742518425194252042521425224252342524425254252642527425284252942530425314253242533425344253542536425374253842539425404254142542425434254442545425464254742548425494255042551425524255342554425554255642557425584255942560425614256242563425644256542566425674256842569425704257142572425734257442575425764257742578425794258042581425824258342584425854258642587425884258942590425914259242593425944259542596425974259842599426004260142602426034260442605426064260742608426094261042611426124261342614426154261642617426184261942620426214262242623426244262542626426274262842629426304263142632426334263442635426364263742638426394264042641426424264342644426454264642647426484264942650426514265242653426544265542656426574265842659426604266142662426634266442665426664266742668426694267042671426724267342674426754267642677426784267942680426814268242683426844268542686426874268842689426904269142692426934269442695426964269742698426994270042701427024270342704427054270642707427084270942710427114271242713427144271542716427174271842719427204272142722427234272442725427264272742728427294273042731427324273342734427354273642737427384273942740427414274242743427444274542746427474274842749427504275142752427534275442755427564275742758427594276042761427624276342764427654276642767427684276942770427714277242773427744277542776427774277842779427804278142782427834278442785427864278742788427894279042791427924279342794427954279642797427984279942800428014280242803428044280542806428074280842809428104281142812428134281442815428164281742818428194282042821428224282342824428254282642827428284282942830428314283242833428344283542836428374283842839428404284142842428434284442845428464284742848428494285042851428524285342854428554285642857428584285942860428614286242863428644286542866428674286842869428704287142872428734287442875428764287742878428794288042881428824288342884428854288642887428884288942890428914289242893428944289542896428974289842899429004290142902429034290442905429064290742908429094291042911429124291342914429154291642917429184291942920429214292242923429244292542926429274292842929429304293142932429334293442935429364293742938429394294042941429424294342944429454294642947429484294942950429514295242953429544295542956429574295842959429604296142962429634296442965429664296742968429694297042971429724297342974429754297642977429784297942980429814298242983429844298542986429874298842989429904299142992429934299442995429964299742998429994300043001430024300343004430054300643007430084300943010430114301243013430144301543016430174301843019430204302143022430234302443025430264302743028430294303043031430324303343034430354303643037430384303943040430414304243043430444304543046430474304843049430504305143052430534305443055430564305743058430594306043061430624306343064430654306643067430684306943070430714307243073430744307543076430774307843079430804308143082430834308443085430864308743088430894309043091430924309343094430954309643097430984309943100431014310243103431044310543106431074310843109431104311143112431134311443115431164311743118431194312043121431224312343124431254312643127431284312943130431314313243133431344313543136431374313843139431404314143142431434314443145431464314743148431494315043151431524315343154431554315643157431584315943160431614316243163431644316543166431674316843169431704317143172431734317443175431764317743178431794318043181431824318343184431854318643187431884318943190431914319243193431944319543196431974319843199432004320143202432034320443205432064320743208432094321043211432124321343214432154321643217432184321943220432214322243223432244322543226432274322843229432304323143232432334323443235432364323743238432394324043241432424324343244432454324643247432484324943250432514325243253432544325543256432574325843259432604326143262432634326443265432664326743268432694327043271432724327343274432754327643277432784327943280432814328243283432844328543286432874328843289432904329143292432934329443295432964329743298432994330043301433024330343304433054330643307433084330943310433114331243313433144331543316433174331843319433204332143322433234332443325433264332743328433294333043331433324333343334433354333643337433384333943340433414334243343433444334543346433474334843349433504335143352433534335443355433564335743358433594336043361433624336343364433654336643367433684336943370433714337243373433744337543376433774337843379433804338143382433834338443385433864338743388433894339043391433924339343394433954339643397433984339943400434014340243403434044340543406434074340843409434104341143412434134341443415434164341743418434194342043421434224342343424434254342643427434284342943430434314343243433434344343543436434374343843439434404344143442434434344443445434464344743448434494345043451434524345343454434554345643457434584345943460434614346243463434644346543466434674346843469434704347143472434734347443475434764347743478434794348043481434824348343484434854348643487434884348943490434914349243493434944349543496434974349843499435004350143502435034350443505435064350743508435094351043511435124351343514435154351643517435184351943520435214352243523435244352543526435274352843529435304353143532435334353443535435364353743538435394354043541435424354343544435454354643547435484354943550435514355243553435544355543556435574355843559435604356143562435634356443565435664356743568435694357043571435724357343574435754357643577435784357943580435814358243583435844358543586435874358843589435904359143592435934359443595435964359743598435994360043601436024360343604436054360643607436084360943610436114361243613436144361543616436174361843619436204362143622436234362443625436264362743628436294363043631436324363343634436354363643637436384363943640436414364243643436444364543646436474364843649436504365143652436534365443655436564365743658436594366043661436624366343664436654366643667436684366943670436714367243673436744367543676436774367843679436804368143682436834368443685436864368743688436894369043691436924369343694436954369643697436984369943700437014370243703437044370543706437074370843709437104371143712437134371443715437164371743718437194372043721437224372343724437254372643727437284372943730437314373243733437344373543736437374373843739437404374143742437434374443745437464374743748437494375043751437524375343754437554375643757437584375943760437614376243763437644376543766437674376843769437704377143772437734377443775437764377743778437794378043781437824378343784437854378643787437884378943790437914379243793437944379543796437974379843799438004380143802438034380443805438064380743808438094381043811438124381343814438154381643817438184381943820438214382243823438244382543826438274382843829438304383143832438334383443835438364383743838438394384043841438424384343844438454384643847438484384943850438514385243853438544385543856438574385843859438604386143862438634386443865438664386743868438694387043871438724387343874438754387643877438784387943880438814388243883438844388543886438874388843889438904389143892438934389443895438964389743898438994390043901439024390343904439054390643907439084390943910439114391243913439144391543916439174391843919439204392143922439234392443925439264392743928439294393043931439324393343934439354393643937439384393943940439414394243943439444394543946439474394843949439504395143952439534395443955439564395743958439594396043961439624396343964439654396643967439684396943970439714397243973439744397543976439774397843979439804398143982439834398443985439864398743988439894399043991439924399343994439954399643997439984399944000440014400244003440044400544006440074400844009440104401144012440134401444015440164401744018440194402044021440224402344024440254402644027440284402944030440314403244033440344403544036440374403844039440404404144042440434404444045440464404744048440494405044051440524405344054440554405644057440584405944060440614406244063440644406544066440674406844069440704407144072440734407444075440764407744078440794408044081440824408344084440854408644087440884408944090440914409244093440944409544096440974409844099441004410144102441034410444105441064410744108441094411044111441124411344114441154411644117441184411944120441214412244123441244412544126441274412844129441304413144132441334413444135441364413744138441394414044141441424414344144441454414644147441484414944150441514415244153441544415544156441574415844159441604416144162441634416444165441664416744168441694417044171441724417344174441754417644177441784417944180441814418244183441844418544186441874418844189441904419144192441934419444195441964419744198441994420044201442024420344204442054420644207442084420944210442114421244213442144421544216442174421844219442204422144222442234422444225442264422744228442294423044231442324423344234442354423644237442384423944240442414424244243442444424544246442474424844249442504425144252442534425444255442564425744258442594426044261442624426344264442654426644267442684426944270442714427244273442744427544276442774427844279442804428144282442834428444285442864428744288442894429044291442924429344294442954429644297442984429944300443014430244303443044430544306443074430844309443104431144312443134431444315443164431744318443194432044321443224432344324443254432644327443284432944330443314433244333443344433544336443374433844339443404434144342443434434444345443464434744348443494435044351443524435344354443554435644357443584435944360443614436244363443644436544366443674436844369443704437144372443734437444375443764437744378443794438044381443824438344384443854438644387443884438944390443914439244393443944439544396443974439844399444004440144402444034440444405444064440744408444094441044411444124441344414444154441644417444184441944420444214442244423444244442544426444274442844429444304443144432444334443444435444364443744438444394444044441444424444344444444454444644447444484444944450444514445244453444544445544456444574445844459444604446144462444634446444465444664446744468444694447044471444724447344474444754447644477444784447944480444814448244483444844448544486444874448844489444904449144492444934449444495444964449744498444994450044501445024450344504445054450644507445084450944510445114451244513445144451544516445174451844519445204452144522445234452444525445264452744528445294453044531445324453344534445354453644537445384453944540445414454244543445444454544546445474454844549445504455144552445534455444555445564455744558445594456044561445624456344564445654456644567445684456944570445714457244573445744457544576445774457844579445804458144582445834458444585445864458744588445894459044591445924459344594445954459644597445984459944600446014460244603446044460544606446074460844609446104461144612446134461444615446164461744618446194462044621446224462344624446254462644627446284462944630446314463244633446344463544636446374463844639446404464144642446434464444645446464464744648446494465044651446524465344654446554465644657446584465944660446614466244663446644466544666446674466844669446704467144672446734467444675446764467744678446794468044681446824468344684446854468644687446884468944690446914469244693446944469544696446974469844699447004470144702447034470444705447064470744708447094471044711447124471344714447154471644717447184471944720447214472244723447244472544726447274472844729447304473144732447334473444735447364473744738447394474044741447424474344744447454474644747447484474944750447514475244753447544475544756447574475844759447604476144762447634476444765447664476744768447694477044771447724477344774447754477644777447784477944780447814478244783447844478544786447874478844789447904479144792447934479444795447964479744798447994480044801448024480344804448054480644807448084480944810448114481244813448144481544816448174481844819448204482144822448234482444825448264482744828448294483044831448324483344834448354483644837448384483944840448414484244843448444484544846448474484844849448504485144852448534485444855448564485744858448594486044861448624486344864448654486644867448684486944870448714487244873448744487544876448774487844879448804488144882448834488444885448864488744888448894489044891448924489344894448954489644897448984489944900449014490244903449044490544906449074490844909449104491144912449134491444915449164491744918449194492044921449224492344924449254492644927449284492944930449314493244933449344493544936449374493844939449404494144942449434494444945449464494744948449494495044951449524495344954449554495644957449584495944960449614496244963449644496544966449674496844969449704497144972449734497444975449764497744978449794498044981449824498344984449854498644987449884498944990449914499244993449944499544996449974499844999450004500145002450034500445005450064500745008450094501045011450124501345014450154501645017450184501945020450214502245023450244502545026450274502845029450304503145032450334503445035450364503745038450394504045041450424504345044450454504645047450484504945050450514505245053450544505545056450574505845059450604506145062450634506445065450664506745068450694507045071450724507345074450754507645077450784507945080450814508245083450844508545086450874508845089450904509145092450934509445095450964509745098450994510045101451024510345104451054510645107451084510945110451114511245113451144511545116451174511845119451204512145122451234512445125451264512745128451294513045131451324513345134451354513645137451384513945140451414514245143451444514545146451474514845149451504515145152451534515445155451564515745158451594516045161451624516345164451654516645167451684516945170451714517245173451744517545176451774517845179451804518145182451834518445185451864518745188451894519045191451924519345194451954519645197451984519945200452014520245203452044520545206452074520845209452104521145212452134521445215452164521745218452194522045221452224522345224452254522645227452284522945230452314523245233452344523545236452374523845239452404524145242452434524445245452464524745248452494525045251452524525345254452554525645257452584525945260452614526245263452644526545266452674526845269452704527145272452734527445275452764527745278452794528045281452824528345284452854528645287452884528945290452914529245293452944529545296452974529845299453004530145302453034530445305453064530745308453094531045311453124531345314453154531645317453184531945320453214532245323453244532545326453274532845329453304533145332453334533445335453364533745338453394534045341453424534345344453454534645347453484534945350453514535245353453544535545356453574535845359453604536145362453634536445365453664536745368453694537045371453724537345374453754537645377453784537945380453814538245383453844538545386453874538845389453904539145392453934539445395453964539745398453994540045401454024540345404454054540645407454084540945410454114541245413454144541545416454174541845419454204542145422454234542445425454264542745428454294543045431454324543345434454354543645437454384543945440454414544245443454444544545446454474544845449454504545145452454534545445455454564545745458454594546045461454624546345464454654546645467454684546945470454714547245473454744547545476454774547845479454804548145482454834548445485454864548745488454894549045491454924549345494454954549645497454984549945500455014550245503455044550545506455074550845509455104551145512455134551445515455164551745518455194552045521455224552345524455254552645527455284552945530455314553245533455344553545536455374553845539455404554145542455434554445545455464554745548455494555045551455524555345554455554555645557455584555945560455614556245563455644556545566455674556845569455704557145572455734557445575455764557745578455794558045581455824558345584455854558645587455884558945590455914559245593455944559545596455974559845599456004560145602456034560445605456064560745608456094561045611456124561345614456154561645617456184561945620456214562245623456244562545626456274562845629456304563145632456334563445635456364563745638456394564045641456424564345644456454564645647456484564945650456514565245653456544565545656456574565845659456604566145662456634566445665456664566745668456694567045671456724567345674456754567645677456784567945680456814568245683456844568545686456874568845689456904569145692456934569445695456964569745698456994570045701457024570345704457054570645707457084570945710457114571245713457144571545716457174571845719457204572145722457234572445725457264572745728457294573045731457324573345734457354573645737457384573945740457414574245743457444574545746457474574845749457504575145752457534575445755457564575745758457594576045761457624576345764457654576645767457684576945770457714577245773457744577545776457774577845779457804578145782457834578445785457864578745788457894579045791457924579345794457954579645797457984579945800458014580245803458044580545806458074580845809458104581145812458134581445815458164581745818458194582045821458224582345824458254582645827458284582945830458314583245833458344583545836458374583845839458404584145842458434584445845458464584745848458494585045851458524585345854458554585645857458584585945860458614586245863458644586545866458674586845869458704587145872458734587445875458764587745878458794588045881458824588345884458854588645887458884588945890458914589245893458944589545896458974589845899459004590145902459034590445905459064590745908459094591045911459124591345914459154591645917459184591945920459214592245923459244592545926459274592845929459304593145932459334593445935459364593745938459394594045941459424594345944459454594645947459484594945950459514595245953459544595545956459574595845959459604596145962459634596445965459664596745968459694597045971459724597345974459754597645977459784597945980459814598245983459844598545986459874598845989459904599145992459934599445995459964599745998459994600046001460024600346004460054600646007460084600946010460114601246013460144601546016460174601846019460204602146022460234602446025460264602746028460294603046031460324603346034460354603646037460384603946040460414604246043460444604546046460474604846049460504605146052460534605446055460564605746058460594606046061460624606346064460654606646067460684606946070460714607246073460744607546076460774607846079460804608146082460834608446085460864608746088460894609046091460924609346094460954609646097460984609946100461014610246103461044610546106461074610846109461104611146112461134611446115461164611746118461194612046121461224612346124461254612646127461284612946130461314613246133461344613546136461374613846139461404614146142461434614446145461464614746148461494615046151461524615346154461554615646157461584615946160461614616246163461644616546166461674616846169461704617146172461734617446175461764617746178461794618046181461824618346184461854618646187461884618946190461914619246193461944619546196461974619846199462004620146202462034620446205462064620746208462094621046211462124621346214462154621646217462184621946220462214622246223462244622546226462274622846229462304623146232462334623446235462364623746238462394624046241462424624346244462454624646247462484624946250462514625246253462544625546256462574625846259462604626146262462634626446265462664626746268462694627046271462724627346274462754627646277462784627946280462814628246283462844628546286462874628846289462904629146292462934629446295462964629746298462994630046301463024630346304463054630646307463084630946310463114631246313463144631546316463174631846319463204632146322463234632446325463264632746328463294633046331463324633346334463354633646337463384633946340463414634246343463444634546346463474634846349463504635146352463534635446355463564635746358463594636046361463624636346364463654636646367463684636946370463714637246373463744637546376463774637846379463804638146382463834638446385463864638746388463894639046391463924639346394463954639646397463984639946400464014640246403464044640546406464074640846409464104641146412464134641446415464164641746418464194642046421464224642346424464254642646427464284642946430464314643246433464344643546436464374643846439464404644146442464434644446445464464644746448464494645046451464524645346454464554645646457464584645946460464614646246463464644646546466464674646846469464704647146472464734647446475464764647746478464794648046481464824648346484464854648646487464884648946490464914649246493464944649546496464974649846499465004650146502465034650446505465064650746508465094651046511465124651346514465154651646517465184651946520465214652246523465244652546526465274652846529465304653146532465334653446535465364653746538465394654046541465424654346544465454654646547465484654946550465514655246553465544655546556465574655846559465604656146562465634656446565465664656746568465694657046571465724657346574465754657646577465784657946580465814658246583465844658546586465874658846589465904659146592465934659446595465964659746598465994660046601466024660346604466054660646607466084660946610466114661246613466144661546616466174661846619466204662146622466234662446625466264662746628466294663046631466324663346634466354663646637466384663946640466414664246643466444664546646466474664846649466504665146652466534665446655466564665746658466594666046661466624666346664466654666646667466684666946670466714667246673466744667546676466774667846679466804668146682466834668446685466864668746688466894669046691466924669346694466954669646697466984669946700467014670246703467044670546706467074670846709467104671146712467134671446715467164671746718467194672046721467224672346724467254672646727467284672946730467314673246733467344673546736467374673846739467404674146742467434674446745467464674746748467494675046751467524675346754467554675646757467584675946760467614676246763467644676546766467674676846769467704677146772467734677446775467764677746778467794678046781467824678346784467854678646787467884678946790467914679246793467944679546796467974679846799468004680146802468034680446805468064680746808468094681046811468124681346814468154681646817468184681946820468214682246823468244682546826468274682846829468304683146832468334683446835468364683746838468394684046841468424684346844468454684646847468484684946850468514685246853468544685546856468574685846859468604686146862468634686446865468664686746868468694687046871468724687346874468754687646877468784687946880468814688246883468844688546886468874688846889468904689146892468934689446895468964689746898468994690046901469024690346904469054690646907469084690946910469114691246913469144691546916469174691846919469204692146922469234692446925469264692746928469294693046931469324693346934469354693646937469384693946940469414694246943469444694546946469474694846949469504695146952469534695446955469564695746958469594696046961469624696346964469654696646967469684696946970469714697246973469744697546976469774697846979469804698146982469834698446985469864698746988469894699046991469924699346994469954699646997469984699947000470014700247003470044700547006470074700847009470104701147012470134701447015470164701747018470194702047021470224702347024470254702647027470284702947030470314703247033470344703547036470374703847039470404704147042470434704447045470464704747048470494705047051470524705347054470554705647057470584705947060470614706247063470644706547066470674706847069470704707147072470734707447075470764707747078470794708047081470824708347084470854708647087470884708947090470914709247093470944709547096470974709847099471004710147102471034710447105471064710747108471094711047111471124711347114471154711647117471184711947120471214712247123471244712547126471274712847129471304713147132471334713447135471364713747138471394714047141471424714347144471454714647147471484714947150471514715247153471544715547156471574715847159471604716147162471634716447165471664716747168471694717047171471724717347174471754717647177471784717947180471814718247183471844718547186471874718847189471904719147192471934719447195471964719747198471994720047201472024720347204472054720647207472084720947210472114721247213472144721547216472174721847219472204722147222472234722447225472264722747228472294723047231472324723347234472354723647237472384723947240472414724247243472444724547246472474724847249472504725147252472534725447255472564725747258472594726047261472624726347264472654726647267472684726947270472714727247273472744727547276472774727847279472804728147282472834728447285472864728747288472894729047291472924729347294472954729647297472984729947300473014730247303473044730547306473074730847309473104731147312473134731447315473164731747318473194732047321473224732347324473254732647327473284732947330473314733247333473344733547336473374733847339473404734147342473434734447345473464734747348473494735047351473524735347354473554735647357473584735947360473614736247363473644736547366473674736847369473704737147372473734737447375473764737747378473794738047381473824738347384473854738647387473884738947390473914739247393473944739547396473974739847399474004740147402474034740447405474064740747408474094741047411474124741347414474154741647417474184741947420474214742247423474244742547426474274742847429474304743147432474334743447435474364743747438474394744047441474424744347444474454744647447474484744947450474514745247453474544745547456474574745847459474604746147462474634746447465474664746747468474694747047471474724747347474474754747647477474784747947480474814748247483474844748547486474874748847489474904749147492474934749447495474964749747498474994750047501475024750347504475054750647507475084750947510475114751247513475144751547516475174751847519475204752147522475234752447525475264752747528475294753047531475324753347534475354753647537475384753947540475414754247543475444754547546475474754847549475504755147552475534755447555475564755747558475594756047561475624756347564475654756647567475684756947570475714757247573475744757547576475774757847579475804758147582475834758447585475864758747588475894759047591475924759347594475954759647597475984759947600476014760247603476044760547606476074760847609476104761147612476134761447615476164761747618476194762047621476224762347624476254762647627476284762947630476314763247633476344763547636476374763847639476404764147642476434764447645476464764747648476494765047651476524765347654476554765647657476584765947660476614766247663476644766547666476674766847669476704767147672476734767447675476764767747678476794768047681476824768347684476854768647687476884768947690476914769247693476944769547696476974769847699477004770147702477034770447705477064770747708477094771047711477124771347714477154771647717477184771947720477214772247723477244772547726477274772847729477304773147732477334773447735477364773747738477394774047741477424774347744477454774647747477484774947750477514775247753477544775547756477574775847759477604776147762477634776447765477664776747768477694777047771477724777347774477754777647777477784777947780477814778247783477844778547786477874778847789477904779147792477934779447795477964779747798477994780047801478024780347804478054780647807478084780947810478114781247813478144781547816478174781847819478204782147822478234782447825478264782747828478294783047831478324783347834478354783647837478384783947840478414784247843478444784547846478474784847849478504785147852478534785447855478564785747858478594786047861478624786347864478654786647867478684786947870478714787247873478744787547876478774787847879478804788147882478834788447885478864788747888478894789047891478924789347894478954789647897478984789947900479014790247903479044790547906479074790847909479104791147912479134791447915479164791747918479194792047921479224792347924479254792647927479284792947930479314793247933479344793547936479374793847939479404794147942479434794447945479464794747948479494795047951479524795347954479554795647957479584795947960479614796247963479644796547966479674796847969479704797147972479734797447975479764797747978479794798047981479824798347984479854798647987479884798947990479914799247993479944799547996479974799847999480004800148002480034800448005480064800748008480094801048011480124801348014480154801648017480184801948020480214802248023480244802548026480274802848029480304803148032480334803448035480364803748038480394804048041480424804348044480454804648047480484804948050480514805248053480544805548056480574805848059480604806148062480634806448065480664806748068480694807048071480724807348074480754807648077480784807948080480814808248083480844808548086480874808848089480904809148092480934809448095480964809748098480994810048101481024810348104481054810648107481084810948110481114811248113481144811548116481174811848119481204812148122481234812448125481264812748128481294813048131481324813348134481354813648137481384813948140481414814248143481444814548146481474814848149481504815148152481534815448155481564815748158481594816048161481624816348164481654816648167481684816948170481714817248173481744817548176481774817848179481804818148182481834818448185481864818748188481894819048191481924819348194481954819648197481984819948200482014820248203482044820548206482074820848209482104821148212482134821448215482164821748218482194822048221482224822348224482254822648227482284822948230482314823248233482344823548236482374823848239482404824148242482434824448245482464824748248482494825048251482524825348254482554825648257482584825948260482614826248263482644826548266482674826848269482704827148272482734827448275482764827748278482794828048281482824828348284482854828648287482884828948290482914829248293482944829548296482974829848299483004830148302483034830448305483064830748308483094831048311483124831348314483154831648317483184831948320483214832248323483244832548326483274832848329483304833148332483334833448335483364833748338483394834048341483424834348344483454834648347483484834948350483514835248353483544835548356483574835848359483604836148362483634836448365483664836748368483694837048371483724837348374483754837648377483784837948380483814838248383483844838548386483874838848389483904839148392483934839448395483964839748398483994840048401484024840348404484054840648407484084840948410484114841248413484144841548416484174841848419484204842148422484234842448425484264842748428484294843048431484324843348434484354843648437484384843948440484414844248443484444844548446484474844848449484504845148452484534845448455484564845748458484594846048461484624846348464484654846648467484684846948470484714847248473484744847548476484774847848479484804848148482484834848448485484864848748488484894849048491484924849348494484954849648497484984849948500485014850248503485044850548506485074850848509485104851148512485134851448515485164851748518485194852048521485224852348524485254852648527485284852948530485314853248533485344853548536485374853848539485404854148542485434854448545485464854748548485494855048551485524855348554485554855648557485584855948560485614856248563485644856548566485674856848569485704857148572485734857448575485764857748578485794858048581485824858348584485854858648587485884858948590485914859248593485944859548596485974859848599486004860148602486034860448605486064860748608486094861048611486124861348614486154861648617486184861948620486214862248623486244862548626486274862848629486304863148632486334863448635486364863748638486394864048641486424864348644486454864648647486484864948650486514865248653486544865548656486574865848659486604866148662486634866448665486664866748668486694867048671486724867348674486754867648677486784867948680486814868248683486844868548686486874868848689486904869148692486934869448695486964869748698486994870048701487024870348704487054870648707487084870948710487114871248713487144871548716487174871848719487204872148722487234872448725487264872748728487294873048731487324873348734487354873648737487384873948740487414874248743487444874548746487474874848749487504875148752487534875448755487564875748758487594876048761487624876348764487654876648767487684876948770487714877248773487744877548776487774877848779487804878148782487834878448785487864878748788487894879048791487924879348794487954879648797487984879948800488014880248803488044880548806488074880848809488104881148812488134881448815488164881748818488194882048821488224882348824488254882648827488284882948830488314883248833488344883548836488374883848839488404884148842488434884448845488464884748848488494885048851488524885348854488554885648857488584885948860488614886248863488644886548866488674886848869488704887148872488734887448875488764887748878488794888048881488824888348884488854888648887488884888948890488914889248893488944889548896488974889848899489004890148902489034890448905489064890748908489094891048911489124891348914489154891648917489184891948920489214892248923489244892548926489274892848929489304893148932489334893448935489364893748938489394894048941489424894348944489454894648947489484894948950489514895248953489544895548956489574895848959489604896148962489634896448965489664896748968489694897048971489724897348974489754897648977489784897948980489814898248983489844898548986489874898848989489904899148992489934899448995489964899748998489994900049001490024900349004490054900649007490084900949010490114901249013490144901549016490174901849019490204902149022490234902449025490264902749028490294903049031490324903349034490354903649037490384903949040490414904249043490444904549046490474904849049490504905149052490534905449055490564905749058490594906049061490624906349064490654906649067490684906949070490714907249073490744907549076490774907849079490804908149082490834908449085490864908749088490894909049091490924909349094490954909649097490984909949100491014910249103491044910549106491074910849109491104911149112491134911449115491164911749118491194912049121491224912349124491254912649127491284912949130491314913249133491344913549136491374913849139491404914149142491434914449145491464914749148491494915049151491524915349154491554915649157491584915949160491614916249163491644916549166491674916849169491704917149172491734917449175491764917749178491794918049181491824918349184491854918649187491884918949190491914919249193491944919549196491974919849199492004920149202492034920449205492064920749208492094921049211492124921349214492154921649217492184921949220492214922249223492244922549226492274922849229492304923149232492334923449235492364923749238492394924049241492424924349244492454924649247492484924949250492514925249253492544925549256492574925849259492604926149262492634926449265492664926749268492694927049271492724927349274492754927649277492784927949280492814928249283492844928549286492874928849289492904929149292492934929449295492964929749298492994930049301493024930349304493054930649307493084930949310493114931249313493144931549316493174931849319493204932149322493234932449325493264932749328493294933049331493324933349334493354933649337493384933949340493414934249343493444934549346493474934849349493504935149352493534935449355493564935749358493594936049361493624936349364493654936649367493684936949370493714937249373493744937549376493774937849379493804938149382493834938449385493864938749388493894939049391493924939349394493954939649397493984939949400494014940249403494044940549406494074940849409494104941149412494134941449415494164941749418494194942049421494224942349424494254942649427494284942949430494314943249433494344943549436494374943849439494404944149442494434944449445494464944749448494494945049451494524945349454494554945649457494584945949460494614946249463494644946549466494674946849469494704947149472494734947449475494764947749478494794948049481494824948349484494854948649487494884948949490494914949249493494944949549496494974949849499495004950149502495034950449505495064950749508495094951049511495124951349514495154951649517495184951949520495214952249523495244952549526495274952849529495304953149532495334953449535495364953749538495394954049541495424954349544495454954649547495484954949550495514955249553495544955549556495574955849559495604956149562495634956449565495664956749568495694957049571495724957349574495754957649577495784957949580495814958249583495844958549586495874958849589495904959149592495934959449595495964959749598495994960049601496024960349604496054960649607496084960949610496114961249613496144961549616496174961849619496204962149622496234962449625496264962749628496294963049631496324963349634496354963649637496384963949640496414964249643496444964549646496474964849649496504965149652496534965449655496564965749658496594966049661496624966349664496654966649667496684966949670496714967249673496744967549676496774967849679496804968149682496834968449685496864968749688496894969049691496924969349694496954969649697496984969949700497014970249703497044970549706497074970849709497104971149712497134971449715497164971749718497194972049721497224972349724497254972649727497284972949730497314973249733497344973549736497374973849739497404974149742497434974449745497464974749748497494975049751497524975349754497554975649757497584975949760497614976249763497644976549766497674976849769497704977149772497734977449775497764977749778497794978049781497824978349784497854978649787497884978949790497914979249793497944979549796497974979849799498004980149802498034980449805498064980749808498094981049811498124981349814498154981649817498184981949820498214982249823498244982549826498274982849829498304983149832498334983449835498364983749838498394984049841498424984349844498454984649847498484984949850498514985249853498544985549856498574985849859498604986149862498634986449865498664986749868498694987049871498724987349874498754987649877498784987949880498814988249883498844988549886498874988849889498904989149892498934989449895498964989749898498994990049901499024990349904499054990649907499084990949910499114991249913499144991549916499174991849919499204992149922499234992449925499264992749928499294993049931499324993349934499354993649937499384993949940499414994249943499444994549946499474994849949499504995149952499534995449955499564995749958499594996049961499624996349964499654996649967499684996949970499714997249973499744997549976499774997849979499804998149982499834998449985499864998749988499894999049991499924999349994499954999649997499984999950000500015000250003500045000550006500075000850009500105001150012500135001450015500165001750018500195002050021500225002350024500255002650027500285002950030500315003250033500345003550036500375003850039500405004150042500435004450045500465004750048500495005050051500525005350054500555005650057500585005950060500615006250063500645006550066500675006850069500705007150072500735007450075500765007750078500795008050081500825008350084500855008650087500885008950090500915009250093500945009550096500975009850099501005010150102501035010450105501065010750108501095011050111501125011350114501155011650117501185011950120501215012250123501245012550126501275012850129501305013150132501335013450135501365013750138501395014050141501425014350144501455014650147501485014950150501515015250153501545015550156501575015850159501605016150162501635016450165501665016750168501695017050171501725017350174501755017650177501785017950180501815018250183501845018550186501875018850189501905019150192501935019450195501965019750198501995020050201502025020350204502055020650207502085020950210502115021250213502145021550216502175021850219502205022150222502235022450225502265022750228502295023050231502325023350234502355023650237502385023950240502415024250243502445024550246502475024850249502505025150252502535025450255502565025750258502595026050261502625026350264502655026650267502685026950270502715027250273502745027550276502775027850279502805028150282502835028450285502865028750288502895029050291502925029350294502955029650297502985029950300503015030250303503045030550306503075030850309503105031150312503135031450315503165031750318503195032050321503225032350324503255032650327503285032950330503315033250333503345033550336503375033850339503405034150342503435034450345503465034750348503495035050351503525035350354503555035650357503585035950360503615036250363503645036550366503675036850369503705037150372503735037450375503765037750378503795038050381503825038350384503855038650387503885038950390503915039250393503945039550396503975039850399504005040150402504035040450405504065040750408504095041050411504125041350414504155041650417504185041950420504215042250423504245042550426504275042850429504305043150432504335043450435504365043750438504395044050441504425044350444504455044650447504485044950450504515045250453504545045550456504575045850459504605046150462504635046450465504665046750468504695047050471504725047350474504755047650477504785047950480504815048250483504845048550486504875048850489504905049150492504935049450495504965049750498504995050050501505025050350504505055050650507505085050950510505115051250513505145051550516505175051850519505205052150522505235052450525505265052750528505295053050531505325053350534505355053650537505385053950540505415054250543505445054550546505475054850549505505055150552505535055450555505565055750558505595056050561505625056350564505655056650567505685056950570505715057250573505745057550576505775057850579505805058150582505835058450585505865058750588505895059050591505925059350594505955059650597505985059950600506015060250603506045060550606506075060850609506105061150612506135061450615506165061750618506195062050621506225062350624506255062650627506285062950630506315063250633506345063550636506375063850639506405064150642506435064450645506465064750648506495065050651506525065350654506555065650657506585065950660506615066250663506645066550666506675066850669506705067150672506735067450675506765067750678506795068050681506825068350684506855068650687506885068950690506915069250693506945069550696506975069850699507005070150702507035070450705507065070750708507095071050711507125071350714507155071650717507185071950720507215072250723507245072550726507275072850729507305073150732507335073450735507365073750738507395074050741507425074350744507455074650747507485074950750507515075250753507545075550756507575075850759507605076150762507635076450765507665076750768507695077050771507725077350774507755077650777507785077950780507815078250783507845078550786507875078850789507905079150792507935079450795507965079750798507995080050801508025080350804508055080650807508085080950810508115081250813508145081550816508175081850819508205082150822508235082450825508265082750828508295083050831508325083350834508355083650837508385083950840508415084250843508445084550846508475084850849508505085150852508535085450855508565085750858508595086050861508625086350864508655086650867508685086950870508715087250873508745087550876508775087850879508805088150882508835088450885508865088750888508895089050891508925089350894508955089650897508985089950900509015090250903509045090550906509075090850909509105091150912509135091450915509165091750918509195092050921509225092350924509255092650927509285092950930509315093250933509345093550936509375093850939509405094150942509435094450945509465094750948509495095050951509525095350954509555095650957509585095950960509615096250963509645096550966509675096850969509705097150972509735097450975509765097750978509795098050981509825098350984509855098650987509885098950990509915099250993509945099550996509975099850999510005100151002510035100451005510065100751008510095101051011510125101351014510155101651017510185101951020510215102251023510245102551026510275102851029510305103151032510335103451035510365103751038510395104051041510425104351044510455104651047510485104951050510515105251053510545105551056510575105851059510605106151062510635106451065510665106751068510695107051071510725107351074510755107651077510785107951080510815108251083510845108551086510875108851089510905109151092510935109451095510965109751098510995110051101511025110351104511055110651107511085110951110511115111251113511145111551116511175111851119511205112151122511235112451125511265112751128511295113051131511325113351134511355113651137511385113951140511415114251143511445114551146511475114851149511505115151152511535115451155511565115751158511595116051161511625116351164511655116651167511685116951170511715117251173511745117551176511775117851179511805118151182511835118451185511865118751188511895119051191511925119351194511955119651197511985119951200512015120251203512045120551206512075120851209512105121151212512135121451215512165121751218512195122051221512225122351224512255122651227512285122951230512315123251233512345123551236512375123851239512405124151242512435124451245512465124751248512495125051251512525125351254512555125651257512585125951260512615126251263512645126551266512675126851269512705127151272512735127451275512765127751278512795128051281512825128351284512855128651287512885128951290512915129251293512945129551296512975129851299513005130151302513035130451305513065130751308513095131051311513125131351314513155131651317513185131951320513215132251323513245132551326513275132851329513305133151332513335133451335513365133751338513395134051341513425134351344513455134651347513485134951350513515135251353513545135551356513575135851359513605136151362513635136451365513665136751368513695137051371513725137351374513755137651377513785137951380513815138251383513845138551386513875138851389513905139151392513935139451395513965139751398513995140051401514025140351404514055140651407514085140951410514115141251413514145141551416514175141851419514205142151422514235142451425514265142751428514295143051431514325143351434514355143651437514385143951440514415144251443514445144551446514475144851449514505145151452514535145451455514565145751458514595146051461514625146351464514655146651467514685146951470514715147251473514745147551476514775147851479514805148151482514835148451485514865148751488514895149051491514925149351494514955149651497514985149951500515015150251503515045150551506515075150851509515105151151512515135151451515515165151751518515195152051521515225152351524515255152651527515285152951530515315153251533515345153551536515375153851539515405154151542515435154451545515465154751548515495155051551515525155351554515555155651557515585155951560515615156251563515645156551566515675156851569515705157151572515735157451575515765157751578515795158051581515825158351584515855158651587515885158951590515915159251593515945159551596515975159851599516005160151602516035160451605516065160751608516095161051611516125161351614516155161651617516185161951620516215162251623516245162551626516275162851629516305163151632516335163451635516365163751638516395164051641516425164351644516455164651647516485164951650516515165251653516545165551656516575165851659516605166151662516635166451665516665166751668516695167051671516725167351674516755167651677516785167951680516815168251683516845168551686516875168851689516905169151692516935169451695516965169751698516995170051701517025170351704517055170651707517085170951710517115171251713517145171551716517175171851719517205172151722517235172451725517265172751728517295173051731517325173351734517355173651737517385173951740517415174251743517445174551746517475174851749517505175151752517535175451755517565175751758517595176051761517625176351764517655176651767517685176951770517715177251773517745177551776517775177851779517805178151782517835178451785517865178751788517895179051791517925179351794517955179651797517985179951800518015180251803518045180551806518075180851809518105181151812518135181451815518165181751818518195182051821518225182351824518255182651827518285182951830518315183251833518345183551836518375183851839518405184151842518435184451845518465184751848518495185051851518525185351854518555185651857518585185951860518615186251863518645186551866518675186851869518705187151872518735187451875518765187751878518795188051881518825188351884518855188651887518885188951890518915189251893518945189551896518975189851899519005190151902519035190451905519065190751908519095191051911519125191351914519155191651917519185191951920519215192251923519245192551926519275192851929519305193151932519335193451935519365193751938519395194051941519425194351944519455194651947519485194951950519515195251953519545195551956519575195851959519605196151962519635196451965519665196751968519695197051971519725197351974519755197651977519785197951980519815198251983519845198551986519875198851989519905199151992519935199451995519965199751998519995200052001520025200352004520055200652007520085200952010520115201252013520145201552016520175201852019520205202152022520235202452025520265202752028520295203052031520325203352034520355203652037520385203952040520415204252043520445204552046520475204852049520505205152052520535205452055520565205752058520595206052061520625206352064520655206652067520685206952070520715207252073520745207552076520775207852079520805208152082520835208452085520865208752088520895209052091520925209352094520955209652097520985209952100521015210252103521045210552106521075210852109521105211152112521135211452115521165211752118521195212052121521225212352124521255212652127521285212952130521315213252133521345213552136521375213852139521405214152142521435214452145521465214752148521495215052151521525215352154521555215652157521585215952160521615216252163521645216552166521675216852169521705217152172521735217452175521765217752178521795218052181521825218352184521855218652187521885218952190521915219252193521945219552196521975219852199522005220152202522035220452205522065220752208522095221052211522125221352214522155221652217522185221952220522215222252223522245222552226522275222852229522305223152232522335223452235522365223752238522395224052241522425224352244522455224652247522485224952250522515225252253522545225552256522575225852259522605226152262522635226452265522665226752268522695227052271522725227352274522755227652277522785227952280522815228252283522845228552286522875228852289522905229152292522935229452295522965229752298522995230052301523025230352304523055230652307523085230952310523115231252313523145231552316523175231852319523205232152322523235232452325523265232752328523295233052331523325233352334523355233652337523385233952340523415234252343523445234552346523475234852349523505235152352523535235452355523565235752358523595236052361523625236352364523655236652367523685236952370523715237252373523745237552376523775237852379523805238152382523835238452385523865238752388523895239052391523925239352394523955239652397523985239952400524015240252403524045240552406524075240852409524105241152412524135241452415524165241752418524195242052421524225242352424524255242652427524285242952430524315243252433524345243552436524375243852439524405244152442524435244452445524465244752448524495245052451524525245352454524555245652457524585245952460524615246252463524645246552466524675246852469524705247152472524735247452475524765247752478524795248052481524825248352484524855248652487524885248952490524915249252493524945249552496524975249852499525005250152502525035250452505525065250752508525095251052511525125251352514525155251652517525185251952520525215252252523525245252552526525275252852529525305253152532525335253452535525365253752538525395254052541525425254352544525455254652547525485254952550525515255252553525545255552556525575255852559525605256152562525635256452565525665256752568525695257052571525725257352574525755257652577525785257952580525815258252583525845258552586525875258852589525905259152592525935259452595525965259752598525995260052601526025260352604526055260652607526085260952610526115261252613526145261552616526175261852619526205262152622526235262452625526265262752628526295263052631526325263352634526355263652637526385263952640526415264252643526445264552646526475264852649526505265152652526535265452655526565265752658526595266052661526625266352664526655266652667526685266952670526715267252673526745267552676526775267852679526805268152682526835268452685526865268752688526895269052691526925269352694526955269652697526985269952700527015270252703527045270552706527075270852709527105271152712527135271452715527165271752718527195272052721527225272352724527255272652727527285272952730527315273252733527345273552736527375273852739527405274152742527435274452745527465274752748527495275052751527525275352754527555275652757527585275952760527615276252763527645276552766527675276852769527705277152772527735277452775527765277752778527795278052781527825278352784527855278652787527885278952790527915279252793527945279552796527975279852799528005280152802528035280452805528065280752808528095281052811528125281352814528155281652817528185281952820528215282252823528245282552826528275282852829528305283152832528335283452835528365283752838528395284052841528425284352844528455284652847528485284952850528515285252853528545285552856528575285852859528605286152862528635286452865528665286752868528695287052871528725287352874528755287652877528785287952880528815288252883528845288552886528875288852889528905289152892528935289452895528965289752898528995290052901529025290352904529055290652907529085290952910529115291252913529145291552916529175291852919529205292152922529235292452925529265292752928529295293052931529325293352934529355293652937529385293952940529415294252943529445294552946529475294852949529505295152952529535295452955529565295752958529595296052961529625296352964529655296652967529685296952970529715297252973529745297552976529775297852979529805298152982529835298452985529865298752988529895299052991529925299352994529955299652997529985299953000530015300253003530045300553006530075300853009530105301153012530135301453015530165301753018530195302053021530225302353024530255302653027530285302953030530315303253033530345303553036530375303853039530405304153042530435304453045530465304753048530495305053051530525305353054530555305653057530585305953060530615306253063530645306553066530675306853069530705307153072530735307453075530765307753078530795308053081530825308353084530855308653087530885308953090530915309253093530945309553096530975309853099531005310153102531035310453105531065310753108531095311053111531125311353114531155311653117531185311953120531215312253123531245312553126531275312853129531305313153132531335313453135531365313753138531395314053141531425314353144531455314653147531485314953150531515315253153531545315553156531575315853159531605316153162531635316453165531665316753168531695317053171531725317353174531755317653177531785317953180531815318253183531845318553186531875318853189531905319153192531935319453195531965319753198531995320053201532025320353204532055320653207532085320953210532115321253213532145321553216532175321853219532205322153222532235322453225532265322753228532295323053231532325323353234532355323653237532385323953240532415324253243532445324553246532475324853249532505325153252532535325453255532565325753258532595326053261532625326353264532655326653267532685326953270532715327253273532745327553276532775327853279532805328153282532835328453285532865328753288532895329053291532925329353294532955329653297532985329953300533015330253303533045330553306533075330853309533105331153312533135331453315533165331753318533195332053321533225332353324533255332653327533285332953330533315333253333533345333553336533375333853339533405334153342533435334453345533465334753348533495335053351533525335353354533555335653357533585335953360533615336253363533645336553366533675336853369533705337153372533735337453375533765337753378533795338053381533825338353384533855338653387533885338953390533915339253393533945339553396533975339853399534005340153402534035340453405534065340753408534095341053411534125341353414534155341653417534185341953420534215342253423534245342553426534275342853429534305343153432534335343453435534365343753438534395344053441534425344353444534455344653447534485344953450534515345253453534545345553456534575345853459534605346153462534635346453465534665346753468534695347053471534725347353474534755347653477534785347953480534815348253483534845348553486534875348853489534905349153492534935349453495534965349753498534995350053501535025350353504535055350653507535085350953510535115351253513535145351553516535175351853519535205352153522535235352453525535265352753528535295353053531535325353353534535355353653537535385353953540535415354253543535445354553546535475354853549535505355153552535535355453555535565355753558535595356053561535625356353564535655356653567535685356953570535715357253573535745357553576535775357853579535805358153582535835358453585535865358753588535895359053591535925359353594535955359653597535985359953600536015360253603536045360553606536075360853609536105361153612536135361453615536165361753618536195362053621536225362353624536255362653627536285362953630536315363253633536345363553636536375363853639536405364153642536435364453645536465364753648536495365053651536525365353654536555365653657536585365953660536615366253663536645366553666536675366853669536705367153672536735367453675536765367753678536795368053681536825368353684536855368653687536885368953690536915369253693536945369553696536975369853699537005370153702537035370453705537065370753708537095371053711537125371353714537155371653717537185371953720537215372253723537245372553726537275372853729537305373153732537335373453735537365373753738537395374053741537425374353744537455374653747537485374953750537515375253753537545375553756537575375853759537605376153762537635376453765537665376753768537695377053771537725377353774537755377653777537785377953780537815378253783537845378553786537875378853789537905379153792537935379453795537965379753798537995380053801538025380353804538055380653807538085380953810538115381253813538145381553816538175381853819538205382153822538235382453825538265382753828538295383053831538325383353834538355383653837538385383953840538415384253843538445384553846538475384853849538505385153852538535385453855538565385753858538595386053861538625386353864538655386653867538685386953870538715387253873538745387553876538775387853879538805388153882538835388453885538865388753888538895389053891538925389353894538955389653897538985389953900539015390253903539045390553906539075390853909539105391153912539135391453915539165391753918539195392053921539225392353924539255392653927539285392953930539315393253933539345393553936539375393853939539405394153942539435394453945539465394753948539495395053951539525395353954539555395653957539585395953960539615396253963539645396553966539675396853969539705397153972539735397453975539765397753978539795398053981539825398353984539855398653987539885398953990539915399253993539945399553996539975399853999540005400154002540035400454005540065400754008540095401054011540125401354014540155401654017540185401954020540215402254023540245402554026540275402854029540305403154032540335403454035540365403754038540395404054041540425404354044540455404654047540485404954050540515405254053540545405554056540575405854059540605406154062540635406454065540665406754068540695407054071540725407354074540755407654077540785407954080540815408254083540845408554086540875408854089540905409154092540935409454095540965409754098540995410054101541025410354104541055410654107541085410954110541115411254113541145411554116541175411854119541205412154122541235412454125541265412754128541295413054131541325413354134541355413654137541385413954140541415414254143541445414554146541475414854149541505415154152541535415454155541565415754158541595416054161541625416354164541655416654167541685416954170541715417254173541745417554176541775417854179541805418154182541835418454185541865418754188541895419054191541925419354194541955419654197541985419954200542015420254203542045420554206542075420854209542105421154212542135421454215542165421754218542195422054221542225422354224542255422654227542285422954230542315423254233542345423554236542375423854239542405424154242542435424454245542465424754248542495425054251542525425354254542555425654257542585425954260542615426254263542645426554266542675426854269542705427154272542735427454275542765427754278542795428054281542825428354284542855428654287542885428954290542915429254293542945429554296542975429854299543005430154302543035430454305543065430754308543095431054311543125431354314543155431654317543185431954320543215432254323543245432554326543275432854329543305433154332543335433454335543365433754338543395434054341543425434354344543455434654347543485434954350543515435254353543545435554356543575435854359543605436154362543635436454365543665436754368543695437054371543725437354374543755437654377543785437954380543815438254383543845438554386543875438854389543905439154392543935439454395543965439754398543995440054401544025440354404544055440654407544085440954410544115441254413544145441554416544175441854419544205442154422544235442454425544265442754428544295443054431544325443354434544355443654437544385443954440544415444254443544445444554446544475444854449544505445154452544535445454455544565445754458544595446054461544625446354464544655446654467544685446954470544715447254473544745447554476544775447854479544805448154482544835448454485544865448754488544895449054491544925449354494544955449654497544985449954500545015450254503545045450554506545075450854509545105451154512545135451454515545165451754518545195452054521545225452354524545255452654527545285452954530545315453254533545345453554536545375453854539545405454154542545435454454545545465454754548545495455054551545525455354554545555455654557545585455954560545615456254563545645456554566545675456854569545705457154572545735457454575545765457754578545795458054581545825458354584545855458654587545885458954590545915459254593545945459554596545975459854599546005460154602546035460454605546065460754608546095461054611546125461354614546155461654617546185461954620546215462254623546245462554626546275462854629546305463154632546335463454635546365463754638546395464054641546425464354644546455464654647546485464954650546515465254653546545465554656546575465854659546605466154662546635466454665546665466754668546695467054671546725467354674546755467654677546785467954680546815468254683546845468554686546875468854689546905469154692546935469454695546965469754698546995470054701547025470354704547055470654707547085470954710547115471254713547145471554716547175471854719547205472154722547235472454725547265472754728547295473054731547325473354734547355473654737547385473954740547415474254743547445474554746547475474854749547505475154752547535475454755547565475754758547595476054761547625476354764547655476654767547685476954770547715477254773547745477554776547775477854779547805478154782547835478454785547865478754788547895479054791547925479354794547955479654797547985479954800548015480254803548045480554806548075480854809548105481154812548135481454815548165481754818548195482054821548225482354824548255482654827548285482954830548315483254833548345483554836548375483854839548405484154842548435484454845548465484754848548495485054851548525485354854548555485654857548585485954860548615486254863548645486554866548675486854869548705487154872548735487454875548765487754878548795488054881548825488354884548855488654887548885488954890548915489254893548945489554896548975489854899549005490154902549035490454905549065490754908549095491054911549125491354914549155491654917549185491954920549215492254923549245492554926549275492854929549305493154932549335493454935549365493754938549395494054941549425494354944549455494654947549485494954950549515495254953549545495554956549575495854959549605496154962549635496454965549665496754968549695497054971549725497354974549755497654977549785497954980549815498254983549845498554986549875498854989549905499154992549935499454995549965499754998549995500055001550025500355004550055500655007550085500955010550115501255013550145501555016550175501855019550205502155022550235502455025550265502755028550295503055031550325503355034550355503655037550385503955040550415504255043550445504555046550475504855049550505505155052550535505455055550565505755058550595506055061550625506355064550655506655067550685506955070550715507255073550745507555076550775507855079550805508155082550835508455085550865508755088550895509055091550925509355094550955509655097550985509955100551015510255103551045510555106551075510855109551105511155112551135511455115551165511755118551195512055121551225512355124551255512655127551285512955130551315513255133551345513555136551375513855139551405514155142551435514455145551465514755148551495515055151551525515355154551555515655157551585515955160551615516255163551645516555166551675516855169551705517155172551735517455175551765517755178551795518055181551825518355184551855518655187551885518955190551915519255193551945519555196551975519855199552005520155202552035520455205552065520755208552095521055211552125521355214552155521655217552185521955220552215522255223552245522555226552275522855229552305523155232552335523455235552365523755238552395524055241552425524355244552455524655247552485524955250552515525255253552545525555256552575525855259552605526155262552635526455265552665526755268552695527055271552725527355274552755527655277552785527955280552815528255283552845528555286552875528855289552905529155292552935529455295552965529755298552995530055301553025530355304553055530655307553085530955310553115531255313553145531555316553175531855319553205532155322553235532455325553265532755328553295533055331553325533355334553355533655337553385533955340553415534255343553445534555346553475534855349553505535155352553535535455355553565535755358553595536055361553625536355364553655536655367553685536955370553715537255373553745537555376553775537855379553805538155382553835538455385553865538755388553895539055391553925539355394553955539655397553985539955400554015540255403554045540555406554075540855409554105541155412554135541455415554165541755418554195542055421554225542355424554255542655427554285542955430554315543255433554345543555436554375543855439554405544155442554435544455445554465544755448554495545055451554525545355454554555545655457554585545955460554615546255463554645546555466554675546855469554705547155472554735547455475554765547755478554795548055481554825548355484554855548655487554885548955490554915549255493554945549555496554975549855499555005550155502555035550455505555065550755508555095551055511555125551355514555155551655517555185551955520555215552255523555245552555526555275552855529555305553155532555335553455535555365553755538555395554055541555425554355544555455554655547555485554955550555515555255553555545555555556555575555855559555605556155562555635556455565555665556755568555695557055571555725557355574555755557655577555785557955580555815558255583555845558555586555875558855589555905559155592555935559455595555965559755598555995560055601556025560355604556055560655607556085560955610556115561255613556145561555616556175561855619556205562155622556235562455625556265562755628556295563055631556325563355634556355563655637556385563955640556415564255643556445564555646556475564855649556505565155652556535565455655556565565755658556595566055661556625566355664556655566655667556685566955670556715567255673556745567555676556775567855679556805568155682556835568455685556865568755688556895569055691556925569355694556955569655697556985569955700557015570255703557045570555706557075570855709557105571155712557135571455715557165571755718557195572055721557225572355724557255572655727557285572955730557315573255733557345573555736557375573855739557405574155742557435574455745557465574755748557495575055751557525575355754557555575655757557585575955760557615576255763557645576555766557675576855769557705577155772557735577455775557765577755778557795578055781557825578355784557855578655787557885578955790557915579255793557945579555796557975579855799558005580155802558035580455805558065580755808558095581055811558125581355814558155581655817558185581955820558215582255823558245582555826558275582855829558305583155832558335583455835558365583755838558395584055841558425584355844558455584655847558485584955850558515585255853558545585555856558575585855859558605586155862558635586455865558665586755868558695587055871558725587355874558755587655877558785587955880558815588255883558845588555886558875588855889558905589155892558935589455895558965589755898558995590055901559025590355904559055590655907559085590955910559115591255913559145591555916559175591855919559205592155922559235592455925559265592755928559295593055931559325593355934559355593655937559385593955940559415594255943559445594555946559475594855949559505595155952559535595455955559565595755958559595596055961559625596355964559655596655967559685596955970559715597255973559745597555976559775597855979559805598155982559835598455985559865598755988559895599055991559925599355994559955599655997559985599956000560015600256003560045600556006560075600856009560105601156012560135601456015560165601756018560195602056021560225602356024560255602656027560285602956030560315603256033560345603556036560375603856039560405604156042560435604456045560465604756048560495605056051560525605356054560555605656057560585605956060560615606256063560645606556066560675606856069560705607156072560735607456075560765607756078560795608056081560825608356084560855608656087560885608956090560915609256093560945609556096560975609856099561005610156102561035610456105561065610756108561095611056111561125611356114561155611656117561185611956120561215612256123561245612556126561275612856129561305613156132561335613456135561365613756138561395614056141561425614356144561455614656147561485614956150561515615256153561545615556156561575615856159561605616156162561635616456165561665616756168561695617056171561725617356174561755617656177561785617956180561815618256183561845618556186561875618856189561905619156192561935619456195561965619756198561995620056201562025620356204562055620656207562085620956210562115621256213562145621556216562175621856219562205622156222562235622456225562265622756228562295623056231562325623356234562355623656237562385623956240562415624256243562445624556246562475624856249562505625156252562535625456255562565625756258562595626056261562625626356264562655626656267562685626956270562715627256273562745627556276562775627856279562805628156282562835628456285562865628756288562895629056291562925629356294562955629656297562985629956300563015630256303563045630556306563075630856309563105631156312563135631456315563165631756318563195632056321563225632356324563255632656327563285632956330563315633256333563345633556336563375633856339563405634156342563435634456345563465634756348563495635056351563525635356354563555635656357563585635956360563615636256363563645636556366563675636856369563705637156372563735637456375563765637756378563795638056381563825638356384563855638656387563885638956390563915639256393563945639556396563975639856399564005640156402564035640456405564065640756408564095641056411564125641356414564155641656417564185641956420564215642256423564245642556426564275642856429564305643156432564335643456435564365643756438564395644056441564425644356444564455644656447564485644956450564515645256453564545645556456564575645856459564605646156462564635646456465564665646756468564695647056471564725647356474564755647656477564785647956480564815648256483564845648556486564875648856489564905649156492564935649456495564965649756498564995650056501565025650356504565055650656507565085650956510565115651256513565145651556516565175651856519565205652156522565235652456525565265652756528565295653056531565325653356534565355653656537565385653956540565415654256543565445654556546565475654856549565505655156552565535655456555565565655756558565595656056561565625656356564565655656656567565685656956570565715657256573565745657556576565775657856579565805658156582565835658456585565865658756588565895659056591565925659356594565955659656597565985659956600566015660256603566045660556606566075660856609566105661156612566135661456615566165661756618566195662056621566225662356624566255662656627566285662956630566315663256633566345663556636566375663856639566405664156642566435664456645566465664756648566495665056651566525665356654566555665656657566585665956660566615666256663566645666556666566675666856669566705667156672566735667456675566765667756678566795668056681566825668356684566855668656687566885668956690566915669256693566945669556696566975669856699567005670156702567035670456705567065670756708567095671056711567125671356714567155671656717567185671956720567215672256723567245672556726567275672856729567305673156732567335673456735567365673756738567395674056741567425674356744567455674656747567485674956750567515675256753567545675556756567575675856759567605676156762567635676456765567665676756768567695677056771567725677356774567755677656777567785677956780567815678256783567845678556786567875678856789567905679156792567935679456795567965679756798567995680056801568025680356804568055680656807568085680956810568115681256813568145681556816568175681856819568205682156822568235682456825568265682756828568295683056831568325683356834568355683656837568385683956840568415684256843568445684556846568475684856849568505685156852568535685456855568565685756858568595686056861568625686356864568655686656867568685686956870568715687256873568745687556876568775687856879568805688156882568835688456885568865688756888568895689056891568925689356894568955689656897568985689956900569015690256903569045690556906569075690856909569105691156912569135691456915569165691756918569195692056921569225692356924569255692656927569285692956930569315693256933569345693556936569375693856939569405694156942569435694456945569465694756948569495695056951569525695356954569555695656957569585695956960569615696256963569645696556966569675696856969569705697156972569735697456975569765697756978569795698056981569825698356984569855698656987569885698956990569915699256993569945699556996569975699856999570005700157002570035700457005570065700757008570095701057011570125701357014570155701657017570185701957020570215702257023570245702557026570275702857029570305703157032570335703457035570365703757038570395704057041570425704357044570455704657047570485704957050570515705257053570545705557056570575705857059570605706157062570635706457065570665706757068570695707057071570725707357074570755707657077570785707957080570815708257083570845708557086570875708857089570905709157092570935709457095570965709757098570995710057101571025710357104571055710657107571085710957110571115711257113571145711557116571175711857119571205712157122571235712457125571265712757128571295713057131571325713357134571355713657137571385713957140571415714257143571445714557146571475714857149571505715157152571535715457155571565715757158571595716057161571625716357164571655716657167571685716957170571715717257173571745717557176571775717857179571805718157182571835718457185571865718757188571895719057191571925719357194571955719657197571985719957200572015720257203572045720557206572075720857209572105721157212572135721457215572165721757218572195722057221572225722357224572255722657227572285722957230572315723257233572345723557236572375723857239572405724157242572435724457245572465724757248572495725057251572525725357254572555725657257572585725957260572615726257263572645726557266572675726857269572705727157272572735727457275572765727757278572795728057281572825728357284572855728657287572885728957290572915729257293572945729557296572975729857299573005730157302573035730457305573065730757308573095731057311573125731357314573155731657317573185731957320573215732257323573245732557326573275732857329573305733157332573335733457335573365733757338573395734057341573425734357344573455734657347573485734957350573515735257353573545735557356573575735857359573605736157362573635736457365573665736757368573695737057371573725737357374573755737657377573785737957380573815738257383573845738557386573875738857389573905739157392573935739457395573965739757398573995740057401574025740357404574055740657407574085740957410574115741257413574145741557416574175741857419574205742157422574235742457425574265742757428574295743057431574325743357434574355743657437574385743957440574415744257443574445744557446574475744857449574505745157452574535745457455574565745757458574595746057461574625746357464574655746657467574685746957470574715747257473574745747557476574775747857479574805748157482574835748457485574865748757488574895749057491574925749357494574955749657497574985749957500575015750257503575045750557506575075750857509575105751157512575135751457515575165751757518575195752057521575225752357524575255752657527575285752957530575315753257533575345753557536575375753857539575405754157542575435754457545575465754757548575495755057551575525755357554575555755657557575585755957560575615756257563575645756557566575675756857569575705757157572575735757457575575765757757578575795758057581575825758357584575855758657587575885758957590575915759257593575945759557596575975759857599576005760157602576035760457605576065760757608576095761057611576125761357614576155761657617576185761957620576215762257623576245762557626576275762857629576305763157632576335763457635576365763757638576395764057641576425764357644576455764657647576485764957650576515765257653576545765557656576575765857659576605766157662576635766457665576665766757668576695767057671576725767357674576755767657677576785767957680576815768257683576845768557686576875768857689576905769157692576935769457695576965769757698576995770057701577025770357704577055770657707577085770957710577115771257713577145771557716577175771857719577205772157722577235772457725577265772757728577295773057731577325773357734577355773657737577385773957740577415774257743577445774557746577475774857749577505775157752577535775457755577565775757758577595776057761577625776357764577655776657767577685776957770577715777257773577745777557776577775777857779577805778157782577835778457785577865778757788577895779057791577925779357794577955779657797577985779957800578015780257803578045780557806578075780857809578105781157812578135781457815578165781757818578195782057821578225782357824578255782657827578285782957830578315783257833578345783557836578375783857839578405784157842578435784457845578465784757848578495785057851578525785357854578555785657857578585785957860578615786257863578645786557866578675786857869578705787157872578735787457875578765787757878578795788057881578825788357884578855788657887578885788957890578915789257893578945789557896578975789857899579005790157902579035790457905579065790757908579095791057911579125791357914579155791657917579185791957920579215792257923579245792557926579275792857929579305793157932579335793457935579365793757938579395794057941579425794357944579455794657947579485794957950579515795257953579545795557956579575795857959579605796157962579635796457965579665796757968579695797057971579725797357974579755797657977579785797957980579815798257983579845798557986579875798857989579905799157992579935799457995579965799757998579995800058001580025800358004580055800658007580085800958010580115801258013580145801558016580175801858019580205802158022580235802458025580265802758028580295803058031580325803358034580355803658037580385803958040580415804258043580445804558046580475804858049580505805158052580535805458055580565805758058580595806058061580625806358064580655806658067580685806958070580715807258073580745807558076580775807858079580805808158082580835808458085580865808758088580895809058091580925809358094580955809658097580985809958100581015810258103581045810558106581075810858109581105811158112581135811458115581165811758118581195812058121581225812358124581255812658127581285812958130581315813258133581345813558136581375813858139581405814158142581435814458145581465814758148581495815058151581525815358154581555815658157581585815958160581615816258163581645816558166581675816858169581705817158172581735817458175581765817758178581795818058181581825818358184581855818658187581885818958190581915819258193581945819558196581975819858199582005820158202582035820458205582065820758208582095821058211582125821358214582155821658217582185821958220582215822258223582245822558226582275822858229582305823158232582335823458235582365823758238582395824058241582425824358244582455824658247582485824958250582515825258253582545825558256582575825858259582605826158262582635826458265582665826758268582695827058271582725827358274582755827658277582785827958280582815828258283582845828558286582875828858289582905829158292582935829458295582965829758298582995830058301583025830358304583055830658307583085830958310583115831258313583145831558316583175831858319583205832158322583235832458325583265832758328583295833058331583325833358334583355833658337583385833958340583415834258343583445834558346583475834858349583505835158352583535835458355583565835758358583595836058361583625836358364583655836658367583685836958370583715837258373583745837558376583775837858379583805838158382583835838458385583865838758388583895839058391583925839358394583955839658397583985839958400584015840258403584045840558406584075840858409584105841158412584135841458415584165841758418584195842058421584225842358424584255842658427584285842958430584315843258433584345843558436584375843858439584405844158442584435844458445584465844758448584495845058451584525845358454584555845658457584585845958460584615846258463584645846558466584675846858469584705847158472584735847458475584765847758478584795848058481584825848358484584855848658487584885848958490584915849258493584945849558496584975849858499585005850158502585035850458505585065850758508585095851058511585125851358514585155851658517585185851958520585215852258523585245852558526585275852858529585305853158532585335853458535585365853758538585395854058541585425854358544585455854658547585485854958550585515855258553585545855558556585575855858559585605856158562585635856458565585665856758568585695857058571585725857358574585755857658577585785857958580585815858258583585845858558586585875858858589585905859158592585935859458595585965859758598585995860058601586025860358604586055860658607586085860958610586115861258613586145861558616586175861858619586205862158622586235862458625586265862758628586295863058631586325863358634586355863658637586385863958640586415864258643586445864558646586475864858649586505865158652586535865458655586565865758658586595866058661586625866358664586655866658667586685866958670586715867258673586745867558676586775867858679586805868158682586835868458685586865868758688586895869058691586925869358694586955869658697586985869958700587015870258703587045870558706587075870858709587105871158712587135871458715587165871758718587195872058721587225872358724587255872658727587285872958730587315873258733587345873558736587375873858739587405874158742587435874458745587465874758748587495875058751587525875358754587555875658757587585875958760587615876258763587645876558766587675876858769587705877158772587735877458775587765877758778587795878058781587825878358784587855878658787587885878958790587915879258793587945879558796587975879858799588005880158802588035880458805588065880758808588095881058811588125881358814588155881658817588185881958820588215882258823588245882558826588275882858829588305883158832588335883458835588365883758838588395884058841588425884358844588455884658847588485884958850588515885258853588545885558856588575885858859588605886158862588635886458865588665886758868588695887058871588725887358874588755887658877588785887958880588815888258883588845888558886588875888858889588905889158892588935889458895588965889758898588995890058901589025890358904589055890658907589085890958910589115891258913589145891558916589175891858919589205892158922589235892458925589265892758928589295893058931589325893358934589355893658937589385893958940589415894258943589445894558946589475894858949589505895158952589535895458955589565895758958589595896058961589625896358964589655896658967589685896958970589715897258973589745897558976589775897858979589805898158982589835898458985589865898758988589895899058991589925899358994589955899658997589985899959000590015900259003590045900559006590075900859009590105901159012590135901459015590165901759018590195902059021590225902359024590255902659027590285902959030590315903259033590345903559036590375903859039590405904159042590435904459045590465904759048590495905059051590525905359054590555905659057590585905959060590615906259063590645906559066590675906859069590705907159072590735907459075590765907759078590795908059081590825908359084590855908659087590885908959090590915909259093590945909559096590975909859099591005910159102591035910459105591065910759108591095911059111591125911359114591155911659117591185911959120591215912259123591245912559126591275912859129591305913159132591335913459135591365913759138591395914059141591425914359144591455914659147591485914959150591515915259153591545915559156591575915859159591605916159162591635916459165591665916759168591695917059171591725917359174591755917659177591785917959180591815918259183591845918559186591875918859189591905919159192591935919459195591965919759198591995920059201592025920359204592055920659207592085920959210592115921259213592145921559216592175921859219592205922159222592235922459225592265922759228592295923059231592325923359234592355923659237592385923959240592415924259243592445924559246592475924859249592505925159252592535925459255592565925759258592595926059261592625926359264592655926659267592685926959270592715927259273592745927559276592775927859279592805928159282592835928459285592865928759288592895929059291592925929359294592955929659297592985929959300593015930259303593045930559306593075930859309593105931159312593135931459315593165931759318593195932059321593225932359324593255932659327593285932959330593315933259333593345933559336593375933859339593405934159342593435934459345593465934759348593495935059351593525935359354593555935659357593585935959360593615936259363593645936559366593675936859369593705937159372593735937459375593765937759378593795938059381593825938359384593855938659387593885938959390593915939259393593945939559396593975939859399594005940159402594035940459405594065940759408594095941059411594125941359414594155941659417594185941959420594215942259423594245942559426594275942859429594305943159432594335943459435594365943759438594395944059441594425944359444594455944659447594485944959450594515945259453594545945559456594575945859459594605946159462594635946459465594665946759468594695947059471594725947359474594755947659477594785947959480594815948259483594845948559486594875948859489594905949159492594935949459495594965949759498594995950059501595025950359504595055950659507595085950959510595115951259513595145951559516595175951859519595205952159522595235952459525595265952759528595295953059531595325953359534595355953659537595385953959540595415954259543595445954559546595475954859549595505955159552595535955459555595565955759558595595956059561595625956359564595655956659567595685956959570595715957259573595745957559576595775957859579595805958159582595835958459585595865958759588595895959059591595925959359594595955959659597595985959959600596015960259603596045960559606596075960859609596105961159612596135961459615596165961759618596195962059621596225962359624596255962659627596285962959630596315963259633596345963559636596375963859639596405964159642596435964459645596465964759648596495965059651596525965359654596555965659657596585965959660596615966259663596645966559666596675966859669596705967159672596735967459675596765967759678596795968059681596825968359684596855968659687596885968959690596915969259693596945969559696596975969859699597005970159702597035970459705597065970759708597095971059711597125971359714597155971659717597185971959720597215972259723597245972559726597275972859729597305973159732597335973459735597365973759738597395974059741597425974359744597455974659747597485974959750597515975259753597545975559756597575975859759597605976159762597635976459765597665976759768597695977059771597725977359774597755977659777597785977959780597815978259783597845978559786597875978859789597905979159792597935979459795597965979759798597995980059801598025980359804598055980659807598085980959810598115981259813598145981559816598175981859819598205982159822598235982459825598265982759828598295983059831598325983359834598355983659837598385983959840598415984259843598445984559846598475984859849598505985159852598535985459855598565985759858598595986059861598625986359864598655986659867598685986959870598715987259873598745987559876598775987859879598805988159882598835988459885598865988759888598895989059891598925989359894598955989659897598985989959900599015990259903599045990559906599075990859909599105991159912599135991459915599165991759918599195992059921599225992359924599255992659927599285992959930599315993259933599345993559936599375993859939599405994159942599435994459945599465994759948599495995059951599525995359954599555995659957599585995959960599615996259963599645996559966599675996859969599705997159972599735997459975599765997759978599795998059981599825998359984599855998659987599885998959990599915999259993599945999559996599975999859999600006000160002600036000460005600066000760008600096001060011600126001360014600156001660017600186001960020600216002260023600246002560026600276002860029600306003160032600336003460035600366003760038600396004060041600426004360044600456004660047600486004960050600516005260053600546005560056600576005860059600606006160062600636006460065600666006760068600696007060071600726007360074600756007660077600786007960080600816008260083600846008560086600876008860089600906009160092600936009460095600966009760098600996010060101601026010360104601056010660107601086010960110601116011260113601146011560116601176011860119601206012160122601236012460125601266012760128601296013060131601326013360134601356013660137601386013960140601416014260143601446014560146601476014860149601506015160152601536015460155601566015760158601596016060161601626016360164601656016660167601686016960170601716017260173601746017560176601776017860179601806018160182601836018460185601866018760188601896019060191601926019360194601956019660197601986019960200602016020260203602046020560206602076020860209602106021160212602136021460215602166021760218602196022060221602226022360224602256022660227602286022960230602316023260233602346023560236602376023860239602406024160242602436024460245602466024760248602496025060251602526025360254602556025660257602586025960260602616026260263602646026560266602676026860269602706027160272602736027460275602766027760278602796028060281602826028360284602856028660287602886028960290602916029260293602946029560296602976029860299603006030160302603036030460305603066030760308603096031060311603126031360314603156031660317603186031960320603216032260323603246032560326603276032860329603306033160332603336033460335603366033760338603396034060341603426034360344603456034660347603486034960350603516035260353603546035560356603576035860359603606036160362603636036460365603666036760368603696037060371603726037360374603756037660377603786037960380603816038260383603846038560386603876038860389603906039160392603936039460395603966039760398603996040060401604026040360404604056040660407604086040960410604116041260413604146041560416604176041860419604206042160422604236042460425604266042760428604296043060431604326043360434604356043660437604386043960440604416044260443604446044560446604476044860449604506045160452604536045460455604566045760458604596046060461604626046360464604656046660467604686046960470604716047260473604746047560476604776047860479604806048160482604836048460485604866048760488604896049060491604926049360494604956049660497604986049960500605016050260503605046050560506605076050860509605106051160512605136051460515605166051760518605196052060521605226052360524605256052660527605286052960530605316053260533605346053560536605376053860539605406054160542605436054460545605466054760548605496055060551605526055360554605556055660557605586055960560605616056260563605646056560566605676056860569605706057160572605736057460575605766057760578605796058060581605826058360584605856058660587605886058960590605916059260593605946059560596605976059860599606006060160602606036060460605606066060760608606096061060611606126061360614606156061660617606186061960620606216062260623606246062560626606276062860629606306063160632606336063460635606366063760638606396064060641606426064360644606456064660647606486064960650606516065260653606546065560656606576065860659606606066160662606636066460665606666066760668606696067060671606726067360674606756067660677606786067960680606816068260683606846068560686606876068860689606906069160692606936069460695606966069760698606996070060701607026070360704607056070660707607086070960710607116071260713607146071560716607176071860719607206072160722607236072460725607266072760728607296073060731607326073360734607356073660737607386073960740607416074260743607446074560746607476074860749607506075160752607536075460755607566075760758607596076060761607626076360764607656076660767607686076960770607716077260773607746077560776607776077860779607806078160782607836078460785607866078760788607896079060791607926079360794607956079660797607986079960800608016080260803608046080560806608076080860809608106081160812608136081460815608166081760818608196082060821608226082360824608256082660827608286082960830608316083260833608346083560836608376083860839608406084160842608436084460845608466084760848608496085060851608526085360854608556085660857608586085960860608616086260863608646086560866608676086860869608706087160872608736087460875608766087760878608796088060881608826088360884608856088660887608886088960890608916089260893608946089560896608976089860899609006090160902609036090460905609066090760908609096091060911609126091360914609156091660917609186091960920609216092260923609246092560926609276092860929609306093160932609336093460935609366093760938609396094060941609426094360944609456094660947609486094960950609516095260953609546095560956609576095860959609606096160962609636096460965609666096760968609696097060971609726097360974609756097660977609786097960980609816098260983609846098560986609876098860989609906099160992609936099460995609966099760998609996100061001610026100361004610056100661007610086100961010610116101261013610146101561016610176101861019610206102161022610236102461025610266102761028610296103061031610326103361034610356103661037610386103961040610416104261043610446104561046610476104861049610506105161052610536105461055610566105761058610596106061061610626106361064610656106661067610686106961070610716107261073610746107561076610776107861079610806108161082610836108461085610866108761088610896109061091610926109361094610956109661097610986109961100611016110261103611046110561106611076110861109611106111161112611136111461115611166111761118611196112061121611226112361124611256112661127611286112961130611316113261133611346113561136611376113861139611406114161142611436114461145611466114761148611496115061151611526115361154611556115661157611586115961160611616116261163611646116561166611676116861169611706117161172611736117461175611766117761178611796118061181611826118361184611856118661187611886118961190611916119261193611946119561196611976119861199612006120161202612036120461205612066120761208612096121061211612126121361214612156121661217612186121961220612216122261223612246122561226612276122861229612306123161232612336123461235612366123761238612396124061241612426124361244612456124661247612486124961250612516125261253612546125561256612576125861259612606126161262612636126461265612666126761268612696127061271612726127361274612756127661277612786127961280612816128261283612846128561286612876128861289612906129161292612936129461295612966129761298612996130061301613026130361304613056130661307613086130961310613116131261313613146131561316613176131861319613206132161322613236132461325613266132761328613296133061331613326133361334613356133661337613386133961340613416134261343613446134561346613476134861349613506135161352613536135461355613566135761358613596136061361613626136361364613656136661367613686136961370613716137261373613746137561376613776137861379613806138161382613836138461385613866138761388613896139061391613926139361394613956139661397613986139961400614016140261403614046140561406614076140861409614106141161412614136141461415614166141761418614196142061421614226142361424614256142661427614286142961430614316143261433614346143561436614376143861439614406144161442614436144461445614466144761448614496145061451614526145361454614556145661457614586145961460614616146261463614646146561466614676146861469614706147161472614736147461475614766147761478614796148061481614826148361484614856148661487614886148961490614916149261493614946149561496614976149861499615006150161502615036150461505615066150761508615096151061511615126151361514615156151661517615186151961520615216152261523615246152561526615276152861529615306153161532615336153461535615366153761538615396154061541615426154361544615456154661547615486154961550615516155261553615546155561556615576155861559615606156161562615636156461565615666156761568615696157061571615726157361574615756157661577615786157961580615816158261583615846158561586615876158861589615906159161592615936159461595615966159761598615996160061601616026160361604616056160661607616086160961610616116161261613616146161561616616176161861619616206162161622616236162461625616266162761628616296163061631616326163361634616356163661637616386163961640616416164261643616446164561646616476164861649616506165161652616536165461655616566165761658616596166061661616626166361664616656166661667616686166961670616716167261673616746167561676616776167861679616806168161682616836168461685616866168761688616896169061691616926169361694616956169661697616986169961700617016170261703617046170561706617076170861709617106171161712617136171461715617166171761718617196172061721617226172361724617256172661727617286172961730617316173261733617346173561736617376173861739617406174161742617436174461745617466174761748617496175061751617526175361754617556175661757617586175961760617616176261763617646176561766617676176861769617706177161772617736177461775617766177761778617796178061781617826178361784617856178661787617886178961790617916179261793617946179561796617976179861799618006180161802618036180461805618066180761808618096181061811618126181361814618156181661817618186181961820618216182261823618246182561826618276182861829618306183161832618336183461835618366183761838618396184061841618426184361844618456184661847618486184961850618516185261853618546185561856618576185861859618606186161862618636186461865618666186761868618696187061871618726187361874618756187661877618786187961880618816188261883618846188561886618876188861889618906189161892618936189461895618966189761898618996190061901619026190361904619056190661907619086190961910619116191261913619146191561916619176191861919619206192161922619236192461925619266192761928619296193061931619326193361934619356193661937619386193961940619416194261943619446194561946619476194861949619506195161952619536195461955619566195761958619596196061961619626196361964619656196661967619686196961970619716197261973619746197561976619776197861979619806198161982619836198461985619866198761988619896199061991619926199361994619956199661997619986199962000620016200262003620046200562006620076200862009620106201162012 |
- #!/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', 1451055666);
- require 'phar://composer.phar/bin/composer';
- __HALT_COMPILER(); ?>
- d|��}������
���composer.phar����+���src/Composer/Autoload/AutoloadGenerator.php�L��2@.V�L��>V]¶������+���src/Composer/Autoload/ClassMapGenerator.php��2@.V��ᘨ*¶���������src/Composer/Cache.phpÇ��2@.VÇ��¹hà¶������%���src/Composer/Command/AboutCommand.php¼��2@.V¼��ZF�‡¶������'���src/Composer/Command/ArchiveCommand.phpß��2@.Vß��Ïã߶������*���src/Composer/Command/ClearCacheCommand.phpZ��2@.VZ��‰ì>¶������ ���src/Composer/Command/Command.php‰��2@.V‰��µvJ¶������&���src/Composer/Command/ConfigCommand.phpÊ6��2@.VÊ6��"~¶������-���src/Composer/Command/CreateProjectCommand.php 3��2@.V 3��Ì?ù¶������'���src/Composer/Command/DependsCommand.php„
- ��2@.V„
- ��)¸Ó¶������(���src/Composer/Command/DiagnoseCommand.php/9��2@.V/9��[zÿ_¶������,���src/Composer/Command/DumpAutoloadCommand.php��2@.V��™Rù¶������&���src/Composer/Command/GlobalCommand.php��2@.V��©¨@•¶������$���src/Composer/Command/HomeCommand.php`
��2@.V`
��sgœ2¶������$���src/Composer/Command/InitCommand.php½7��2@.V½7��g$hG¶������'���src/Composer/Command/InstallCommand.php��2@.V��`Cí¶������(���src/Composer/Command/LicensesCommand.php��2@.V��Âv襶������&���src/Composer/Command/RemoveCommand.phpn��2@.Vn��€Ës¶������'���src/Composer/Command/RequireCommand.php½��2@.V½��Ĉ”Ķ������)���src/Composer/Command/RunScriptCommand.php���2@.V���âè2Ú¶������+���src/Composer/Command/ScriptAliasCommand.php²��2@.V²��ñÇ$½¶������&���src/Composer/Command/SearchCommand.phpa ��2@.Va ��ÐU}P¶������*���src/Composer/Command/SelfUpdateCommand.phpË��2@.VË��¾< à¶������$���src/Composer/Command/ShowCommand.php§0��2@.V§0��o
- î¶������&���src/Composer/Command/StatusCommand.phpœ ��2@.Vœ ��#ƒ‡c¶������(���src/Composer/Command/SuggestsCommand.phpÿ��2@.Vÿ��¾?gж������&���src/Composer/Command/UpdateCommand.php��2@.V��Ït»a¶������(���src/Composer/Command/ValidateCommand.php½��2@.V½��pòL.¶���������src/Composer/Composer.php) ��2@.V) ��Û
B¶���������src/Composer/Config.php2��2@.V2��§76q¶������-���src/Composer/Config/ConfigSourceInterface.php®��2@.V®��6J[ª¶������(���src/Composer/Config/JsonConfigSource.php“��2@.V“��*íÞT¶������$���src/Composer/Console/Application.php0!��2@.V0!��-LÒf¶������,���src/Composer/Console/HtmlOutputFormatter.php3��2@.V3��Ú�Eu¶������-���src/Composer/DependencyResolver/Decisions.phpQ��2@.VQ��?˜¬$¶������1���src/Composer/DependencyResolver/DefaultPolicy.phpÖ��2@.VÖ��9ÁÖõ¶������>���src/Composer/DependencyResolver/Operation/InstallOperation.phpC��2@.VC��´\õ*¶������I���src/Composer/DependencyResolver/Operation/MarkAliasInstalledOperation.php÷��2@.V÷��ïÎà÷¶������K���src/Composer/DependencyResolver/Operation/MarkAliasUninstalledOperation.phpý��2@.Vý��3#†¶������@���src/Composer/DependencyResolver/Operation/OperationInterface.phpÓ���2@.VÓ���Ùâ&ä¶������=���src/Composer/DependencyResolver/Operation/SolverOperation.php¹��2@.V¹��&¢e
- ¶������@���src/Composer/DependencyResolver/Operation/UninstallOperation.phpI��2@.VI��FûÂɶ������=���src/Composer/DependencyResolver/Operation/UpdateOperation.phph��2@.Vh��öSÕ]¶������3���src/Composer/DependencyResolver/PolicyInterface.php”��2@.V”��°�¶������(���src/Composer/DependencyResolver/Pool.phpª!��2@.Vª!��Elü8¶������+���src/Composer/DependencyResolver/Problem.phpÀ��2@.VÀ��ØVìñ¶������+���src/Composer/DependencyResolver/Request.php€��2@.V€��Ðwƒ¶������(���src/Composer/DependencyResolver/Rule.phpç��2@.Vç��gì¬T¶������+���src/Composer/DependencyResolver/RuleSet.php
- ��2@.V
- ��:Z�E¶������4���src/Composer/DependencyResolver/RuleSetGenerator.php]��2@.V]��4“Ñ9¶������3���src/Composer/DependencyResolver/RuleSetIterator.php��2@.V��}õÇù¶������2���src/Composer/DependencyResolver/RuleWatchChain.phpi��2@.Vi��hïš,¶������2���src/Composer/DependencyResolver/RuleWatchGraph.phpÜ��2@.VÜ��‰8¶������1���src/Composer/DependencyResolver/RuleWatchNode.phpç��2@.Vç��—Þȶ������*���src/Composer/DependencyResolver/Solver.php7��2@.V7��@ÿ¶������6���src/Composer/DependencyResolver/SolverBugException.php˜��2@.V˜��"qN¶������;���src/Composer/DependencyResolver/SolverProblemsException.php(��2@.V(��S‹Ž¼¶������/���src/Composer/DependencyResolver/Transaction.phpÔ��2@.VÔ�� 3ô¶������-���src/Composer/Downloader/ArchiveDownloader.php‡��2@.V‡��¬¸£ ¶������1���src/Composer/Downloader/ChangeReportInterface.phpÌ���2@.VÌ���¯à¨¿¶������+���src/Composer/Downloader/DownloadManager.php���2@.V���F«ü¶������/���src/Composer/Downloader/DownloaderInterface.phpÊ��2@.VÊ��gs!l¶������*���src/Composer/Downloader/FileDownloader.phpn��2@.Vn��
„ò®¶������/���src/Composer/Downloader/FilesystemException.php��2@.V��]T½ˆ¶������)���src/Composer/Downloader/GitDownloader.phpÕ$��2@.VÕ$��²–�¶������*���src/Composer/Downloader/GzipDownloader.phpÈ��2@.VÈ��äßж������(���src/Composer/Downloader/HgDownloader.phpd��2@.Vd��«.½¶������*���src/Composer/Downloader/PathDownloader.php8��2@.V8��se̶������0���src/Composer/Downloader/PearPackageExtractor.phpu��2@.Vu��z„‡¶������.���src/Composer/Downloader/PerforceDownloader.phpy��2@.Vy��(Ž)3¶������*���src/Composer/Downloader/PharDownloader.phpå���2@.Vå���ÞÉç¶������)���src/Composer/Downloader/RarDownloader.phpß��2@.Vß��¾¼¶������)���src/Composer/Downloader/SvnDownloader.php\��2@.V\��.[¶������)���src/Composer/Downloader/TarDownloader.phpã���2@.Vã���Í’X?¶������.���src/Composer/Downloader/TransportException.php–��2@.V–��h"Br¶������)���src/Composer/Downloader/VcsDownloader.php¹��2@.V¹��N+¶¶������)���src/Composer/Downloader/ZipDownloader.phpC��2@.VC��]^+¶������&���src/Composer/EventDispatcher/Event.php ��2@.V ��±™jï¶������0���src/Composer/EventDispatcher/EventDispatcher.php5��2@.V5��%¾Å¶������9���src/Composer/EventDispatcher/EventSubscriberInterface.php©���2@.V©���h·0¶���������src/Composer/Factory.php!.��2@.V!.��M-XT¶���������src/Composer/IO/BaseIO.phpp��2@.Vp��ÈNñZ¶���������src/Composer/IO/BufferIO.php��2@.V��hvá¶���������src/Composer/IO/ConsoleIO.php8��2@.V8��Ãô¶���������src/Composer/IO/IOInterface.php„��2@.V„��´=Så¶���������src/Composer/IO/NullIO.php³��2@.V³��~1Ķ���������src/Composer/Installer.php„��2@.V„��ì™–¶������.���src/Composer/Installer/InstallationManager.php��2@.V��ÓýÇÛ¶������)���src/Composer/Installer/InstallerEvent.php��2@.V��lÔzi¶������*���src/Composer/Installer/InstallerEvents.phpÞ���2@.VÞ���ìŸ@G¶������-���src/Composer/Installer/InstallerInterface.phpã��2@.Vã��^ƒ“ʶ������+���src/Composer/Installer/LibraryInstaller.phpö��2@.Vö��›é7B¶������/���src/Composer/Installer/MetapackageInstaller.phpœ��2@.Vœ��ÆÅ!¶������(���src/Composer/Installer/NoopInstaller.php+��2@.V+��À·M}¶������'���src/Composer/Installer/PackageEvent.phpe��2@.Ve��;° ¶������(���src/Composer/Installer/PackageEvents.php¸��2@.V¸��dbØs¶������(���src/Composer/Installer/PearInstaller.phpV��2@.VV���zð¶������*���src/Composer/Installer/PluginInstaller.php
- ��2@.V
- ��6À¢�¶������+���src/Composer/Installer/ProjectInstaller.php��2@.V��*0@P¶���������src/Composer/Json/JsonFile.php���2@.V���’Üþ¶������#���src/Composer/Json/JsonFormatter.php��2@.V��Ðqu¶������%���src/Composer/Json/JsonManipulator.php*��2@.V*��r%¶������-���src/Composer/Json/JsonValidationException.php\��2@.V\��.Xóܶ������%���src/Composer/Package/AliasPackage.php"��2@.V"��í©˜·¶������7���src/Composer/Package/Archiver/ArchivableFilesFinder.php¾��2@.V¾��„Œõɶ������0���src/Composer/Package/Archiver/ArchiveManager.phpz��2@.Vz��!sK™¶������3���src/Composer/Package/Archiver/ArchiverInterface.phpï���2@.Vï���<ʸ¶������3���src/Composer/Package/Archiver/BaseExcludeFilter.php‘��2@.V‘��[ÿ0=¶������7���src/Composer/Package/Archiver/ComposerExcludeFilter.php��2@.V��‹SZ0¶������2���src/Composer/Package/Archiver/GitExcludeFilter.phpw��2@.Vw��LgU»¶������1���src/Composer/Package/Archiver/HgExcludeFilter.php��2@.V��~”¸¶������.���src/Composer/Package/Archiver/PharArchiver.php[��2@.V[��Ê5Íø¶������$���src/Composer/Package/BasePackage.phpß��2@.Vß��ï¤ ¶������(���src/Composer/Package/CompletePackage.phpÿ��2@.Vÿ��o+ã ¶������1���src/Composer/Package/CompletePackageInterface.phpõ��2@.Võ��¦Ê�ò¶������+���src/Composer/Package/Dumper/ArrayDumper.phpì��2@.Vì��ª–æ¶���������src/Composer/Package/Link.phpD��2@.VD��LО¶������7���src/Composer/Package/LinkConstraint/EmptyConstraint.phpƒ��2@.Vƒ��¥,ED¶������?���src/Composer/Package/LinkConstraint/LinkConstraintInterface.phpe��2@.Ve���ÇþŸ¶������7���src/Composer/Package/LinkConstraint/MultiConstraint.phpƒ��2@.Vƒ��Ó6W¶������:���src/Composer/Package/LinkConstraint/SpecificConstraint.php…��2@.V…��û¾b¶������9���src/Composer/Package/LinkConstraint/VersionConstraint.phpY��2@.VY��"+\Q¶������+���src/Composer/Package/Loader/ArrayLoader.phpç��2@.Vç��MùØr¶������7���src/Composer/Package/Loader/InvalidPackageException.phpE��2@.VE��xb¾¶������*���src/Composer/Package/Loader/JsonLoader.phpù��2@.Vù��!~ˆ{¶������/���src/Composer/Package/Loader/LoaderInterface.php²���2@.V²���¦}úζ������1���src/Composer/Package/Loader/RootPackageLoader.php[��2@.V[��ñÊ&u¶������5���src/Composer/Package/Loader/ValidatingArrayLoader.phpÎ/��2@.VÎ/��‹Ú`L¶���������src/Composer/Package/Locker.phpŠ!��2@.VŠ!��†{¹€¶������ ���src/Composer/Package/Package.php»��2@.V»��¼Jâ¶������)���src/Composer/Package/PackageInterface.php ��2@.V ��ûÇ^ƶ������)���src/Composer/Package/RootAliasPackage.phpy��2@.Vy��ÀE'¶������$���src/Composer/Package/RootPackage.phpn��2@.Vn��áACO¶������-���src/Composer/Package/RootPackageInterface.php´��2@.V´��êqKж������/���src/Composer/Package/Version/VersionGuesser.phpû��2@.Vû��9¼Ò¶������.���src/Composer/Package/Version/VersionParser.phpò��2@.Vò��&Cf¶������0���src/Composer/Package/Version/VersionSelector.phpÃ��2@.VÃ��A‡¥6¶������$���src/Composer/Plugin/CommandEvent.phpâ��2@.Vâ��³ÆÇW¶������$���src/Composer/Plugin/PluginEvents.php¤���2@.V¤���0ïÞX¶������'���src/Composer/Plugin/PluginInterface.phpô���2@.Vô���1‰%¶������%���src/Composer/Plugin/PluginManager.php£��2@.V£��CßO¶������,���src/Composer/Plugin/PreFileDownloadEvent.php`��2@.V`���9-ζ������+���src/Composer/Repository/ArrayRepository.php|
��2@.V|
��õ{^f¶������.���src/Composer/Repository/ArtifactRepository.phpG��2@.VG��àÈ=À¶������.���src/Composer/Repository/ComposerRepository.phpä@��2@.Vä@��߈eÒ¶������/���src/Composer/Repository/CompositeRepository.php.��2@.V.��CÅx¶������0���src/Composer/Repository/FilesystemRepository.phpÀ��2@.VÀ��&xb£¶������4���src/Composer/Repository/InstalledArrayRepository.php£���2@.V£���/ö~>¶������9���src/Composer/Repository/InstalledFilesystemRepository.php£���2@.V£���V
- •_¶������8���src/Composer/Repository/InstalledRepositoryInterface.php‡���2@.V‡���£9p¶������6���src/Composer/Repository/InvalidRepositoryException.phpn���2@.Vn���à“똶������-���src/Composer/Repository/PackageRepository.phpG��2@.VG��í:k¶������*���src/Composer/Repository/PathRepository.php‰��2@.V‰��t¶±¶������2���src/Composer/Repository/Pear/BaseChannelReader.php6��2@.V6��.fi!¶������,���src/Composer/Repository/Pear/ChannelInfo.phpÄ��2@.VÄ��:T*ɶ������.���src/Composer/Repository/Pear/ChannelReader.phpn��2@.Vn��š8¶������4���src/Composer/Repository/Pear/ChannelRest10Reader.phpÁ ��2@.VÁ ��O€ë¶������4���src/Composer/Repository/Pear/ChannelRest11Reader.php& ��2@.V& ��òUb¶������5���src/Composer/Repository/Pear/DependencyConstraint.phpq��2@.Vq��9=¶������/���src/Composer/Repository/Pear/DependencyInfo.phpq��2@.Vq��fºTò¶������8���src/Composer/Repository/Pear/PackageDependencyParser.php%��2@.V%��j?“¶������,���src/Composer/Repository/Pear/PackageInfo.php°��2@.V°��Ÿ
¸¶������,���src/Composer/Repository/Pear/ReleaseInfo.php’��2@.V’��o“ŠÃ¶������*���src/Composer/Repository/PearRepository.php���2@.V���~ãs_¶������.���src/Composer/Repository/PlatformRepository.php{��2@.V{���™Úض������/���src/Composer/Repository/RepositoryInterface.phpÚ��2@.VÚ��7@€¶������-���src/Composer/Repository/RepositoryManager.phpæ��2@.Væ��¯YÙI¶������7���src/Composer/Repository/RepositorySecurityException.phpo���2@.Vo���pÕ«ª¶������2���src/Composer/Repository/Vcs/GitBitbucketDriver.phpì��2@.Vì��Fÿô¶������)���src/Composer/Repository/Vcs/GitDriver.php��2@.V��\îï¶������,���src/Composer/Repository/Vcs/GitHubDriver.phpá'��2@.Vá'��“ü@¶������1���src/Composer/Repository/Vcs/HgBitbucketDriver.phpô
��2@.Vô
��˜áWõ¶������(���src/Composer/Repository/Vcs/HgDriver.phpà��2@.Và��ñ‘綶������.���src/Composer/Repository/Vcs/PerforceDriver.php"
- ��2@.V"
- ��°`ìE¶������)���src/Composer/Repository/Vcs/SvnDriver.php²��2@.V²��Ë W¶������)���src/Composer/Repository/Vcs/VcsDriver.phpÑ��2@.VÑ��å%R¶������2���src/Composer/Repository/Vcs/VcsDriverInterface.phpˆ��2@.Vˆ��ŽP©Î¶������)���src/Composer/Repository/VcsRepository.php;��2@.V;��ayÉ£¶������3���src/Composer/Repository/WritableArrayRepository.php��2@.V��¾G*¶������7���src/Composer/Repository/WritableRepositoryInterface.php‰��2@.V‰��‘/sï¶������$���src/Composer/Script/CommandEvent.phpW���2@.VW���£VZt¶���������src/Composer/Script/Event.phpµ��2@.Vµ��lt¦M¶������$���src/Composer/Script/PackageEvent.phpœ���2@.Vœ���§ÿÉ
¶������$���src/Composer/Script/ScriptEvents.phpP��2@.VP��‡�¶¶������ ���src/Composer/Util/AuthHelper.phpË��2@.VË��>zx–¶������$���src/Composer/Util/ComposerMirror.php±��2@.V±��½øض������%���src/Composer/Util/ConfigValidator.phpƒ��2@.Vƒ��YFQ!¶������"���src/Composer/Util/ErrorHandler.phpY��2@.VY��³vB¶������ ���src/Composer/Util/Filesystem.phpJ&��2@.VJ&��§�ßc¶���������src/Composer/Util/Git.php��2@.V��¥S|Ŷ���������src/Composer/Util/GitHub.php–
- ��2@.V–
- ��Êï'”¶������$���src/Composer/Util/NoProxyPattern.php¾��2@.V¾��Z+°m¶���������src/Composer/Util/Perforce.php3��2@.V3��¶-Ñȶ������%���src/Composer/Util/ProcessExecutor.phpí��2@.Ví��bF‘«¶������&���src/Composer/Util/RemoteFilesystem.php +��2@.V +��=$5¶������!���src/Composer/Util/SpdxLicense.php��2@.V��œ@›ƒ¶������*���src/Composer/Util/StreamContextFactory.phpÎ��2@.VÎ��ëä³Y¶���������src/Composer/Util/Svn.php†��2@.V†��e@î¶���������src/bootstrap.phpÅ��2@.VÅ��¨¯2�¶������%���src/Composer/Autoload/ClassLoader.php”0��2@.V”0��¸Lh¦¶���������res/composer-schema.json7U��2@.V7U��)Š¨>¶������6���vendor/composer/spdx-licenses/res/spdx-exceptions.json¹��2@.V¹��kw°¶������4���vendor/composer/spdx-licenses/res/spdx-licenses.json¿]��2@.V¿]��%z"�¶������*���vendor/seld/cli-prompt/res/hiddeninput.exe�$��2@.V�$��•�¥v¶������@���vendor/symfony/console/Symfony/Component/Console/Application.phpÎR��2@.VÎR��?sK¶������D���vendor/symfony/console/Symfony/Component/Console/Command/Command.phpð��2@.Vð��pŶ������H���vendor/symfony/console/Symfony/Component/Console/Command/HelpCommand.php6��2@.V6��#¯¾}¶������H���vendor/symfony/console/Symfony/Component/Console/Command/ListCommand.php³��2@.V³��VÓé¶������B���vendor/symfony/console/Symfony/Component/Console/ConsoleEvents.phpï���2@.Vï���
ÕH¸¶������V���vendor/symfony/console/Symfony/Component/Console/Descriptor/ApplicationDescription.php��2@.V��ù0Ðj¶������J���vendor/symfony/console/Symfony/Component/Console/Descriptor/Descriptor.php\��2@.V\��WJ[í¶������S���vendor/symfony/console/Symfony/Component/Console/Descriptor/DescriptorInterface.phpü���2@.Vü���±Qµ¶������N���vendor/symfony/console/Symfony/Component/Console/Descriptor/JsonDescriptor.php2
��2@.V2
��†ca¶������R���vendor/symfony/console/Symfony/Component/Console/Descriptor/MarkdownDescriptor.php
- ��2@.V
- ���LÛ*¶������N���vendor/symfony/console/Symfony/Component/Console/Descriptor/TextDescriptor.php4��2@.V4��`âÐ8¶������M���vendor/symfony/console/Symfony/Component/Console/Descriptor/XmlDescriptor.php ��2@.V ��…{îm¶������N���vendor/symfony/console/Symfony/Component/Console/Event/ConsoleCommandEvent.php²��2@.V²��Zk‰2¶������G���vendor/symfony/console/Symfony/Component/Console/Event/ConsoleEvent.phpÅ��2@.VÅ��ÒxÛ\¶������P���vendor/symfony/console/Symfony/Component/Console/Event/ConsoleExceptionEvent.php��2@.V��á2é¶������P���vendor/symfony/console/Symfony/Component/Console/Event/ConsoleTerminateEvent.phpz��2@.Vz��³,îL¶������N���vendor/symfony/console/Symfony/Component/Console/Formatter/OutputFormatter.php���2@.V���%šÒ¬¶������W���vendor/symfony/console/Symfony/Component/Console/Formatter/OutputFormatterInterface.php˜��2@.V˜��3l~´¶������S���vendor/symfony/console/Symfony/Component/Console/Formatter/OutputFormatterStyle.php��2@.V��,{ZŠ¶������\���vendor/symfony/console/Symfony/Component/Console/Formatter/OutputFormatterStyleInterface.phpŽ��2@.VŽ��öëÄ=¶������X���vendor/symfony/console/Symfony/Component/Console/Formatter/OutputFormatterStyleStack.php
- ��2@.V
- ��,½-¶������P���vendor/symfony/console/Symfony/Component/Console/Helper/DebugFormatterHelper.phpx��2@.Vx��žH@¶������L���vendor/symfony/console/Symfony/Component/Console/Helper/DescriptorHelper.php9��2@.V9��ûùäð¶������H���vendor/symfony/console/Symfony/Component/Console/Helper/DialogHelper.php��2@.V��ø=ÜÓ¶������K���vendor/symfony/console/Symfony/Component/Console/Helper/FormatterHelper.phpc��2@.Vc��“ý«N¶������B���vendor/symfony/console/Symfony/Component/Console/Helper/Helper.phpß��2@.Vß��o¾ã¶������K���vendor/symfony/console/Symfony/Component/Console/Helper/HelperInterface.phpï���2@.Vï���=e¶������E���vendor/symfony/console/Symfony/Component/Console/Helper/HelperSet.php/��2@.V/��âw�d¶������L���vendor/symfony/console/Symfony/Component/Console/Helper/InputAwareHelper.phpc��2@.Vc��ñø�|¶������I���vendor/symfony/console/Symfony/Component/Console/Helper/ProcessHelper.phpâ��2@.Vâ��|̼¶������G���vendor/symfony/console/Symfony/Component/Console/Helper/ProgressBar.php$��2@.V$��ô¶������J���vendor/symfony/console/Symfony/Component/Console/Helper/ProgressHelper.phpƒ��2@.Vƒ��“h™¶������J���vendor/symfony/console/Symfony/Component/Console/Helper/QuestionHelper.php��2@.V��RŠ¶������A���vendor/symfony/console/Symfony/Component/Console/Helper/Table.php��2@.V��‚¸A)¶������G���vendor/symfony/console/Symfony/Component/Console/Helper/TableHelper.phpØ
- ��2@.VØ
- ��,
¶������J���vendor/symfony/console/Symfony/Component/Console/Helper/TableSeparator.php[���2@.V[���LV¡¶������F���vendor/symfony/console/Symfony/Component/Console/Helper/TableStyle.phpÕ��2@.VÕ��æ"ðù¶������D���vendor/symfony/console/Symfony/Component/Console/Input/ArgvInput.phpÑ��2@.VÑ��íÐ�¶������E���vendor/symfony/console/Symfony/Component/Console/Input/ArrayInput.phpû ��2@.Vû ��âö¥p¶������@���vendor/symfony/console/Symfony/Component/Console/Input/Input.php
- ��2@.V
- ��ÇýT¶������H���vendor/symfony/console/Symfony/Component/Console/Input/InputArgument.phpž��2@.Vž��K]ìi¶������N���vendor/symfony/console/Symfony/Component/Console/Input/InputAwareInterface.phpš���2@.Vš���‡jTŸ¶������J���vendor/symfony/console/Symfony/Component/Console/Input/InputDefinition.php��2@.V��˜£JM¶������I���vendor/symfony/console/Symfony/Component/Console/Input/InputInterface.php ��2@.V ��9”øǶ������F���vendor/symfony/console/Symfony/Component/Console/Input/InputOption.php«��2@.V«��ꆮ½¶������F���vendor/symfony/console/Symfony/Component/Console/Input/StringInput.php‹��2@.V‹��†uný¶������8���vendor/symfony/console/Symfony/Component/Console/LICENSE)��2@.V)��ë&•¶������I���vendor/symfony/console/Symfony/Component/Console/Logger/ConsoleLogger.php; ��2@.V; ��#ØB~¶������J���vendor/symfony/console/Symfony/Component/Console/Output/BufferedOutput.php_��2@.V_��ûBÍ·¶������I���vendor/symfony/console/Symfony/Component/Console/Output/ConsoleOutput.php±��2@.V±��)m¶������R���vendor/symfony/console/Symfony/Component/Console/Output/ConsoleOutputInterface.phpå���2@.Vå���rNô�¶������F���vendor/symfony/console/Symfony/Component/Console/Output/NullOutput.php¿��2@.V¿��`5E˶������B���vendor/symfony/console/Symfony/Component/Console/Output/Output.php§��2@.V§��Ú _¶������K���vendor/symfony/console/Symfony/Component/Console/Output/OutputInterface.phpI��2@.VI��ÈâãB¶������H���vendor/symfony/console/Symfony/Component/Console/Output/StreamOutput.php£��2@.V£���_Õ¶������L���vendor/symfony/console/Symfony/Component/Console/Question/ChoiceQuestion.php^��2@.V^��C‚¦Û¶������R���vendor/symfony/console/Symfony/Component/Console/Question/ConfirmationQuestion.phpK��2@.VK��õÃTȶ������F���vendor/symfony/console/Symfony/Component/Console/Question/Question.php®��2@.V®��.e8Ö¶������:���vendor/symfony/console/Symfony/Component/Console/Shell.php1��2@.V1��UÈ,¶������M���vendor/symfony/console/Symfony/Component/Console/Tester/ApplicationTester.phpÔ��2@.VÔ��¬ì¤d¶������I���vendor/symfony/console/Symfony/Component/Console/Tester/CommandTester.php®��2@.V®��EÙš|¶������W���vendor/symfony/filesystem/Symfony/Component/Filesystem/Exception/ExceptionInterface.phpk���2@.Vk���€Ûèà¶������Z���vendor/symfony/filesystem/Symfony/Component/Filesystem/Exception/FileNotFoundException.php¼��2@.V¼��pí\¶¶������P���vendor/symfony/filesystem/Symfony/Component/Filesystem/Exception/IOException.php‰��2@.V‰��Ö0ÿn¶������Y���vendor/symfony/filesystem/Symfony/Component/Filesystem/Exception/IOExceptionInterface.php¦���2@.V¦���jÙwM¶������E���vendor/symfony/filesystem/Symfony/Component/Filesystem/Filesystem.php¤&��2@.V¤&��Cäs¶������>���vendor/symfony/filesystem/Symfony/Component/Filesystem/LICENSE)��2@.V)��ë&•¶������F���vendor/symfony/filesystem/Symfony/Component/Filesystem/LockHandler.phpÊ��2@.VÊ��¤¸X¿¶������J���vendor/symfony/finder/Symfony/Component/Finder/Adapter/AbstractAdapter.php¤
- ��2@.V¤
- ��¢)z9¶������N���vendor/symfony/finder/Symfony/Component/Finder/Adapter/AbstractFindAdapter.phpÝ��2@.VÝ��Þ_“ø¶������K���vendor/symfony/finder/Symfony/Component/Finder/Adapter/AdapterInterface.php¯��2@.V¯��‹éȶ������I���vendor/symfony/finder/Symfony/Component/Finder/Adapter/BsdFindAdapter.php{��2@.V{��Q,D2¶������I���vendor/symfony/finder/Symfony/Component/Finder/Adapter/GnuFindAdapter.php^��2@.V^��ßz˜r¶������E���vendor/symfony/finder/Symfony/Component/Finder/Adapter/PhpAdapter.php+��2@.V+��&˜îÒ¶������H���vendor/symfony/finder/Symfony/Component/Finder/Comparator/Comparator.phpŒ��2@.VŒ��wþT¶������L���vendor/symfony/finder/Symfony/Component/Finder/Comparator/DateComparator.php%��2@.V%��L¿EǶ������N���vendor/symfony/finder/Symfony/Component/Finder/Comparator/NumberComparator.php~��2@.V~��”‡ x¶������R���vendor/symfony/finder/Symfony/Component/Finder/Exception/AccessDeniedException.php„���2@.V„���½¾sœ¶������T���vendor/symfony/finder/Symfony/Component/Finder/Exception/AdapterFailureException.php��2@.V��mŒ_,¶������O���vendor/symfony/finder/Symfony/Component/Finder/Exception/ExceptionInterface.php„���2@.V„���Gz-¶������Z���vendor/symfony/finder/Symfony/Component/Finder/Exception/OperationNotPermitedException.phpŠ���2@.VŠ���U88¶������Y���vendor/symfony/finder/Symfony/Component/Finder/Exception/ShellCommandFailureException.php$��2@.V$��C”sÓ¶������H���vendor/symfony/finder/Symfony/Component/Finder/Expression/Expression.php}��2@.V}��/·cð¶������B���vendor/symfony/finder/Symfony/Component/Finder/Expression/Glob.php¡��2@.V¡��3^äë¶������C���vendor/symfony/finder/Symfony/Component/Finder/Expression/Regex.php���2@.V���S7Pæ¶������L���vendor/symfony/finder/Symfony/Component/Finder/Expression/ValueInterface.php;��2@.V;��îãÓ¶������9���vendor/symfony/finder/Symfony/Component/Finder/Finder.php#��2@.V#���Ó$ê¶������7���vendor/symfony/finder/Symfony/Component/Finder/Glob.php
��2@.V
��¥ M¶������P���vendor/symfony/finder/Symfony/Component/Finder/Iterator/CustomFilterIterator.php]��2@.V]��tà±µ¶������S���vendor/symfony/finder/Symfony/Component/Finder/Iterator/DateRangeFilterIterator.phpz��2@.Vz��}¢¶������T���vendor/symfony/finder/Symfony/Component/Finder/Iterator/DepthRangeFilterIterator.phpð��2@.Vð��ß0™¶������Z���vendor/symfony/finder/Symfony/Component/Finder/Iterator/ExcludeDirectoryFilterIterator.php”��2@.V”��"ÖóÁ¶������M���vendor/symfony/finder/Symfony/Component/Finder/Iterator/FilePathsIterator.php���2@.V���ýòäQ¶������R���vendor/symfony/finder/Symfony/Component/Finder/Iterator/FileTypeFilterIterator.php\��2@.V\��p‘'˜¶������U���vendor/symfony/finder/Symfony/Component/Finder/Iterator/FilecontentFilterIterator.php#��2@.V#��Ú_VǶ������R���vendor/symfony/finder/Symfony/Component/Finder/Iterator/FilenameFilterIterator.php‡��2@.V‡��F ’¶������J���vendor/symfony/finder/Symfony/Component/Finder/Iterator/FilterIterator.php†��2@.V†��0£¾Ô¶������V���vendor/symfony/finder/Symfony/Component/Finder/Iterator/MultiplePcreFilterIterator.phpØ��2@.VØ��Òù“¶������N���vendor/symfony/finder/Symfony/Component/Finder/Iterator/PathFilterIterator.php¸��2@.V¸��E*E¶������V���vendor/symfony/finder/Symfony/Component/Finder/Iterator/RecursiveDirectoryIterator.phpY��2@.VY��êÓÊܶ������S���vendor/symfony/finder/Symfony/Component/Finder/Iterator/SizeRangeFilterIterator.phpg��2@.Vg��!Ô—é¶������L���vendor/symfony/finder/Symfony/Component/Finder/Iterator/SortableIterator.phpÞ��2@.VÞ��ö³%¶������6���vendor/symfony/finder/Symfony/Component/Finder/LICENSE)��2@.V)��ë&•¶������@���vendor/symfony/finder/Symfony/Component/Finder/Shell/Command.phpÊ
- ��2@.VÊ
- ��É_ï¶������>���vendor/symfony/finder/Symfony/Component/Finder/Shell/Shell.phpé��2@.Vé��¿ëÛ•¶������>���vendor/symfony/finder/Symfony/Component/Finder/SplFileInfo.phpû��2@.Vû��‘†6¶������Q���vendor/symfony/process/Symfony/Component/Process/Exception/ExceptionInterface.phpf���2@.Vf���]ö>T¶������W���vendor/symfony/process/Symfony/Component/Process/Exception/InvalidArgumentException.php¨���2@.V¨���ÐÀ+_¶������M���vendor/symfony/process/Symfony/Component/Process/Exception/LogicException.php”���2@.V”��� ³ãñ¶������U���vendor/symfony/process/Symfony/Component/Process/Exception/ProcessFailedException.php<��2@.V<��"wÛn¶������W���vendor/symfony/process/Symfony/Component/Process/Exception/ProcessTimedOutException.php��2@.V��. Ãá¶������O���vendor/symfony/process/Symfony/Component/Process/Exception/RuntimeException.php˜���2@.V˜���¢Ø:¶������E���vendor/symfony/process/Symfony/Component/Process/ExecutableFinder.php~��2@.V~��+…¶������8���vendor/symfony/process/Symfony/Component/Process/LICENSE)��2@.V)��ë&•¶������H���vendor/symfony/process/Symfony/Component/Process/PhpExecutableFinder.phpù��2@.Vù��}E᪶������?���vendor/symfony/process/Symfony/Component/Process/PhpProcess.php×��2@.V×��Š€«¶������H���vendor/symfony/process/Symfony/Component/Process/Pipes/AbstractPipes.php���2@.V���˜|¥¾¶������I���vendor/symfony/process/Symfony/Component/Process/Pipes/PipesInterface.phpD��2@.VD��vØ������D���vendor/symfony/process/Symfony/Component/Process/Pipes/UnixPipes.php¤��2@.V¤��øUt¶������G���vendor/symfony/process/Symfony/Component/Process/Pipes/WindowsPipes.php½��2@.V½���.X£¶������<���vendor/symfony/process/Symfony/Component/Process/Process.phpÚN��2@.VÚN��ZEkv¶������C���vendor/symfony/process/Symfony/Component/Process/ProcessBuilder.php��2@.V���ïy¶������A���vendor/symfony/process/Symfony/Component/Process/ProcessUtils.php‹��2@.V‹��
- c†¶���������vendor/seld/jsonlint/LICENSE"��2@.V"��aƒsy¶������5���vendor/seld/jsonlint/src/Seld/JsonLint/JsonParser.php)1��2@.V)1��?5R3¶������0���vendor/seld/jsonlint/src/Seld/JsonLint/Lexer.php��2@.V��‰„m!¶������;���vendor/seld/jsonlint/src/Seld/JsonLint/ParsingException.php��2@.V��‰²ñ¶������4���vendor/seld/jsonlint/src/Seld/JsonLint/Undefined.php>���2@.V>���ÿqŸŸ¶���������vendor/seld/cli-prompt/LICENSE"��2@.V"��ˆñ?e¶������&���vendor/seld/cli-prompt/res/example.php'��2@.V'��I£¶������(���vendor/seld/cli-prompt/src/CliPrompt.php��2@.V��é™v¶������(���vendor/justinrainbow/json-schema/LICENSE÷��2@.V÷��xÞxt¶������T���vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/CollectionConstraint.php ��2@.V ��¨Ö
- ¨¶������J���vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/Constraint.php‰��2@.V‰��!Êf¹¶������S���vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/ConstraintInterface.phpN��2@.VN��øÆMy¶������N���vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/EnumConstraint.phpO��2@.VO�� Ú"¶������P���vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/FormatConstraint.php®
��2@.V®
���'®»¶������P���vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/NumberConstraint.phpµ��2@.Vµ��@ð¶������P���vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/ObjectConstraint.phpë
- ��2@.Vë
- ��Ì.#ä¶������P���vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/SchemaConstraint.php ��2@.V ��ÈÌÕâ¶������P���vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/StringConstraint.php©��2@.V©��^¯R¶������N���vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/TypeConstraint.php��2@.V��÷³¼¶������S���vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/UndefinedConstraint.php¢��2@.V¢��òí×®¶������V���vendor/justinrainbow/json-schema/src/JsonSchema/Exception/InvalidArgumentException.phpv���2@.Vv���¬ «"¶������]���vendor/justinrainbow/json-schema/src/JsonSchema/Exception/InvalidSchemaMediaTypeException.phpv���2@.Vv���ŠCÓ¶������W���vendor/justinrainbow/json-schema/src/JsonSchema/Exception/InvalidSourceUriException.phpw���2@.Vw���N-ò[¶������S���vendor/justinrainbow/json-schema/src/JsonSchema/Exception/JsonDecodingException.phpÞ��2@.VÞ��†¾©‘¶������W���vendor/justinrainbow/json-schema/src/JsonSchema/Exception/ResourceNotFoundException.phpo���2@.Vo���Æ$"Ŷ������R���vendor/justinrainbow/json-schema/src/JsonSchema/Exception/UriResolverException.phpj���2@.Vj���SÓdz¶������?���vendor/justinrainbow/json-schema/src/JsonSchema/RefResolver.phpÀ
��2@.V���c«¶������T���vendor/justinrainbow/json-schema/src/JsonSchema/Uri/Retrievers/AbstractRetriever.phpÜ���2@.VÜ���]j¶������G���vendor/justinrainbow/json-schema/src/JsonSchema/Uri/Retrievers/Curl.phpt��2@.Vt��I·ý�¶������R���vendor/justinrainbow/json-schema/src/JsonSchema/Uri/Retrievers/FileGetContents.phpb��2@.Vb��WýÁ¶������R���vendor/justinrainbow/json-schema/src/JsonSchema/Uri/Retrievers/PredefinedArray.php*��2@.V*��-3ÿ¶������X���vendor/justinrainbow/json-schema/src/JsonSchema/Uri/Retrievers/UriRetrieverInterface.php©���2@.V©���CO¶������C���vendor/justinrainbow/json-schema/src/JsonSchema/Uri/UriResolver.phpR ��2@.VR ��pÿi1¶������D���vendor/justinrainbow/json-schema/src/JsonSchema/Uri/UriRetriever.phpa��2@.Va��¾,Η¶������=���vendor/justinrainbow/json-schema/src/JsonSchema/Validator.phpæ��2@.Væ��,u¶������%���vendor/composer/spdx-licenses/LICENSE��2@.V��Bhí¶������2���vendor/composer/spdx-licenses/src/SpdxLicenses.phpå��2@.Vå��=Ø7¶���������vendor/composer/semver/LICENSE��2@.V��Bhí¶������)���vendor/composer/semver/src/Comparator.php��2@.V��wlƒï¶������<���vendor/composer/semver/src/Constraint/AbstractConstraint.phpk��2@.Vk��è§Àm¶������4���vendor/composer/semver/src/Constraint/Constraint.phpù
- ��2@.Vù
- ��¸Èõ¶������=���vendor/composer/semver/src/Constraint/ConstraintInterface.php��2@.V��¾sX¶������9���vendor/composer/semver/src/Constraint/EmptyConstraint.phpé��2@.Vé��!-Ø™¶������9���vendor/composer/semver/src/Constraint/MultiConstraint.phpf��2@.Vf��Dðì>¶������%���vendor/composer/semver/src/Semver.phpv��2@.Vv��‹×È›¶������,���vendor/composer/semver/src/VersionParser.php (��2@.V (��´MPÿ¶���������vendor/autoload.php‡���2@.V‡���F*W~¶������'���vendor/composer/autoload_namespaces.php¼��2@.V¼���D¶������!���vendor/composer/autoload_psr4.php��2@.V��šù‹®¶������%���vendor/composer/autoload_classmap.phpd���2@.Vd���Z¡¦H¶������!���vendor/composer/autoload_real.php7��2@.V7��›O‰¶���������vendor/composer/ClassLoader.phpB��2@.VB��é”í¶���������bin/composerl��2@.Vl��Ԛà ¶���������LICENSE3��2@.V3��fýÞX¶������<?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;
- private $classMapAuthoritative = 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 setClassMapAuthoritative($classMapAuthoritative)
- {
- $this->classMapAuthoritative = (boolean) $classMapAuthoritative;
- }
- public function dump(Config $config, InstalledRepositoryInterface $localRepo, PackageInterface $mainPackage, InstallationManager $installationManager, $targetDir, $scanPsr0Packages = false, $suffix = '')
- {
- if ($this->classMapAuthoritative) {
- $scanPsr0Packages = true;
- }
- $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';
- $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) {
- $namespacesToScan = array();
- foreach (array('psr-0', 'psr-4') as $psrType) {
- foreach ($autoloads[$psrType] as $namespace => $paths) {
- $namespacesToScan[$namespace][] = array('paths' => $paths, 'type' => $psrType);
- }
- }
- krsort($namespacesToScan);
- foreach ($namespacesToScan as $namespace => $groups) {
- foreach ($groups as $group) {
- $psrType = $group['type'];
- foreach ($group['paths'] as $dir) {
- $dir = $filesystem->normalizePath($filesystem->isAbsolutePath($dir) ? $dir : $basePath.'/'.$dir);
- if (!is_dir($dir)) {
- continue;
- }
- $whitelist = sprintf(
- '{%s/%s.+$}',
- 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) {
- $pathCode = $this->getPathCode($filesystem, $basePath, $vendorPath, $path).",\n";
- if (!isset($classMap[$class])) {
- $classMap[$class] = $pathCode;
- } elseif ($this->io && $classMap[$class] !== $pathCode && !preg_match('{/(test|fixture|example|stub)s?/}i', strtr($classMap[$class].' '.$path, '\\', '/'))) {
- $this->io->writeError(
- '<warning>Warning: Ambiguous class resolution, "'.$class.'"'.
- ' was found in both "'.str_replace(array('$vendorDir . \'', "',\n"), array($vendorPath, ''), $classMap[$class]).'" and "'.$path.'", the first will be used.</warning>'
- );
- }
- }
- }
- }
- }
- }
- foreach ($autoloads['classmap'] as $dir) {
- foreach (ClassMapGenerator::createMap($dir, null, $this->io) as $class => $path) {
- $pathCode = $this->getPathCode($filesystem, $basePath, $vendorPath, $path).",\n";
- if (!isset($classMap[$class])) {
- $classMap[$class] = $pathCode;
- } elseif ($this->io && $classMap[$class] !== $pathCode && !preg_match('{/(test|fixture|example|stub)s?/}i', strtr($classMap[$class].' '.$path, '\\', '/'))) {
- $this->io->writeError(
- '<warning>Warning: Ambiguous class resolution, "'.$class.'"'.
- ' was found in both "'.str_replace(array('$vendorDir . \'', "',\n"), array($vendorPath, ''), $classMap[$class]).'" and "'.$path.'", the first will be used.</warning>'
- );
- }
- }
- }
- ksort($classMap);
- foreach ($classMap as $class => $code) {
- $classmapFile .= ' '.var_export($class, true).' => '.$code;
- }
- $classmapFile .= ");\n";
- if (!$suffix) {
- if (!$config->get('autoloader-suffix') && is_readable($vendorPath.'/autoload.php')) {
- $content = file_get_contents($vendorPath.'/autoload.php');
- if (preg_match('{ComposerAutoloaderInit([^:\s]+)::}', $content, $match)) {
- $suffix = $match[1];
- }
- }
- 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);
- $includePathFilePath = $targetDir.'/include_paths.php';
- if ($includePathFileContents = $this->getIncludePathsFile($packageMap, $filesystem, $basePath, $vendorPath, $vendorPathCode52, $appBaseDirCode)) {
- file_put_contents($includePathFilePath, $includePathFileContents);
- } elseif (file_exists($includePathFilePath)) {
- unlink($includePathFilePath);
- }
- $includeFilesFilePath = $targetDir.'/autoload_files.php';
- if ($includeFilesFileContents = $this->getIncludeFilesFile($autoloads['files'], $filesystem, $basePath, $vendorPath, $vendorPathCode52, $appBaseDirCode)) {
- file_put_contents($includeFilesFilePath, $includeFilesFileContents);
- } elseif (file_exists($includeFilesFilePath)) {
- unlink($includeFilesFilePath);
- }
- file_put_contents($vendorPath.'/autoload.php', $this->getAutoloadFile($vendorPathToTargetDirCode, $suffix));
- file_put_contents($targetDir.'/autoload_real.php', $this->getAutoloadRealFile(true, (bool) $includePathFileContents, $targetDirLoader, (bool) $includeFilesFileContents, $vendorPathCode, $appBaseDirCode, $suffix, $useGlobalIncludePath, $prependAutoloader));
- $this->safeCopy(__DIR__.'/ClassLoader.php', $targetDir.'/ClassLoader.php');
- $this->safeCopy(__DIR__.'/../../../LICENSE', $targetDir.'/LICENSE');
- $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(array_reverse($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)
- {
-
-
-
-
-
- $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 ($this->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;
- }
- protected function safeCopy($source, $target)
- {
- $source = fopen($source, 'r');
- $target = fopen($target, 'w+');
- stream_copy_to_stream($source, $target);
- fclose($source);
- fclose($target);
- }
- }
- <?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|stub)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)
- {
- $extraTypes = PHP_VERSION_ID < 50400 ? '' : '|trait';
- if (defined('HHVM_VERSION') && version_compare(HHVM_VERSION, '3.3', '>=')) {
- $extraTypes .= '|enum';
- }
- 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'.$extraTypes.')\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'.$extraTypes.') \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);
- } elseif ($matches['type'][$i] === 'enum') {
-
-
-
- $name = rtrim($name, ':');
- }
- $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) && !@mkdir($this->root, 0777, true))
- || !is_writable($this->root)
- ) {
- $this->io->writeError('<warning>Cannot create cache directory ' . $this->root . ', or directory is not writable. Proceeding without cache</warning>');
- $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 ($this->io->isDebug()) {
- $this->io->writeError('<warning>Failed to write into cache: '.$e->getMessage().'</warning>');
- }
- 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)) {
- try {
- touch($this->root . $file, filemtime($this->root . $file), time());
- } catch (\ErrorException $e) {
-
- 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 https://getcomposer.org/ for more information.</comment>
- EOT
- );
- }
- }
- <?php
- namespace Composer\Command;
- use Composer\Factory;
- use Composer\IO\IOInterface;
- use Composer\Config;
- use Composer\Repository\CompositeRepository;
- use Composer\Script\ScriptEvents;
- use Composer\Plugin\CommandEvent;
- use Composer\Plugin\PluginEvents;
- use Composer\Util\Filesystem;
- 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'),
- new InputOption('dir', false, InputOption::VALUE_REQUIRED, 'Write the archive to this directory'),
- new InputOption('file', false, InputOption::VALUE_REQUIRED, 'Write the archive with the given file name.'
- .' Note that the format will be appended.'),
- ))
- ->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)
- {
- $config = Factory::createConfig();
- $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);
- }
- if (null === $input->getOption('format')) {
- $input->setOption('format', $config->get('archive-format'));
- }
- if (null === $input->getOption('dir')) {
- $input->setOption('dir', $config->get('archive-dir'));
- }
- $returnCode = $this->archive(
- $this->getIO(),
- $config,
- $input->getArgument('package'),
- $input->getArgument('version'),
- $input->getOption('format'),
- $input->getOption('dir'),
- $input->getOption('file')
- );
- if (0 === $returnCode && $composer) {
- $composer->getEventDispatcher()->dispatchScript(ScriptEvents::POST_ARCHIVE_CMD);
- }
- return $returnCode;
- }
- protected function archive(IOInterface $io, Config $config, $packageName = null, $version = null, $format = 'tar', $dest = '.', $fileName = null)
- {
- $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 into "'.$dest.'".</info>');
- $packagePath = $archiveManager->archive($package, $format, $dest, $fileName);
- $fs = new Filesystem;
- $shortPath = $fs->findShortestPath(getcwd(), $packagePath, true);
- $io->writeError('Created: ', false);
- $io->write(strlen($shortPath) < strlen($packagePath) ? $shortPath : $packagePath);
- 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();
- $repo = 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)));
- $repo = new CompositeRepository($defaultRepos);
- }
- $packages = $repo->findPackages($packageName, $version);
- 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'),
- 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') && null !== $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') ?: trim(getenv('COMPOSER')) ?: 'composer.json');
- if ($configFile === 'composer.json' && !file_exists($configFile) && realpath(getcwd()) === realpath($this->config->get('home'))) {
- file_put_contents($configFile, "{\n}\n");
- }
- $this->configFile = new JsonFile($configFile);
- $this->configSource = new JsonConfigSource($this->configFile);
- $authConfigFile = $input->getOption('global')
- ? ($this->config->get('home') . '/auth.json')
- : dirname(realpath($configFile)) . '/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'];
- $match = false;
- foreach ($bits as $bit) {
- $key = isset($key) ? $key.'.'.$bit : $bit;
- $match = false;
- if (isset($data[$key])) {
- $match = true;
- $data = $data[$key];
- unset($key);
- }
- }
- if (!$match) {
- throw new \RuntimeException($settingKey.' is not defined.');
- }
- $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; }),
- 'archive-dir' => array('is_string', function ($val) { return $val; }),
- 'archive-format' => 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),
- 'prefer-stable' => array($booleanValidator, $booleanNormalizer),
- 'minimum-stability' => array(
- function ($val) { return in_array($val, array('dev', 'alpha', 'beta', 'RC', 'stable'), true); },
- function ($val) { return $val; },
- ),
- );
- $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('/^platform\.(.+)/', $settingKey, $matches)) {
- if ($input->getOption('unset')) {
- return $this->configSource->removeConfigSetting($settingKey);
- }
- return $this->configSource->addConfigSetting($settingKey, $values[0]);
- }
- 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;
- $io = $this->getIO();
- 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);
- $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) {
- $io->write('[<comment>' . $k . $key . '</comment>] <info>' . $rawVal . ' (' . $value . ')</info>');
- } else {
- $io->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();
- $io = $this->getIO();
- $this->updatePreferredOptions($config, $input, $preferSource, $preferDist, true);
- if ($input->getOption('no-custom-installers')) {
- $io->writeError('<warning>You are using the deprecated option "no-custom-installers". Use "no-plugins" instead.</warning>');
- $input->setOption('no-plugins', true);
- }
- return $this->installProject(
- $io,
- $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);
- $composer->getDownloadManager()->setOutputProgress(!$noProgress);
- $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);
- }
- if (function_exists('pcntl_signal')) {
- declare (ticks = 100);
- pcntl_signal(SIGINT, function () use ($directory) {
- $fs = new Filesystem();
- $fs->removeDirectory($directory);
- exit(130);
- });
- }
- $io->writeError('<info>Installing ' . $package->getName() . ' (' . $package->getFullPrettyVersion(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($io);
- $installedFromVcs = 'source' === $package->getInstallationSource();
- $io->writeError('<info>Created project in ' . $directory . '</info>');
- chdir($directory);
- $_SERVER['COMPOSER_ROOT_VERSION'] = $package->getPrettyVersion();
- putenv('COMPOSER_ROOT_VERSION='.$_SERVER['COMPOSER_ROOT_VERSION']);
- 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, $keepVcsRequiresPreferSource = false)
- {
- $preferSource = false;
- $preferDist = false;
- 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') || ($keepVcsRequiresPreferSource && $input->getOption('keep-vcs'))) {
- $preferSource = $input->getOption('prefer-source') || ($keepVcsRequiresPreferSource && $input->getOption('keep-vcs'));
- $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();
- $io = $this->getIO();
- 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);
- $io->write($messages);
- } else {
- $io->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);
- $io = $this->getIO();
- if ($composer) {
- $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'diagnose', $input, $output);
- $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
- $io->write('Checking composer.json: ', false);
- $this->outputResult($this->checkComposerSchema());
- }
- if ($composer) {
- $config = $composer->getConfig();
- } else {
- $config = Factory::createConfig();
- }
- $this->rfs = new RemoteFilesystem($io, $config);
- $this->process = new ProcessExecutor($io);
- $io->write('Checking platform settings: ', false);
- $this->outputResult($this->checkPlatform());
- $io->write('Checking git settings: ', false);
- $this->outputResult($this->checkGit());
- $io->write('Checking http connectivity to packagist: ', false);
- $this->outputResult($this->checkHttp('http'));
- $io->write('Checking https connectivity to packagist: ', false);
- $this->outputResult($this->checkHttp('https'));
- $opts = stream_context_get_options(StreamContextFactory::getContext('http://example.org'));
- if (!empty($opts['http']['proxy'])) {
- $io->write('Checking HTTP proxy: ', false);
- $this->outputResult($this->checkHttpProxy());
- $io->write('Checking HTTP proxy support for request_fulluri: ', false);
- $this->outputResult($this->checkHttpProxyFullUriRequestParam());
- $io->write('Checking HTTPS proxy support for request_fulluri: ', false);
- $this->outputResult($this->checkHttpsProxyFullUriRequestParam());
- }
- if ($oauth = $config->get('github-oauth')) {
- foreach ($oauth as $domain => $token) {
- $io->write('Checking '.$domain.' oauth access: ', false);
- $this->outputResult($this->checkGithubOauth($domain, $token));
- }
- } else {
- $io->write('Checking github.com rate limit: ', false);
- try {
- $rate = $this->getGithubRateLimit('github.com');
- $this->outputResult(true);
- if (10 > $rate['remaining']) {
- $io->write('<warning>WARNING</warning>');
- $io->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']
- ));
- }
- } catch (\Exception $e) {
- if ($e instanceof TransportException && $e->getCode() === 401) {
- $this->outputResult('<comment>The oauth token for github.com seems invalid, run "composer config --global --unset github-oauth.github.com" to remove it</comment>');
- } else {
- $this->outputResult($e);
- }
- }
- }
- $io->write('Checking disk free space: ', false);
- $this->outputResult($this->checkDiskSpace($config));
- $io->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($proto)
- {
- try {
- $this->rfs->getContents('packagist.org', $proto . '://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');
- }
- $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'];
- }
- 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)
- {
- $io = $this->getIO();
- if (true === $result) {
- $io->write('<info>OK</info>');
- } else {
- $this->failures++;
- $io->write('<error>FAIL</error>');
- if ($result instanceof \Exception) {
- $io->write('['.get_class($result).'] '.$result->getMessage());
- } elseif ($result) {
- $io->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 (!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 (PHP_VERSION_ID < 50302) {
- $errors['php'] = PHP_VERSION;
- }
- if (!isset($errors['php']) && PHP_VERSION_ID < 50304) {
- $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 '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('classmap-authoritative', 'a', InputOption::VALUE_NONE, 'Autoload classes from the classmap only. Implicitly enables `--optimize`.'),
- 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');
- $authoritative = $input->getOption('classmap-authoritative') || $config->get('classmap-authoritative');
- if ($optimize || $authoritative) {
- $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->setClassMapAuthoritative($authoritative);
- $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;
- use Composer\Factory;
- use Composer\Package\CompletePackageInterface;
- use Composer\Repository\RepositoryInterface;
- use Composer\Repository\ArrayRepository;
- 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();
- $io = $this->getIO();
- $return = 0;
- foreach ($input->getArgument('packages') as $packageName) {
- $handled = false;
- $packageExists = false;
- foreach ($repos as $repo) {
- foreach ($repo->findPackages($packageName) as $package) {
- $packageExists = true;
- if ($this->handlePackage($package, $input->getOption('homepage'), $input->getOption('show'))) {
- $handled = true;
- break 2;
- }
- }
- }
- if (!$packageExists) {
- $return = 1;
- $io->writeError('<warning>Package '.$packageName.' not found</warning>');
- }
- if (!$handled) {
- $return = 1;
- $io->writeError('<warning>'.($input->getOption('homepage') ? 'Invalid or missing homepage' : 'Invalid or missing repository URL').' for '.$packageName.'</warning>');
- }
- }
- return $return;
- }
- private function handlePackage(CompletePackageInterface $package, $showHomepage, $showOnly)
- {
- $support = $package->getSupport();
- $url = isset($support['source']) ? $support['source'] : $package->getSourceUrl();
- if (!$url || $showHomepage) {
- $url = $package->getHomepage();
- }
- if (!$url || !filter_var($url, FILTER_VALIDATE_URL)) {
- return false;
- }
- if ($showOnly) {
- $this->getIO()->write(sprintf('<info>%s</info>', $url));
- } else {
- $this->openBrowser($url);
- }
- return true;
- }
- 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_merge(
- array(new ArrayRepository(array($composer->getPackage()))),
- array($composer->getRepositoryManager()->getLocalRepository()),
- $composer->getRepositoryManager()->getRepositories()
- );
- }
- $defaultRepos = Factory::createDefaultRepositories($this->getIO());
- return $defaultRepos;
- }
- }
- <?php
- namespace Composer\Command;
- use Composer\DependencyResolver\Pool;
- use Composer\Json\JsonFile;
- use Composer\Factory;
- use Composer\Package\BasePackage;
- use Composer\Package\Version\VersionParser;
- use Composer\Package\Version\VersionSelector;
- use Composer\Repository\CompositeRepository;
- use Composer\Repository\PlatformRepository;
- 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;
- 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('type', null, InputOption::VALUE_OPTIONAL, 'Type 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)
- {
- $whitelist = array('name', 'description', 'author', 'type', '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);
- $io = $this->getIO();
- if ($input->isInteractive()) {
- $io->writeError(array('', $json, ''));
- if (!$io->askConfirmation('Do you confirm generation [<comment>yes</comment>]? ', true)) {
- $io->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 ($io->askConfirmation($question, true)) {
- $this->addVendorIgnore($ignoreFile);
- }
- }
- }
- }
- protected function interact(InputInterface $input, OutputInterface $output)
- {
- $git = $this->getGitConfig();
- $io = $this->getIO();
- $formatter = $this->getHelperSet()->get('formatter');
- $io->writeError(array(
- '',
- $formatter->formatBlock('Welcome to the Composer config generator', 'bg=blue;fg=white', true),
- '',
- ));
- $io->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 = $io->askAndValidate(
- 'Package name (<vendor>/<name>) [<comment>'.$name.'</comment>]: ',
- 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;
- },
- null,
- $name
- );
- $input->setOption('name', $name);
- $description = $input->getOption('description') ?: false;
- $description = $io->ask(
- 'Description [<comment>'.$description.'</comment>]: ',
- $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 = $io->askAndValidate(
- 'Author [<comment>'.$author.'</comment>]: ',
- function ($value) use ($self, $author) {
- $value = $value ?: $author;
- $author = $self->parseAuthorString($value);
- return sprintf('%s <%s>', $author['name'], $author['email']);
- },
- null,
- $author
- );
- $input->setOption('author', $author);
- $minimumStability = $input->getOption('stability') ?: null;
- $minimumStability = $io->askAndValidate(
- 'Minimum Stability [<comment>'.$minimumStability.'</comment>]: ',
- 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;
- },
- null,
- $minimumStability
- );
- $input->setOption('stability', $minimumStability);
- $type = $input->getOption('type') ?: false;
- $type = $io->ask(
- 'Package Type [<comment>'.$type.'</comment>]: ',
- $type
- );
- $input->setOption('type', $type);
- $license = $input->getOption('license') ?: false;
- $license = $io->ask(
- 'License [<comment>'.$license.'</comment>]: ',
- $license
- );
- $input->setOption('license', $license);
- $io->writeError(array('', 'Define your dependencies.', ''));
- $question = 'Would you like to define your dependencies (require) interactively [<comment>yes</comment>]? ';
- $requirements = array();
- if ($io->askConfirmation($question, true)) {
- $requirements = $this->determineRequirements($input, $output, $input->getOption('require'));
- }
- $input->setOption('require', $requirements);
- $question = 'Would you like to define your dev dependencies (require-dev) interactively [<comment>yes</comment>]? ';
- $devRequirements = array();
- if ($io->askConfirmation($question, true)) {
- $devRequirements = $this->determineRequirements($input, $output, $input->getOption('require-dev'));
- }
- $input->setOption('require-dev', $devRequirements);
- }
- public function parseAuthorString($author)
- {
- if (preg_match('/^(?P<name>[- \.,\p{L}\p{N}\'’]+) <(?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 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())
- {
- if ($requires) {
- $requires = $this->normalizeRequirements($requires);
- $result = array();
- $io = $this->getIO();
- foreach ($requires as $requirement) {
- if (!isset($requirement['version'])) {
- $version = $this->findBestVersionForPackage($input, $requirement['name']);
- $requirement['version'] = $version;
- $io->writeError(sprintf(
- 'Using version <info>%s</info> for <info>%s</info>',
- $requirement['version'],
- $requirement['name']
- ));
- }
- $result[] = $requirement['name'] . ' ' . $requirement['version'];
- }
- return $result;
- }
- $versionParser = new VersionParser();
- $io = $this->getIO();
- while (null !== $package = $io->ask('Search for a package: ')) {
- $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) {
- $io->writeError(array(
- '',
- sprintf('Found <info>%s</info> packages matching <info>%s</info>', count($matches), $package),
- '',
- ));
- $io->writeError($choices);
- $io->writeError('');
- $validator = function ($selection) use ($matches, $versionParser) {
- if ('' === $selection) {
- return false;
- }
- if (is_numeric($selection) && isset($matches[(int) $selection])) {
- $package = $matches[(int) $selection];
- return $package['name'];
- }
- if (preg_match('{^\s*(?P<name>[\S/]+)(?:\s+(?P<version>\S+))?\s*$}', $selection, $packageMatches)) {
- if (isset($packageMatches['version'])) {
- $versionParser->parseConstraints($packageMatches['version']);
- return $packageMatches['name'].' '.$packageMatches['version'];
- }
- return $packageMatches['name'];
- }
- throw new \Exception('Not a valid selection');
- };
- $package = $io->askAndValidate(
- 'Enter package # to add, or the complete package name if it is not listed: ',
- $validator,
- 3,
- false
- );
- }
- if (false !== $package && false === strpos($package, ' ')) {
- $validator = function ($input) {
- $input = trim($input);
- return $input ?: false;
- };
- $constraint = $io->askAndValidate(
- 'Enter the version constraint to require (or leave blank to use the latest version): ',
- $validator,
- 3,
- false
- );
- if (false === $constraint) {
- $constraint = $this->findBestVersionForPackage($input, $package);
- $io->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 (PHP_VERSION_ID < 50303) {
- 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('classmap-authoritative', 'a', InputOption::VALUE_NONE, 'Autoload classes from the classmap only. Implicitly enables `--optimize-autoloader`.'),
- 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)
- {
- $io = $this->getIO();
- if ($args = $input->getArgument('packages')) {
- $io->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')) {
- $io->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')) {
- $io->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'));
- $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');
- $authoritative = $input->getOption('classmap-authoritative') || $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)
- ->setClassMapAuthoritative($authoritative)
- ->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\Plugin\CommandEvent;
- use Composer\Plugin\PluginEvents;
- use Composer\Package\PackageInterface;
- use Composer\Repository\RepositoryInterface;
- use Symfony\Component\Console\Helper\Table;
- 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();
- if ($input->getOption('no-dev')) {
- $packages = $this->filterRequiredPackages($repo, $root);
- } else {
- $packages = $this->appendPackages($repo->getPackages(), array());
- }
- ksort($packages);
- $io = $this->getIO();
- switch ($format = $input->getOption('format')) {
- case 'text':
- $io->write('Name: <comment>'.$root->getPrettyName().'</comment>');
- $io->write('Version: <comment>'.$root->getFullPrettyVersion().'</comment>');
- $io->write('Licenses: <comment>'.(implode(', ', $root->getLicense()) ?: 'none').'</comment>');
- $io->write('Dependencies:');
- $io->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(),
- $package->getFullPrettyVersion(),
- implode(', ', $package->getLicense()) ?: 'none',
- ));
- }
- $table->render();
- break;
- case 'json':
- foreach ($packages as $package) {
- $dependencies[$package->getPrettyName()] = array(
- 'version' => $package->getFullPrettyVersion(),
- 'license' => $package->getLicense(),
- );
- }
- $io->write(JsonFile::encode(array(
- 'name' => $root->getPrettyName(),
- 'version' => $root->getFullPrettyVersion(),
- '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).'),
- new InputOption('optimize-autoloader', 'o', InputOption::VALUE_NONE, 'Optimize autoloader during autoloader dump'),
- new InputOption('classmap-authoritative', 'a', InputOption::VALUE_NONE, 'Autoload classes from the classmap only. Implicitly enables `--optimize-autoloader`.'),
- ))
- ->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';
- $io = $this->getIO();
- foreach ($packages as $package) {
- if (isset($composer[$type][$package])) {
- $json->removeLink($type, $package);
- } elseif (isset($composer[$altType][$package])) {
- $io->writeError('<warning>'.$package.' could not be found in '.$type.' but it is present in '.$altType.'</warning>');
- if ($io->isInteractive()) {
- if ($io->askConfirmation('Do you want to remove it from '.$altType.' [<comment>yes</comment>]? ', true)) {
- $json->removeLink($altType, $package);
- }
- }
- } else {
- $io->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'));
- $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');
- $optimize = $input->getOption('optimize-autoloader') || $composer->getConfig()->get('optimize-autoloader');
- $authoritative = $input->getOption('classmap-authoritative') || $composer->getConfig()->get('classmap-authoritative');
- $install
- ->setVerbose($input->getOption('verbose'))
- ->setDevMode($updateDevMode)
- ->setOptimizeAutoloader($optimize)
- ->setClassMapAuthoritative($authoritative)
- ->setUpdate(true)
- ->setUpdateWhitelist($packages)
- ->setWhitelistDependencies($input->getOption('update-with-dependencies'))
- ->setIgnorePlatformRequirements($input->getOption('ignore-platform-reqs'))
- ;
- $status = $install->run();
- if ($status !== 0) {
- $io->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\Semver\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'),
- new InputOption('optimize-autoloader', 'o', InputOption::VALUE_NONE, 'Optimize autoloader during autoloader dump'),
- new InputOption('classmap-authoritative', 'a', InputOption::VALUE_NONE, 'Autoload classes from the classmap only. Implicitly enables `--optimize-autoloader`.'),
- ))
- ->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();
- $io = $this->getIO();
- $newlyCreated = !file_exists($file);
- if (!file_exists($file) && !file_put_contents($file, "{\n}\n")) {
- $io->writeError('<error>'.$file.' could not be created.</error>');
- return 1;
- }
- if (!is_readable($file)) {
- $io->writeError('<error>'.$file.' is not readable.</error>');
- return 1;
- }
- if (!is_writable($file)) {
- $io->writeError('<error>'.$file.' is not writable.</error>');
- return 1;
- }
- if (filesize($file) === 0) {
- file_put_contents($file, "{\n}\n");
- }
- $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);
- }
- $io->writeError('<info>'.$file.' has been '.($newlyCreated ? 'created' : 'updated').'</info>');
- if ($input->getOption('no-update')) {
- return 0;
- }
- $updateDevMode = !$input->getOption('update-no-dev');
- $optimize = $input->getOption('optimize-autoloader') || $composer->getConfig()->get('optimize-autoloader');
- $authoritative = $input->getOption('classmap-authoritative') || $composer->getConfig()->get('classmap-authoritative');
- $this->resetComposer();
- $composer = $this->getComposer();
- $composer->getDownloadManager()->setOutputProgress(!$input->getOption('no-progress'));
- $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)
- ->setOptimizeAutoloader($optimize)
- ->setClassMapAuthoritative($authoritative)
- ->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) {
- $io->writeError("\n".'<error>Installation failed, deleting '.$file.'.</error>');
- unlink($json->getPath());
- } else {
- $io->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)) {
- $_SERVER['PATH'] = realpath($binDir).PATH_SEPARATOR.getenv('PATH');
- putenv('PATH='.$_SERVER['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;
- }
- $io = $this->getIO();
- $io->writeError('<info>scripts:</info>');
- foreach ($scripts as $name => $script) {
- $io->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)) {
- $_SERVER['PATH'] = realpath($binDir).PATH_SEPARATOR.getenv('PATH');
- putenv('PATH='.$_SERVER['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;
- $io = $this->getIO();
- 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($io);
- $io->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) {
- $io->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();
- $io = $this->getIO();
- $remoteFilesystem = new RemoteFilesystem($io, $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) {
- $io->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) {
- $io->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
- );
- $io->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)) {
- $io->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;
- $io->writeError('<info>Removing: '.$file.'</info>');
- $fs->remove($file);
- }
- }
- if ($err = $this->setLocalPhar($localFilename, $tempFilename, $backupFile)) {
- $io->writeError('<error>The file is corrupted ('.$err->getMessage().').</error>');
- $io->writeError('<error>Please re-run the self-update command to try again.</error>');
- return 1;
- }
- if (file_exists($backupFile)) {
- $io->writeError('Use <info>composer self-update --rollback</info> to return to version '.Composer::VERSION);
- } else {
- $io->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;
- $io = $this->getIO();
- $io->writeError(sprintf("Rolling back to version <info>%s</info>.", $rollbackVersion));
- if ($err = $this->setLocalPhar($localFilename, $oldFile)) {
- $io->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\Semver\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;
- use Composer\Spdx\SpdxLicenses;
- 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);
- $io = $this->getIO();
- 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($io);
- $repos = new CompositeRepository($defaultRepos);
- $io->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($io);
- $io->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($package, $versions, $installedRepo);
- $this->printLinks($package, 'requires');
- $this->printLinks($package, 'devRequires', 'requires (dev)');
- if ($package->getSuggests()) {
- $io->write("\n<info>suggests</info>");
- foreach ($package->getSuggests() as $suggested => $reason) {
- $io->write($suggested . ' <comment>' . $reason . '</comment>');
- }
- }
- $this->printLinks($package, 'provides');
- $this->printLinks($package, 'conflicts');
- $this->printLinks($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) {
- $io->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($package->getFullPrettyVersion()));
- } else {
- $nameLength = max($nameLength, $package);
- }
- }
- list($width) = $this->getApplication()->getTerminalDimensions();
- if (null === $width) {
-
- $width = PHP_INT_MAX;
- }
- if (defined('PHP_WINDOWS_VERSION_BUILD')) {
- $width--;
- }
- if ($input->getOption('path') && null === $composer) {
- $io->writeError('No composer.json found in the current directory, disabling "path" option');
- $input->setOption('path', false);
- }
- $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($package->getFullPrettyVersion(), $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);
- }
- $io->write('');
- }
- if ($tree) {
- $io->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 && $preferred = $policy->selectPreferredPackages($pool, array(), $matches)) {
- $matchedPackage = $pool->literalToPackage($preferred[0]);
- }
- return array($matchedPackage, $versions);
- }
- protected function printMeta(CompletePackageInterface $package, array $versions, RepositoryInterface $installedRepo)
- {
- $io = $this->getIO();
- $io->write('<info>name</info> : ' . $package->getPrettyName());
- $io->write('<info>descrip.</info> : ' . $package->getDescription());
- $io->write('<info>keywords</info> : ' . join(', ', $package->getKeywords() ?: array()));
- $this->printVersions($package, $versions, $installedRepo);
- $io->write('<info>type</info> : ' . $package->getType());
- $this->printLicenses($package);
- $io->write('<info>source</info> : ' . sprintf('[%s] <comment>%s</comment> %s', $package->getSourceType(), $package->getSourceUrl(), $package->getSourceReference()));
- $io->write('<info>dist</info> : ' . sprintf('[%s] <comment>%s</comment> %s', $package->getDistType(), $package->getDistUrl(), $package->getDistReference()));
- $io->write('<info>names</info> : ' . implode(', ', $package->getNames()));
- if ($package->isAbandoned()) {
- $replacement = ($package->getReplacementPackage() !== null)
- ? ' The author suggests using the ' . $package->getReplacementPackage(). ' package instead.'
- : null;
- $io->writeError(
- sprintf('<warning>Attention: This package is abandoned and no longer maintained.%s</warning>', $replacement)
- );
- }
- if ($package->getSupport()) {
- $io->write("\n<info>support</info>");
- foreach ($package->getSupport() as $type => $value) {
- $io->write('<comment>' . $type . '</comment> : '.$value);
- }
- }
- if ($package->getAutoload()) {
- $io->write("\n<info>autoload</info>");
- foreach ($package->getAutoload() as $type => $autoloads) {
- $io->write('<comment>' . $type . '</comment>');
- if ($type === 'psr-0') {
- foreach ($autoloads as $name => $path) {
- $io->write(($name ?: '*') . ' => ' . (is_array($path) ? implode(', ', $path) : ($path ?: '.')));
- }
- } elseif ($type === 'psr-4') {
- foreach ($autoloads as $name => $path) {
- $io->write(($name ?: '*') . ' => ' . (is_array($path) ? implode(', ', $path) : ($path ?: '.')));
- }
- } elseif ($type === 'classmap') {
- $io->write(implode(', ', $autoloads));
- }
- }
- if ($package->getIncludePaths()) {
- $io->write('<comment>include-path</comment>');
- $io->write(implode(', ', $package->getIncludePaths()));
- }
- }
- }
- protected function printVersions(CompletePackageInterface $package, array $versions, RepositoryInterface $installedRepo)
- {
- 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(CompletePackageInterface $package, $linkType, $title = null)
- {
- $title = $title ?: $linkType;
- $io = $this->getIO();
- if ($links = $package->{'get'.ucfirst($linkType)}()) {
- $io->write("\n<info>" . $title . "</info>");
- foreach ($links as $link) {
- $io->write($link->getTarget() . ' <comment>' . $link->getPrettyConstraint() . '</comment>');
- }
- }
- }
- protected function printLicenses(CompletePackageInterface $package)
- {
- $spdxLicenses = new SpdxLicenses();
- $licenses = $package->getLicense();
- $io = $this->getIO();
- foreach ($licenses as $licenseId) {
- $license = $spdxLicenses->getLicenseByIdentifier($licenseId);
- if (!$license) {
- $out = $licenseId;
- } else {
- if ($license[1] === true) {
- $out = sprintf('%s (%s) (OSI approved) %s', $license[0], $licenseId, $license[2]);
- } else {
- $out = sprintf('%s (%s) %s', $license[0], $licenseId, $license[2]);
- }
- }
- $io->write('<info>license</info> : ' . $out);
- }
- }
- }
- <?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();
- $io = $this->getIO();
- foreach ($installedRepo->getPackages() as $package) {
- $downloader = $dm->getDownloaderForInstalledPackage($package);
- if ($downloader instanceof ChangeReportInterface) {
- $targetDir = $im->getInstallPath($package);
- if (is_link($targetDir)) {
- $errors[$targetDir] = $targetDir . ' is a symbolic link.';
- }
- if ($changes = $downloader->getLocalChanges($package, $targetDir)) {
- $errors[$targetDir] = $changes;
- }
- }
- }
- if (!$errors) {
- $io->writeError('<info>No local changes</info>');
- } else {
- $io->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)));
- $io->write('<info>'.$path.'</info>:');
- $io->write($indentedChanges);
- } else {
- $io->write($path);
- }
- }
- if ($errors && !$input->getOption('verbose')) {
- $io->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 Symfony\Component\Console\Input\InputArgument;
- use Symfony\Component\Console\Input\InputInterface;
- use Symfony\Component\Console\Input\InputOption;
- use Symfony\Component\Console\Output\OutputInterface;
- class SuggestsCommand extends Command
- {
- protected function configure()
- {
- $this
- ->setName('suggests')
- ->setDescription('Show package suggestions')
- ->setDefinition(array(
- new InputOption('no-dev', null, InputOption::VALUE_NONE, 'Exclude suggestions from require-dev packages'),
- new InputArgument('packages', InputArgument::IS_ARRAY | InputArgument::OPTIONAL, 'Packages that you want to list suggestions from.'),
- ))
- ->setHelp(<<<EOT
- The <info>%command.name%</info> command shows suggested packages.
- With <info>-v</info> you also see which package suggested it and why.
- EOT
- )
- ;
- }
- protected function execute(InputInterface $input, OutputInterface $output)
- {
- $lock = $this->getComposer()->getLocker()->getLockData();
- if (empty($lock)) {
- throw new \RuntimeException('Lockfile seems to be empty?');
- }
- $packages = $lock['packages'];
- if (!$input->getOption('no-dev')) {
- $packages += $lock['packages-dev'];
- }
- $filter = $input->getArgument('packages');
- foreach ($packages as $package) {
- if (empty($package['suggest'])) {
- continue;
- }
- if (!empty($filter) && !in_array($package['name'], $filter)) {
- continue;
- }
- $this->printSuggestions($packages, $package['name'], $package['suggest']);
- }
- }
- protected function printSuggestions($installed, $source, $suggestions)
- {
- foreach ($suggestions as $suggestion => $reason) {
- foreach ($installed as $package) {
- if ($package['name'] === $suggestion) {
- continue 2;
- }
- }
- if (empty($reason)) {
- $reason = '*';
- }
- $this->printSuggestion($source, $suggestion, $reason);
- }
- }
- protected function printSuggestion($package, $suggestion, $reason)
- {
- $io = $this->getIO();
- if ($io->isVerbose()) {
- $io->write(sprintf('<comment>%s</comment> suggests <info>%s</info>: %s', $package, $suggestion, $reason));
- } else {
- $io->write(sprintf('<info>%s</info>', $suggestion));
- }
- }
- }
- <?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('classmap-authoritative', 'a', InputOption::VALUE_NONE, 'Autoload classes from the classmap only. Implicitly enables `--optimize-autoloader`.'),
- 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)
- {
- $io = $this->getIO();
- if ($input->getOption('no-custom-installers')) {
- $io->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')) {
- $io->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'));
- $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');
- $authoritative = $input->getOption('classmap-authoritative') || $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)
- ->setClassMapAuthoritative($authoritative)
- ->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\Factory;
- 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 and composer.lock')
- ->setDefinition(array(
- new InputOption('no-check-all', null, InputOption::VALUE_NONE, 'Do not make a complete validation'),
- new InputOption('no-check-lock', null, InputOption::VALUE_NONE, 'Do not check if lock file is up to date'),
- new InputOption('no-check-publish', null, InputOption::VALUE_NONE, 'Do not check for publish errors'),
- new InputOption('with-dependencies', 'A', InputOption::VALUE_NONE, 'Also validate the composer.json of all installed dependencies'),
- new InputOption('strict', null, InputOption::VALUE_NONE, 'Return a non-zero exit code for warnings as well as errors'),
- new InputArgument('file', InputArgument::OPTIONAL, 'path to composer.json file', './composer.json'),
- ))
- ->setHelp(<<<EOT
- The validate command validates a given composer.json and composer.lock
- Exit codes in case of errors are:
- 1 validation warning(s), only when --strict is given
- 2 validation error(s)
- 3 file unreadable or missing
- EOT
- );
- }
- protected function execute(InputInterface $input, OutputInterface $output)
- {
- $file = $input->getArgument('file');
- $io = $this->getIO();
- if (!file_exists($file)) {
- $io->writeError('<error>' . $file . ' not found.</error>');
- return 3;
- }
- if (!is_readable($file)) {
- $io->writeError('<error>' . $file . ' is not readable.</error>');
- return 3;
- }
- $validator = new ConfigValidator($io);
- $checkAll = $input->getOption('no-check-all') ? 0 : ValidatingArrayLoader::CHECK_ALL;
- $checkPublish = !$input->getOption('no-check-publish');
- $checkLock = !$input->getOption('no-check-lock');
- $isStrict = $input->getOption('strict');
- list($errors, $publishErrors, $warnings) = $validator->validate($file, $checkAll);
- $lockErrors = array();
- $composer = Factory::create($io, $file);
- $locker = $composer->getLocker();
- if ($locker->isLocked() && !$locker->isFresh()) {
- $lockErrors[] = 'The lock file is not up to date with the latest changes in composer.json.';
- }
- $this->outputResult($io, $file, $errors, $warnings, $checkPublish, $publishErrors, $checkLock, $lockErrors, true);
- $exitCode = $errors || ($publishErrors && $checkPublish) || ($lockErrors && $checkLock) ? 2 : ($isStrict && $warnings ? 1 : 0);
- if ($input->getOption('with-dependencies')) {
- $localRepo = $composer->getRepositoryManager()->getLocalRepository();
- foreach ($localRepo->getPackages() as $package) {
- $path = $composer->getInstallationManager()->getInstallPath($package);
- $file = $path . '/composer.json';
- if (is_dir($path) && file_exists($file)) {
- list($errors, $publishErrors, $warnings) = $validator->validate($file, $checkAll);
- $this->outputResult($io, $package->getPrettyName(), $errors, $warnings, $checkPublish, $publishErrors);
- $depCode = $errors || ($publishErrors && $checkPublish) ? 2 : ($isStrict && $warnings ? 1 : 0);
- $exitCode = max($depCode, $exitCode);
- }
- }
- }
- return $exitCode;
- }
- private function outputResult($io, $name, &$errors, &$warnings, $checkPublish = false, $publishErrors = array(), $checkLock = false, $lockErrors = array(), $printSchemaUrl = false)
- {
- if (!$errors && !$publishErrors && !$warnings) {
- $io->write('<info>' . $name . ' is valid</info>');
- } elseif (!$errors && !$publishErrors) {
- $io->writeError('<info>' . $name . ' is valid, but with a few warnings</info>');
- if ($printSchemaUrl) {
- $io->writeError('<warning>See https://getcomposer.org/doc/04-schema.md for details on the schema</warning>');
- }
- } elseif (!$errors) {
- $io->writeError('<info>' . $name . ' is valid for simple usage with composer but has</info>');
- $io->writeError('<info>strict errors that make it unable to be published as a package:</info>');
- if ($printSchemaUrl) {
- $io->writeError('<warning>See https://getcomposer.org/doc/04-schema.md for details on the schema</warning>');
- }
- } else {
- $io->writeError('<error>' . $name . ' is invalid, the following errors/warnings were found:</error>');
- }
- if ($checkPublish) {
- $errors = array_merge($errors, $publishErrors);
- } else {
- $warnings = array_merge($warnings, $publishErrors);
- }
- if ($checkLock) {
- $errors = array_merge($errors, $lockErrors);
- } else {
- $warnings = array_merge($warnings, $lockErrors);
- }
- $messages = array(
- 'error' => $errors,
- 'warning' => $warnings,
- );
- foreach ($messages as $style => $msgs) {
- foreach ($msgs as $msg) {
- $io->writeError('<' . $style . '>' . $msg . '</' . $style . '>');
- }
- }
- }
- }
- <?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 = '4f934d928260e126b5d06392e12ee20fae258232';
- const BRANCH_ALIAS_VERSION = '1.0-dev';
- const RELEASE_DATE = '2015-10-26 15:01:06';
- 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;
- 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,
- 'store-auths' => 'prompt',
- 'platform' => array(),
- 'archive-format' => 'tar',
- 'archive-dir' => '.',
-
-
- );
- 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 == self::RELATIVE_PATHS) ? $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\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 (preg_match('{^(github-oauth|http-basic|platform)\.}', $key)) {
- 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 (preg_match('{^(github-oauth|http-basic|platform)\.}', $key)) {
- 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\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\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());
- }
- 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());
- ErrorHandler::register($this->io);
- $io = $this->getIO();
- if (PHP_VERSION_ID < 50302) {
- $io->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) {
- $io->writeError(sprintf('<warning>Warning: This development build of composer is over 60 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 ($io->isDebug() >= 4) {
- $io->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)) {
- $io->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)) {
- $io->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)
- {
- $io = $this->getIO();
- 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)
- ) {
- $io->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')) {
- $io->writeError('<error>The following exception may be caused by a stale entry in your cmd.exe AutoRun</error>');
- $io->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')) {
- $io->writeError('<error>The following exception is caused by a lack of memory and not having swap configured</error>');
- $io->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\SuggestsCommand();
- $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;
- }
- }
- <?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);
- $clearEscapeCodes = '(?:39|49|0|22|24|25|27|28)';
- return preg_replace_callback("{\033\[([0-9;]+)m(.*?)\033\[(?:".$clearEscapeCodes.";)*?".$clearEscapeCodes."m}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 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\Semver\Constraint\Constraint;
- 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 Constraint($operator, $b->getVersion());
- $version = new Constraint('==', $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)
- {
- return $this->selectPreferredPackages($pool, $installedMap, $literals, $requiredPackage);
- }
- public function selectPreferredPackages(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->pruneToHighestPriorityOrInstalled($pool, $installedMap, $literals);
- $literals = $this->pruneToBestVersion($pool, $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;
- use Composer\Package\PackageInterface;
- 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;
- use Composer\Package\PackageInterface;
- 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\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 $package->getFullPrettyVersion();
- }
- }
- <?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 selectPreferredPackages(Pool $pool, array $installedMap, array $literals);
- }
- <?php
- namespace Composer\DependencyResolver;
- use Composer\Package\BasePackage;
- use Composer\Package\AliasPackage;
- use Composer\Semver\VersionParser;
- use Composer\Semver\Constraint\ConstraintInterface;
- use Composer\Semver\Constraint\Constraint;
- use Composer\Semver\Constraint\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 implements \Countable
- {
- 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())
- {
- $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 count()
- {
- return count($this->packages);
- }
- public function whatProvides($name, ConstraintInterface $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 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, ConstraintInterface $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 Constraint('==', $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(spl_object_hash($rule), 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') {
- $available = $this->pool->whatProvides($job['packageName']);
- $version = count($available) ? $available[0]->getPrettyVersion() : phpversion();
- $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 ('. $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\Semver\Constraint\ConstraintInterface;
- class Request
- {
- protected $jobs;
- public function __construct()
- {
- $this->jobs = array();
- }
- public function install($packageName, ConstraintInterface $constraint = null)
- {
- $this->addJob($packageName, 'install', $constraint);
- }
- public function update($packageName, ConstraintInterface $constraint = null)
- {
- $this->addJob($packageName, 'update', $constraint);
- }
- public function remove($packageName, ConstraintInterface $constraint = null)
- {
- $this->addJob($packageName, 'remove', $constraint);
- }
- public function fix($packageName, ConstraintInterface $constraint = null)
- {
- $this->addJob($packageName, 'install', $constraint, true);
- }
- protected function addJob($packageName, $cmd, ConstraintInterface $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;
- const BITFIELD_TYPE = 0;
- const BITFIELD_REASON = 8;
- const BITFIELD_DISABLED = 16;
- public $literals;
- protected $bitfield;
- protected $reasonData;
- public function __construct(array $literals, $reason, $reasonData, $job = null)
- {
- sort($literals);
- $this->literals = $literals;
- $this->reasonData = $reasonData;
- if ($job) {
- $this->job = $job;
- }
- $this->bitfield = (0 << self::BITFIELD_DISABLED) |
- ($reason << self::BITFIELD_REASON) |
- (255 << self::BITFIELD_TYPE);
- }
- public function getHash()
- {
- $data = unpack('ihash', md5(implode(',', $this->literals), true));
- return $data['hash'];
- }
- public function getJob()
- {
- return isset($this->job) ? $this->job : null;
- }
- public function getReason()
- {
- return ($this->bitfield & (255 << self::BITFIELD_REASON)) >> self::BITFIELD_REASON;
- }
- public function getReasonData()
- {
- return $this->reasonData;
- }
- public function getRequiredPackage()
- {
- if ($this->getReason() === self::RULE_JOB_INSTALL) {
- return $this->reasonData;
- }
- if ($this->getReason() === self::RULE_PACKAGE_REQUIRES) {
- return $this->reasonData->getTarget();
- }
- }
- public function equals(Rule $rule)
- {
- 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->bitfield = ($this->bitfield & ~(255 << self::BITFIELD_TYPE)) | ((255 & $type) << self::BITFIELD_TYPE);
- }
- public function getType()
- {
- return ($this->bitfield & (255 << self::BITFIELD_TYPE)) >> self::BITFIELD_TYPE;
- }
- public function disable()
- {
- $this->bitfield = ($this->bitfield & ~(255 << self::BITFIELD_DISABLED)) | (1 << self::BITFIELD_DISABLED);
- }
- public function enable()
- {
- $this->bitfield = $this->bitfield & ~(255 << self::BITFIELD_DISABLED);
- }
- public function isDisabled()
- {
- return (bool) (($this->bitfield & (255 << self::BITFIELD_DISABLED)) >> self::BITFIELD_DISABLED);
- }
- public function isEnabled()
- {
- return !(($this->bitfield & (255 << self::BITFIELD_DISABLED)) >> self::BITFIELD_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->getReason()) {
- 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 ('. phpversion() .') or "config.platform.php" value 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(
- 255 => '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);
- $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[255]);
- 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 $jobs;
- 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);
- }
- public function getRuleSetSize()
- {
- return count($this->rules);
- }
- 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 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[spl_object_hash($newRule)] = $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->selectPreferredPackages($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 $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 $problem, Rule $conflictRule)
- {
- $why = spl_object_hash($conflictRule);
- 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(Rule $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(Rule $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[spl_object_hash($rule)];
- $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 <https://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) {
- if ($this->io->isDebug()) {
- $this->io->writeError(' Invalid zip file ('.$e->getMessage().'), retrying...');
- } else {
- $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();
- }
- } elseif ($package->getDistReference() && strpos($url, 'bitbucket.org')) {
- if (preg_match('{^https?://(?:www\.)?bitbucket\.org/([^/]+)/([^/]+)/get/(.+)\.(zip|tar\.gz|tar\.bz2)$}i', $url, $match)) {
- $url = 'https://bitbucket.org/' . $match[1] . '/'. $match[2] . '/get/' . $package->getDistReference() . '.' . $match[4];
- }
- }
- 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;
- 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\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\Config;
- use Composer\Cache;
- use Composer\IO\IOInterface;
- use Composer\Package\PackageInterface;
- 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>" . $package->getFullPrettyVersion() . "</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>" . $package->getFullPrettyVersion() . "</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\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 https://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,d,'.($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 'd':
- $this->viewDiff($path);
- 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',
- ' d - view local modifications (diff)',
- ));
- 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 viewDiff($path)
- {
- $path = $this->normalizePath($path);
- if (0 !== $this->process->execute('git diff HEAD', $output, $path)) {
- throw new \RuntimeException("Could not view diff\n\n:".$this->process->getErrorOutput());
- }
- $this->io->writeError($output);
- }
- 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 https://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\Package\PackageInterface;
- use Symfony\Component\Filesystem\Exception\IOException;
- use Symfony\Component\Filesystem\Filesystem;
- class PathDownloader extends FileDownloader
- {
- public function download(PackageInterface $package, $path)
- {
- $fileSystem = new Filesystem();
- $this->filesystem->removeDirectory($path);
- $this->io->writeError(sprintf(
- ' - Installing <info>%s</info> (<comment>%s</comment>)',
- $package->getName(),
- $package->getFullPrettyVersion()
- ));
- $url = $package->getDistUrl();
- $realUrl = realpath($url);
- if (false === $realUrl || !file_exists($realUrl) || !is_dir($realUrl)) {
- throw new \RuntimeException(sprintf(
- 'Path "%s" is not found',
- $url
- ));
- }
- try {
- $shortestPath = $this->filesystem->findShortestPath($path, $realUrl);
- $fileSystem->symlink($shortestPath, $path);
- $this->io->writeError(sprintf(' Symlinked from %s', $url));
- } catch (IOException $e) {
- $fileSystem->mirror($realUrl, $path);
- $this->io->writeError(sprintf(' Mirrored from %s', $url));
- }
- $this->io->writeError('');
- }
- }
- <?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_string(file_get_contents($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 https://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\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>" . $package->getFullPrettyVersion() . "</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 = $initial->getFullPrettyVersion();
- $to = $target->getFullPrettyVersion();
- }
- $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\CommandEvent;
- 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()));
- $exec = $callable . ($args === '' ? '' : ' '.$args);
- if ($this->io->isVerbose()) {
- $this->io->writeError(sprintf('> %s: %s', $event->getName(), $exec));
- } else {
- $this->io->writeError(sprintf('> %s', $exec));
- }
- if (0 !== ($exitCode = $this->process->execute($exec))) {
- $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);
- if ($this->io->isVerbose()) {
- $this->io->writeError(sprintf('> %s: %s::%s', $event->getName(), $className, $methodName));
- } else {
- $this->io->writeError(sprintf('> %s::%s', $className, $methodName));
- }
- 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\Package\Version\VersionGuesser;
- 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\Semver\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($config->get('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 https://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);
- }
- $dispatcher = new EventDispatcher($composer, $io);
- $composer->setEventDispatcher($dispatcher);
- $rm = $this->createRepositoryManager($io, $config, $dispatcher);
- $composer->setRepositoryManager($rm);
- $this->addLocalRepository($rm, $vendorDir);
- $parser = new VersionParser;
- $guesser = new VersionGuesser($config, new ProcessExecutor($io), $parser);
- $loader = new Package\Loader\RootPackageLoader($rm, $config, $parser, $guesser);
- $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, file_get_contents($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('svn', 'Composer\Repository\VcsRepository');
- $rm->setRepositoryClass('perforce', 'Composer\Repository\VcsRepository');
- $rm->setRepositoryClass('hg', 'Composer\Repository\VcsRepository');
- $rm->setRepositoryClass('artifact', 'Composer\Repository\ArtifactRepository');
- $rm->setRepositoryClass('path', 'Composer\Repository\PathRepository');
- 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));
- $dm->setDownloader('path', new Downloader\PathDownloader($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\IO;
- use Composer\Config;
- use Composer\Util\ProcessExecutor;
- 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 ($creds = $config->get('http-basic')) {
- foreach ($creds as $domain => $cred) {
- $this->setAuthentication($domain, $cred['username'], $cred['password']);
- }
- }
- ProcessExecutor::setTimeout((int) $config->get('process-timeout'));
- }
- }
- <?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\Console\Question\ConfirmationQuestion;
- use Symfony\Component\Console\Question\Question;
- 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() >= OutputInterface::VERBOSITY_VERY_VERBOSE;
- }
- public function isDebug()
- {
- return $this->output->getVerbosity() >= OutputInterface::VERBOSITY_DEBUG;
- }
- 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)
- {
- $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);
- }
- if ($stderr) {
- $this->lastMessageErr = $messages;
- } else {
- $this->lastMessage = $messages;
- }
- }
- public function ask($question, $default = null)
- {
- $output = $this->output;
- if ($output instanceof ConsoleOutputInterface) {
- $output = $output->getErrorOutput();
- }
- $helper = $this->helperSet->get('question');
- $question = new Question($question, $default);
- return $helper->ask($this->input, $output, $question);
- }
- public function askConfirmation($question, $default = true)
- {
- $output = $this->output;
- if ($output instanceof ConsoleOutputInterface) {
- $output = $output->getErrorOutput();
- }
- $helper = $this->helperSet->get('question');
- $question = new ConfirmationQuestion($question, $default);
- return $helper->ask($this->input, $output, $question);
- }
- public function askAndValidate($question, $validator, $attempts = null, $default = null)
- {
- $output = $this->output;
- if ($output instanceof ConsoleOutputInterface) {
- $output = $output->getErrorOutput();
- }
- $helper = $this->helperSet->get('question');
- $question = new Question($question, $default);
- $question->setValidator($validator);
- $question->setMaxAttempts($attempts);
- return $helper->ask($this->input, $output, $question);
- }
- public function askAndHideAnswer($question)
- {
- $this->writeError($question, false);
- return \Seld\CliPrompt\CliPrompt::hiddenPrompt(true);
- }
- }
- <?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 = null, $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;
- 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\PolicyInterface;
- 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\Semver\Constraint\Constraint;
- 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\Repository\WritableRepositoryInterface;
- 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 $classMapAuthoritative = 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();
- if (!$this->update && $this->locker->isLocked()) {
- $platformOverrides = $this->locker->getPlatformOverrides();
- } else {
- $platformOverrides = $this->config->get('platform') ?: array();
- }
- $platformRepo = new PlatformRepository(array(), $platformOverrides);
- $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) {
- if (!$this->dryRun) {
- $this->installationManager->notifyInstalls($this->io);
- }
- throw $e;
- }
- if (!$this->dryRun) {
- $this->installationManager->notifyInstalls($this->io);
- }
- 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(
- "<warning>Package %s is abandoned, you should avoid using it. %s.</warning>",
- $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($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,
- $this->config->get('platform') ?: array()
- );
- 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->setClassMapAuthoritative($this->classMapAuthoritative);
- $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 = !$this->update && $this->locker->isLocked();
-
-
- if ($installFromLock || (!empty($this->updateWhitelist) && $this->locker->isLocked())) {
- 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, $installFromLock ? $lockedRepository : null);
- $pool->addRepository($installedRepo, $aliases);
- if (!$installFromLock) {
- $repositories = $this->repositoryManager->getRepositories();
- foreach ($repositories as $repository) {
- $pool->addRepository($repository, $aliases);
- }
- }
-
-
- if ($lockedRepository) {
- $pool->addRepository($lockedRepository, $aliases);
- }
- $request = $this->createRequest($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 Constraint('=', $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) {
- $currentPackages = $this->getCurrentPackages($withDevReqs, $installedRepo);
- $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 Constraint('=', $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 Constraint('=', $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, $installedRepo, $lockedRepository, $installFromLock, $withDevReqs, '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());
- }
- if ($this->io->isVerbose()) {
- $this->io->writeError("Analyzed ".count($pool)." packages to resolve dependencies");
- $this->io->writeError("Analyzed ".$solver->getRuleSetSize()." rules to resolve dependencies");
- }
- $operations = $this->processDevPackages($localRepo, $pool, $policy, $repositories, $installedRepo, $lockedRepository, $installFromLock, $withDevReqs, '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->getTargetPackage()->getSourceReference() === $operation->getInitialPackage()->getSourceReference())
- && (!$operation->getTargetPackage()->getDistReference() || $operation->getTargetPackage()->getDistReference() === $operation->getInitialPackage()->getDistReference())
- ) {
- 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();
- }
- }
- if (!$this->dryRun) {
- $this->processPackageUrls($pool, $policy, $localRepo, $repositories);
- $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 Constraint('=', $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(RootPackageInterface $rootPackage, PlatformRepository $platformRepo)
- {
- $request = new Request();
- $constraint = new Constraint('=', $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 Constraint('=', $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, $installedRepo, $lockedRepository, $installFromLock, $withDevReqs, $task, array $operations = null)
- {
- if ($task === 'force-updates' && null === $operations) {
- throw new \InvalidArgumentException('Missing operations argument');
- }
- if ($task === 'force-links') {
- $operations = array();
- }
- if (!$installFromLock && $this->updateWhitelist) {
- $currentPackages = $this->getCurrentPackages($withDevReqs, $installedRepo);
- }
- 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)) {
- foreach ($currentPackages as $curPackage) {
- if ($curPackage->isDev() && $curPackage->getName() === $package->getName() && $curPackage->getVersion() === $package->getVersion()) {
- if ($task === 'force-links') {
- $package->setRequires($curPackage->getRequires());
- $package->setConflicts($curPackage->getConflicts());
- $package->setProvides($curPackage->getProvides());
- $package->setReplaces($curPackage->getReplaces());
- } elseif ($task === 'force-updates') {
- if (($curPackage->getSourceReference() && $curPackage->getSourceReference() !== $package->getSourceReference())
- || ($curPackage->getDistReference() && $curPackage->getDistReference() !== $package->getDistReference())
- ) {
- $operations[] = new UpdateOperation($package, $curPackage);
- }
- }
- break;
- }
- }
- continue;
- }
- $matches = $pool->whatProvides($package->getName(), new Constraint('=', $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->selectPreferredPackages($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 getCurrentPackages($withDevReqs, $installedRepo)
- {
- if ($this->locker->isLocked()) {
- try {
- return $this->locker->getLockedRepository($withDevReqs)->getPackages();
- } catch (\RuntimeException $e) {
- return $this->locker->getLockedRepository()->getPackages();
- }
- }
- return $installedRepo->getPackages();
- }
- 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 processPackageUrls($pool, $policy, $localRepo, $repositories)
- {
- if (!$this->update) {
- return;
- }
- foreach ($localRepo->getCanonicalPackages() as $package) {
- $matches = $pool->whatProvides($package->getName(), new Constraint('=', $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->selectPreferredPackages($pool, array(), $matches)) {
- $newPackage = $pool->literalToPackage($matches[0]);
- $sourceUrl = $package->getSourceUrl();
- $newSourceUrl = $newPackage->getSourceUrl();
- if ($sourceUrl !== $newSourceUrl) {
- $package->setSourceType($newPackage->getSourceType());
- $package->setSourceUrl($newSourceUrl);
- $package->setSourceReference($newPackage->getSourceReference());
- }
-
- if (preg_match('{^https?://(?:(?:www\.)?bitbucket\.org|(api\.)?github\.com)/}', $newPackage->getDistUrl())) {
- $package->setDistUrl($newPackage->getDistUrl());
- }
- }
- }
- }
- 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;
- if (!$this->optimizeAutoloader) {
-
- $this->setClassMapAuthoritative(false);
- }
- return $this;
- }
- public function setClassMapAuthoritative($classMapAuthoritative = false)
- {
- $this->classMapAuthoritative = (boolean) $classMapAuthoritative;
- if ($this->classMapAuthoritative) {
- $this->setOptimizeAutoloader(true);
- }
- 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\Installer;
- use Composer\IO\IOInterface;
- 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(IOInterface $io)
- {
- foreach ($this->notifiablePackages as $repoUrl => $packages) {
- $repositoryName = parse_url($repoUrl, PHP_URL_HOST);
- if ($io->hasAuthentication($repositoryName)) {
- $auth = $io->getAuthentication($repositoryName);
- $authStr = base64_encode($auth['username'] . ':' . $auth['password']);
- $authHeader = 'Authorization: Basic '.$authStr;
- }
- 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,
- ),
- );
- if (isset($authHeader)) {
- $opts['http']['header'][] = $authHeader;
- }
- $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,
- ),
- );
- if (isset($authHeader)) {
- $opts['http']['header'][] = $authHeader;
- }
- $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;
- use InvalidArgumentException;
- 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');
- }
- }
- if ((is_dir($this->binDir)) && ($this->filesystem->isDirEmpty($this->binDir))) {
- @rmdir($this->binDir);
- }
- }
- 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\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\IO\IOInterface;
- use Composer\Repository\InstalledRepositoryInterface;
- use Composer\Package\PackageInterface;
- class PluginInstaller extends LibraryInstaller
- {
- private $installationManager;
- 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\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 (PHP_VERSION_ID >= 50400) {
- $json = json_encode($data, $options);
- if (false === $json) {
- self::throwEncodeError(json_last_error());
- }
- 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);
- if (false === $json) {
- self::throwEncodeError(json_last_error());
- }
- $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;
- }
- private static function throwEncodeError($code)
- {
- switch ($code) {
- case JSON_ERROR_DEPTH:
- $msg = 'Maximum stack depth exceeded';
- break;
- case JSON_ERROR_STATE_MISMATCH:
- $msg = 'Underflow or the modes mismatch';
- break;
- case JSON_ERROR_CTRL_CHAR:
- $msg = 'Unexpected control character found';
- break;
- case JSON_ERROR_UTF8:
- $msg = 'Malformed UTF-8 characters, possibly incorrectly encoded';
- break;
- default:
- $msg = 'Unknown error';
- }
- throw new \RuntimeException('JSON encoding failed: '.$msg);
- }
- public static function parseJson($json, $file = null)
- {
- if (null === $json) {
- return;
- }
- $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;
- use Composer\Repository\PlatformRepository;
- 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);
- $this->sortPackages($requirements);
- $links = $this->format($requirements);
- }
- $this->contents = $matches[1] . $matches[2] . $links . $matches[4];
- return true;
- }
- private function sortPackages(array &$packages = array())
- {
- $prefix = function ($requirement) {
- if (preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $requirement)) {
- return preg_replace(
- array(
- '/^php/',
- '/^hhvm/',
- '/^ext/',
- '/^lib/',
- '/^\D/',
- ),
- array(
- '0-$0',
- '1-$0',
- '2-$0',
- '3-$0',
- '4-$0',
- ),
- $requirement
- );
- }
- return '5-'.$requirement;
- };
- uksort($packages, function ($a, $b) use ($prefix) {
- return strnatcmp($prefix($a), $prefix($b));
- });
- }
- 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);
- $subName = null;
- if (in_array($mainNode, array('config', 'repositories')) && false !== strpos($name, '.')) {
- list($name, $subName) = explode('.', $name, 2);
- }
- if (!isset($decoded[$mainNode])) {
- if ($subName !== null) {
- $this->addMainKey($mainNode, array($name => array($subName => $value)));
- } else {
- $this->addMainKey($mainNode, array($name => $value));
- }
- 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.'}')) {
- 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('{^([ \t]+)"}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\Semver\Constraint\Constraint;
- use Composer\Semver\VersionParser;
- class AliasPackage extends BasePackage implements CompletePackageInterface
- {
- protected $version;
- protected $prettyVersion;
- protected $dev;
- protected $aliasOf;
- protected $rootPackageAlias = false;
- protected $stability;
- protected $requires;
- protected $devRequires;
- 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', 'conflicts', 'provides', 'replaces') as $type) {
- $links = $aliasOf->{'get' . ucfirst($type)}();
- $this->$type = $this->replaceSelfVersionDependencies($links, $type);
- }
- }
- 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;
- }
- protected function replaceSelfVersionDependencies(array $links, $linkType)
- {
- if (in_array($linkType, array('conflicts', 'provides', 'replaces'), true)) {
- $newLinks = array();
- foreach ($links as $link) {
- if ('self.version' === $link->getPrettyConstraint()) {
- $newLinks[] = new Link($link->getSource(), $link->getTarget(), new Constraint('=', $this->version), $linkType, $this->prettyVersion);
- }
- }
- $links = array_merge($links, $newLinks);
- } else {
- foreach ($links as $index => $link) {
- if ('self.version' === $link->getPrettyConstraint()) {
- $links[$index] = new Link($link->getSource(), $link->getTarget(), new Constraint('=', $this->version), $linkType, $this->prettyVersion);
- }
- }
- }
- return $links;
- }
- 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\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();
- $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, $fileName = null)
- {
- 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();
- if (null === $fileName) {
- $packageName = $this->getPackageFilename($package);
- } else {
- $packageName = $fileName;
- }
- $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 getFullPrettyVersion($truncate = true)
- {
- if (!$this->isDev() || !in_array($this->getSourceType(), array('hg', 'git'))) {
- return $this->getPrettyVersion();
- }
- if ($truncate && strlen($this->getSourceReference()) === 40) {
- return $this->getPrettyVersion() . ' ' . substr($this->getSourceReference(), 0, 7);
- }
- return $this->getPrettyVersion() . ' ' . $this->getSourceReference();
- }
- 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\Semver\Constraint\ConstraintInterface;
- class Link
- {
- protected $source;
- protected $target;
- protected $constraint;
- protected $description;
- protected $prettyConstraint;
- public function __construct($source, $target, ConstraintInterface $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;
- use Composer\Semver\Constraint\EmptyConstraint as SemverEmptyConstraint;
- @trigger_error('The ' . __NAMESPACE__ . '\EmptyConstraint class is deprecated, use Composer\Semver\Constraint\EmptyConstraint instead.', E_USER_DEPRECATED);
- class EmptyConstraint extends SemverEmptyConstraint implements LinkConstraintInterface
- {
- }
- <?php
- namespace Composer\Package\LinkConstraint;
- use Composer\Semver\Constraint\ConstraintInterface;
- @trigger_error('The ' . __NAMESPACE__ . '\LinkConstraintInterface interface is deprecated, use Composer\Semver\Constraint\ConstraintInterface instead.', E_USER_DEPRECATED);
- interface LinkConstraintInterface extends ConstraintInterface
- {
- }
- <?php
- namespace Composer\Package\LinkConstraint;
- use Composer\Semver\Constraint\MultiConstraint as SemverMultiConstraint;
- @trigger_error('The ' . __NAMESPACE__ . '\MultiConstraint class is deprecated, use Composer\Semver\Constraint\MultiConstraint instead.', E_USER_DEPRECATED);
- class MultiConstraint extends SemverMultiConstraint implements LinkConstraintInterface
- {
- }
- <?php
- namespace Composer\Package\LinkConstraint;
- use Composer\Semver\Constraint\AbstractConstraint;
- @trigger_error('The ' . __NAMESPACE__ . '\SpecificConstraint abstract class is deprecated, use Composer\Semver\Constraint\AbstractConstraint instead.', E_USER_DEPRECATED);
- abstract class SpecificConstraint extends AbstractConstraint implements LinkConstraintInterface
- {
- }
- <?php
- namespace Composer\Package\LinkConstraint;
- use Composer\Semver\Constraint\Constraint;
- @trigger_error('The ' . __NAMESPACE__ . '\VersionConstraint class is deprecated, use Composer\Semver\Constraint\Constraint instead.', E_USER_DEPRECATED);
- class VersionConstraint extends Constraint implements LinkConstraintInterface
- {
- }
- <?php
- namespace Composer\Package\Loader;
- use Composer\Package;
- use Composer\Package\AliasPackage;
- use Composer\Package\Link;
- use Composer\Package\RootAliasPackage;
- use Composer\Package\RootPackageInterface;
- use Composer\Semver\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->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 = preg_match('/^\d++$/D', $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 parseLinks($source, $sourceVersion, $description, $links)
- {
- $res = array();
- foreach ($links as $target => $constraint) {
- if ('self.version' === $constraint) {
- $parsedConstraint = $this->versionParser->parseConstraints($sourceVersion);
- } else {
- $parsedConstraint = $this->versionParser->parseConstraints($constraint);
- }
- $res[strtolower($target)] = new Link($source, $target, $parsedConstraint, $description, $constraint);
- }
- return $res;
- }
- 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\VersionGuesser;
- use Composer\Semver\VersionParser;
- use Composer\Repository\RepositoryManager;
- use Composer\Util\ProcessExecutor;
- class RootPackageLoader extends ArrayLoader
- {
- private $manager;
- private $config;
- private $versionGuesser;
- public function __construct(RepositoryManager $manager, Config $config, VersionParser $parser = null, VersionGuesser $versionGuesser = null)
- {
- parent::__construct($parser);
- $this->manager = $manager;
- $this->config = $config;
- $this->versionGuesser = $versionGuesser ?: new VersionGuesser($config, new ProcessExecutor(), $this->versionParser);
- }
- public function load(array $config, $class = 'Composer\Package\RootPackage')
- {
- if (!isset($config['name'])) {
- $config['name'] = '__root__';
- }
- $autoVersioned = false;
- if (!isset($config['version'])) {
- if (getenv('COMPOSER_ROOT_VERSION')) {
- $version = getenv('COMPOSER_ROOT_VERSION');
- } else {
- $version = $this->versionGuesser->guessVersion($config, getcwd());
- }
- if (!$version) {
- $version = '1.0.0';
- $autoVersioned = true;
- }
- $config['version'] = $version;
- }
- $realPackage = $package = parent::load($config, $class);
- if ($realPackage instanceof AliasPackage) {
- $realPackage = $package->getAliasOf();
- }
- if ($autoVersioned) {
- $realPackage->replaceVersion($realPackage->getVersion(), 'No version set (parsed as 1.0.0)');
- }
- 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;
- }
- }
- <?php
- namespace Composer\Package\Loader;
- use Composer\Package;
- use Composer\Package\BasePackage;
- use Composer\Semver\Constraint\Constraint;
- use Composer\Semver\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', '[\p{N}\p{L} ._-]+');
- 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', 'docs') 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', 'docs') 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 Constraint('=', $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\Util\Git as GitUtil;
- use Composer\IO\IOInterface;
- use Seld\JsonLint\ParsingException;
- class Locker
- {
- private $lockFile;
- private $repositoryManager;
- private $installationManager;
- private $hash;
- private $contentHash;
- private $loader;
- private $dumper;
- private $process;
- private $lockDataCache;
- public function __construct(IOInterface $io, JsonFile $lockFile, RepositoryManager $repositoryManager, InstallationManager $installationManager, $composerFileContents)
- {
- $this->lockFile = $lockFile;
- $this->repositoryManager = $repositoryManager;
- $this->installationManager = $installationManager;
- $this->hash = md5($composerFileContents);
- $this->contentHash = $this->getContentHash($composerFileContents);
- $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();
- if (!empty($lock['content-hash'])) {
- return $this->contentHash === $lock['content-hash'];
- }
- 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();
- $requirements = array();
- if (!empty($lockData['platform'])) {
- $requirements = $this->loader->parseLinks(
- '__ROOT__',
- '1.0.0',
- 'requires',
- isset($lockData['platform']) ? $lockData['platform'] : array()
- );
- }
- if ($withDevReqs && !empty($lockData['platform-dev'])) {
- $devRequirements = $this->loader->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 getPlatformOverrides()
- {
- $lockData = $this->getLockData();
- return isset($lockData['platform-overrides']) ? $lockData['platform-overrides'] : array();
- }
- 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, array $platformOverrides)
- {
- $lock = array(
- '_readme' => array('This file locks the dependencies of your project to a known state',
- 'Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file',
- 'This file is @gener'.'ated automatically', ),
- 'hash' => $this->hash,
- 'content-hash' => $this->contentHash,
- '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 ($platformOverrides) {
- $lock['platform-overrides'] = $platformOverrides;
- }
- 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;
- }
- try {
- $isLocked = $this->isLocked();
- } catch (ParsingException $e) {
- $isLocked = false;
- }
- if (!$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;
- }
- private function getContentHash($composerFileContents)
- {
- $content = json_decode($composerFileContents, true);
- $relevantKeys = array(
- 'name',
- 'version',
- 'require',
- 'require-dev',
- 'conflict',
- 'replace',
- 'provide',
- 'minimum-stability',
- 'prefer-stable',
- 'repositories',
- 'extra',
- );
- $relevantContent = array();
- foreach (array_intersect($relevantKeys, array_keys($content)) as $key) {
- $relevantContent[$key] = $content[$key];
- }
- if (isset($content['config']['platform'])) {
- $relevantContent['config']['platform'] = $content['config']['platform'];
- }
- ksort($relevantContent);
- return md5(json_encode($relevantContent));
- }
- }
- <?php
- namespace Composer\Package;
- use Composer\Semver\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 getFullPrettyVersion($truncate = true);
- 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)
- {
- $this->requires = $this->replaceSelfVersionDependencies($require, 'requires');
- $this->aliasOf->setRequires($require);
- }
- public function setDevRequires(array $devRequire)
- {
- $this->devRequires = $this->replaceSelfVersionDependencies($devRequire, 'devRequires');
- $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\Config;
- use Composer\Repository\Vcs\HgDriver;
- use Composer\IO\NullIO;
- use Composer\Semver\VersionParser as SemverVersionParser;
- use Composer\Util\Git as GitUtil;
- use Composer\Util\ProcessExecutor;
- use Composer\Util\Svn as SvnUtil;
- class VersionGuesser
- {
- private $config;
- private $process;
- private $versionParser;
- public function __construct(Config $config, ProcessExecutor $process, SemverVersionParser $versionParser)
- {
- $this->config = $config;
- $this->process = $process;
- $this->versionParser = $versionParser;
- }
- public function guessVersion(array $packageConfig, $path)
- {
- if (function_exists('proc_open')) {
- $version = $this->guessGitVersion($packageConfig, $path);
- if (null !== $version) {
- return $version;
- }
- $version = $this->guessHgVersion($packageConfig, $path);
- if (null !== $version) {
- return $version;
- }
- return $this->guessSvnVersion($packageConfig, $path);
- }
- }
- private function guessGitVersion(array $packageConfig, $path)
- {
- GitUtil::cleanEnv();
- if (0 === $this->process->execute('git describe --exact-match --tags', $output, $path)) {
- try {
- return $this->versionParser->normalize(trim($output));
- } catch (\Exception $e) {
- }
- }
- if (0 === $this->process->execute('git branch --no-color --no-abbrev -v', $output, $path)) {
- $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($packageConfig, $version, $branches, 'git rev-list %candidate%..%branch%', $path);
- return $version;
- }
- }
- private function guessHgVersion(array $packageConfig, $path)
- {
- if (0 === $this->process->execute('hg branch', $output, $path)) {
- $branch = trim($output);
- $version = $this->versionParser->normalizeBranch($branch);
- $isFeatureBranch = 0 === strpos($version, 'dev-');
- if ('9999999-dev' === $version) {
- $version = 'dev-'.$branch;
- }
- if (!$isFeatureBranch) {
- return $version;
- }
- $driver = new HgDriver(array('url' => $path), new NullIO(), $this->config, $this->process);
- $branches = array_keys($driver->getBranches());
- $version = $this->guessFeatureVersion($packageConfig, $version, $branches, 'hg log -r "not ancestors(\'%candidate%\') and ancestors(\'%branch%\')" --template "{node}\\n"', $path);
- return $version;
- }
- }
- private function guessFeatureVersion(array $packageConfig, $version, array $branches, $scmCmdline, $path)
- {
-
- if ((isset($packageConfig['extra']['branch-alias']) && !isset($packageConfig['extra']['branch-alias'][$version]))
- || strpos(json_encode($packageConfig), '"self.version"')
- ) {
- $branch = preg_replace('{^dev-}', '', $version);
- $length = PHP_INT_MAX;
- $nonFeatureBranches = '';
- if (!empty($packageConfig['non-feature-branches'])) {
- $nonFeatureBranches = implode('|', $packageConfig['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, $path)) {
- 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 $packageConfig, $path)
- {
- SvnUtil::cleanEnv();
- if (0 === $this->process->execute('svn info --xml', $output, $path)) {
- $trunkPath = isset($packageConfig['trunk-path']) ? preg_quote($packageConfig['trunk-path'], '#') : 'trunk';
- $branchesPath = isset($packageConfig['branches-path']) ? preg_quote($packageConfig['branches-path'], '#') : 'branches';
- $tagsPath = isset($packageConfig['tags-path']) ? preg_quote($packageConfig['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\Version;
- use Composer\Semver\VersionParser as SemverVersionParser;
- class VersionParser extends SemverVersionParser
- {
- 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;
- use Composer\Semver\VersionParser as SemverVersionParser;
- 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(strtolower($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);
- if (count($semanticVersionParts) == 4 && preg_match('{^0\D?}', $semanticVersionParts[3])) {
- if ($semanticVersionParts[0] === '0') {
- unset($semanticVersionParts[3]);
- } else {
- unset($semanticVersionParts[2], $semanticVersionParts[3]);
- }
- $version = implode('.', $semanticVersionParts);
- } else {
- return $prettyVersion;
- }
- if ($stability != 'stable') {
- $version .= '@'.$stability;
- }
- return '^' . $version;
- }
- private function getParser()
- {
- if ($this->parser === null) {
- $this->parser = new SemverVersionParser();
- }
- 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\Semver\VersionParser;
- use Composer\Repository\RepositoryInterface;
- use Composer\Package\AliasPackage;
- use Composer\Package\PackageInterface;
- use Composer\Package\Link;
- use Composer\Semver\Constraint\Constraint;
- 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 ('composer-plugin-api' === $link->getTarget()) {
- $requiresComposer = $link->getConstraint();
- break;
- }
- }
- if (!$requiresComposer) {
- throw new \RuntimeException("Plugin ".$package->getName()." is missing a require statement for a version of the composer-plugin-api package.");
- }
- $currentPluginApiVersion = $this->getPluginApiVersion();
- $currentPluginApiConstraint = new Constraint('==', $this->versionParser->normalize($currentPluginApiVersion));
- if (!$requiresComposer->matches($currentPluginApiConstraint)) {
- $this->io->writeError('<warning>The "' . $package->getName() . '" plugin was skipped because it requires a Plugin API version ("' . $requiresComposer->getPrettyString() . '") that does not match your Composer installation ("' . $currentPluginApiVersion . '"). You may need to run composer update with the "--no-plugins" option.</warning>');
- continue;
- }
- $this->registerPackage($package);
- } elseif ('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);
- }
- protected function getPluginApiVersion()
- {
- return PluginInterface::PLUGIN_API_VERSION;
- }
- }
- <?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\Semver\VersionParser;
- use Composer\Semver\Constraint\ConstraintInterface;
- use Composer\Semver\Constraint\Constraint;
- class ArrayRepository implements RepositoryInterface
- {
- protected $packages;
- public function __construct(array $packages = array())
- {
- foreach ($packages as $package) {
- $this->addPackage($package);
- }
- }
- public function findPackage($name, $constraint)
- {
- $name = strtolower($name);
- if (!$constraint instanceof ConstraintInterface) {
- $versionParser = new VersionParser();
- $constraint = $versionParser->parseConstraints($constraint);
- }
- foreach ($this->getPackages() as $package) {
- if ($name === $package->getName()) {
- $pkgConstraint = new Constraint('==', $package->getVersion());
- if ($constraint->matches($pkgConstraint)) {
- return $package;
- }
- }
- }
- }
- public function findPackages($name, $constraint = null)
- {
- $name = strtolower($name);
- $packages = array();
- if (null !== $constraint && !$constraint instanceof ConstraintInterface) {
- $versionParser = new VersionParser();
- $constraint = $versionParser->parseConstraints($constraint);
- }
- foreach ($this->getPackages() as $package) {
- if ($name === $package->getName()) {
- $pkgConstraint = new Constraint('==', $package->getVersion());
- if (null === $constraint || $constraint->matches($pkgConstraint)) {
- $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;
- use Composer\Package\Loader\LoaderInterface;
- 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, \RecursiveDirectoryIterator::FOLLOW_SYMLINKS);
- $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\PackageInterface;
- use Composer\Package\AliasPackage;
- use Composer\Semver\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;
- use Composer\Semver\Constraint\ConstraintInterface;
- use Composer\Semver\Constraint\Constraint;
- 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, $constraint)
- {
- if (!$this->hasProviders()) {
- return parent::findPackage($name, $constraint);
- }
- $name = strtolower($name);
- if (!$constraint instanceof ConstraintInterface) {
- $versionParser = new VersionParser();
- $constraint = $versionParser->parseConstraints($constraint);
- }
- foreach ($this->getProviderNames() as $providerName) {
- if ($name === $providerName) {
- $packages = $this->whatProvides(new Pool('dev'), $providerName);
- foreach ($packages as $package) {
- if ($name === $package->getName()) {
- $pkgConstraint = new Constraint('==', $package->getVersion());
- if ($constraint->matches($pkgConstraint)) {
- return $package;
- }
- }
- }
- }
- }
- }
- public function findPackages($name, $constraint = null)
- {
- if (!$this->hasProviders()) {
- return parent::findPackages($name, $constraint);
- }
- $name = strtolower($name);
- if (null !== $constraint && !$constraint instanceof ConstraintInterface) {
- $versionParser = new VersionParser();
- $constraint = $versionParser->parseConstraints($constraint);
- }
- $packages = array();
- foreach ($this->getProviderNames() as $providerName) {
- if ($name === $providerName) {
- $candidates = $this->whatProvides(new Pool('dev'), $providerName);
- foreach ($candidates as $package) {
- if ($name === $package->getName()) {
- $pkgConstraint = new Constraint('==', $package->getVersion());
- if (null === $constraint || $constraint->matches($pkgConstraint)) {
- $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);
- $this->baseUrl = str_replace('https://', 'http://', $this->baseUrl);
- }
- 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;
- }
- if (($pos = strpos($filename, '$')) && preg_match('{^https?://.*}i', $filename)) {
- $filename = substr($filename, 0, $pos) . '%24' . substr($filename, $pos + 1);
- }
- $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, $constraint)
- {
- foreach ($this->repositories as $repository) {
- $package = $repository->findPackage($name, $constraint);
- if (null !== $package) {
- return $package;
- }
- }
- return null;
- }
- public function findPackages($name, $constraint = null)
- {
- $packages = array();
- foreach ($this->repositories as $repository) {
- $packages[] = $repository->findPackages($name, $constraint);
- }
- 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 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;
- use Composer\Config;
- use Composer\IO\IOInterface;
- use Composer\Json\JsonFile;
- use Composer\Package\Loader\ArrayLoader;
- use Composer\Package\Version\VersionGuesser;
- use Composer\Semver\VersionParser;
- use Composer\Util\ProcessExecutor;
- class PathRepository extends ArrayRepository
- {
- private $loader;
- private $versionGuesser;
- private $url;
- private $process;
- public function __construct(array $repoConfig, IOInterface $io, Config $config)
- {
- if (!isset($repoConfig['url'])) {
- throw new \RuntimeException('You must specify the `url` configuration for the path repository');
- }
- $this->loader = new ArrayLoader();
- $this->url = $repoConfig['url'];
- $this->process = new ProcessExecutor($io);
- $this->versionGuesser = new VersionGuesser($config, $this->process, new VersionParser());
- parent::__construct();
- }
- protected function initialize()
- {
- parent::initialize();
- foreach ($this->getUrlMatches() as $url) {
- $path = realpath($url) . '/';
- $composerFilePath = $path.'composer.json';
- if (!file_exists($composerFilePath)) {
- continue;
- }
- $json = file_get_contents($composerFilePath);
- $package = JsonFile::parseJson($json, $composerFilePath);
- $package['dist'] = array(
- 'type' => 'path',
- 'url' => $url,
- 'reference' => '',
- );
- if (!isset($package['version'])) {
- $package['version'] = $this->versionGuesser->guessVersion($package, $path) ?: 'dev-master';
- }
- if (is_dir($path.'/.git') && 0 === $this->process->execute('git log -n1 --pretty=%H', $output, $path)) {
- $package['dist']['reference'] = trim($output);
- }
- $package = $this->loader->load($package);
- $this->addPackage($package);
- }
- if (count($this->getPackages()) == 0) {
- throw new \RuntimeException(sprintf('No `composer.json` file found in any path repository in "%s"', $this->url));
- }
- }
- private function getUrlMatches()
- {
- return glob($this->url, GLOB_MARK | GLOB_ONLYDIR);
- }
- }
- <?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\Semver\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\Semver\Constraint\Constraint;
- 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 Constraint('==', $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 Constraint('==', $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\Config;
- use Composer\Package\PackageInterface;
- use Composer\Package\CompletePackage;
- use Composer\Semver\VersionParser;
- use Composer\Plugin\PluginInterface;
- class PlatformRepository extends ArrayRepository
- {
- const PLATFORM_PACKAGE_REGEX = '{^(?:php(?:-64bit)?|hhvm|(?:ext|lib)-[^/]+)$}i';
- private $overrides = array();
- public function __construct(array $packages = array(), array $overrides = array())
- {
- foreach ($overrides as $name => $version) {
- $this->overrides[strtolower($name)] = array('name' => $name, 'version' => $version);
- }
- parent::__construct($packages);
- }
- protected function initialize()
- {
- parent::initialize();
- $versionParser = new VersionParser();
-
- foreach ($this->overrides as $override) {
- if (!preg_match(self::PLATFORM_PACKAGE_REGEX, $override['name'])) {
- throw new \InvalidArgumentException('Invalid platform package name in config.platform: '.$override['name']);
- }
- $version = $versionParser->normalize($override['version']);
- $package = new CompletePackage($override['name'], $version, $override['version']);
- $package->setDescription('Overridden virtual platform package '.$override['name']);
- parent::addPackage($package);
- }
- $prettyVersion = PluginInterface::PLUGIN_API_VERSION;
- $version = $versionParser->normalize($prettyVersion);
- $composerPluginApi = new CompletePackage('composer-plugin-api', $version, $prettyVersion);
- $composerPluginApi->setDescription('The Composer Plugin API');
- $this->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');
- $this->addPackage($php);
- if (PHP_INT_SIZE === 8) {
- $php64 = new CompletePackage('php-64bit', $version, $prettyVersion);
- $php64->setDescription('The PHP interpreter (64bit)');
- $this->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');
- $this->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');
- $this->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)');
- $this->addPackage($hhvm);
- }
- }
- public function addPackage(PackageInterface $package)
- {
- if (isset($this->overrides[strtolower($package->getName())])) {
- return;
- }
- parent::addPackage($package);
- }
- 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, $constraint);
- public function findPackages($name, $constraint = 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;
- use Composer\Package\PackageInterface;
- 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, $constraint)
- {
- foreach ($this->repositories as $repository) {
- if ($package = $repository->findPackage($name, $constraint)) {
- return $package;
- }
- }
- }
- public function findPackages($name, $constraint)
- {
- $packages = array();
- foreach ($this->repositories as $repository) {
- $packages = array_merge($packages, $repository->findPackages($name, $constraint));
- }
- 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];
- if ($this->originUrl === 'www.github.com') {
- $this->originUrl = 'github.com';
- }
- $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(preg_replace('{^www\.}i', '', $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\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\Semver\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',
- '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->isVeryVerbose();
- $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');
- },
- null,
- '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;
- use Composer\Spdx\SpdxLicenses;
- 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 SpdxLicenses();
- 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);
- $publishErrors[] = 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";
- }
- }
- if (isset($manifest['autoload']['psr-0'][''])) {
- $warnings[] = "Defining autoload.psr-0 with an empty namespace prefix is a bad idea for performance";
- }
- if (isset($manifest['autoload']['psr-4'][''])) {
- $warnings[] = "Defining autoload.psr-4 with an empty namespace prefix is a bad idea for performance";
- }
- 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;
- use Composer\IO\IOInterface;
- class ErrorHandler
- {
- private static $io;
- 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.";
- }
- if ($level !== E_DEPRECATED && $level !== E_USER_DEPRECATED) {
- throw new \ErrorException($message, 0, $level, $file, $line);
- }
- if (self::$io) {
- self::$io->writeError('<warning>Deprecation Notice: '.$message.' in '.$file.':'.$line.'</warning>');
- if (self::$io->isVerbose()) {
- self::$io->writeError('<warning>Stack trace:</warning>');
- self::$io->writeError(array_filter(array_map(function ($a) {
- if (isset($a['line'], $a['file'])) {
- return '<warning> '.$a['file'].':'.$a['line'].'</warning>';
- }
- return null;
- }, array_slice(debug_backtrace(), 2))));
- }
- }
- }
- public static function register(IOInterface $io = null)
- {
- set_error_handler(array(__CLASS__, 'handle'));
- self::$io = $io;
- }
- }
- <?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 = rtrim($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);
- }
- public 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);
- $command = call_user_func($commandCallable, $url);
- if ($bypassSshForGitHub || 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 ($this->isAuthenticationFailure($url, $match)) {
- 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);
- }
- }
- private function isAuthenticationFailure($url, &$match)
- {
- if (!preg_match('{(https?://)([^/]+)(.*)$}i', $url, $match)) {
- return false;
- }
- $authFailures = array('fatal: Authentication failed', 'remote error: Invalid username or password.');
- foreach ($authFailures as $authFailure) {
- if (strpos($this->process->getErrorOutput(), $authFailure) !== false) {
- return true;
- }
- }
- return false;
- }
- 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');
- unset($_SERVER['GIT_ASKPASS']);
- }
- if (getenv('GIT_DIR')) {
- putenv('GIT_DIR');
- unset($_SERVER['GIT_DIR']);
- }
- if (getenv('GIT_WORK_TREE')) {
- putenv('GIT_WORK_TREE');
- unset($_SERVER['GIT_WORK_TREE']);
- }
- if (getenv('LANGUAGE') !== 'C') {
- putenv('LANGUAGE=C');
- }
- putenv("DYLD_LIBRARY_PATH");
- unset($_SERVER['DYLD_LIBRARY_PATH']);
- }
- public static function getGitHubDomainsRegex(Config $config)
- {
- return '('.implode('|', array_map('preg_quote', $config->get('github-domains'))).')';
- }
- public static function sanitizeUrl($message)
- {
- return preg_replace('{://([^@]+?):.+?@}', '://$1:***@', $message);
- }
- private function throwException($message, $url)
- {
- clearstatcache();
- 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;
- 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);
- }
- $note = 'Composer';
- if ($this->config->get('github-expose-hostname') === true && 0 === $this->process->execute('hostname', $output)) {
- $note .= ' on ' . trim($output);
- }
- $note .= ' ' . date('Y-m-d Hi');
- $url = 'https://'.$originUrl.'/settings/tokens/new?scopes=repo&description=' . str_replace('%20', '+', rawurlencode($note));
- $this->io->writeError(sprintf('Head to %s', $url));
- $this->io->writeError(sprintf('to retrieve a token. It will be stored in "%s" for future use by Composer.', $this->config->getAuthConfigSource()->getName()));
- $token = trim($this->io->askAndHideAnswer('Token (hidden): '));
- if (!$token) {
- $this->io->writeError('<warning>No token given, aborting.</warning>');
- $this->io->writeError('You can also add it manually later by using "composer config github-oauth.github.com <token>"');
- return false;
- }
- $this->io->setAuthentication($originUrl, $token, 'x-oauth-basic');
- try {
- $apiUrl = ('github.com' === $originUrl) ? 'api.github.com' : $originUrl . '/api/v3';
- $this->remoteFilesystem->getContents($originUrl, 'https://'. $apiUrl . '/rate_limit', false, array(
- 'retry-auth-failure' => false,
- ));
- } catch (TransportException $e) {
- if (in_array($e->getCode(), array(403, 401))) {
- $this->io->writeError('<error>Invalid token provided.</error>');
- $this->io->writeError('You can also add it manually later by using "composer config github-oauth.github.com <token>"');
- return false;
- }
- throw $e;
- }
- $this->config->getConfigSource()->removeConfigSetting('github-oauth.'.$originUrl);
- $this->config->getAuthConfigSource()->addConfigSetting('github-oauth.'.$originUrl, $token);
- $this->io->writeError('<info>Token stored successfully.</info>');
- return true;
- }
- }
- <?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;
- private $degradedMode = false;
- 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 ($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['http'])) {
- $options['http']['ignore_errors'] = true;
- }
- if ($this->degradedMode && substr($fileUrl, 0, 21) === 'http://packagist.org/') {
- $fileUrl = 'http://' . gethostbyname('packagist.org') . substr($fileUrl, 20);
- }
- $ctx = StreamContextFactory::getContext($fileUrl, $options, array('notification' => array($this, 'callbackGet')));
- if ($this->progress) {
- $this->io->writeError(" Downloading: <comment>Connecting...</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) {
- if (!$this->degradedMode && false !== strpos($e->getMessage(), 'Operation timed out')) {
- $this->degradedMode = true;
- $this->io->writeError(array(
- '<error>'.$e->getMessage().'</error>',
- '<error>Retrying with degraded mode, check https://getcomposer.org/doc/articles/troubleshooting.md#degraded-mode for more info</error>',
- ));
- return $this->get($this->originUrl, $this->fileUrl, $additionalOptions, $this->fileName, $this->progress);
- }
- 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 ($this->progress && !$this->retry) {
- $this->io->overwriteError(" Downloading: <comment>100%</comment>");
- }
- 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;
- } elseif (preg_match('{^HTTP/}i', $header)) {
-
- $decode = false;
- }
- }
- if ($decode) {
- try {
- if (PHP_VERSION_ID >= 50400) {
- $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');
- }
- } catch (\Exception $e) {
- if ($this->degradedMode) {
- throw $e;
- }
- $this->degradedMode = true;
- $this->io->writeError(array(
- '<error>Failed to decode response: '.$e->getMessage().'</error>',
- '<error>Retrying with degraded mode, check https://getcomposer.org/doc/articles/troubleshooting.md#degraded-mode for more info</error>',
- ));
- return $this->get($this->originUrl, $this->fileUrl, $additionalOptions, $this->fileName, $this->progress);
- }
- }
- }
- 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);
- }
- if (!$this->degradedMode && false !== strpos($e->getMessage(), 'Operation timed out')) {
- $this->degradedMode = true;
- $this->io->writeError(array(
- '<error>'.$e->getMessage().'</error>',
- '<error>Retrying with degraded mode, check https://getcomposer.org/doc/articles/troubleshooting.md#degraded-mode for more info</error>',
- ));
- return $this->get($this->originUrl, $this->fileUrl, $additionalOptions, $this->fileName, $this->progress);
- }
- 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;
- case STREAM_NOTIFY_AUTH_RESULT:
- if (403 === $messageCode) {
- if (!$this->retryAuthFailure) {
- break;
- }
- $this->promptAuthAndRetry($messageCode, $message);
- }
- 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 = round($bytesTransferred / $this->bytesMax * 100);
- if ((0 === $progression % 5) && 100 !== $progression && $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.', please create a GitHub OAuth token '.($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 ($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->degradedMode) {
-
- $options['http']['protocol_version'] = 1.1;
- $headers[] = 'Connection: close';
- }
- if ($this->io->hasAuthentication($originUrl)) {
- $auth = $this->io->getAuthentication($originUrl);
- if ('github.com' === $originUrl && 'x-oauth-basic' === $auth['password']) {
- $options['github-token'] = $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;
- }
- return $options;
- }
- }
- <?php
- namespace Composer\Util;
- use Composer\Spdx\SpdxLicenses;
- @trigger_error('The ' . __NAMESPACE__ . '\SpdxLicense class is deprecated, use Composer\Spdx\SpdxLicenses instead.', E_USER_DEPRECATED);
- class SpdxLicense extends SpdxLicenses
- {
- }
- <?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 (PHP_VERSION_ID < 50600) {
- $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");
- unset($_SERVER['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;
- }
- $errorOutput = $this->process->getErrorOutput();
- $fullOutput = implode("\n", array($output, $errorOutput));
- if (false === stripos($fullOutput, 'Could not authenticate to server:')
- && false === stripos($fullOutput, 'authorization failed')
- && false === stripos($fullOutput, 'svn: E170001:')
- && false === stripos($fullOutput, 'svn: E215004:')) {
- throw new \RuntimeException($fullOutput);
- }
- 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 ('.$fullOutput.')'
- );
- }
- 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
- 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
- /*
- * 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 https://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."
- },
- "platform": {
- "type": "object",
- "description": "This is a hash of package name (keys) and version (values) that will be used to mock the platform packages on this machine.",
- "additionalProperties": true
- },
- "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."
- },
- "archive-format": {
- "type": "string",
- "description": "The default archiving format when not provided on cli, defaults to \"tar\"."
- },
- "archive-dir": {
- "type": "string",
- "description": "The default archive path when not provided on cli, defaults to \".\"."
- }
- }
- },
- "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 preferred 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"
- },
- "docs": {
- "type": "string",
- "description": "URL to the documentation.",
- "format": "uri"
- }
- }
- },
- "non-feature-branches": {
- "type": ["array"],
- "description": "A set of string or regex patterns for non-numeric branch names that will not be handled as feature branches.",
- "items": {
- "type": "string"
- }
- }
- }
- }
- {
- "389-exception": [
- "389 Directory Server\nException"
- ],
- "Autoconf-exception-2.0": [
- "Autoconf exception 2.0"
- ],
- "Autoconf-exception-3.0": [
- "Autoconf exception 3.0"
- ],
- "Bison-exception-2.2": [
- "Bison exception 2.2"
- ],
- "Classpath-exception-2.0": [
- "Classpath exception 2.0"
- ],
- "CLISP-exception-2.0": [
- "CLISP exception 2.0"
- ],
- "eCos-exception-2.0": [
- "eCos exception 2.0"
- ],
- "FLTK-exception": [
- "FLTK exception"
- ],
- "Font-exception-2.0": [
- "Font exception 2.0"
- ],
- "freertos-exception-2.0": [
- "FreeRTOS Exception 2.0"
- ],
- "GCC-exception-2.0": [
- "GCC Runtime Library exception 2.0"
- ],
- "GCC-exception-3.1": [
- "GCC Runtime Library exception 3.1"
- ],
- "gnu-javamail-exception": [
- "GNU JavaMail exception"
- ],
- "i2p-gpl-java-exception": [
- "i2p GPL+Java Exception"
- ],
- "Libtool-exception": [
- "Libtool Exception"
- ],
- "LZMA-exception": [
- "LZMA exception"
- ],
- "mif-exception": [
- "Macros and Inline Functions Exception"
- ],
- "Nokia-Qt-exception-1.1": [
- "Nokia Qt LGPL exception 1.1"
- ],
- "Qwt-exception-1.0": [
- "Qwt exception 1.0"
- ],
- "u-boot-exception-2.0": [
- "U-Boot exception 2.0"
- ],
- "WxWindows-exception-3.1": [
- "WxWindows Library Exception 3.1"
- ]
- }{
- "AAL": [
- "Attribution Assurance License",
- true
- ],
- "Abstyles": [
- "Abstyles License",
- false
- ],
- "Adobe-2006": [
- "Adobe Systems Incorporated Source Code License Agreement",
- false
- ],
- "Adobe-Glyph": [
- "Adobe Glyph List License",
- false
- ],
- "ADSL": [
- "Amazon Digital Services License",
- false
- ],
- "AFL-1.1": [
- "Academic Free License v1.1",
- true
- ],
- "AFL-1.2": [
- "Academic Free License v1.2",
- true
- ],
- "AFL-2.0": [
- "Academic Free License v2.0",
- true
- ],
- "AFL-2.1": [
- "Academic Free License v2.1",
- true
- ],
- "AFL-3.0": [
- "Academic Free License v3.0",
- true
- ],
- "Afmparse": [
- "Afmparse License",
- false
- ],
- "AGPL-1.0": [
- "Affero General Public License v1.0",
- false
- ],
- "AGPL-3.0": [
- "GNU Affero General Public License v3.0",
- true
- ],
- "Aladdin": [
- "Aladdin Free Public License",
- false
- ],
- "AMDPLPA": [
- "AMD's plpa_map.c License",
- false
- ],
- "AML": [
- "Apple MIT License",
- false
- ],
- "AMPAS": [
- "Academy of Motion Picture Arts and Sciences BSD",
- false
- ],
- "ANTLR-PD": [
- "ANTLR Software Rights Notice",
- false
- ],
- "Apache-1.0": [
- "Apache License 1.0",
- false
- ],
- "Apache-1.1": [
- "Apache License 1.1",
- true
- ],
- "Apache-2.0": [
- "Apache License 2.0",
- true
- ],
- "APAFML": [
- "Adobe Postscript AFM License",
- false
- ],
- "APL-1.0": [
- "Adaptive Public License 1.0",
- true
- ],
- "APSL-1.0": [
- "Apple Public Source License 1.0",
- true
- ],
- "APSL-1.1": [
- "Apple Public Source License 1.1",
- true
- ],
- "APSL-1.2": [
- "Apple Public Source License 1.2",
- true
- ],
- "APSL-2.0": [
- "Apple Public Source License 2.0",
- true
- ],
- "Artistic-1.0": [
- "Artistic License 1.0",
- true
- ],
- "Artistic-1.0-cl8": [
- "Artistic License 1.0 w/clause 8",
- true
- ],
- "Artistic-1.0-Perl": [
- "Artistic License 1.0 (Perl)",
- true
- ],
- "Artistic-2.0": [
- "Artistic License 2.0",
- true
- ],
- "Bahyph": [
- "Bahyph License",
- false
- ],
- "Barr": [
- "Barr License",
- false
- ],
- "Beerware": [
- "Beerware License",
- false
- ],
- "BitTorrent-1.0": [
- "BitTorrent Open Source License v1.0",
- false
- ],
- "BitTorrent-1.1": [
- "BitTorrent Open Source License v1.1",
- false
- ],
- "Borceux": [
- "Borceux license",
- false
- ],
- "BSD-2-Clause": [
- "BSD 2-clause \"Simplified\" License",
- true
- ],
- "BSD-2-Clause-FreeBSD": [
- "BSD 2-clause FreeBSD License",
- false
- ],
- "BSD-2-Clause-NetBSD": [
- "BSD 2-clause NetBSD License",
- false
- ],
- "BSD-3-Clause": [
- "BSD 3-clause \"New\" or \"Revised\" License",
- true
- ],
- "BSD-3-Clause-Attribution": [
- "BSD with attribution",
- false
- ],
- "BSD-3-Clause-Clear": [
- "BSD 3-clause Clear License",
- false
- ],
- "BSD-3-Clause-LBNL": [
- "Lawrence Berkeley National Labs BSD variant license",
- false
- ],
- "BSD-4-Clause": [
- "BSD 4-clause \"Original\" or \"Old\" License",
- false
- ],
- "BSD-4-Clause-UC": [
- "BSD-4-Clause (University of California-Specific)",
- false
- ],
- "BSD-Protection": [
- "BSD Protection License",
- false
- ],
- "BSL-1.0": [
- "Boost Software License 1.0",
- true
- ],
- "bzip2-1.0.5": [
- "bzip2 and libbzip2 License v1.0.5",
- false
- ],
- "bzip2-1.0.6": [
- "bzip2 and libbzip2 License v1.0.6",
- false
- ],
- "Caldera": [
- "Caldera License",
- false
- ],
- "CATOSL-1.1": [
- "Computer Associates Trusted Open Source License 1.1",
- true
- ],
- "CC-BY-1.0": [
- "Creative Commons Attribution 1.0",
- false
- ],
- "CC-BY-2.0": [
- "Creative Commons Attribution 2.0",
- false
- ],
- "CC-BY-2.5": [
- "Creative Commons Attribution 2.5",
- false
- ],
- "CC-BY-3.0": [
- "Creative Commons Attribution 3.0",
- false
- ],
- "CC-BY-4.0": [
- "Creative Commons Attribution 4.0",
- false
- ],
- "CC-BY-NC-1.0": [
- "Creative Commons Attribution Non Commercial 1.0",
- false
- ],
- "CC-BY-NC-2.0": [
- "Creative Commons Attribution Non Commercial 2.0",
- false
- ],
- "CC-BY-NC-2.5": [
- "Creative Commons Attribution Non Commercial 2.5",
- false
- ],
- "CC-BY-NC-3.0": [
- "Creative Commons Attribution Non Commercial 3.0",
- false
- ],
- "CC-BY-NC-4.0": [
- "Creative Commons Attribution Non Commercial 4.0",
- false
- ],
- "CC-BY-NC-ND-1.0": [
- "Creative Commons Attribution Non Commercial No Derivatives 1.0",
- false
- ],
- "CC-BY-NC-ND-2.0": [
- "Creative Commons Attribution Non Commercial No Derivatives 2.0",
- false
- ],
- "CC-BY-NC-ND-2.5": [
- "Creative Commons Attribution Non Commercial No Derivatives 2.5",
- false
- ],
- "CC-BY-NC-ND-3.0": [
- "Creative Commons Attribution Non Commercial No Derivatives 3.0",
- false
- ],
- "CC-BY-NC-ND-4.0": [
- "Creative Commons Attribution Non Commercial No Derivatives 4.0",
- false
- ],
- "CC-BY-NC-SA-1.0": [
- "Creative Commons Attribution Non Commercial Share Alike 1.0",
- false
- ],
- "CC-BY-NC-SA-2.0": [
- "Creative Commons Attribution Non Commercial Share Alike 2.0",
- false
- ],
- "CC-BY-NC-SA-2.5": [
- "Creative Commons Attribution Non Commercial Share Alike 2.5",
- false
- ],
- "CC-BY-NC-SA-3.0": [
- "Creative Commons Attribution Non Commercial Share Alike 3.0",
- false
- ],
- "CC-BY-NC-SA-4.0": [
- "Creative Commons Attribution Non Commercial Share Alike 4.0",
- false
- ],
- "CC-BY-ND-1.0": [
- "Creative Commons Attribution No Derivatives 1.0",
- false
- ],
- "CC-BY-ND-2.0": [
- "Creative Commons Attribution No Derivatives 2.0",
- false
- ],
- "CC-BY-ND-2.5": [
- "Creative Commons Attribution No Derivatives 2.5",
- false
- ],
- "CC-BY-ND-3.0": [
- "Creative Commons Attribution No Derivatives 3.0",
- false
- ],
- "CC-BY-ND-4.0": [
- "Creative Commons Attribution No Derivatives 4.0",
- false
- ],
- "CC-BY-SA-1.0": [
- "Creative Commons Attribution Share Alike 1.0",
- false
- ],
- "CC-BY-SA-2.0": [
- "Creative Commons Attribution Share Alike 2.0",
- false
- ],
- "CC-BY-SA-2.5": [
- "Creative Commons Attribution Share Alike 2.5",
- false
- ],
- "CC-BY-SA-3.0": [
- "Creative Commons Attribution Share Alike 3.0",
- false
- ],
- "CC-BY-SA-4.0": [
- "Creative Commons Attribution Share Alike 4.0",
- false
- ],
- "CC0-1.0": [
- "Creative Commons Zero v1.0 Universal",
- false
- ],
- "CDDL-1.0": [
- "Common Development and Distribution License 1.0",
- true
- ],
- "CDDL-1.1": [
- "Common Development and Distribution License 1.1",
- false
- ],
- "CECILL-1.0": [
- "CeCILL Free Software License Agreement v1.0",
- false
- ],
- "CECILL-1.1": [
- "CeCILL Free Software License Agreement v1.1",
- false
- ],
- "CECILL-2.0": [
- "CeCILL Free Software License Agreement v2.0",
- false
- ],
- "CECILL-B": [
- "CeCILL-B Free Software License Agreement",
- false
- ],
- "CECILL-C": [
- "CeCILL-C Free Software License Agreement",
- false
- ],
- "ClArtistic": [
- "Clarified Artistic License",
- false
- ],
- "CNRI-Jython": [
- "CNRI Jython License",
- false
- ],
- "CNRI-Python": [
- "CNRI Python License",
- true
- ],
- "CNRI-Python-GPL-Compatible": [
- "CNRI Python Open Source GPL Compatible License Agreement",
- false
- ],
- "Condor-1.1": [
- "Condor Public License v1.1",
- false
- ],
- "CPAL-1.0": [
- "Common Public Attribution License 1.0",
- true
- ],
- "CPL-1.0": [
- "Common Public License 1.0",
- true
- ],
- "CPOL-1.02": [
- "Code Project Open License 1.02",
- false
- ],
- "Crossword": [
- "Crossword License",
- false
- ],
- "CUA-OPL-1.0": [
- "CUA Office Public License v1.0",
- true
- ],
- "Cube": [
- "Cube License",
- false
- ],
- "D-FSL-1.0": [
- "Deutsche Freie Software Lizenz",
- false
- ],
- "diffmark": [
- "diffmark license",
- false
- ],
- "DOC": [
- "DOC License",
- false
- ],
- "Dotseqn": [
- "Dotseqn License",
- false
- ],
- "DSDP": [
- "DSDP License",
- false
- ],
- "dvipdfm": [
- "dvipdfm License",
- false
- ],
- "ECL-1.0": [
- "Educational Community License v1.0",
- true
- ],
- "ECL-2.0": [
- "Educational Community License v2.0",
- true
- ],
- "EFL-1.0": [
- "Eiffel Forum License v1.0",
- true
- ],
- "EFL-2.0": [
- "Eiffel Forum License v2.0",
- true
- ],
- "eGenix": [
- "eGenix.com Public License 1.1.0",
- false
- ],
- "Entessa": [
- "Entessa Public License v1.0",
- true
- ],
- "EPL-1.0": [
- "Eclipse Public License 1.0",
- true
- ],
- "ErlPL-1.1": [
- "Erlang Public License v1.1",
- false
- ],
- "EUDatagrid": [
- "EU DataGrid Software License",
- true
- ],
- "EUPL-1.0": [
- "European Union Public License 1.0",
- false
- ],
- "EUPL-1.1": [
- "European Union Public License 1.1",
- true
- ],
- "Eurosym": [
- "Eurosym License",
- false
- ],
- "Fair": [
- "Fair License",
- true
- ],
- "Frameworx-1.0": [
- "Frameworx Open License 1.0",
- true
- ],
- "FreeImage": [
- "FreeImage Public License v1.0",
- false
- ],
- "FSFUL": [
- "FSF Unlimited License",
- false
- ],
- "FSFULLR": [
- "FSF Unlimited License (with License Retention)",
- false
- ],
- "FTL": [
- "Freetype Project License",
- false
- ],
- "GFDL-1.1": [
- "GNU Free Documentation License v1.1",
- false
- ],
- "GFDL-1.2": [
- "GNU Free Documentation License v1.2",
- false
- ],
- "GFDL-1.3": [
- "GNU Free Documentation License v1.3",
- false
- ],
- "Giftware": [
- "Giftware License",
- false
- ],
- "GL2PS": [
- "GL2PS License",
- false
- ],
- "Glide": [
- "3dfx Glide License",
- false
- ],
- "Glulxe": [
- "Glulxe License",
- false
- ],
- "gnuplot": [
- "gnuplot License",
- false
- ],
- "GPL-1.0": [
- "GNU General Public License v1.0 only",
- false
- ],
- "GPL-2.0": [
- "GNU General Public License v2.0 only",
- true
- ],
- "GPL-3.0": [
- "GNU General Public License v3.0 only",
- true
- ],
- "gSOAP-1.3b": [
- "gSOAP Public License v1.3b",
- false
- ],
- "HaskellReport": [
- "Haskell Language Report License",
- false
- ],
- "HPND": [
- "Historic Permission Notice and Disclaimer",
- true
- ],
- "IBM-pibs": [
- "IBM PowerPC Initialization and Boot Software",
- false
- ],
- "ICU": [
- "ICU License",
- false
- ],
- "IJG": [
- "Independent JPEG Group License",
- false
- ],
- "ImageMagick": [
- "ImageMagick License",
- false
- ],
- "iMatix": [
- "iMatix Standard Function Library Agreement",
- false
- ],
- "Imlib2": [
- "Imlib2 License",
- false
- ],
- "Intel": [
- "Intel Open Source License",
- true
- ],
- "Intel-ACPI": [
- "Intel ACPI Software License Agreement",
- false
- ],
- "IPA": [
- "IPA Font License",
- true
- ],
- "IPL-1.0": [
- "IBM Public License v1.0",
- true
- ],
- "ISC": [
- "ISC License",
- true
- ],
- "JasPer-2.0": [
- "JasPer License",
- false
- ],
- "JSON": [
- "JSON License",
- false
- ],
- "Latex2e": [
- "Latex2e License",
- false
- ],
- "Leptonica": [
- "Leptonica License",
- false
- ],
- "LGPL-2.0": [
- "GNU Library General Public License v2 only",
- true
- ],
- "LGPL-2.1": [
- "GNU Lesser General Public License v2.1 only",
- true
- ],
- "LGPL-3.0": [
- "GNU Lesser General Public License v3.0 only",
- true
- ],
- "LGPLLR": [
- "Lesser General Public License For Linguistic Resources",
- false
- ],
- "Libpng": [
- "libpng License",
- false
- ],
- "libtiff": [
- "libtiff License",
- false
- ],
- "LPL-1.0": [
- "Lucent Public License Version 1.0",
- true
- ],
- "LPL-1.02": [
- "Lucent Public License v1.02",
- true
- ],
- "LPPL-1.0": [
- "LaTeX Project Public License v1.0",
- false
- ],
- "LPPL-1.1": [
- "LaTeX Project Public License v1.1",
- false
- ],
- "LPPL-1.2": [
- "LaTeX Project Public License v1.2",
- false
- ],
- "LPPL-1.3a": [
- "LaTeX Project Public License 1.3a",
- false
- ],
- "LPPL-1.3c": [
- "LaTeX Project Public License v1.3c",
- true
- ],
- "MakeIndex": [
- "MakeIndex License",
- false
- ],
- "MirOS": [
- "MirOS Licence",
- true
- ],
- "MIT": [
- "MIT License",
- true
- ],
- "MIT-advertising": [
- "Enlightenment License (e16)",
- false
- ],
- "MIT-CMU": [
- "CMU License",
- false
- ],
- "MIT-enna": [
- "enna License",
- false
- ],
- "MIT-feh": [
- "feh License",
- false
- ],
- "MITNFA": [
- "MIT +no-false-attribs license",
- false
- ],
- "Motosoto": [
- "Motosoto License",
- true
- ],
- "mpich2": [
- "mpich2 License",
- false
- ],
- "MPL-1.0": [
- "Mozilla Public License 1.0",
- true
- ],
- "MPL-1.1": [
- "Mozilla Public License 1.1",
- true
- ],
- "MPL-2.0": [
- "Mozilla Public License 2.0",
- true
- ],
- "MPL-2.0-no-copyleft-exception": [
- "Mozilla Public License 2.0 (no copyleft exception)",
- true
- ],
- "MS-PL": [
- "Microsoft Public License",
- true
- ],
- "MS-RL": [
- "Microsoft Reciprocal License",
- true
- ],
- "MTLL": [
- "Matrix Template Library License",
- false
- ],
- "Multics": [
- "Multics License",
- true
- ],
- "Mup": [
- "Mup License",
- false
- ],
- "NASA-1.3": [
- "NASA Open Source Agreement 1.3",
- true
- ],
- "Naumen": [
- "Naumen Public License",
- true
- ],
- "NBPL-1.0": [
- "Net Boolean Public License v1",
- false
- ],
- "NCSA": [
- "University of Illinois/NCSA Open Source License",
- true
- ],
- "NetCDF": [
- "NetCDF license",
- false
- ],
- "Newsletr": [
- "Newsletr License",
- false
- ],
- "NGPL": [
- "Nethack General Public License",
- true
- ],
- "NLPL": [
- "No Limit Public License",
- false
- ],
- "Nokia": [
- "Nokia Open Source License",
- true
- ],
- "NOSL": [
- "Netizen Open Source License",
- false
- ],
- "Noweb": [
- "Noweb License",
- false
- ],
- "NPL-1.0": [
- "Netscape Public License v1.0",
- false
- ],
- "NPL-1.1": [
- "Netscape Public License v1.1",
- false
- ],
- "NPOSL-3.0": [
- "Non-Profit Open Software License 3.0",
- true
- ],
- "NRL": [
- "NRL License",
- false
- ],
- "NTP": [
- "NTP License",
- true
- ],
- "Nunit": [
- "Nunit License",
- false
- ],
- "OCLC-2.0": [
- "OCLC Research Public License 2.0",
- true
- ],
- "ODbL-1.0": [
- "ODC Open Database License v1.0",
- false
- ],
- "OFL-1.0": [
- "SIL Open Font License 1.0",
- false
- ],
- "OFL-1.1": [
- "SIL Open Font License 1.1",
- true
- ],
- "OGTSL": [
- "Open Group Test Suite License",
- true
- ],
- "OLDAP-1.1": [
- "Open LDAP Public License v1.1",
- false
- ],
- "OLDAP-1.2": [
- "Open LDAP Public License v1.2",
- false
- ],
- "OLDAP-1.3": [
- "Open LDAP Public License v1.3",
- false
- ],
- "OLDAP-1.4": [
- "Open LDAP Public License v1.4",
- false
- ],
- "OLDAP-2.0": [
- "Open LDAP Public License v2.0 (or possibly 2.0A and 2.0B)",
- false
- ],
- "OLDAP-2.0.1": [
- "Open LDAP Public License v2.0.1",
- false
- ],
- "OLDAP-2.1": [
- "Open LDAP Public License v2.1",
- false
- ],
- "OLDAP-2.2": [
- "Open LDAP Public License v2.2",
- false
- ],
- "OLDAP-2.2.1": [
- "Open LDAP Public License v2.2.1",
- false
- ],
- "OLDAP-2.2.2": [
- "Open LDAP Public License 2.2.2",
- false
- ],
- "OLDAP-2.3": [
- "Open LDAP Public License v2.3",
- false
- ],
- "OLDAP-2.4": [
- "Open LDAP Public License v2.4",
- false
- ],
- "OLDAP-2.5": [
- "Open LDAP Public License v2.5",
- false
- ],
- "OLDAP-2.6": [
- "Open LDAP Public License v2.6",
- false
- ],
- "OLDAP-2.7": [
- "Open LDAP Public License v2.7",
- false
- ],
- "OLDAP-2.8": [
- "Open LDAP Public License v2.8",
- false
- ],
- "OML": [
- "Open Market License",
- false
- ],
- "OpenSSL": [
- "OpenSSL License",
- false
- ],
- "OPL-1.0": [
- "Open Public License v1.0",
- false
- ],
- "OSL-1.0": [
- "Open Software License 1.0",
- true
- ],
- "OSL-1.1": [
- "Open Software License 1.1",
- false
- ],
- "OSL-2.0": [
- "Open Software License 2.0",
- true
- ],
- "OSL-2.1": [
- "Open Software License 2.1",
- true
- ],
- "OSL-3.0": [
- "Open Software License 3.0",
- true
- ],
- "PDDL-1.0": [
- "ODC Public Domain Dedication & License 1.0",
- false
- ],
- "PHP-3.0": [
- "PHP License v3.0",
- true
- ],
- "PHP-3.01": [
- "PHP License v3.01",
- false
- ],
- "Plexus": [
- "Plexus Classworlds License",
- false
- ],
- "PostgreSQL": [
- "PostgreSQL License",
- true
- ],
- "psfrag": [
- "psfrag License",
- false
- ],
- "psutils": [
- "psutils License",
- false
- ],
- "Python-2.0": [
- "Python License 2.0",
- true
- ],
- "Qhull": [
- "Qhull License",
- false
- ],
- "QPL-1.0": [
- "Q Public License 1.0",
- true
- ],
- "Rdisc": [
- "Rdisc License",
- false
- ],
- "RHeCos-1.1": [
- "Red Hat eCos Public License v1.1",
- false
- ],
- "RPL-1.1": [
- "Reciprocal Public License 1.1",
- true
- ],
- "RPL-1.5": [
- "Reciprocal Public License 1.5",
- true
- ],
- "RPSL-1.0": [
- "RealNetworks Public Source License v1.0",
- true
- ],
- "RSA-MD": [
- "RSA Message-Digest License",
- false
- ],
- "RSCPL": [
- "Ricoh Source Code Public License",
- true
- ],
- "Ruby": [
- "Ruby License",
- false
- ],
- "SAX-PD": [
- "Sax Public Domain Notice",
- false
- ],
- "Saxpath": [
- "Saxpath License",
- false
- ],
- "SCEA": [
- "SCEA Shared Source License",
- false
- ],
- "SGI-B-1.0": [
- "SGI Free Software License B v1.0",
- false
- ],
- "SGI-B-1.1": [
- "SGI Free Software License B v1.1",
- false
- ],
- "SGI-B-2.0": [
- "SGI Free Software License B v2.0",
- false
- ],
- "SimPL-2.0": [
- "Simple Public License 2.0",
- true
- ],
- "SISSL": [
- "Sun Industry Standards Source License v1.1",
- true
- ],
- "SISSL-1.2": [
- "Sun Industry Standards Source License v1.2",
- false
- ],
- "Sleepycat": [
- "Sleepycat License",
- true
- ],
- "SMLNJ": [
- "Standard ML of New Jersey License",
- false
- ],
- "SNIA": [
- "SNIA Public License 1.1",
- false
- ],
- "Spencer-86": [
- "Spencer License 86",
- false
- ],
- "Spencer-94": [
- "Spencer License 94",
- false
- ],
- "Spencer-99": [
- "Spencer License 99",
- false
- ],
- "SPL-1.0": [
- "Sun Public License v1.0",
- true
- ],
- "SugarCRM-1.1.3": [
- "SugarCRM Public License v1.1.3",
- false
- ],
- "SWL": [
- "Scheme Widget Library (SWL) Software License Agreement",
- false
- ],
- "TCL": [
- "TCL/TK License",
- false
- ],
- "TMate": [
- "TMate Open Source License",
- false
- ],
- "TORQUE-1.1": [
- "TORQUE v2.5+ Software License v1.1",
- false
- ],
- "TOSL": [
- "Trusster Open Source License",
- false
- ],
- "Unicode-TOU": [
- "Unicode Terms of Use",
- false
- ],
- "Unlicense": [
- "The Unlicense",
- false
- ],
- "UPL-1.0": [
- "Universal Permissive License v1.0",
- true
- ],
- "Vim": [
- "Vim License",
- false
- ],
- "VOSTROM": [
- "VOSTROM Public License for Open Source",
- false
- ],
- "VSL-1.0": [
- "Vovida Software License v1.0",
- true
- ],
- "W3C": [
- "W3C Software Notice and License (2002-12-31)",
- true
- ],
- "W3C-19980720": [
- "W3C Software Notice and License (1998-07-20)",
- false
- ],
- "Watcom-1.0": [
- "Sybase Open Watcom Public License 1.0",
- true
- ],
- "Wsuipa": [
- "Wsuipa License",
- false
- ],
- "WTFPL": [
- "Do What The F*ck You Want To Public License",
- false
- ],
- "X11": [
- "X11 License",
- false
- ],
- "Xerox": [
- "Xerox License",
- false
- ],
- "XFree86-1.1": [
- "XFree86 License 1.1",
- false
- ],
- "xinetd": [
- "xinetd License",
- false
- ],
- "Xnet": [
- "X.Net License",
- true
- ],
- "xpp": [
- "XPP License",
- false
- ],
- "XSkat": [
- "XSkat License",
- false
- ],
- "YPL-1.0": [
- "Yahoo! Public License v1.0",
- false
- ],
- "YPL-1.1": [
- "Yahoo! Public License v1.1",
- false
- ],
- "Zed": [
- "Zed License",
- false
- ],
- "Zend-2.0": [
- "Zend License v2.0",
- false
- ],
- "Zimbra-1.3": [
- "Zimbra Public License v1.3",
- false
- ],
- "Zimbra-1.4": [
- "Zimbra Public License v1.4",
- false
- ],
- "Zlib": [
- "zlib License",
- true
- ],
- "zlib-acknowledgement": [
- "zlib/libpng License with Acknowledgement",
- false
- ],
- "ZPL-1.1": [
- "Zope Public License 1.1",
- false
- ],
- "ZPL-2.0": [
- "Zope Public License 2.0",
- true
- ],
- "ZPL-2.1": [
- "Zope Public License 2.1",
- false
- ]
- }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)) {
- 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)) {
- 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) && false === getenv('SHELL_INTERACTIVE')) {
- $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 ('' !== $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_text' => $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 &$commandsSet) {
- ksort($commandsSet);
- }
- unset($commandsSet);
- 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(" command [options] [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('/([^\\\\]?)</', '$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)
- {
- $message = (string) $message;
- $offset = 0;
- $output = '';
- $tagRegex = '[a-z][a-z0-9_=;-]*';
- preg_match_all("#<(($tagRegex) | /($tagRegex)?)>#ix", $message, $matches, PREG_OFFSET_CAPTURE);
- foreach ($matches[0] as $i => $match) {
- $pos = $match[1];
- $text = $match[0];
- if (0 != $pos && '\\' == $message[$pos - 1]) {
- continue;
- }
- $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 (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),
- 'default' => array('set' => 39, '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),
- 'default' => array('set' => 49, '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 (!in_array(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', 'default');
- 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));
- }
- $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)
- {
- $e = null;
- while (false === $attempts || $attempts--) {
- if (null !== $e) {
- $output->writeln($this->getHelperSet()->get('formatter')->formatBlock($e->getMessage(), 'error'));
- }
- try {
- return call_user_func($validator, $interviewer());
- } catch (\Exception $e) {
- }
- }
- throw $e;
- }
- }
- <?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)
- {
- if (!is_array($messages)) {
- $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();
- for ($i = 0; isset($lines[$i]); ++$i) {
- $messages[] = $lines[$i].str_repeat(' ', $len - $this->strlen($lines[$i]));
- }
- if ($large) {
- $messages[] = str_repeat(' ', $len);
- }
- for ($i = 0; isset($messages[$i]); ++$i) {
- $messages[$i] = sprintf('<%s>%s</%s>', $style, $messages[$i], $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 = (int) ($this->step / $this->redrawFreq);
- $currPeriod = (int) ($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 = (int) ($this->current / $this->redrawFreq);
- $this->current = $current;
- $currPeriod = (int) ($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 $this;
- }
- 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 (false === strpos($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_strwidth') && false !== $encoding = mb_detect_encoding($cell)) {
- $width += strlen($cell) - mb_strwidth($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));
- }
- 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)) {
- if (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)
- {
- parent::__construct($this->openOutputStream(), $verbosity, $decorated, $formatter);
- $this->stderr = new StreamOutput($this->openErrorStream(), $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 false === $this->isRunningOS400();
- }
- protected function hasStderrSupport()
- {
- return false === $this->isRunningOS400();
- }
- private function isRunningOS400()
- {
- return 'OS400' === php_uname('s');
- }
- private function openOutputStream()
- {
- $outputStream = $this->hasStdoutSupport() ? 'php://stdout' : 'php://output';
- return @fopen($outputStream, 'w') ?: fopen('php://output', 'w');
- }
- private function openErrorStream()
- {
- $errorStream = $this->hasStderrSupport() ? 'php://stderr' : 'php://output';
- return fopen($errorStream, 'w');
- }
- }
- <?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));
- }
- $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 = (false === $line || '' === $line) ? 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 = array_merge(array('command' => $this->command->getName()), $input);
- }
- $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\Filesystem\Exception;
- interface ExceptionInterface
- {
- }
- <?php
- namespace Symfony\Component\Filesystem\Exception;
- class FileNotFoundException extends IOException
- {
- public function __construct($message = null, $code = 0, \Exception $previous = null, $path = null)
- {
- if (null === $message) {
- if (null === $path) {
- $message = 'File could not be found.';
- } else {
- $message = sprintf('File "%s" could not be found.', $path);
- }
- }
- parent::__construct($message, $code, $previous, $path);
- }
- }
- <?php
- namespace Symfony\Component\Filesystem\Exception;
- class IOException extends \RuntimeException implements IOExceptionInterface
- {
- private $path;
- public function __construct($message, $code = 0, \Exception $previous = null, $path = null)
- {
- $this->path = $path;
- parent::__construct($message, $code, $previous);
- }
- public function getPath()
- {
- return $this->path;
- }
- }
- <?php
- namespace Symfony\Component\Filesystem\Exception;
- interface IOExceptionInterface extends ExceptionInterface
- {
- public function getPath();
- }
- <?php
- namespace Symfony\Component\Filesystem;
- use Symfony\Component\Filesystem\Exception\IOException;
- use Symfony\Component\Filesystem\Exception\FileNotFoundException;
- class Filesystem
- {
- public function copy($originFile, $targetFile, $override = false)
- {
- if (stream_is_local($originFile) && !is_file($originFile)) {
- throw new FileNotFoundException(sprintf('Failed to copy "%s" because file does not exist.', $originFile), 0, null, $originFile);
- }
- $this->mkdir(dirname($targetFile));
- $doCopy = true;
- if (!$override && null === parse_url($originFile, PHP_URL_HOST) && is_file($targetFile)) {
- $doCopy = filemtime($originFile) > filemtime($targetFile);
- }
- if ($doCopy) {
- if (false === $source = @fopen($originFile, 'r')) {
- throw new IOException(sprintf('Failed to copy "%s" to "%s" because source file could not be opened for reading.', $originFile, $targetFile), 0, null, $originFile);
- }
- if (false === $target = @fopen($targetFile, 'w', null, stream_context_create(array('ftp' => array('overwrite' => true))))) {
- throw new IOException(sprintf('Failed to copy "%s" to "%s" because target file could not be opened for writing.', $originFile, $targetFile), 0, null, $originFile);
- }
- $bytesCopied = stream_copy_to_stream($source, $target);
- fclose($source);
- fclose($target);
- unset($source, $target);
- if (!is_file($targetFile)) {
- throw new IOException(sprintf('Failed to copy "%s" to "%s".', $originFile, $targetFile), 0, null, $originFile);
- }
- if (stream_is_local($originFile) && $bytesCopied !== filesize($originFile)) {
- throw new IOException(sprintf('Failed to copy the whole content of "%s" to "%s %g bytes copied".', $originFile, $targetFile, $bytesCopied), 0, null, $originFile);
- }
- }
- }
- public function mkdir($dirs, $mode = 0777)
- {
- foreach ($this->toIterator($dirs) as $dir) {
- if (is_dir($dir)) {
- continue;
- }
- if (true !== @mkdir($dir, $mode, true)) {
- $error = error_get_last();
- if (!is_dir($dir)) {
- if ($error) {
- throw new IOException(sprintf('Failed to create "%s": %s.', $dir, $error['message']), 0, null, $dir);
- }
- throw new IOException(sprintf('Failed to create "%s"', $dir), 0, null, $dir);
- }
- }
- }
- }
- public function exists($files)
- {
- foreach ($this->toIterator($files) as $file) {
- if (!file_exists($file)) {
- return false;
- }
- }
- return true;
- }
- public function touch($files, $time = null, $atime = null)
- {
- foreach ($this->toIterator($files) as $file) {
- $touch = $time ? @touch($file, $time, $atime) : @touch($file);
- if (true !== $touch) {
- throw new IOException(sprintf('Failed to touch "%s".', $file), 0, null, $file);
- }
- }
- }
- public function remove($files)
- {
- $files = iterator_to_array($this->toIterator($files));
- $files = array_reverse($files);
- foreach ($files as $file) {
- if (!file_exists($file) && !is_link($file)) {
- continue;
- }
- if (is_dir($file) && !is_link($file)) {
- $this->remove(new \FilesystemIterator($file));
- if (true !== @rmdir($file)) {
- throw new IOException(sprintf('Failed to remove directory "%s".', $file), 0, null, $file);
- }
- } else {
- if ('\\' === DIRECTORY_SEPARATOR && is_dir($file)) {
- if (true !== @rmdir($file)) {
- throw new IOException(sprintf('Failed to remove file "%s".', $file), 0, null, $file);
- }
- } else {
- if (true !== @unlink($file)) {
- throw new IOException(sprintf('Failed to remove file "%s".', $file), 0, null, $file);
- }
- }
- }
- }
- }
- public function chmod($files, $mode, $umask = 0000, $recursive = false)
- {
- foreach ($this->toIterator($files) as $file) {
- if ($recursive && is_dir($file) && !is_link($file)) {
- $this->chmod(new \FilesystemIterator($file), $mode, $umask, true);
- }
- if (true !== @chmod($file, $mode & ~$umask)) {
- throw new IOException(sprintf('Failed to chmod file "%s".', $file), 0, null, $file);
- }
- }
- }
- public function chown($files, $user, $recursive = false)
- {
- foreach ($this->toIterator($files) as $file) {
- if ($recursive && is_dir($file) && !is_link($file)) {
- $this->chown(new \FilesystemIterator($file), $user, true);
- }
- if (is_link($file) && function_exists('lchown')) {
- if (true !== @lchown($file, $user)) {
- throw new IOException(sprintf('Failed to chown file "%s".', $file), 0, null, $file);
- }
- } else {
- if (true !== @chown($file, $user)) {
- throw new IOException(sprintf('Failed to chown file "%s".', $file), 0, null, $file);
- }
- }
- }
- }
- public function chgrp($files, $group, $recursive = false)
- {
- foreach ($this->toIterator($files) as $file) {
- if ($recursive && is_dir($file) && !is_link($file)) {
- $this->chgrp(new \FilesystemIterator($file), $group, true);
- }
- if (is_link($file) && function_exists('lchgrp')) {
- if (true !== @lchgrp($file, $group) || (defined('HHVM_VERSION') && !posix_getgrnam($group))) {
- throw new IOException(sprintf('Failed to chgrp file "%s".', $file), 0, null, $file);
- }
- } else {
- if (true !== @chgrp($file, $group)) {
- throw new IOException(sprintf('Failed to chgrp file "%s".', $file), 0, null, $file);
- }
- }
- }
- }
- public function rename($origin, $target, $overwrite = false)
- {
- if (!$overwrite && is_readable($target)) {
- throw new IOException(sprintf('Cannot rename because the target "%s" already exists.', $target), 0, null, $target);
- }
- if (true !== @rename($origin, $target)) {
- throw new IOException(sprintf('Cannot rename "%s" to "%s".', $origin, $target), 0, null, $target);
- }
- }
- public function symlink($originDir, $targetDir, $copyOnWindows = false)
- {
- if ('\\' === DIRECTORY_SEPARATOR && $copyOnWindows) {
- $this->mirror($originDir, $targetDir);
- return;
- }
- $this->mkdir(dirname($targetDir));
- $ok = false;
- if (is_link($targetDir)) {
- if (readlink($targetDir) != $originDir) {
- $this->remove($targetDir);
- } else {
- $ok = true;
- }
- }
- if (!$ok && true !== @symlink($originDir, $targetDir)) {
- $report = error_get_last();
- if (is_array($report)) {
- if ('\\' === DIRECTORY_SEPARATOR && false !== strpos($report['message'], 'error code(1314)')) {
- throw new IOException('Unable to create symlink due to error code 1314: \'A required privilege is not held by the client\'. Do you have the required Administrator-rights?');
- }
- throw new IOException(sprintf('Failed to create symbolic link from "%s" to "%s".', $originDir, $targetDir), 0, null, $targetDir);
- }
- throw new IOException(sprintf('Failed to create symbolic link from %s to %s', $originDir, $targetDir));
- }
- }
- public function makePathRelative($endPath, $startPath)
- {
- if ('\\' === DIRECTORY_SEPARATOR) {
- $endPath = strtr($endPath, '\\', '/');
- $startPath = strtr($startPath, '\\', '/');
- }
- $startPathArr = explode('/', trim($startPath, '/'));
- $endPathArr = explode('/', trim($endPath, '/'));
- $index = 0;
- while (isset($startPathArr[$index]) && isset($endPathArr[$index]) && $startPathArr[$index] === $endPathArr[$index]) {
- ++$index;
- }
- $depth = count($startPathArr) - $index;
- $traverser = str_repeat('../', $depth);
- $endPathRemainder = implode('/', array_slice($endPathArr, $index));
- $relativePath = $traverser.('' !== $endPathRemainder ? $endPathRemainder.'/' : '');
- return '' === $relativePath ? './' : $relativePath;
- }
- public function mirror($originDir, $targetDir, \Traversable $iterator = null, $options = array())
- {
- $targetDir = rtrim($targetDir, '/\\');
- $originDir = rtrim($originDir, '/\\');
- if ($this->exists($targetDir) && isset($options['delete']) && $options['delete']) {
- $deleteIterator = $iterator;
- if (null === $deleteIterator) {
- $flags = \FilesystemIterator::SKIP_DOTS;
- $deleteIterator = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($targetDir, $flags), \RecursiveIteratorIterator::CHILD_FIRST);
- }
- foreach ($deleteIterator as $file) {
- $origin = str_replace($targetDir, $originDir, $file->getPathname());
- if (!$this->exists($origin)) {
- $this->remove($file);
- }
- }
- }
- $copyOnWindows = false;
- if (isset($options['copy_on_windows'])) {
- $copyOnWindows = $options['copy_on_windows'];
- }
- if (null === $iterator) {
- $flags = $copyOnWindows ? \FilesystemIterator::SKIP_DOTS | \FilesystemIterator::FOLLOW_SYMLINKS : \FilesystemIterator::SKIP_DOTS;
- $iterator = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($originDir, $flags), \RecursiveIteratorIterator::SELF_FIRST);
- }
- if ($this->exists($originDir)) {
- $this->mkdir($targetDir);
- }
- foreach ($iterator as $file) {
- $target = str_replace($originDir, $targetDir, $file->getPathname());
- if ($copyOnWindows) {
- if (is_link($file) || is_file($file)) {
- $this->copy($file, $target, isset($options['override']) ? $options['override'] : false);
- } elseif (is_dir($file)) {
- $this->mkdir($target);
- } else {
- throw new IOException(sprintf('Unable to guess "%s" file type.', $file), 0, null, $file);
- }
- } else {
- if (is_link($file)) {
- $this->symlink($file->getRealPath(), $target);
- } elseif (is_dir($file)) {
- $this->mkdir($target);
- } elseif (is_file($file)) {
- $this->copy($file, $target, isset($options['override']) ? $options['override'] : false);
- } else {
- throw new IOException(sprintf('Unable to guess "%s" file type.', $file), 0, null, $file);
- }
- }
- }
- }
- public function isAbsolutePath($file)
- {
- return (strspn($file, '/\\', 0, 1)
- || (strlen($file) > 3 && ctype_alpha($file[0])
- && substr($file, 1, 1) === ':'
- && (strspn($file, '/\\', 2, 1))
- )
- || null !== parse_url($file, PHP_URL_SCHEME)
- );
- }
- public function dumpFile($filename, $content, $mode = 0666)
- {
- $dir = dirname($filename);
- if (!is_dir($dir)) {
- $this->mkdir($dir);
- } elseif (!is_writable($dir)) {
- throw new IOException(sprintf('Unable to write to the "%s" directory.', $dir), 0, null, $dir);
- }
- $tmpFile = tempnam($dir, basename($filename));
- if (false === @file_put_contents($tmpFile, $content)) {
- throw new IOException(sprintf('Failed to write file "%s".', $filename), 0, null, $filename);
- }
- $this->rename($tmpFile, $filename, true);
- if (null !== $mode) {
- $this->chmod($filename, $mode);
- }
- }
- private function toIterator($files)
- {
- if (!$files instanceof \Traversable) {
- $files = new \ArrayObject(is_array($files) ? $files : array($files));
- }
- return $files;
- }
- }
- 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\Filesystem;
- use Symfony\Component\Filesystem\Exception\IOException;
- class LockHandler
- {
- private $file;
- private $handle;
- public function __construct($name, $lockPath = null)
- {
- $lockPath = $lockPath ?: sys_get_temp_dir();
- if (!is_dir($lockPath)) {
- $fs = new Filesystem();
- $fs->mkdir($lockPath);
- }
- if (!is_writable($lockPath)) {
- throw new IOException(sprintf('The directory "%s" is not writable.', $lockPath), 0, null, $lockPath);
- }
- $this->file = sprintf('%s/sf.%s.%s.lock', $lockPath, preg_replace('/[^a-z0-9\._-]+/i', '-', $name), hash('sha256', $name));
- }
- public function lock($blocking = false)
- {
- if ($this->handle) {
- return true;
- }
- $errorLevel = error_reporting(0);
- set_error_handler('var_dump', 0);
- if (!$this->handle = fopen($this->file, 'r')) {
- if ($this->handle = fopen($this->file, 'x')) {
- chmod($this->file, 0444);
- } elseif (!$this->handle = fopen($this->file, 'r')) {
- usleep(100);
- $this->handle = fopen($this->file, 'r');
- }
- }
- restore_error_handler();
- error_reporting($errorLevel);
- if (!$this->handle) {
- $error = error_get_last();
- throw new IOException($error['message'], 0, null, $this->file);
- }
-
- if (!flock($this->handle, LOCK_EX | ($blocking ? 0 : LOCK_NB))) {
- fclose($this->handle);
- $this->handle = null;
- return false;
- }
- return true;
- }
- public function release()
- {
- if ($this->handle) {
- flock($this->handle, LOCK_UN | LOCK_NB);
- fclose($this->handle);
- $this->handle = null;
- }
- }
- }
- <?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 |= static::IGNORE_DOT_FILES;
- } else {
- $this->ignore &= ~static::IGNORE_DOT_FILES;
- }
- return $this;
- }
- public function ignoreVCS($ignoreVCS)
- {
- if ($ignoreVCS) {
- $this->ignore |= static::IGNORE_VCS_FILES;
- } else {
- $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, (defined('GLOB_BRACE') ? GLOB_BRACE : 0) | 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;
- 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;
- 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;
- 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 instanceof self ? array($bit) : $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 (getenv('PHP_BINARY') ?: 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
- {
- public function __construct($script, $cwd = null, array $env = array(), $timeout = 60, array $options = array())
- {
- $executableFinder = new PhpExecutableFinder();
- if (false === $php = $executableFinder->find()) {
- $php = null;
- }
- parent::__construct($php, $cwd, $env, $script, $timeout, $options);
- }
- public function setPhpBinary($php)
- {
- $this->setCommandLine($php);
- }
- public function start($callback = null)
- {
- if (null === $this->getCommandLine()) {
- throw new RuntimeException('Unable to find the PHP executable.');
- }
- 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.');
- }
- if ($tty && (!file_exists('/dev/tty') || !is_readable('/dev/tty'))) {
- throw new RuntimeException('TTY mode requires /dev/tty to be readable.');
- }
- $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('/(")/', $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];
- }
- }
- 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) 2015 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
- require __DIR__.'/../vendor/autoload.php';
- echo 'Say hello (visible): ';
- $answer = Seld\CliPrompt\CliPrompt::prompt();
- echo 'You answered: '.$answer . PHP_EOL;
- echo 'Say hello (hidden): ';
- $answer = Seld\CliPrompt\CliPrompt::hiddenPrompt();
- echo 'You answered: '.$answer . PHP_EOL;
- <?php
- namespace Seld\CliPrompt;
- class CliPrompt
- {
- public static function prompt()
- {
- $stdin = fopen('php://stdin', 'r');
- $answer = self::trimAnswer(fgets($stdin, 4096));
- fclose($stdin);
- return $answer;
- }
- public static function hiddenPrompt($allowFallback = false)
- {
- if (defined('PHP_WINDOWS_VERSION_BUILD')) {
- $exe = __DIR__.'\\..\\res\\hiddeninput.exe';
- if ('phar:' === substr(__FILE__, 0, 5)) {
- $tmpExe = sys_get_temp_dir().'/hiddeninput.exe';
-
- $source = fopen($exe, 'r');
- $target = fopen($tmpExe, 'w+');
- stream_copy_to_stream($source, $target);
- fclose($source);
- fclose($target);
- unset($source, $target);
- $exe = $tmpExe;
- }
- $answer = self::trimAnswer(shell_exec($exe));
- if (isset($tmpExe)) {
- unlink($tmpExe);
- }
- echo PHP_EOL;
- return $answer;
- }
- 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)) {
- $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 = self::trimAnswer(shell_exec($command));
- echo PHP_EOL;
- return $value;
- }
- }
- if (!$allowFallback) {
- throw new \RuntimeException('Could not prompt for input in a secure fashion, aborting');
- }
- return self::prompt();
- }
- private static function trimAnswer($str)
- {
- return preg_replace('{\r?\n$}D', '', $str);
- }
- }
- 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 CollectionConstraint 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 . " items in the array");
- }
- if (isset($schema->maxItems) && count($value) > $schema->maxItems) {
- $this->addError($path, "There must be a maximum of " . $schema->maxItems . " items 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 UndefinedConstraint(), $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 CollectionConstraint($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 ObjectConstraint($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 TypeConstraint($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 UndefinedConstraint($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 StringConstraint($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 NumberConstraint($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 EnumConstraint($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 FormatConstraint($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 EnumConstraint extends Constraint
- {
- public function check($element, $schema = null, $path = null, $i = null)
- {
- if ($element instanceof UndefinedConstraint && (!isset($schema->required) || !$schema->required)) {
- return;
- }
- foreach ($schema->enum as $enum) {
- $type = gettype($element);
- if ($type === gettype($enum)) {
- if ($type == "object") {
- if ($element == $enum)
- return;
- } else {
- if ($element === $enum)
- return;
- }
- }
- }
- $this->addError($path, "Does not have a value in the enumeration " . print_r($schema->enum, true));
- }
- }
- <?php
- namespace JsonSchema\Constraints;
- class FormatConstraint 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:
- 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 NumberConstraint 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 ObjectConstraint extends Constraint
- {
- function check($element, $definition = null, $path = null, $additionalProp = null, $patternProperties = null)
- {
- if ($element instanceof UndefinedConstraint) {
- 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 UndefinedConstraint());
- $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 UndefinedConstraint());
- $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 SchemaConstraint 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 StringConstraint 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 TypeConstraint 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 TypeConstraint($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) {
- $this->addErrors($errors);
- return;
- }
- } 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 UndefinedConstraint 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 UndefinedConstraint) && isset($schema->required) && is_array($schema->required) ) {
- foreach ($schema->required as $required) {
- if (!property_exists($value, $required)) {
- $this->addError($required, "The property " . $required . " is required");
- }
- }
- } else if (isset($schema->required) && !is_array($schema->required)) {
- if ( $schema->required && $value instanceof UndefinedConstraint) {
- $this->addError($path, "Is missing and it is required");
- }
- }
- }
- if (!($value instanceof UndefinedConstraint)) {
- $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 UndefinedConstraint) {
- 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\Exception\JsonDecodingException;
- use JsonSchema\Uri\Retrievers\UriRetrieverInterface;
- use JsonSchema\Uri\UriRetriever;
- class RefResolver
- {
- protected static $depth = 0;
- public static $maxDepth = 7;
- protected $uriRetriever = null;
- protected $rootSchema = 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) {
- throw new JsonDecodingException(JSON_ERROR_DEPTH);
- }
- ++self::$depth;
- if (! is_object($schema)) {
- --self::$depth;
- return;
- }
- if (null === $sourceUri && ! empty($schema->id)) {
- $sourceUri = $schema->id;
- }
- if (null === $this->rootSchema) {
- $this->rootSchema = $schema;
- }
- $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;
- }
- $splitRef = explode('#', $schema->$ref, 2);
- $refDoc = $splitRef[0];
- $refPath = null;
- if (count($splitRef) === 2) {
- $refPath = explode('/', $splitRef[1]);
- array_shift($refPath);
- }
- if (empty($refDoc) && empty($refPath)) {
- return;
- }
- if (!empty($refDoc)) {
- $refSchema = $this->fetchRef($refDoc, $sourceUri);
- } else {
- $refSchema = $this->rootSchema;
- }
- if (null !== $refPath) {
- $refSchema = $this->resolveRefSegment($refSchema, $refPath);
- }
- unset($schema->$ref);
- foreach (get_object_vars($refSchema) as $prop => $value) {
- $schema->$prop = $value;
- }
- }
- public function setUriRetriever(UriRetriever $retriever)
- {
- $this->uriRetriever = $retriever;
- return $this;
- }
- protected function resolveRefSegment($data, $pathParts)
- {
- foreach ($pathParts as $path) {
- $path = strtr($path, array('~1' => '/', '~0' => '~', '%25' => '%'));
- if (is_array($data)) {
- $data = $data[$path];
- } else {
- $data = $data->{$path};
- }
- }
- return $data;
- }
- }
- <?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
- )));
- set_error_handler(function() use ($uri) {
- throw new ResourceNotFoundException('JSON schema not found at ' . $uri);
- });
- $response = file_get_contents($uri);
- restore_error_handler();
- 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;
- 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 = explode('/', $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;
- }
- 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;
- use JsonSchema\Exception\ResourceNotFoundException;
- class UriRetriever
- {
- protected $uriRetriever = null;
- private $schemaCache = array();
- 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 ResourceNotFoundException(
- 'Fragment "' . $parsed['fragment'] . '" not found'
- . ' in ' . $uri
- );
- }
- if (! is_object($jsonSchema)) {
- throw new 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);
- if ($jsonSchema instanceof \stdClass) {
- $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'] = UriResolver::combineRelativePathWithBasePath($path, $basePath);
- return $this->generate($baseComponents);
- }
- public function isValid($uri)
- {
- $components = $this->parse($uri);
- return !empty($components);
- }
- }
- <?php
- namespace JsonSchema;
- use JsonSchema\Constraints\SchemaConstraint;
- use JsonSchema\Constraints\Constraint;
- class Validator extends Constraint
- {
- const SCHEMA_MEDIA_TYPE = 'application/schema+json';
- public function check($value, $schema = null, $path = null, $i = null)
- {
- $validator = new SchemaConstraint($this->checkMode, $this->uriRetriever);
- $validator->check($value, $schema);
- $this->addErrors(array_unique($validator->getErrors(), SORT_REGULAR));
- }
- }
- Copyright (C) 2015 Composer
- 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 Composer\Spdx;
- class SpdxLicenses
- {
- const LICENSES_FILE = 'spdx-licenses.json';
- const EXCEPTIONS_FILE = 'spdx-exceptions.json';
- private $licenses;
- private $licensesExpression;
- private $exceptions;
- private $exceptionsExpression;
- public function __construct()
- {
- $this->loadLicenses();
- $this->loadExceptions();
- }
- public function getLicenseByIdentifier($identifier)
- {
- if (!isset($this->licenses[$identifier])) {
- return;
- }
- $license = $this->licenses[$identifier];
- $license[] = 'https://spdx.org/licenses/' . $identifier . '.html#licenseText';
- return $license;
- }
- public function getExceptionByIdentifier($identifier)
- {
- if (!isset($this->exceptions[$identifier])) {
- return;
- }
- $license = $this->exceptions[$identifier];
- $license[] = 'https://spdx.org/licenses/' . $identifier . '.html#licenseExceptionText';
- return $license;
- }
- public function getIdentifierByName($name)
- {
- foreach ($this->licenses as $identifier => $licenseData) {
- if ($licenseData[0] === $name) {
- return $identifier;
- }
- }
- foreach ($this->exceptions as $identifier => $licenseData) {
- if ($licenseData[0] === $name) {
- return $identifier;
- }
- }
- }
- public function isOsiApprovedByIdentifier($identifier)
- {
- return $this->licenses[$identifier][1];
- }
- 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);
- }
- public static function getResourcesDir()
- {
- return dirname(__DIR__) . '/res';
- }
- private function loadLicenses()
- {
- if (null === $this->licenses) {
- $json = file_get_contents(self::getResourcesDir() . '/' . self::LICENSES_FILE);
- $this->licenses = json_decode($json, true);
- }
- }
- private function loadExceptions()
- {
- if (null === $this->exceptions) {
- $json = file_get_contents(self::getResourcesDir() . '/' . self::EXCEPTIONS_FILE);
- $this->exceptions = json_decode($json, true);
- }
- }
- private function getLicensesExpression()
- {
- if (null === $this->licensesExpression) {
- $licenses = array_map('preg_quote', array_keys($this->licenses));
- rsort($licenses);
- $licenses = implode('|', $licenses);
- $this->licensesExpression = $licenses;
- }
- return $this->licensesExpression;
- }
- private function getExceptionsExpression()
- {
- if (null === $this->exceptionsExpression) {
- $exceptions = array_map('preg_quote', array_keys($this->exceptions));
- rsort($exceptions);
- $exceptions = implode('|', $exceptions);
- $this->exceptionsExpression = $exceptions;
- }
- return $this->exceptionsExpression;
- }
- private function isValidLicenseString($license)
- {
- if (isset($this->licenses[$license])) {
- return true;
- }
- $licenses = $this->getLicensesExpression();
- $exceptions = $this->getExceptionsExpression();
- $regex = <<<REGEX
- {
- (?(DEFINE)
- # idstring: 1*( ALPHA / DIGIT / - / . )
- (?<idstring>[\pL\pN.-]{1,})
- # license-id: taken from list
- (?<licenseid>${licenses})
- # license-exception-id: taken from list
- (?<licenseexceptionid>${exceptions})
- # license-ref: [DocumentRef-1*(idstring):]LicenseRef-1*(idstring)
- (?<licenseref>(?:DocumentRef-(?&idstring):)?LicenseRef-(?&idstring))
- # simple-expresssion: license-id / license-id+ / license-ref
- (?<simple_expression>(?&licenseid)\+? | (?&licenseid) | (?&licenseref))
- # compound-expression: 1*(
- # simple-expression /
- # simple-expression WITH license-exception-id /
- # compound-expression AND compound-expression /
- # compound-expression OR compound-expression
- # ) / ( compound-expression ) )
- (?<compound_head>
- (?&simple_expression) ( \s+ (?:with|WITH) \s+ (?&licenseexceptionid))?
- | \( \s* (?&compound_expression) \s* \)
- )
- (?<compound_expression>
- (?&compound_head) (?: \s+ (?:and|AND|or|OR) \s+ (?&compound_expression))?
- )
- # license-expression: 1*1(simple-expression / compound-expression)
- (?<license_expression>(?&compound_expression) | (?&simple_expression))
- ) # end of define
- ^(NONE | NOASSERTION | (?&license_expression))$
- }x
- REGEX;
- $match = preg_match($regex, $license);
- if (0 === $match) {
- return false;
- }
- if (false === $match) {
- throw new \RuntimeException('Regex failed to compile/run.');
- }
- return true;
- }
- }
- Copyright (C) 2015 Composer
- 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 Composer\Semver;
- use Composer\Semver\Constraint\Constraint;
- class Comparator
- {
- public static function greaterThan($version1, $version2)
- {
- return self::compare($version1, '>', $version2);
- }
- public static function greaterThanOrEqualTo($version1, $version2)
- {
- return self::compare($version1, '>=', $version2);
- }
- public static function lessThan($version1, $version2)
- {
- return self::compare($version1, '<', $version2);
- }
- public static function lessThanOrEqualTo($version1, $version2)
- {
- return self::compare($version1, '<=', $version2);
- }
- public static function equalTo($version1, $version2)
- {
- return self::compare($version1, '==', $version2);
- }
- public static function notEqualTo($version1, $version2)
- {
- return self::compare($version1, '!=', $version2);
- }
- public static function compare($version1, $operator, $version2)
- {
- $constraint = new Constraint($operator, $version2);
- return $constraint->matches(new Constraint('==', $version1));
- }
- }
- <?php
- namespace Composer\Semver\Constraint;
- abstract class AbstractConstraint implements ConstraintInterface
- {
- protected $prettyString;
- public function matches(ConstraintInterface $provider)
- {
- if ($provider instanceof MultiConstraint) {
- return $provider->matches($this);
- }
- if ($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\Semver\Constraint;
- class Constraint extends AbstractConstraint
- {
- const OP_EQ = 0;
- const OP_LT = 1;
- const OP_LE = 2;
- const OP_GT = 3;
- const OP_GE = 4;
- const OP_NE = 5;
- private static $transOpStr = array(
- '=' => self::OP_EQ,
- '==' => self::OP_EQ,
- '<' => self::OP_LT,
- '<=' => self::OP_LE,
- '>' => self::OP_GT,
- '>=' => self::OP_GE,
- '<>' => self::OP_NE,
- '!=' => self::OP_NE,
- );
- private static $transOpInt = array(
- self::OP_EQ => '==',
- self::OP_LT => '<',
- self::OP_LE => '<=',
- self::OP_GT => '>',
- self::OP_GE => '>=',
- self::OP_NE => '!=',
- );
- private $operator;
- private $version;
- public static function getSupportedOperators()
- {
- return array_keys(self::$transOpStr);
- }
- public function __construct($operator, $version)
- {
- if (!isset(self::$transOpStr[$operator])) {
- throw new \InvalidArgumentException(sprintf(
- 'Invalid operator "%s" given, expected one of: %s',
- $operator,
- implode(', ', self::getSupportedOperators())
- ));
- }
- $this->operator = self::$transOpStr[$operator];
- $this->version = $version;
- }
- public function versionCompare($a, $b, $operator, $compareBranches = false)
- {
- if (!isset(self::$transOpStr[$operator])) {
- throw new \InvalidArgumentException(sprintf(
- 'Invalid operator "%s" given, expected one of: %s',
- $operator,
- implode(', ', self::getSupportedOperators())
- ));
- }
- $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(Constraint $provider, $compareBranches = false)
- {
- $noEqualOp = str_replace('=', '', self::$transOpInt[$this->operator]);
- $providerNoEqualOp = str_replace('=', '', self::$transOpInt[$provider->operator]);
- $isEqualOp = self::OP_EQ === $this->operator;
- $isNonEqualOp = self::OP_NE === $this->operator;
- $isProviderEqualOp = self::OP_EQ === $provider->operator;
- $isProviderNonEqualOp = self::OP_NE === $provider->operator;
-
- if ($isNonEqualOp || $isProviderNonEqualOp) {
- return !$isEqualOp && !$isProviderEqualOp
- || $this->versionCompare($provider->version, $this->version, '!=', $compareBranches);
- }
-
- if ($this->operator !== self::OP_EQ && $noEqualOp === $providerNoEqualOp) {
- return true;
- }
- if ($this->versionCompare($provider->version, $this->version, self::$transOpInt[$this->operator], $compareBranches)) {
-
- if ($provider->version === $this->version
- && self::$transOpInt[$provider->operator] === $providerNoEqualOp
- && self::$transOpInt[$this->operator] !== $noEqualOp) {
- return false;
- }
- return true;
- }
- return false;
- }
- public function __toString()
- {
- return self::$transOpInt[$this->operator] . ' ' . $this->version;
- }
- }
- <?php
- namespace Composer\Semver\Constraint;
- interface ConstraintInterface
- {
- public function matches(ConstraintInterface $provider);
- public function setPrettyString($prettyString);
- public function getPrettyString();
- public function __toString();
- }
- <?php
- namespace Composer\Semver\Constraint;
- class EmptyConstraint implements ConstraintInterface
- {
- protected $prettyString;
- public function matches(ConstraintInterface $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\Semver\Constraint;
- class MultiConstraint implements ConstraintInterface
- {
- protected $constraints;
- protected $prettyString;
- protected $conjunctive;
- public function __construct(array $constraints, $conjunctive = true)
- {
- $this->constraints = $constraints;
- $this->conjunctive = $conjunctive;
- }
- public function matches(ConstraintInterface $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[] = (string) $constraint;
- }
- return '[' . implode($this->conjunctive ? ' ' : ' || ', $constraints) . ']';
- }
- }
- <?php
- namespace Composer\Semver;
- use Composer\Semver\Constraint\Constraint;
- class Semver
- {
- const SORT_ASC = 1;
- const SORT_DESC = -1;
- private static $versionParser;
- public static function satisfies($version, $constraints)
- {
- if (null === self::$versionParser) {
- self::$versionParser = new VersionParser();
- }
- $versionParser = self::$versionParser;
- $provider = new Constraint('==', $versionParser->normalize($version));
- $constraints = $versionParser->parseConstraints($constraints);
- return $constraints->matches($provider);
- }
- public static function satisfiedBy(array $versions, $constraints)
- {
- $versions = array_filter($versions, function ($version) use ($constraints) {
- return Semver::satisfies($version, $constraints);
- });
- return array_values($versions);
- }
- public static function sort(array $versions)
- {
- return self::usort($versions, self::SORT_ASC);
- }
- public static function rsort(array $versions)
- {
- return self::usort($versions, self::SORT_DESC);
- }
- private static function usort(array $versions, $direction)
- {
- if (null === self::$versionParser) {
- self::$versionParser = new VersionParser();
- }
- $versionParser = self::$versionParser;
- $normalized = array();
-
- foreach ($versions as $key => $version) {
- $normalized[] = array($versionParser->normalize($version), $key);
- }
- usort($normalized, function (array $left, array $right) use ($direction) {
- if ($left[0] === $right[0]) {
- return 0;
- }
- if (Comparator::lessThan($left[0], $right[0])) {
- return -$direction;
- }
- return $direction;
- });
- $sorted = array();
- foreach ($normalized as $item) {
- $sorted[] = $versions[$item[1]];
- }
- return $sorted;
- }
- }
- <?php
- namespace Composer\Semver;
- use Composer\Semver\Constraint\ConstraintInterface;
- use Composer\Semver\Constraint\EmptyConstraint;
- use Composer\Semver\Constraint\MultiConstraint;
- use Composer\Semver\Constraint\Constraint;
- class VersionParser
- {
- private static $modifierRegex = '[._-]?(?:(stable|beta|b|RC|alpha|a|patch|pl|p)(?:[.-]?(\d+))?)?([.-]?dev)?';
- private static $stabilities = array(
- 'stable', 'RC', 'beta', 'alpha', '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 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,5})(\.\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;
- }
- 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 parseConstraints($constraints)
- {
- $prettyConstraint = $constraints;
- if (preg_match('{^([^,\s]*?)@(' . implode('|', self::$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) {
- foreach ($this->parseConstraint($constraint) as $parsedConstraint) {
- $constraintObjects[] = $parsedConstraint;
- }
- }
- } 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('|', self::$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 = 'v?(\d+)(?:\.(\d+))?(?:\.(\d+))?(?:\.(\d+))?' . self::$modifierRegex . '(?:\+[^\s]+)?';
-
-
-
-
- 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 Constraint('>=', $lowVersion);
-
- $highPosition = max(1, $position - 1);
- $highVersion = $this->manipulateVersionString($matches, $highPosition, 1) . '-dev';
- $upperBound = new Constraint('<', $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 Constraint('>=', $lowVersion);
-
- $highVersion = $this->manipulateVersionString($matches, $position, 1) . '-dev';
- $upperBound = new Constraint('<', $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 Constraint('<', $highVersion));
- }
- return array(
- new Constraint('>=', $lowVersion),
- new Constraint('<', $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 Constraint('>=', $lowVersion . $lowStabilitySuffix);
- $empty = function ($x) {
- return ($x === 0 || $x === '0') ? false : empty($x);
- };
- if ((!$empty($matches[11]) && !$empty($matches[12])) || !empty($matches[14]) || !empty($matches[16])) {
- $highVersion = $this->normalize($matches['to']);
- $upperBound = new Constraint('<=', $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 Constraint('<', $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] || '>=' === $matches[1]) {
- if (!preg_match('/-' . self::$modifierRegex . '$/', strtolower($matches[2]))) {
- if (substr($matches[2], 0, 4) !== 'dev-') {
- $version .= '-dev';
- }
- }
- }
- return array(new Constraint($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;
- }
- }
- }
- <?php
- require_once __DIR__ . '/composer' . '/autoload_real.php';
- return ComposerAutoloaderInitComposerPhar1445871666::getLoader();
- <?php
- $vendorDir = dirname(dirname(__FILE__));
- $baseDir = dirname($vendorDir);
- return array(
- 'Symfony\\Component\\Process\\' => array($vendorDir . '/symfony/process'),
- 'Symfony\\Component\\Finder\\' => array($vendorDir . '/symfony/finder'),
- 'Symfony\\Component\\Filesystem\\' => array($vendorDir . '/symfony/filesystem'),
- 'Symfony\\Component\\Console\\' => array($vendorDir . '/symfony/console'),
- 'Composer' => array($baseDir . '/src'),
- );
- <?php
- $vendorDir = dirname(dirname(__FILE__));
- $baseDir = dirname($vendorDir);
- return array(
- 'Seld\\PharUtils\\' => array($vendorDir . '/seld/phar-utils/src'),
- 'Seld\\JsonLint\\' => array($vendorDir . '/seld/jsonlint/src/Seld/JsonLint'),
- 'Seld\\CliPrompt\\' => array($vendorDir . '/seld/cli-prompt/src'),
- 'JsonSchema\\' => array($vendorDir . '/justinrainbow/json-schema/src/JsonSchema'),
- 'Composer\\Spdx\\' => array($vendorDir . '/composer/spdx-licenses/src'),
- 'Composer\\Semver\\' => array($vendorDir . '/composer/semver/src'),
- );
- <?php
- $vendorDir = dirname(dirname(__FILE__));
- $baseDir = dirname($vendorDir);
- return array(
- );
- <?php
- class ComposerAutoloaderInitComposerPhar1445871666
- {
- 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('ComposerAutoloaderInitComposerPhar1445871666', 'loadClassLoader'), true, true);
- self::$loader = $loader = new \Composer\Autoload\ClassLoader();
- spl_autoload_unregister(array('ComposerAutoloaderInitComposerPhar1445871666', 'loadClassLoader'));
- $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 composerRequireComposerPhar1445871666($file)
- {
- require $file;
- }
- <?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 1GB
- if ($memoryLimit != -1 && $memoryInBytes($memoryLimit) < 1024 * 1024 * 1024) {
- @ini_set('memory_limit', '1G');
- }
- unset($memoryInBytes, $memoryLimit);
- }
- // run the command application
- $application = new Application();
- $application->run();
- Copyright (c) 2015 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.
- �î8U�rÛ° k&Úå£èÖŒú^˜���GBMB
|