index.php 295 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757575857595760576157625763576457655766576757685769577057715772577357745775577657775778577957805781578257835784578557865787578857895790579157925793579457955796579757985799580058015802580358045805580658075808580958105811581258135814581558165817581858195820582158225823582458255826582758285829583058315832583358345835583658375838583958405841584258435844584558465847584858495850585158525853585458555856585758585859586058615862586358645865586658675868586958705871587258735874587558765877587858795880588158825883588458855886588758885889589058915892589358945895589658975898589959005901590259035904590559065907590859095910591159125913591459155916591759185919592059215922592359245925592659275928592959305931593259335934593559365937593859395940594159425943594459455946594759485949595059515952595359545955595659575958595959605961596259635964596559665967596859695970597159725973597459755976597759785979598059815982598359845985598659875988598959905991599259935994599559965997599859996000600160026003600460056006600760086009601060116012601360146015601660176018601960206021602260236024602560266027602860296030603160326033603460356036603760386039604060416042604360446045604660476048604960506051605260536054605560566057605860596060606160626063606460656066606760686069607060716072607360746075607660776078607960806081608260836084608560866087608860896090609160926093609460956096609760986099610061016102610361046105610661076108610961106111611261136114611561166117611861196120612161226123612461256126612761286129613061316132613361346135613661376138613961406141614261436144614561466147614861496150615161526153615461556156615761586159616061616162616361646165616661676168616961706171617261736174617561766177617861796180618161826183618461856186618761886189619061916192619361946195619661976198619962006201620262036204620562066207620862096210621162126213621462156216621762186219622062216222622362246225622662276228622962306231623262336234623562366237623862396240624162426243624462456246624762486249625062516252625362546255625662576258625962606261626262636264626562666267626862696270627162726273627462756276627762786279628062816282628362846285628662876288628962906291629262936294629562966297629862996300630163026303630463056306630763086309631063116312631363146315631663176318631963206321632263236324632563266327632863296330633163326333633463356336633763386339634063416342634363446345634663476348634963506351635263536354635563566357635863596360636163626363636463656366636763686369637063716372637363746375637663776378637963806381638263836384638563866387638863896390639163926393639463956396639763986399640064016402640364046405640664076408640964106411641264136414641564166417641864196420642164226423642464256426642764286429643064316432643364346435643664376438643964406441644264436444644564466447644864496450645164526453645464556456645764586459
  1. <?php
  2. /* Copyright (C) 2004-2023 Laurent Destailleur <eldy@users.sourceforge.net>
  3. * Copyright (C) 2018-2019 Nicolas ZABOURI <info@inovea-conseil.com>
  4. * Copyright (C) 2023 Alexandre Janniaux <alexandre.janniaux@gmail.com>
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation; either version 3 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with this program. If not, see <https://www.gnu.org/licenses/>.
  18. *
  19. * You can also make a direct call the page with parameter like this:
  20. * htdocs/modulebuilder/index.php?module=Inventory@/pathtodolibarr/htdocs/product
  21. */
  22. /**
  23. * \file htdocs/modulebuilder/index.php
  24. * \brief Home page for module builder module
  25. *
  26. * You can add parameter dirins=/home/ldestailleur/git/dolibarr/htdocs/mymodule to force generation of module
  27. * into the dirins directory.
  28. */
  29. if (!defined('NOSCANPOSTFORINJECTION')) {
  30. define('NOSCANPOSTFORINJECTION', '1'); // Do not check anti SQL+XSS injection attack test
  31. }
  32. // Load Dolibarr environment
  33. require '../main.inc.php';
  34. require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
  35. require_once DOL_DOCUMENT_ROOT.'/core/lib/admin.lib.php';
  36. require_once DOL_DOCUMENT_ROOT.'/core/class/html.formadmin.class.php';
  37. require_once DOL_DOCUMENT_ROOT.'/core/lib/modulebuilder.lib.php';
  38. require_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php';
  39. require_once DOL_DOCUMENT_ROOT.'/core/class/utils.class.php';
  40. // Load translation files required by the page
  41. $langs->loadLangs(array("admin", "modulebuilder", "other", "cron", "errors"));
  42. // GET Parameters
  43. $action = GETPOST('action', 'aZ09');
  44. $confirm = GETPOST('confirm', 'alpha');
  45. $cancel = GETPOST('cancel', 'alpha');
  46. $sortfield = GETPOST('sortfield', 'alpha');
  47. $sortorder = GETPOST('sortorder', 'alpha');
  48. $module = GETPOST('module', 'alpha');
  49. $tab = GETPOST('tab', 'aZ09');
  50. $tabobj = GETPOST('tabobj', 'alpha');
  51. $tabdic = GETPOST('tabdic', 'alpha');
  52. $propertykey = GETPOST('propertykey', 'alpha');
  53. if (empty($module)) {
  54. $module = 'initmodule';
  55. }
  56. if (empty($tab)) {
  57. $tab = 'description';
  58. }
  59. if (empty($tabobj)) {
  60. $tabobj = 'newobjectifnoobj';
  61. }
  62. if (empty($tabdic)) {
  63. $tabdic = 'newdicifnodic';
  64. }
  65. $file = GETPOST('file', 'alpha');
  66. $modulename = dol_sanitizeFileName(GETPOST('modulename', 'alpha'));
  67. $objectname = dol_sanitizeFileName(GETPOST('objectname', 'alpha'));
  68. $dicname = dol_sanitizeFileName(GETPOST('dicname', 'alpha'));
  69. $editorname= GETPOST('editorname', 'alpha');
  70. $editorurl= GETPOST('editorurl', 'alpha');
  71. $version= GETPOST('version', 'alpha');
  72. $family= GETPOST('family', 'alpha');
  73. $picto= GETPOST('idpicto', 'alpha');
  74. $idmodule= GETPOST('idmodule', 'alpha');
  75. // Security check
  76. if (!isModEnabled('modulebuilder')) {
  77. accessforbidden('Module ModuleBuilder not enabled');
  78. }
  79. if (!$user->hasRight("modulebuilder", "run")) {
  80. accessforbidden('ModuleBuilderNotAllowed');
  81. }
  82. // Dir for custom dirs
  83. $tmp = explode(',', $dolibarr_main_document_root_alt);
  84. $dirins = $tmp[0];
  85. $dirread = $dirins;
  86. $forceddirread = 0;
  87. $tmpdir = explode('@', $module);
  88. if (!empty($tmpdir[1])) {
  89. $module = $tmpdir[0];
  90. $dirread = $tmpdir[1];
  91. $forceddirread = 1;
  92. }
  93. if (GETPOST('dirins', 'alpha')) {
  94. $dirread = $dirins = GETPOST('dirins', 'alpha');
  95. $forceddirread = 1;
  96. }
  97. $FILEFLAG = 'modulebuilder.txt';
  98. $now = dol_now();
  99. $newmask = 0;
  100. if (empty($newmask) && !empty($conf->global->MAIN_UMASK)) {
  101. $newmask = $conf->global->MAIN_UMASK;
  102. }
  103. if (empty($newmask)) { // This should no happen
  104. $newmask = '0664';
  105. }
  106. $result = restrictedArea($user, 'modulebuilder', null);
  107. $error = 0;
  108. $form = new Form($db);
  109. // Define $listofmodules
  110. $dirsrootforscan = array($dirread);
  111. // Add also the core modules into the list of modules to show/edit
  112. if ($dirread != DOL_DOCUMENT_ROOT && ($conf->global->MAIN_FEATURES_LEVEL >= 2 || !empty($conf->global->MODULEBUILDER_ADD_DOCUMENT_ROOT))) {
  113. $dirsrootforscan[] = DOL_DOCUMENT_ROOT;
  114. }
  115. // Search modules to edit
  116. $textforlistofdirs = '<!-- Directory scanned -->'."\n";
  117. $listofmodules = array();
  118. $i = 0;
  119. foreach ($dirsrootforscan as $tmpdirread) {
  120. $moduletype = 'external';
  121. if ($tmpdirread == DOL_DOCUMENT_ROOT) {
  122. $moduletype = 'internal';
  123. }
  124. $dirsincustom = dol_dir_list($tmpdirread, 'directories');
  125. if (is_array($dirsincustom) && count($dirsincustom) > 0) {
  126. foreach ($dirsincustom as $dircustomcursor) {
  127. $fullname = $dircustomcursor['fullname'];
  128. if (dol_is_file($fullname.'/'.$FILEFLAG)) {
  129. // Get real name of module (MyModule instead of mymodule)
  130. $dirtoscanrel = basename($fullname).'/core/modules/';
  131. $descriptorfiles = dol_dir_list(dirname($fullname).'/'.$dirtoscanrel, 'files', 0, 'mod.*\.class\.php$');
  132. if (empty($descriptorfiles)) { // If descriptor not found into module dir, we look into main module dir.
  133. $dirtoscanrel = 'core/modules/';
  134. $descriptorfiles = dol_dir_list($fullname.'/../'.$dirtoscanrel, 'files', 0, 'mod'.strtoupper(basename($fullname)).'\.class\.php$');
  135. }
  136. $modulenamewithcase = '';
  137. $moduledescriptorrelpath = '';
  138. $moduledescriptorfullpath = '';
  139. foreach ($descriptorfiles as $descriptorcursor) {
  140. $modulenamewithcase = preg_replace('/^mod/', '', $descriptorcursor['name']);
  141. $modulenamewithcase = preg_replace('/\.class\.php$/', '', $modulenamewithcase);
  142. $moduledescriptorrelpath = $dirtoscanrel.$descriptorcursor['name'];
  143. $moduledescriptorfullpath = $descriptorcursor['fullname'];
  144. //var_dump($descriptorcursor);
  145. }
  146. if ($modulenamewithcase) {
  147. $listofmodules[$dircustomcursor['name']] = array(
  148. 'modulenamewithcase'=>$modulenamewithcase,
  149. 'moduledescriptorrelpath'=> $moduledescriptorrelpath,
  150. 'moduledescriptorfullpath'=>$moduledescriptorfullpath,
  151. 'moduledescriptorrootpath'=>$tmpdirread,
  152. 'moduletype'=>$moduletype
  153. );
  154. }
  155. //var_dump($listofmodules);
  156. }
  157. }
  158. }
  159. if ($forceddirread && empty($listofmodules)) { // $forceddirread is 1 if we forced dir to read with dirins=... or with module=...@mydir
  160. $listofmodules[strtolower($module)] = array(
  161. 'modulenamewithcase'=>$module,
  162. 'moduledescriptorrelpath'=> 'notyetimplemented',
  163. 'moduledescriptorfullpath'=> 'notyetimplemented',
  164. 'moduledescriptorrootpath'=> 'notyetimplemented',
  165. );
  166. }
  167. // Show description of content
  168. $newdircustom = $dirins;
  169. if (empty($newdircustom)) {
  170. $newdircustom = img_warning();
  171. }
  172. // If dirread was forced to somewhere else, by using URL
  173. // htdocs/modulebuilder/index.php?module=Inventory@/home/ldestailleur/git/dolibarr/htdocs/product
  174. if (empty($i)) {
  175. $textforlistofdirs .= $langs->trans("DirScanned").' : ';
  176. } else {
  177. $textforlistofdirs .= ', ';
  178. }
  179. $textforlistofdirs .= '<strong class="wordbreakimp">'.$tmpdirread.'</strong>';
  180. if ($tmpdirread == DOL_DOCUMENT_ROOT) {
  181. if (getDolGlobalInt('MAIN_FEATURES_LEVEL') >= 2) {
  182. $textforlistofdirs .= $form->textwithpicto('', $langs->trans("ConstantIsOn", "MAIN_FEATURES_LEVEL"));
  183. }
  184. if (getDolGlobalString('MODULEBUILDER_ADD_DOCUMENT_ROOT')) {
  185. $textforlistofdirs .= $form->textwithpicto('', $langs->trans("ConstantIsOn", "MODULEBUILDER_ADD_DOCUMENT_ROOT"));
  186. }
  187. }
  188. $i++;
  189. }
  190. /*
  191. * Actions
  192. */
  193. if ($dirins && $action == 'initmodule' && $modulename) {
  194. $modulename = ucfirst($modulename); // Force first letter in uppercase
  195. if (preg_match('/[^a-z0-9_]/i', $modulename)) {
  196. $error++;
  197. setEventMessages($langs->trans("SpaceOrSpecialCharAreNotAllowed"), null, 'errors');
  198. }
  199. if (!$error) {
  200. $srcdir = DOL_DOCUMENT_ROOT.'/modulebuilder/template';
  201. $destdir = $dirins.'/'.strtolower($modulename);
  202. $arrayreplacement = array(
  203. 'mymodule'=>strtolower($modulename),
  204. 'MyModule'=>$modulename
  205. );
  206. $result = dolCopyDir($srcdir, $destdir, 0, 0, $arrayreplacement);
  207. //dol_mkdir($destfile);
  208. if ($result <= 0) {
  209. if ($result < 0) {
  210. $error++;
  211. $langs->load("errors");
  212. setEventMessages($langs->trans("ErrorFailToCopyDir", $srcdir, $destdir), null, 'errors');
  213. } else {
  214. // $result == 0
  215. setEventMessages($langs->trans("AllFilesDidAlreadyExist", $srcdir, $destdir), null, 'warnings');
  216. }
  217. }
  218. // Copy last html.formsetup.class.php' to backport folder
  219. $tryToCopyFromSetupClass = true;
  220. $backportDest = $destdir .'/backport/v16/core/class';
  221. $backportFileSrc = DOL_DOCUMENT_ROOT.'/core/class/html.formsetup.class.php';
  222. $backportFileDest = $backportDest.'/html.formsetup.class.php';
  223. $result = dol_mkdir($backportDest);
  224. if ($result < 0) {
  225. $error++;
  226. $langs->load("errors");
  227. setEventMessages($langs->trans("ErrorFailToCreateDir", $backportDest), null, 'errors');
  228. $tryToCopyFromSetupClass = false;
  229. }
  230. if ($tryToCopyFromSetupClass) {
  231. $result = dol_copy($backportFileSrc, $backportFileDest);
  232. if ($result <= 0) {
  233. if ($result < 0) {
  234. $error++;
  235. $langs->load("errors");
  236. setEventMessages($langs->trans("ErrorFailToCopyFile", $backportFileSrc, $backportFileDest), null, 'errors');
  237. } else {
  238. setEventMessages($langs->trans("FileDidAlreadyExist", $backportFileDest), null, 'warnings');
  239. }
  240. }
  241. }
  242. if (!empty($conf->global->MODULEBUILDER_USE_ABOUT)) {
  243. dol_delete_file($destdir.'/admin/about.php');
  244. }
  245. // Delete dir and files that can be generated in sub tabs later if we need them (we want a minimal module first)
  246. dol_delete_dir_recursive($destdir.'/build/doxygen');
  247. dol_delete_dir_recursive($destdir.'/core/modules/mailings');
  248. dol_delete_dir_recursive($destdir.'/core/modules/'.strtolower($modulename));
  249. dol_delete_dir_recursive($destdir.'/core/tpl');
  250. dol_delete_dir_recursive($destdir.'/core/triggers');
  251. dol_delete_dir_recursive($destdir.'/doc');
  252. //dol_delete_dir_recursive($destdir.'/.tx');
  253. dol_delete_dir_recursive($destdir.'/core/boxes');
  254. dol_delete_file($destdir.'/admin/myobject_extrafields.php');
  255. dol_delete_file($destdir.'/sql/data.sql');
  256. dol_delete_file($destdir.'/sql/update_x.x.x-y.y.y.sql');
  257. dol_delete_file($destdir.'/class/actions_'.strtolower($modulename).'.class.php');
  258. dol_delete_file($destdir.'/class/api_'.strtolower($modulename).'.class.php');
  259. dol_delete_file($destdir.'/css/'.strtolower($modulename).'.css.php');
  260. dol_delete_file($destdir.'/js/'.strtolower($modulename).'.js.php');
  261. dol_delete_file($destdir.'/scripts/'.strtolower($modulename).'.php');
  262. dol_delete_file($destdir.'/test/phpunit/'.$modulename.'FunctionnalTest.php');
  263. // Delete some files related to Object (because the previous dolCopyDir has copied everything)
  264. dol_delete_file($destdir.'/myobject_card.php');
  265. dol_delete_file($destdir.'/myobject_contact.php');
  266. dol_delete_file($destdir.'/myobject_note.php');
  267. dol_delete_file($destdir.'/myobject_document.php');
  268. dol_delete_file($destdir.'/myobject_agenda.php');
  269. dol_delete_file($destdir.'/myobject_list.php');
  270. dol_delete_file($destdir.'/lib/'.strtolower($modulename).'_myobject.lib.php');
  271. dol_delete_file($destdir.'/test/phpunit/MyObjectTest.php');
  272. dol_delete_file($destdir.'/sql/llx_'.strtolower($modulename).'_myobject.sql');
  273. dol_delete_file($destdir.'/sql/llx_'.strtolower($modulename).'_myobject_extrafields.sql');
  274. dol_delete_file($destdir.'/sql/llx_'.strtolower($modulename).'_myobject.key.sql');
  275. dol_delete_file($destdir.'/sql/llx_'.strtolower($modulename).'_myobject_extrafields.key.sql');
  276. dol_delete_file($destdir.'/class/myobject.class.php');
  277. dol_delete_dir($destdir.'/class', 1);
  278. dol_delete_dir($destdir.'/sql', 1);
  279. dol_delete_dir($destdir.'/scripts', 1);
  280. dol_delete_dir($destdir.'/js', 1);
  281. dol_delete_dir($destdir.'/css', 1);
  282. dol_delete_dir($destdir.'/test/phpunit', 1);
  283. dol_delete_dir($destdir.'/test', 1);
  284. }
  285. // Edit PHP files
  286. if (!$error) {
  287. $listofphpfilestoedit = dol_dir_list($destdir, 'files', 1, '\.(php|MD|js|sql|txt|xml|lang)$', '', 'fullname', SORT_ASC, 0, 1);
  288. foreach ($listofphpfilestoedit as $phpfileval) {
  289. //var_dump($phpfileval['fullname']);
  290. $arrayreplacement = array(
  291. 'mymodule'=>strtolower($modulename),
  292. 'MyModule'=>$modulename,
  293. 'MYMODULE'=>strtoupper($modulename),
  294. 'My module'=>$modulename,
  295. 'my module'=>$modulename,
  296. 'Mon module'=>$modulename,
  297. 'mon module'=>$modulename,
  298. 'htdocs/modulebuilder/template'=>strtolower($modulename),
  299. '---Put here your own copyright and developer email---'=>dol_print_date($now, '%Y').' '.$user->getFullName($langs).($user->email ? ' <'.$user->email.'>' : ''),
  300. 'Editor name'=>$editorname,
  301. 'https://www.example.com'=>$editorurl,
  302. '$this->version = \'1.0\''=>'$this->version = \''.$version.'\'',
  303. '$this->picto = \'generic\';'=>(empty($picto)) ? '$this->picto = \'generic\'' : '$this->picto = \''.$picto.'\';',
  304. "modulefamily" =>$family,
  305. '500000'=>$idmodule
  306. );
  307. if (!empty($conf->global->MODULEBUILDER_SPECIFIC_AUTHOR)) {
  308. $arrayreplacement['---Put here your own copyright and developer email---'] = dol_print_date($now, '%Y').' ' . getDolGlobalString('MODULEBUILDER_SPECIFIC_AUTHOR');
  309. }
  310. $result = dolReplaceInFile($phpfileval['fullname'], $arrayreplacement);
  311. //var_dump($result);
  312. if ($result < 0) {
  313. setEventMessages($langs->trans("ErrorFailToMakeReplacementInto", $phpfileval['fullname']), null, 'errors');
  314. }
  315. }
  316. if (!empty($conf->global->MODULEBUILDER_SPECIFIC_README)) {
  317. setEventMessages($langs->trans("ContentOfREADMECustomized"), null, 'warnings');
  318. dol_delete_file($destdir.'/README.md');
  319. file_put_contents($destdir.'/README.md', $conf->global->MODULEBUILDER_SPECIFIC_README);
  320. }
  321. // for create file to add properties
  322. // file_put_contents($destdir.'/'.strtolower($modulename).'propertycard.php','');
  323. // $srcFileCard = DOL_DOCUMENT_ROOT.'/modulebuilder/card.php';
  324. // $destFileCard = $dirins.'/'.strtolower($modulename).'/template/card.php';
  325. // dol_copy($srcFileCard, $destdir.'/'.strtolower($modulename).'propertycard.php', 0,1, $arrayreplacement);
  326. }
  327. if (!$error) {
  328. setEventMessages('ModuleInitialized', null);
  329. $module = $modulename;
  330. clearstatcache(true);
  331. if (function_exists('opcache_invalidate')) {
  332. opcache_reset(); // remove the include cache hell !
  333. }
  334. header("Location: ".$_SERVER["PHP_SELF"].'?module='.$modulename);
  335. exit;
  336. }
  337. }
  338. // init API, PHPUnit
  339. if ($dirins && in_array($action, array('initapi', 'initphpunit', 'initpagecontact', 'initpagedocument', 'initpagenote', 'initpageagenda')) && !empty($module)) {
  340. $modulename = ucfirst($module); // Force first letter in uppercase
  341. $objectname = $tabobj;
  342. $varnametoupdate = '';
  343. $dirins = $listofmodules[strtolower($module)]['moduledescriptorrootpath'];
  344. $destdir = $dirins.'/'.strtolower($module);
  345. // Get list of existing objects
  346. $objects = dolGetListOfObjectClasses($destdir);
  347. if ($action == 'initapi') {
  348. if (file_exists($dirins.'/'.strtolower($module).'/class/api_'.strtolower($module).'.class.php')) {
  349. $result = dol_copy(DOL_DOCUMENT_ROOT.'/modulebuilder/template/class/api_mymodule.class.php', $dirins.'/'.strtolower($module).'/class/api_'.strtolower($module).'.class.php', 0, 1);
  350. }
  351. dol_mkdir($dirins.'/'.strtolower($module).'/class');
  352. $srcdir = DOL_DOCUMENT_ROOT.'/modulebuilder/template';
  353. $srcfile = $srcdir.'/class/api_mymodule.class.php';
  354. $destfile = $dirins.'/'.strtolower($module).'/class/api_'.strtolower($module).'.class.php';
  355. } elseif ($action == 'initphpunit') {
  356. dol_mkdir($dirins.'/'.strtolower($module).'/test/phpunit');
  357. $srcdir = DOL_DOCUMENT_ROOT.'/modulebuilder/template';
  358. $srcfile = $srcdir.'/test/phpunit/MyObjectTest.php';
  359. $destfile = $dirins.'/'.strtolower($module).'/test/phpunit/'.strtolower($objectname).'Test.php';
  360. } elseif ($action == 'initpagecontact') {
  361. dol_mkdir($dirins.'/'.strtolower($module));
  362. $srcdir = DOL_DOCUMENT_ROOT.'/modulebuilder/template';
  363. $srcfile = $srcdir.'/myobject_contact.php';
  364. $destfile = $dirins.'/'.strtolower($module).'/'.strtolower($objectname).'_contact.php';
  365. $varnametoupdate = 'showtabofpagecontact';
  366. } elseif ($action == 'initpagedocument') {
  367. dol_mkdir($dirins.'/'.strtolower($module));
  368. $srcdir = DOL_DOCUMENT_ROOT.'/modulebuilder/template';
  369. $srcfile = $srcdir.'/myobject_document.php';
  370. $destfile = $dirins.'/'.strtolower($module).'/'.strtolower($objectname).'_document.php';
  371. $varnametoupdate = 'showtabofpagedocument';
  372. } elseif ($action == 'initpagenote') {
  373. dol_mkdir($dirins.'/'.strtolower($module));
  374. $srcdir = DOL_DOCUMENT_ROOT.'/modulebuilder/template';
  375. $srcfile = $srcdir.'/myobject_note.php';
  376. $destfile = $dirins.'/'.strtolower($module).'/'.strtolower($objectname).'_note.php';
  377. $varnametoupdate = 'showtabofpagenote';
  378. } elseif ($action == 'initpageagenda') {
  379. dol_mkdir($dirins.'/'.strtolower($module));
  380. $srcdir = DOL_DOCUMENT_ROOT.'/modulebuilder/template';
  381. $srcfile = $srcdir.'/myobject_agenda.php';
  382. $destfile = $dirins.'/'.strtolower($module).'/'.strtolower($objectname).'_agenda.php';
  383. $varnametoupdate = 'showtabofpageagenda';
  384. }
  385. //var_dump($srcfile);
  386. //var_dump($destfile);
  387. if (!file_exists($destfile)) {
  388. $result = dol_copy($srcfile, $destfile, 0, 0);
  389. }
  390. if ($result > 0) {
  391. //var_dump($phpfileval['fullname']);
  392. $arrayreplacement = array(
  393. 'mymodule'=>strtolower($modulename),
  394. 'MyModule'=>$modulename,
  395. 'MYMODULE'=>strtoupper($modulename),
  396. 'My module'=>$modulename,
  397. 'my module'=>$modulename,
  398. 'Mon module'=>$modulename,
  399. 'mon module'=>$modulename,
  400. 'htdocs/modulebuilder/template'=>strtolower($modulename),
  401. 'myobject'=>strtolower($objectname),
  402. 'MyObject'=>$objectname,
  403. 'MYOBJECT'=>strtoupper($objectname),
  404. '---Put here your own copyright and developer email---'=>dol_print_date($now, '%Y').' '.$user->getFullName($langs).($user->email ? ' <'.$user->email.'>' : '')
  405. );
  406. if (count($objects) > 1) {
  407. addObjectsToApiFile($destfile, $objects, $modulename);
  408. } else {
  409. dolReplaceInFile($destfile, $arrayreplacement);
  410. dolReplaceInFile($destfile, array('/*begin methods CRUD*/' => '/*begin methods CRUD*/'."\n\t".'/*CRUD FOR '.strtoupper($objectname).'*/', '/*end methods CRUD*/' => '/*END CRUD FOR '.strtoupper($objectname).'*/'."\n\t".'/*end methods CRUD*/'));
  411. }
  412. if ($varnametoupdate) {
  413. // Now we update the object file to set $$varnametoupdate to 1
  414. $srcfile = $dirins.'/'.strtolower($module).'/lib/'.strtolower($module).'_'.strtolower($objectname).'.lib.php';
  415. $arrayreplacement = array('/\$'.$varnametoupdate.' = 0;/' => '$'.$varnametoupdate.' = 1;');
  416. dolReplaceInFile($srcfile, $arrayreplacement, '', 0, 0, 1);
  417. }
  418. } else {
  419. $langs->load("errors");
  420. setEventMessages($langs->trans('ErrorFailToCreateFile', $destfile), null, 'errors');
  421. }
  422. }
  423. // init ExtraFields
  424. if ($dirins && $action == 'initsqlextrafields' && !empty($module)) {
  425. $modulename = ucfirst($module); // Force first letter in uppercase
  426. $objectname = $tabobj;
  427. dol_mkdir($dirins.'/'.strtolower($module).'/sql');
  428. $srcdir = DOL_DOCUMENT_ROOT.'/modulebuilder/template';
  429. $srcfile1 = $srcdir.'/sql/llx_mymodule_myobject_extrafields.sql';
  430. $destfile1 = $dirins.'/'.strtolower($module).'/sql/llx_'.strtolower($module).'_'.strtolower($objectname).'_extrafields.sql';
  431. //var_dump($srcfile);
  432. //var_dump($destfile);
  433. $result1 = dol_copy($srcfile1, $destfile1, 0, 0);
  434. $srcfile2 = $srcdir.'/sql/llx_mymodule_myobject_extrafields.key.sql';
  435. $destfile2 = $dirins.'/'.strtolower($module).'/sql/llx_'.strtolower($module).'_'.strtolower($objectname).'_extrafields.key.sql';
  436. //var_dump($srcfile);
  437. //var_dump($destfile);
  438. $result2 = dol_copy($srcfile2, $destfile2, 0, 0);
  439. if ($result1 > 0 && $result2 > 0) {
  440. $modulename = ucfirst($module); // Force first letter in uppercase
  441. //var_dump($phpfileval['fullname']);
  442. $arrayreplacement = array(
  443. 'mymodule'=>strtolower($modulename),
  444. 'MyModule'=>$modulename,
  445. 'MYMODULE'=>strtoupper($modulename),
  446. 'My module'=>$modulename,
  447. 'my module'=>$modulename,
  448. 'Mon module'=>$modulename,
  449. 'mon module'=>$modulename,
  450. 'htdocs/modulebuilder/template'=>strtolower($modulename),
  451. 'My Object'=>$objectname,
  452. 'MyObject'=>$objectname,
  453. 'my object'=>strtolower($objectname),
  454. 'myobject'=>strtolower($objectname),
  455. '---Put here your own copyright and developer email---'=>dol_print_date($now, '%Y').' '.$user->getFullName($langs).($user->email ? ' <'.$user->email.'>' : '')
  456. );
  457. dolReplaceInFile($destfile1, $arrayreplacement);
  458. dolReplaceInFile($destfile2, $arrayreplacement);
  459. } else {
  460. $langs->load("errors");
  461. if ($result1 <= 0) {
  462. setEventMessages($langs->trans('ErrorFailToCreateFile', $destfile1), null, 'errors');
  463. }
  464. if ($result2 <= 0) {
  465. setEventMessages($langs->trans('ErrorFailToCreateFile', $destfile2), null, 'errors');
  466. }
  467. }
  468. // Now we update the object file to set $isextrafieldmanaged to 1
  469. $srcfile = $dirins.'/'.strtolower($module).'/class/'.strtolower($objectname).'.class.php';
  470. $arrayreplacement = array('/\$isextrafieldmanaged = 0;/' => '$isextrafieldmanaged = 1;');
  471. dolReplaceInFile($srcfile, $arrayreplacement, '', 0, 0, 1);
  472. }
  473. // init Hook
  474. if ($dirins && $action == 'inithook' && !empty($module)) {
  475. dol_mkdir($dirins.'/'.strtolower($module).'/class');
  476. $srcdir = DOL_DOCUMENT_ROOT.'/modulebuilder/template';
  477. $srcfile = $srcdir.'/class/actions_mymodule.class.php';
  478. $destfile = $dirins.'/'.strtolower($module).'/class/actions_'.strtolower($module).'.class.php';
  479. //var_dump($srcfile);
  480. //var_dump($destfile);
  481. $result = dol_copy($srcfile, $destfile, 0, 0);
  482. if ($result > 0) {
  483. $modulename = ucfirst($module); // Force first letter in uppercase
  484. //var_dump($phpfileval['fullname']);
  485. $arrayreplacement = array(
  486. 'mymodule'=>strtolower($modulename),
  487. 'MyModule'=>$modulename,
  488. 'MYMODULE'=>strtoupper($modulename),
  489. 'My module'=>$modulename,
  490. 'my module'=>$modulename,
  491. 'Mon module'=>$modulename,
  492. 'mon module'=>$modulename,
  493. 'htdocs/modulebuilder/template'=>strtolower($modulename),
  494. '---Put here your own copyright and developer email---'=>dol_print_date($now, '%Y').' '.$user->getFullName($langs).($user->email ? ' <'.$user->email.'>' : '')
  495. );
  496. dolReplaceInFile($destfile, $arrayreplacement);
  497. } else {
  498. $langs->load("errors");
  499. setEventMessages($langs->trans('ErrorFailToCreateFile', $destfile), null, 'errors');
  500. }
  501. }
  502. // init Trigger
  503. if ($dirins && $action == 'inittrigger' && !empty($module)) {
  504. dol_mkdir($dirins.'/'.strtolower($module).'/core/triggers');
  505. $srcdir = DOL_DOCUMENT_ROOT.'/modulebuilder/template';
  506. $srcfile = $srcdir.'/core/triggers/interface_99_modMyModule_MyModuleTriggers.class.php';
  507. $destfile = $dirins.'/'.strtolower($module).'/core/triggers/interface_99_mod'.$module.'_'.$module.'Triggers.class.php';
  508. //var_dump($srcfile);
  509. //var_dump($destfile);
  510. $result = dol_copy($srcfile, $destfile, 0, 0);
  511. if ($result > 0) {
  512. $modulename = ucfirst($module); // Force first letter in uppercase
  513. //var_dump($phpfileval['fullname']);
  514. $arrayreplacement = array(
  515. 'mymodule'=>strtolower($modulename),
  516. 'MyModule'=>$modulename,
  517. 'MYMODULE'=>strtoupper($modulename),
  518. 'My module'=>$modulename,
  519. 'my module'=>$modulename,
  520. 'Mon module'=>$modulename,
  521. 'mon module'=>$modulename,
  522. 'htdocs/modulebuilder/template'=>strtolower($modulename),
  523. '---Put here your own copyright and developer email---'=>dol_print_date($now, '%Y').' '.$user->getFullName($langs).($user->email ? ' <'.$user->email.'>' : '')
  524. );
  525. dolReplaceInFile($destfile, $arrayreplacement);
  526. } else {
  527. $langs->load("errors");
  528. setEventMessages($langs->trans('ErrorFailToCreateFile', $destfile), null, 'errors');
  529. }
  530. }
  531. // init Widget
  532. if ($dirins && $action == 'initwidget' && !empty($module)) {
  533. dol_mkdir($dirins.'/'.strtolower($module).'/core/boxes');
  534. $srcdir = DOL_DOCUMENT_ROOT.'/modulebuilder/template';
  535. $srcfile = $srcdir.'/core/boxes/mymodulewidget1.php';
  536. $destfile = $dirins.'/'.strtolower($module).'/core/boxes/'.strtolower($module).'widget1.php';
  537. //var_dump($srcfile);
  538. //var_dump($destfile);
  539. $result = dol_copy($srcfile, $destfile, 0, 0);
  540. if ($result > 0) {
  541. $modulename = ucfirst($module); // Force first letter in uppercase
  542. //var_dump($phpfileval['fullname']);
  543. $arrayreplacement = array(
  544. 'mymodule'=>strtolower($modulename),
  545. 'MyModule'=>$modulename,
  546. 'MYMODULE'=>strtoupper($modulename),
  547. 'My module'=>$modulename,
  548. 'my module'=>$modulename,
  549. 'Mon module'=>$modulename,
  550. 'mon module'=>$modulename,
  551. 'htdocs/modulebuilder/template'=>strtolower($modulename),
  552. '---Put here your own copyright and developer email---'=>dol_print_date($now, '%Y').' '.$user->getFullName($langs).($user->email ? ' <'.$user->email.'>' : '')
  553. );
  554. dolReplaceInFile($destfile, $arrayreplacement);
  555. } else {
  556. $langs->load("errors");
  557. setEventMessages($langs->trans('ErrorFailToCreateFile', $destfile), null, 'errors');
  558. }
  559. }
  560. // init CSS
  561. if ($dirins && $action == 'initcss' && !empty($module)) {
  562. dol_mkdir($dirins.'/'.strtolower($module).'/css');
  563. $srcdir = DOL_DOCUMENT_ROOT.'/modulebuilder/template';
  564. $srcfile = $srcdir.'/css/mymodule.css.php';
  565. $destfile = $dirins.'/'.strtolower($module).'/css/'.strtolower($module).'.css.php';
  566. //var_dump($srcfile);
  567. //var_dump($destfile);
  568. $result = dol_copy($srcfile, $destfile, 0, 0);
  569. if ($result > 0) {
  570. $modulename = ucfirst($module); // Force first letter in uppercase
  571. //var_dump($phpfileval['fullname']);
  572. $arrayreplacement = array(
  573. 'mymodule'=>strtolower($modulename),
  574. 'MyModule'=>$modulename,
  575. 'MYMODULE'=>strtoupper($modulename),
  576. 'My module'=>$modulename,
  577. 'my module'=>$modulename,
  578. 'Mon module'=>$modulename,
  579. 'mon module'=>$modulename,
  580. 'htdocs/modulebuilder/template'=>strtolower($modulename),
  581. '---Put here your own copyright and developer email---'=>dol_print_date($now, '%Y').' '.$user->getFullName($langs).($user->email ? ' <'.$user->email.'>' : ''),
  582. );
  583. dolReplaceInFile($destfile, $arrayreplacement);
  584. // Update descriptor file to uncomment file
  585. $srcfile = $dirins.'/'.strtolower($module).'/core/modules/mod'.$module.'.class.php';
  586. $arrayreplacement = array('/\/\/\s*\''.preg_quote('/'.strtolower($module).'/css/'.strtolower($module).'.css.php', '/').'\'/' => '\'/'.strtolower($module).'/css/'.strtolower($module).'.css.php\'');
  587. dolReplaceInFile($srcfile, $arrayreplacement, '', 0, 0, 1);
  588. } else {
  589. $langs->load("errors");
  590. setEventMessages($langs->trans('ErrorFailToCreateFile', $destfile), null, 'errors');
  591. }
  592. }
  593. // init JS
  594. if ($dirins && $action == 'initjs' && !empty($module)) {
  595. dol_mkdir($dirins.'/'.strtolower($module).'/js');
  596. $srcdir = DOL_DOCUMENT_ROOT.'/modulebuilder/template';
  597. $srcfile = $srcdir.'/js/mymodule.js.php';
  598. $destfile = $dirins.'/'.strtolower($module).'/js/'.strtolower($module).'.js.php';
  599. //var_dump($srcfile);
  600. //var_dump($destfile);
  601. $result = dol_copy($srcfile, $destfile, 0, 0);
  602. if ($result > 0) {
  603. $modulename = ucfirst($module); // Force first letter in uppercase
  604. //var_dump($phpfileval['fullname']);
  605. $arrayreplacement = array(
  606. 'mymodule'=>strtolower($modulename),
  607. 'MyModule'=>$modulename,
  608. 'MYMODULE'=>strtoupper($modulename),
  609. 'My module'=>$modulename,
  610. 'my module'=>$modulename,
  611. 'Mon module'=>$modulename,
  612. 'mon module'=>$modulename,
  613. 'htdocs/modulebuilder/template'=>strtolower($modulename),
  614. '---Put here your own copyright and developer email---'=>dol_print_date($now, '%Y').' '.$user->getFullName($langs).($user->email ? ' <'.$user->email.'>' : '')
  615. );
  616. dolReplaceInFile($destfile, $arrayreplacement);
  617. // Update descriptor file to uncomment file
  618. $srcfile = $dirins.'/'.strtolower($module).'/core/modules/mod'.$module.'.class.php';
  619. $arrayreplacement = array('/\/\/\s*\''.preg_quote('/'.strtolower($module).'/js/'.strtolower($module).'.js.php', '/').'\'/' => '\'/'.strtolower($module).'/js/'.strtolower($module).'.js.php\'');
  620. dolReplaceInFile($srcfile, $arrayreplacement, '', 0, 0, 1);
  621. } else {
  622. $langs->load("errors");
  623. setEventMessages($langs->trans('ErrorFailToCreateFile', $destfile), null, 'errors');
  624. }
  625. }
  626. // init CLI
  627. if ($dirins && $action == 'initcli' && !empty($module)) {
  628. dol_mkdir($dirins.'/'.strtolower($module).'/scripts');
  629. $srcdir = DOL_DOCUMENT_ROOT.'/modulebuilder/template';
  630. $srcfile = $srcdir.'/scripts/mymodule.php';
  631. $destfile = $dirins.'/'.strtolower($module).'/scripts/'.strtolower($module).'.php';
  632. //var_dump($srcfile);
  633. //var_dump($destfile);
  634. $result = dol_copy($srcfile, $destfile, 0, 0);
  635. if ($result > 0) {
  636. $modulename = ucfirst($module); // Force first letter in uppercase
  637. //var_dump($phpfileval['fullname']);
  638. $arrayreplacement = array(
  639. 'mymodule'=>strtolower($modulename),
  640. 'MyModule'=>$modulename,
  641. 'MYMODULE'=>strtoupper($modulename),
  642. 'My module'=>$modulename,
  643. 'my module'=>$modulename,
  644. 'Mon module'=>$modulename,
  645. 'mon module'=>$modulename,
  646. 'htdocs/modulebuilder/template'=>strtolower($modulename),
  647. '__MYCOMPANY_NAME__'=>$mysoc->name,
  648. '__KEYWORDS__'=>$modulename,
  649. '__USER_FULLNAME__'=>$user->getFullName($langs),
  650. '__USER_EMAIL__'=>$user->email,
  651. '__YYYY-MM-DD__'=>dol_print_date($now, 'dayrfc'),
  652. '---Put here your own copyright and developer email---'=>dol_print_date($now, 'dayrfc').' '.$user->getFullName($langs).($user->email ? ' <'.$user->email.'>' : '')
  653. );
  654. dolReplaceInFile($destfile, $arrayreplacement);
  655. } else {
  656. $langs->load("errors");
  657. setEventMessages($langs->trans('ErrorFailToCreateFile', $destfile), null, 'errors');
  658. }
  659. }
  660. // init Doc
  661. if ($dirins && $action == 'initdoc' && !empty($module)) {
  662. dol_mkdir($dirins.'/'.strtolower($module).'/doc');
  663. $srcdir = DOL_DOCUMENT_ROOT.'/modulebuilder/template';
  664. $srcfile = $srcdir.'/doc/Documentation.asciidoc';
  665. $destfile = $dirins.'/'.strtolower($module).'/doc/Documentation.asciidoc';
  666. //var_dump($srcfile);
  667. //var_dump($destfile);
  668. $result = dol_copy($srcfile, $destfile, 0, 0);
  669. if ($result > 0) {
  670. $modulename = ucfirst($module); // Force first letter in uppercase
  671. $modulelowercase = strtolower($module);
  672. //var_dump($phpfileval['fullname']);
  673. $arrayreplacement = array(
  674. 'mymodule'=>strtolower($modulename),
  675. 'MyModule'=>$modulename,
  676. 'MYMODULE'=>strtoupper($modulename),
  677. 'My module'=>$modulename,
  678. 'my module'=>$modulename,
  679. 'Mon module'=>$modulename,
  680. 'mon module'=>$modulename,
  681. 'htdocs/modulebuilder/template'=>strtolower($modulename),
  682. '__MYCOMPANY_NAME__'=>$mysoc->name,
  683. '__KEYWORDS__'=>$modulename,
  684. '__USER_FULLNAME__'=>$user->getFullName($langs),
  685. '__USER_EMAIL__'=>$user->email,
  686. '__YYYY-MM-DD__'=>dol_print_date($now, 'dayrfc'),
  687. '---Put here your own copyright and developer email---'=>dol_print_date($now, 'dayrfc').' '.$user->getFullName($langs).($user->email ? ' <'.$user->email.'>' : '')
  688. );
  689. dolReplaceInFile($destfile, $arrayreplacement);
  690. // add table of properties
  691. $dirins = $listofmodules[strtolower($module)]['moduledescriptorrootpath'];
  692. $destdir = $dirins.'/'.strtolower($module);
  693. $objects = dolGetListOfObjectClasses($destdir);
  694. foreach ($objects as $path=>$obj) {
  695. writePropsInAsciiDoc($path, $obj, $destfile);
  696. }
  697. // add table of permissions
  698. $moduledescriptorfile = $dirins.'/'.strtolower($module).'/core/modules/mod'.$module.'.class.php';
  699. writePermsInAsciiDoc($moduledescriptorfile, $destfile);
  700. // add api urls if file exist
  701. if (file_exists($dirins.'/'.strtolower($module).'/class/api_'.strtolower($module).'.class.php')) {
  702. $apiFile = $dirins.'/'.strtolower($module).'/class/api_'.strtolower($module).'.class.php';
  703. writeApiUrlsInDoc($apiFile, $destfile);
  704. }
  705. // add ChangeLog in Doc
  706. if (file_exists($dirins.'/'.strtolower($module).'/ChangeLog.md')) {
  707. $changeLog = $dirins.'/'.strtolower($module).'/ChangeLog.md';
  708. $string = file_get_contents($changeLog);
  709. $replace = explode("\n", $string);
  710. $strreplace = array();
  711. foreach ($replace as $line) {
  712. if ($line === '') {
  713. continue;
  714. }
  715. if (strpos($line, '##') !== false) {
  716. $strreplace[$line] = str_replace('##', '', $line);
  717. } else {
  718. $strreplace[$line] = $line;
  719. }
  720. }
  721. $stringLog = implode("\n", $strreplace);
  722. dolReplaceInFile($destfile, array('//include::ChangeLog.md[]' => '','__CHANGELOG__' => $stringLog));
  723. }
  724. // Delete old documentation files
  725. $FILENAMEDOC = $modulelowercase.'.html';
  726. $FILENAMEDOCPDF = $modulelowercase.'.pdf';
  727. $outputfiledoc = dol_buildpath($modulelowercase, 0).'/doc/'.$FILENAMEDOC;
  728. $outputfiledocurl = dol_buildpath($modulelowercase, 1).'/doc/'.$FILENAMEDOC;
  729. $outputfiledocpdf = dol_buildpath($modulelowercase, 0).'/doc/'.$FILENAMEDOCPDF;
  730. $outputfiledocurlpdf = dol_buildpath($modulelowercase, 1).'/doc/'.$FILENAMEDOCPDF;
  731. dol_delete_file($outputfiledoc, 0, 0, 0, null, false, 0);
  732. dol_delete_file($outputfiledocpdf, 0, 0, 0, null, false, 0);
  733. } else {
  734. $langs->load("errors");
  735. setEventMessages($langs->trans('ErrorFailToCreateFile', $destfile), null, 'errors');
  736. }
  737. }
  738. // add Language
  739. if ($dirins && $action == 'addlanguage' && !empty($module)) {
  740. $newlangcode = GETPOST('newlangcode', 'aZ09');
  741. if ($newlangcode) {
  742. $modulelowercase = strtolower($module);
  743. // Dir for module
  744. $diroflang = dol_buildpath($modulelowercase, 0);
  745. if ($diroflang == $dolibarr_main_document_root.'/'.$modulelowercase) {
  746. // This is not a custom module, we force diroflang to htdocs root
  747. $diroflang = $dolibarr_main_document_root;
  748. $srcfile = $diroflang.'/langs/en_US/'.$modulelowercase.'.lang';
  749. $destfile = $diroflang.'/langs/'.$newlangcode.'/'.$modulelowercase.'.lang';
  750. $result = dol_copy($srcfile, $destfile, 0, 0);
  751. if ($result < 0) {
  752. setEventMessages($langs->trans("ErrorFailToCopyFile", $srcfile, $destfile), null, 'errors');
  753. }
  754. } else {
  755. $srcdir = $diroflang.'/langs/en_US';
  756. $srcfile = $diroflang.'/langs/en_US/'.$modulelowercase.'.lang';
  757. $destdir = $diroflang.'/langs/'.$newlangcode;
  758. $arrayofreplacement = array();
  759. if (!dol_is_dir($srcfile) || !dol_is_file($srcfile)) {
  760. $srcdir = DOL_DOCUMENT_ROOT.'/modulebuilder/template/langs/en_US';
  761. $arrayofreplacement = array('mymodule'=>$modulelowercase);
  762. }
  763. $result = dolCopyDir($srcdir, $destdir, 0, 0, $arrayofreplacement);
  764. }
  765. } else {
  766. setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Language")), null, 'errors');
  767. }
  768. }
  769. // Remove/delete File
  770. if ($dirins && $action == 'confirm_removefile' && !empty($module)) {
  771. $objectname = $tabobj;
  772. $dirins = $listofmodules[strtolower($module)]['moduledescriptorrootpath'];
  773. $destdir = $dirins.'/'.strtolower($module);
  774. $relativefilename = dol_sanitizePathName(GETPOST('file', 'restricthtml'));
  775. // Now we delete the file
  776. if ($relativefilename) {
  777. $dirnametodelete = dirname($relativefilename);
  778. $filetodelete = $dirins.'/'.$relativefilename;
  779. $dirtodelete = $dirins.'/'.$dirnametodelete;
  780. //check when we want delete api_file
  781. if (strpos($relativefilename, 'api') !== false) {
  782. $file_api = $destdir.'/class/api_'.strtolower($module).'.class.php';
  783. $removeFile = removeObjectFromApiFile($file_api, $objectname, $module);
  784. $var = getFromFile($file_api, '/*begin methods CRUD*/', '/*end methods CRUD*/');
  785. if (str_word_count($var) == 0) {
  786. $result = dol_delete_file($filetodelete);
  787. }
  788. if ($removeFile) {
  789. setEventMessages($langs->trans("ApiObjectDeleted"), null);
  790. }
  791. } else {
  792. $result = dol_delete_file($filetodelete);
  793. }
  794. if (!$result) {
  795. setEventMessages($langs->trans("ErrorFailToDeleteFile", basename($filetodelete)), null, 'errors');
  796. } else {
  797. // If we delete a .sql file, we delete also the other .sql file
  798. if (preg_match('/\.sql$/', $relativefilename)) {
  799. if (preg_match('/\.key\.sql$/', $relativefilename)) {
  800. $relativefilename = preg_replace('/\.key\.sql$/', '.sql', $relativefilename);
  801. $filetodelete = $dirins.'/'.$relativefilename;
  802. $result = dol_delete_file($filetodelete);
  803. } elseif (preg_match('/\.sql$/', $relativefilename)) {
  804. $relativefilename = preg_replace('/\.sql$/', '.key.sql', $relativefilename);
  805. $filetodelete = $dirins.'/'.$relativefilename;
  806. $result = dol_delete_file($filetodelete);
  807. }
  808. }
  809. if (dol_is_dir_empty($dirtodelete)) {
  810. dol_delete_dir($dirtodelete);
  811. }
  812. // Update descriptor file to comment file
  813. if (in_array($tab, array('css', 'js'))) {
  814. $srcfile = $dirins.'/'.strtolower($module).'/core/modules/mod'.$module.'.class.php';
  815. $arrayreplacement = array('/^\s*\''.preg_quote('/'.$relativefilename, '/').'\',*/m'=>' // \'/'.$relativefilename.'\',');
  816. dolReplaceInFile($srcfile, $arrayreplacement, '', 0, 0, 1);
  817. }
  818. if (preg_match('/_extrafields/', $relativefilename)) {
  819. // Now we update the object file to set $isextrafieldmanaged to 0
  820. $srcfile = $dirins.'/'.strtolower($module).'/class/'.strtolower($objectname).'.class.php';
  821. $arrayreplacement = array('/\$isextrafieldmanaged = 1;/' => '$isextrafieldmanaged = 0;');
  822. dolReplaceInFile($srcfile, $arrayreplacement, '', 0, 0, 1);
  823. }
  824. // Now we update the lib file to set $showtabofpagexxx to 0
  825. $varnametoupdate = '';
  826. $reg = array();
  827. if (preg_match('/_([a-z]+)\.php$/', $relativefilename, $reg)) {
  828. $varnametoupdate = 'showtabofpage'.$reg[1];
  829. }
  830. if ($varnametoupdate) {
  831. $srcfile = $dirins.'/'.strtolower($module).'/lib/'.strtolower($module).'_'.strtolower($objectname).'.lib.php';
  832. $arrayreplacement = array('/\$'.$varnametoupdate.' = 1;/' => '$'.$varnametoupdate.' = 0;');
  833. dolReplaceInFile($srcfile, $arrayreplacement, '', 0, 0, 1);
  834. }
  835. }
  836. }
  837. }
  838. // Init an object
  839. if ($dirins && $action == 'initobject' && $module && $objectname) {
  840. $objectname = ucfirst($objectname);
  841. $dirins = $dirread = $listofmodules[strtolower($module)]['moduledescriptorrootpath'];
  842. $moduletype = $listofmodules[strtolower($module)]['moduletype'];
  843. if (preg_match('/[^a-z0-9_]/i', $objectname)) {
  844. $error++;
  845. setEventMessages($langs->trans("SpaceOrSpecialCharAreNotAllowed"), null, 'errors');
  846. $tabobj = 'newobject';
  847. }
  848. if (class_exists($objectname)) {
  849. // TODO Add a more efficient detection. Scan disk ?
  850. $error++;
  851. setEventMessages($langs->trans("AnObjectWithThisClassNameAlreadyExists"), null, 'errors');
  852. $tabobj = 'newobject';
  853. }
  854. $srcdir = DOL_DOCUMENT_ROOT.'/modulebuilder/template';
  855. $destdir = $dirins.'/'.strtolower($module);
  856. // The dir was not created by init
  857. dol_mkdir($destdir.'/class');
  858. dol_mkdir($destdir.'/img');
  859. dol_mkdir($destdir.'/lib');
  860. dol_mkdir($destdir.'/scripts');
  861. dol_mkdir($destdir.'/sql');
  862. // Scan dir class to find if an object with same name already exists.
  863. if (!$error) {
  864. $dirlist = dol_dir_list($destdir.'/class', 'files', 0, '\.txt$');
  865. $alreadyfound = false;
  866. foreach ($dirlist as $key => $val) {
  867. $filefound = preg_replace('/\.txt$/', '', $val['name']);
  868. if (strtolower($objectname) == strtolower($filefound) && $objectname != $filefound) {
  869. $alreadyfound = true;
  870. $error++;
  871. setEventMessages($langs->trans("AnObjectAlreadyExistWithThisNameAndDiffCase"), null, 'errors');
  872. break;
  873. }
  874. }
  875. }
  876. // If we must reuse a table for properties, define $stringforproperties
  877. $stringforproperties = '';
  878. $tablename = GETPOST('initfromtablename', 'alpha');
  879. if ($tablename) {
  880. $_results = $db->DDLDescTable($tablename);
  881. if (empty($_results)) {
  882. $error++;
  883. $langs->load("errors");
  884. setEventMessages($langs->trans("ErrorTableNotFound", $tablename), null, 'errors');
  885. } else {
  886. /**
  887. * 'type' field format ('integer', 'integer:ObjectClass:PathToClass[:AddCreateButtonOrNot[:Filter[:Sortfield]]]', 'sellist:TableName:LabelFieldName[:KeyFieldName[:KeyFieldParent[:Filter[:Sortfield]]]]', 'varchar(x)', 'double(24,8)', 'real', 'price', 'text', 'text:none', 'html', 'date', 'datetime', 'timestamp', 'duration', 'mail', 'phone', 'ip', 'url', 'password')
  888. * Note: Filter can be a string like "(t.ref:like:'SO-%') or (t.date_creation:<:'20160101') or (t.nature:is:NULL)"
  889. * 'label' the translation key.
  890. * 'picto' is code of a picto to show before value in forms
  891. * 'enabled' is a condition when the field must be managed (Example: 1 or '$conf->global->MY_SETUP_PARAM' or 'isModEnabled("multicurrency")' ...)
  892. * 'position' is the sort order of field.
  893. * 'notnull' is set to 1 if not null in database. Set to -1 if we must set data to null if empty ('' or 0).
  894. * 'visible' says if field is visible in list (Examples: 0=Not visible, 1=Visible on list and create/update/view forms, 2=Visible on list only, 3=Visible on create/update/view form only (not list), 4=Visible on list and update/view form only (not create). 5=Visible on list and view only (not create/not update). Using a negative value means field is not shown by default on list but can be selected for viewing)
  895. * 'noteditable' says if field is not editable (1 or 0)
  896. * 'alwayseditable' says if field can be modified also when status is not draft ('1' or '0')
  897. * 'default' is a default value for creation (can still be overwrote by the Setup of Default Values if field is editable in creation form). Note: If default is set to '(PROV)' and field is 'ref', the default value will be set to '(PROVid)' where id is rowid when a new record is created.
  898. * 'index' if we want an index in database.
  899. * 'foreignkey'=>'tablename.field' if the field is a foreign key (it is recommanded to name the field fk_...).
  900. * 'searchall' is 1 if we want to search in this field when making a search from the quick search button.
  901. * 'isameasure' must be set to 1 or 2 if field can be used for measure. Field type must be summable like integer or double(24,8). Use 1 in most cases, or 2 if you don't want to see the column total into list (for example for percentage)
  902. * 'css' and 'cssview' and 'csslist' is the CSS style to use on field. 'css' is used in creation and update. 'cssview' is used in view mode. 'csslist' is used for columns in lists. For example: 'css'=>'minwidth300 maxwidth500 widthcentpercentminusx', 'cssview'=>'wordbreak', 'csslist'=>'tdoverflowmax200'
  903. * 'help' is a 'TranslationString' to use to show a tooltip on field. You can also use 'TranslationString:keyfortooltiponlick' for a tooltip on click.
  904. * 'showoncombobox' if value of the field must be visible into the label of the combobox that list record
  905. * 'disabled' is 1 if we want to have the field locked by a 'disabled' attribute. In most cases, this is never set into the definition of $fields into class, but is set dynamically by some part of code.
  906. * 'arrayofkeyval' to set a list of values if type is a list of predefined values. For example: array("0"=>"Draft","1"=>"Active","-1"=>"Cancel"). Note that type can be 'integer' or 'varchar'
  907. * 'autofocusoncreate' to have field having the focus on a create form. Only 1 field should have this property set to 1.
  908. * 'comment' is not used. You can store here any text of your choice. It is not used by application.
  909. * 'validate' is 1 if need to validate with $this->validateField()
  910. * 'copytoclipboard' is 1 or 2 to allow to add a picto to copy value into clipboard (1=picto after label, 2=picto after value)
  911. */
  912. /*public $fields=array(
  913. 'rowid' =>array('type'=>'integer', 'label'=>'TechnicalID', 'enabled'=>1, 'visible'=>-2, 'notnull'=>1, 'index'=>1, 'position'=>1, 'comment'=>'Id'),
  914. 'ref' =>array('type'=>'varchar(128)', 'label'=>'Ref', 'enabled'=>1, 'visible'=>1, 'notnull'=>1, 'showoncombobox'=>1, 'index'=>1, 'position'=>10, 'searchall'=>1, 'comment'=>'Reference of object'),
  915. 'entity' =>array('type'=>'integer', 'label'=>'Entity', 'enabled'=>1, 'visible'=>0, 'default'=>1, 'notnull'=>1, 'index'=>1, 'position'=>20),
  916. 'label' =>array('type'=>'varchar(255)', 'label'=>'Label', 'enabled'=>1, 'visible'=>1, 'position'=>30, 'searchall'=>1, 'css'=>'minwidth200', 'help'=>'Help text', 'alwayseditable'=>'1'),
  917. 'amount' =>array('type'=>'double(24,8)', 'label'=>'Amount', 'enabled'=>1, 'visible'=>1, 'default'=>'null', 'position'=>40, 'searchall'=>0, 'isameasure'=>1, 'help'=>'Help text'),
  918. 'fk_soc' =>array('type'=>'integer:Societe:societe/class/societe.class.php', 'label'=>'ThirdParty', 'visible'=>1, 'enabled'=>1, 'position'=>50, 'notnull'=>-1, 'index'=>1, 'searchall'=>1, 'help'=>'LinkToThirdparty'),
  919. 'description' =>array('type'=>'text', 'label'=>'Descrption', 'enabled'=>1, 'visible'=>0, 'position'=>60),
  920. 'note_public' =>array('type'=>'html', 'label'=>'NotePublic', 'enabled'=>1, 'visible'=>0, 'position'=>61),
  921. 'note_private' =>array('type'=>'html', 'label'=>'NotePrivate', 'enabled'=>1, 'visible'=>0, 'position'=>62),
  922. 'date_creation' =>array('type'=>'datetime', 'label'=>'DateCreation', 'enabled'=>1, 'visible'=>-2, 'notnull'=>1, 'position'=>500),
  923. 'tms' =>array('type'=>'timestamp', 'label'=>'DateModification', 'enabled'=>1, 'visible'=>-2, 'notnull'=>1, 'position'=>501),
  924. //'date_valid' =>array('type'=>'datetime', 'label'=>'DateCreation', 'enabled'=>1, 'visible'=>-2, 'position'=>502),
  925. 'fk_user_creat' =>array('type'=>'integer', 'label'=>'UserAuthor', 'enabled'=>1, 'visible'=>-2, 'notnull'=>1, 'position'=>510),
  926. 'fk_user_modif' =>array('type'=>'integer', 'label'=>'UserModif', 'enabled'=>1, 'visible'=>-2, 'notnull'=>-1, 'position'=>511),
  927. //'fk_user_valid' =>array('type'=>'integer', 'label'=>'UserValidation', 'enabled'=>1, 'visible'=>-1, 'position'=>512),
  928. 'import_key' =>array('type'=>'varchar(14)', 'label'=>'ImportId', 'enabled'=>1, 'visible'=>-2, 'notnull'=>-1, 'index'=>0, 'position'=>1000),
  929. 'status' =>array('type'=>'integer', 'label'=>'Status', 'enabled'=>1, 'visible'=>1, 'notnull'=>1, 'default'=>0, 'index'=>1, 'position'=>1000, 'arrayofkeyval'=>array(0=>'Draft', 1=>'Active', -1=>'Cancel')),
  930. );*/
  931. $stringforproperties = '// BEGIN MODULEBUILDER PROPERTIES'."\n";
  932. $stringforproperties .= 'public $fields=array('."\n";
  933. $i = 10;
  934. while ($obj = $db->fetch_object($_results)) {
  935. // fieldname
  936. $fieldname = $obj->Field;
  937. // type
  938. $type = $obj->Type;
  939. if ($type == 'int(11)') {
  940. $type = 'integer';
  941. }
  942. if ($type == 'float') {
  943. $type = 'real';
  944. }
  945. if (strstr($type, 'tinyint')) {
  946. $type = 'integer';
  947. }
  948. if ($obj->Field == 'fk_soc') {
  949. $type = 'integer:Societe:societe/class/societe.class.php';
  950. }
  951. if (preg_match('/^fk_proj/', $obj->Field)) {
  952. $type = 'integer:Project:projet/class/project.class.php:1:fk_statut=1';
  953. }
  954. if (preg_match('/^fk_prod/', $obj->Field)) {
  955. $type = 'integer:Product:product/class/product.class.php:1';
  956. }
  957. if ($obj->Field == 'fk_warehouse') {
  958. $type = 'integer:Entrepot:product/stock/class/entrepot.class.php';
  959. }
  960. if (preg_match('/^(fk_user|fk_commercial)/', $obj->Field)) {
  961. $type = 'integer:User:user/class/user.class.php';
  962. }
  963. // notnull
  964. $notnull = ($obj->Null == 'YES' ? 0 : 1);
  965. if ($fieldname == 'fk_user_modif') {
  966. $notnull = -1;
  967. }
  968. // label
  969. $label = preg_replace('/_/', '', ucfirst($fieldname));
  970. if ($fieldname == 'rowid') {
  971. $label = 'TechnicalID';
  972. }
  973. if ($fieldname == 'import_key') {
  974. $label = 'ImportId';
  975. }
  976. if ($fieldname == 'fk_soc') {
  977. $label = 'ThirdParty';
  978. }
  979. if ($fieldname == 'tms') {
  980. $label = 'DateModification';
  981. }
  982. if ($fieldname == 'datec') {
  983. $label = 'DateCreation';
  984. }
  985. if ($fieldname == 'date_valid') {
  986. $label = 'DateValidation';
  987. }
  988. if ($fieldname == 'datev') {
  989. $label = 'DateValidation';
  990. }
  991. if ($fieldname == 'note_private') {
  992. $label = 'NotePublic';
  993. }
  994. if ($fieldname == 'note_public') {
  995. $label = 'NotePrivate';
  996. }
  997. if ($fieldname == 'fk_user_creat') {
  998. $label = 'UserAuthor';
  999. }
  1000. if ($fieldname == 'fk_user_modif') {
  1001. $label = 'UserModif';
  1002. }
  1003. if ($fieldname == 'fk_user_valid') {
  1004. $label = 'UserValidation';
  1005. }
  1006. // visible
  1007. $visible = -1;
  1008. if ($fieldname == 'entity') {
  1009. $visible = -2;
  1010. }
  1011. if ($fieldname == 'import_key') {
  1012. $visible = -2;
  1013. }
  1014. if ($fieldname == 'fk_user_creat') {
  1015. $visible = -2;
  1016. }
  1017. if ($fieldname == 'fk_user_modif') {
  1018. $visible = -2;
  1019. }
  1020. if (in_array($fieldname, array('ref_ext', 'model_pdf', 'note_public', 'note_private'))) {
  1021. $visible = 0;
  1022. }
  1023. // enabled
  1024. $enabled = 1;
  1025. // default
  1026. $default = '';
  1027. if ($fieldname == 'entity') {
  1028. $default = 1;
  1029. }
  1030. // position
  1031. $position = $i;
  1032. if (in_array($fieldname, array('status', 'statut', 'fk_status', 'fk_statut'))) {
  1033. $position = 500;
  1034. }
  1035. if ($fieldname == 'import_key') {
  1036. $position = 900;
  1037. }
  1038. // $alwayseditable
  1039. if ($fieldname == 'label') {
  1040. $alwayseditable = 1;
  1041. }
  1042. // index
  1043. $index = 0;
  1044. if ($fieldname == 'entity') {
  1045. $index = 1;
  1046. }
  1047. // css, cssview, csslist
  1048. $css = '';
  1049. $cssview = '';
  1050. $csslist = '';
  1051. if (preg_match('/^fk_/', $fieldname)) {
  1052. $css = 'maxwidth500 widthcentpercentminusxx';
  1053. }
  1054. if ($fieldname == 'label') {
  1055. $css = 'minwidth300';
  1056. $cssview = 'wordbreak';
  1057. }
  1058. if (in_array($fieldname, array('note_public', 'note_private'))) {
  1059. $cssview = 'wordbreak';
  1060. }
  1061. if (in_array($fieldname, array('ref', 'label')) || preg_match('/integer:/', $type)) {
  1062. $csslist = 'tdoverflowmax150';
  1063. }
  1064. // type
  1065. $picto = $obj->Picto;
  1066. if ($obj->Field == 'fk_soc') {
  1067. $picto = 'company';
  1068. }
  1069. if (preg_match('/^fk_proj/', $obj->Field)) {
  1070. $picto = 'project';
  1071. }
  1072. // Build the property string
  1073. $stringforproperties .= "'".$obj->Field."'=>array('type'=>'".$type."', 'label'=>'".$label."',";
  1074. if ($default != '') {
  1075. $stringforproperties .= " 'default'=>".$default.",";
  1076. }
  1077. $stringforproperties .= " 'enabled'=>".$enabled.",";
  1078. $stringforproperties .= " 'visible'=>".$visible;
  1079. if ($notnull) {
  1080. $stringforproperties .= ", 'notnull'=>".$notnull;
  1081. }
  1082. if ($alwayseditable) {
  1083. $stringforproperties .= ", 'alwayseditable'=>1";
  1084. }
  1085. if ($fieldname == 'ref' || $fieldname == 'code') {
  1086. $stringforproperties .= ", 'showoncombobox'=>1";
  1087. }
  1088. $stringforproperties .= ", 'position'=>".$position;
  1089. if ($index) {
  1090. $stringforproperties .= ", 'index'=>".$index;
  1091. }
  1092. if ($picto) {
  1093. $stringforproperties .= ", 'picto'=>'".$picto."'";
  1094. }
  1095. if ($css) {
  1096. $stringforproperties .= ", 'css'=>'".$css."'";
  1097. }
  1098. if ($cssview) {
  1099. $stringforproperties .= ", 'cssview'=>'".$cssview."'";
  1100. }
  1101. if ($csslist) {
  1102. $stringforproperties .= ", 'csslist'=>'".$csslist."'";
  1103. }
  1104. $stringforproperties .= "),\n";
  1105. $i += 5;
  1106. }
  1107. $stringforproperties .= ');'."\n";
  1108. $stringforproperties .= '// END MODULEBUILDER PROPERTIES'."\n";
  1109. }
  1110. }
  1111. if (!$error) {
  1112. // Copy some files
  1113. $filetogenerate = array(
  1114. 'myobject_card.php'=>strtolower($objectname).'_card.php',
  1115. 'myobject_note.php'=>strtolower($objectname).'_note.php',
  1116. 'myobject_contact.php'=>strtolower($objectname).'_contact.php',
  1117. 'myobject_document.php'=>strtolower($objectname).'_document.php',
  1118. 'myobject_agenda.php'=>strtolower($objectname).'_agenda.php',
  1119. 'myobject_list.php'=>strtolower($objectname).'_list.php',
  1120. 'admin/myobject_extrafields.php'=>'admin/'.strtolower($objectname).'_extrafields.php',
  1121. 'lib/mymodule_myobject.lib.php'=>'lib/'.strtolower($module).'_'.strtolower($objectname).'.lib.php',
  1122. //'test/phpunit/MyObjectTest.php'=>'test/phpunit/'.strtolower($objectname).'Test.php',
  1123. 'sql/llx_mymodule_myobject.sql'=>'sql/llx_'.strtolower($module).'_'.strtolower($objectname).'.sql',
  1124. 'sql/llx_mymodule_myobject.key.sql'=>'sql/llx_'.strtolower($module).'_'.strtolower($objectname).'.key.sql',
  1125. 'sql/llx_mymodule_myobject_extrafields.sql'=>'sql/llx_'.strtolower($module).'_'.strtolower($objectname).'_extrafields.sql',
  1126. 'sql/llx_mymodule_myobject_extrafields.key.sql'=>'sql/llx_'.strtolower($module).'_'.strtolower($objectname).'_extrafields.key.sql',
  1127. //'scripts/mymodule.php'=>'scripts/'.strtolower($objectname).'.php',
  1128. 'class/myobject.class.php'=>'class/'.strtolower($objectname).'.class.php',
  1129. //'class/api_mymodule.class.php'=>'class/api_'.strtolower($module).'.class.php',
  1130. );
  1131. if (GETPOST('includerefgeneration', 'aZ09')) {
  1132. dol_mkdir($destdir.'/core/modules/'.strtolower($module));
  1133. $filetogenerate += array(
  1134. 'core/modules/mymodule/mod_myobject_advanced.php'=>'core/modules/'.strtolower($module).'/mod_'.strtolower($objectname).'_advanced.php',
  1135. 'core/modules/mymodule/mod_myobject_standard.php'=>'core/modules/'.strtolower($module).'/mod_'.strtolower($objectname).'_standard.php',
  1136. 'core/modules/mymodule/modules_myobject.php'=>'core/modules/'.strtolower($module).'/modules_'.strtolower($objectname).'.php',
  1137. );
  1138. }
  1139. if (GETPOST('includedocgeneration', 'aZ09')) {
  1140. dol_mkdir($destdir.'/core/modules/'.strtolower($module));
  1141. dol_mkdir($destdir.'/core/modules/'.strtolower($module).'/doc');
  1142. $filetogenerate += array(
  1143. 'core/modules/mymodule/doc/doc_generic_myobject_odt.modules.php'=>'core/modules/'.strtolower($module).'/doc/doc_generic_'.strtolower($objectname).'_odt.modules.php',
  1144. 'core/modules/mymodule/doc/pdf_standard_myobject.modules.php'=>'core/modules/'.strtolower($module).'/doc/pdf_standard_'.strtolower($objectname).'.modules.php'
  1145. );
  1146. }
  1147. if (GETPOST('generatepermissions', 'aZ09')) {
  1148. $firstobjectname = 'myobject';
  1149. $pathtofile = $listofmodules[strtolower($module)]['moduledescriptorrelpath'];
  1150. dol_include_once($pathtofile);
  1151. $class = 'mod'.$module;
  1152. if (class_exists($class)) {
  1153. try {
  1154. $moduleobj = new $class($db);
  1155. } catch (Exception $e) {
  1156. $error++;
  1157. dol_print_error($db, $e->getMessage());
  1158. }
  1159. }
  1160. $rights = $moduleobj->rights;
  1161. $moduledescriptorfile = $destdir.'/core/modules/mod'.$module.'.class.php';
  1162. $checkComment=checkExistComment($moduledescriptorfile, 1);
  1163. if ($checkComment < 0) {
  1164. setEventMessages($langs->trans("WarningCommentNotFound", $langs->trans("Permissions"), "mod".$module."class.php"), null, 'warnings');
  1165. } else {
  1166. $generatePerms = reWriteAllPermissions($moduledescriptorfile, $rights, null, null, $objectname, $module, -2);
  1167. if ($generatePerms < 0) {
  1168. setEventMessages($langs->trans("WarningPermissionAlreadyExist", $langs->transnoentities($objectname)), null, 'warnings');
  1169. }
  1170. }
  1171. }
  1172. if (!$error) {
  1173. foreach ($filetogenerate as $srcfile => $destfile) {
  1174. $result = dol_copy($srcdir.'/'.$srcfile, $destdir.'/'.$destfile, $newmask, 0);
  1175. if ($result <= 0) {
  1176. if ($result < 0) {
  1177. $error++;
  1178. $langs->load("errors");
  1179. setEventMessages($langs->trans("ErrorFailToCopyFile", $srcdir.'/'.$srcfile, $destdir.'/'.$destfile), null, 'errors');
  1180. } else {
  1181. // $result == 0
  1182. setEventMessages($langs->trans("FileAlreadyExists", $destfile), null, 'warnings');
  1183. }
  1184. }
  1185. $arrayreplacement = array(
  1186. '/myobject\.class\.php/' => strtolower($objectname).'.class.php',
  1187. '/myobject\.lib\.php/' => strtolower($objectname).'.lib.php',
  1188. );
  1189. dolReplaceInFile($destdir.'/'.$destfile, $arrayreplacement, '', 0, 0, 1);
  1190. }
  1191. }
  1192. // Replace property section with $stringforproperties
  1193. if (!$error && $stringforproperties) {
  1194. //var_dump($stringforproperties);exit;
  1195. $arrayreplacement = array(
  1196. '/\/\/ BEGIN MODULEBUILDER PROPERTIES.*\/\/ END MODULEBUILDER PROPERTIES/ims' => $stringforproperties
  1197. );
  1198. dolReplaceInFile($destdir.'/class/'.strtolower($objectname).'.class.php', $arrayreplacement, '', 0, 0, 1);
  1199. }
  1200. // Edit the class 'class/'.strtolower($objectname).'.class.php'
  1201. if (GETPOST('includerefgeneration', 'aZ09')) {
  1202. // Replace 'visible'=>1, 'noteditable'=>0, 'default'=>''
  1203. $arrayreplacement = array(
  1204. '/\'visible\'=>1,\s*\'noteditable\'=>0,\s*\'default\'=>\'\'/' => "'visible'=>4, 'noteditable'=>1, 'default'=>'(PROV)'"
  1205. );
  1206. //var_dump($arrayreplacement);exit;
  1207. //var_dump($destdir.'/class/'.strtolower($objectname).'.class.php');exit;
  1208. dolReplaceInFile($destdir.'/class/'.strtolower($objectname).'.class.php', $arrayreplacement, '', 0, 0, 1);
  1209. $arrayreplacement = array(
  1210. '/\'models\' => 0,/' => '\'models\' => 1,'
  1211. );
  1212. dolReplaceInFile($destdir.'/core/modules/mod'.$module.'.class.php', $arrayreplacement, '', 0, 0, 1);
  1213. }
  1214. // Edit the setup file and the card page
  1215. if (GETPOST('includedocgeneration', 'aZ09')) {
  1216. // Replace some var init into some files
  1217. $arrayreplacement = array(
  1218. '/\$includedocgeneration = 0;/' => '$includedocgeneration = 1;'
  1219. );
  1220. dolReplaceInFile($destdir.'/class/'.strtolower($objectname).'.class.php', $arrayreplacement, '', 0, 0, 1);
  1221. dolReplaceInFile($destdir.'/'.strtolower($objectname).'_card.php', $arrayreplacement, '', 0, 0, 1);
  1222. $arrayreplacement = array(
  1223. '/\'models\' => 0,/' => '\'models\' => 1,'
  1224. );
  1225. dolReplaceInFile($destdir.'/core/modules/mod'.$module.'.class.php', $arrayreplacement, '', 0, 0, 1);
  1226. }
  1227. // TODO Update entries '$myTmpObjects['MyObject']=array('includerefgeneration'=>0, 'includedocgeneration'=>0);'
  1228. // Scan for object class files
  1229. $listofobject = dol_dir_list($destdir.'/class', 'files', 0, '\.class\.php$');
  1230. $firstobjectname = '';
  1231. foreach ($listofobject as $fileobj) {
  1232. if (preg_match('/^api_/', $fileobj['name'])) {
  1233. continue;
  1234. }
  1235. if (preg_match('/^actions_/', $fileobj['name'])) {
  1236. continue;
  1237. }
  1238. $tmpcontent = file_get_contents($fileobj['fullname']);
  1239. $reg = array();
  1240. if (preg_match('/class\s+([^\s]*)\s+extends\s+CommonObject/ims', $tmpcontent, $reg)) {
  1241. $objectnameloop = $reg[1];
  1242. if (empty($firstobjectname)) {
  1243. $firstobjectname = $objectnameloop;
  1244. }
  1245. }
  1246. // Regenerate left menu entry in descriptor for $objectname
  1247. $stringtoadd = "
  1248. \$this->menu[\$r++]=array(
  1249. 'fk_menu'=>'fk_mainmenu=mymodule',
  1250. 'type'=>'left',
  1251. 'titre'=>'MyObject',
  1252. 'prefix' => img_picto('', \$this->picto, 'class=\"paddingright pictofixedwidth valignmiddle\"'),
  1253. 'mainmenu'=>'mymodule',
  1254. 'leftmenu'=>'myobject',
  1255. 'url'=>'/mymodule/myobject_list.php',
  1256. 'langs'=>'mymodule@mymodule',
  1257. 'position'=>1000+\$r,
  1258. 'enabled'=>'\$conf->mymodule->enabled',
  1259. 'perms'=>'\$user->hasRight(\"mymodule\", \"myobject\", \"read\")',
  1260. 'target'=>'',
  1261. 'user'=>2,
  1262. );
  1263. \$this->menu[\$r++]=array(
  1264. 'fk_menu'=>'fk_mainmenu=mymodule,fk_leftmenu=myobject',
  1265. 'type'=>'left',
  1266. 'titre'=>'List MyObject',
  1267. 'mainmenu'=>'mymodule',
  1268. 'leftmenu'=>'mymodule_myobject_list',
  1269. 'url'=>'/mymodule/myobject_list.php',
  1270. 'langs'=>'mymodule@mymodule',
  1271. 'position'=>1000+\$r,
  1272. 'enabled'=>'\$conf->mymodule->enabled',
  1273. 'perms'=>'\$user->hasRight(\"mymodule\", \"myobject\", \"read\")',
  1274. 'target'=>'',
  1275. 'user'=>2,
  1276. );
  1277. \$this->menu[\$r++]=array(
  1278. 'fk_menu'=>'fk_mainmenu=mymodule,fk_leftmenu=myobject',
  1279. 'type'=>'left',
  1280. 'titre'=>'New MyObject',
  1281. 'mainmenu'=>'mymodule',
  1282. 'leftmenu'=>'mymodule_myobject_new',
  1283. 'url'=>'/mymodule/myobject_card.php?action=create',
  1284. 'langs'=>'mymodule@mymodule',
  1285. 'position'=>1000+\$r,
  1286. 'enabled'=>'\$conf->mymodule->enabled',
  1287. 'perms'=>'\$user->hasRight(\"mymodule\", \"myobject\", \"write\")',
  1288. 'target'=>'',
  1289. 'user'=>2
  1290. );\n";
  1291. $stringtoadd = preg_replace('/MyObject/', $objectname, $stringtoadd);
  1292. $stringtoadd = preg_replace('/mymodule/', strtolower($module), $stringtoadd);
  1293. $stringtoadd = preg_replace('/myobject/', strtolower($objectname), $stringtoadd);
  1294. $moduledescriptorfile = $destdir.'/core/modules/mod'.$module.'.class.php';
  1295. }
  1296. // TODO Allow a replace with regex using dolReplaceInFile with param arryreplacementisregex to 1
  1297. // TODO Avoid duplicate addition
  1298. // load class and check if menu exist with same object name
  1299. $pathtofile = $listofmodules[strtolower($module)]['moduledescriptorrelpath'];
  1300. dol_include_once($pathtofile);
  1301. $class = 'mod'.$module;
  1302. if (class_exists($class)) {
  1303. try {
  1304. $moduleobj = new $class($db);
  1305. } catch (Exception $e) {
  1306. $error++;
  1307. dol_print_error($db, $e->getMessage());
  1308. }
  1309. }
  1310. $menus = $moduleobj->menu;
  1311. $counter = 0 ;
  1312. foreach ($menus as $menu) {
  1313. if ($menu['leftmenu'] == strtolower($objectname)) {
  1314. $counter++;
  1315. }
  1316. }
  1317. if (!$counter) {
  1318. $checkComment = checkExistComment($moduledescriptorfile, 0);
  1319. if ($checkComment < 0) {
  1320. $error++;
  1321. setEventMessages($langs->trans("WarningCommentNotFound", $langs->trans("Menus"), "mod".$module."class.php"), null, 'warnings');
  1322. } else {
  1323. dolReplaceInFile($moduledescriptorfile, array('/* END MODULEBUILDER LEFTMENU MYOBJECT */' => '/*LEFTMENU '.strtoupper($objectname).'*/'.$stringtoadd."\n\t\t".'/*END LEFTMENU '.strtoupper($objectname).'*/'."\n\t\t".'/* END MODULEBUILDER LEFTMENU MYOBJECT */'));
  1324. }
  1325. }
  1326. // Add module descriptor to list of files to replace "MyObject' string with real name of object.
  1327. $filetogenerate[] = 'core/modules/mod'.$module.'.class.php';
  1328. }
  1329. if (!$error) {
  1330. // Edit PHP files to make replacement
  1331. foreach ($filetogenerate as $destfile) {
  1332. $phpfileval['fullname'] = $destdir.'/'.$destfile;
  1333. //var_dump($phpfileval['fullname']);
  1334. $arrayreplacement = array(
  1335. 'mymodule'=>strtolower($module),
  1336. 'MyModule'=>$module,
  1337. 'MYMODULE'=>strtoupper($module),
  1338. 'My module'=>$module,
  1339. 'my module'=>$module,
  1340. 'mon module'=>$module,
  1341. 'Mon module'=>$module,
  1342. 'htdocs/modulebuilder/template/'=>strtolower($modulename),
  1343. 'myobject'=>strtolower($objectname),
  1344. 'MyObject'=>$objectname,
  1345. //'MYOBJECT'=>strtoupper($objectname),
  1346. '---Put here your own copyright and developer email---'=>dol_print_date($now, '%Y').' '.$user->getFullName($langs).($user->email ? ' <'.$user->email.'>' : '')
  1347. );
  1348. if (!empty($conf->global->MODULEBUILDER_SPECIFIC_AUTHOR)) {
  1349. $arrayreplacement['---Put here your own copyright and developer email---'] = dol_print_date($now, '%Y').' ' . getDolGlobalString('MODULEBUILDER_SPECIFIC_AUTHOR');
  1350. }
  1351. $result = dolReplaceInFile($phpfileval['fullname'], $arrayreplacement);
  1352. //var_dump($result);
  1353. if ($result < 0) {
  1354. setEventMessages($langs->trans("ErrorFailToMakeReplacementInto", $phpfileval['fullname']), null, 'errors');
  1355. }
  1356. }
  1357. }
  1358. if (!$error) {
  1359. // Edit the class file to write properties
  1360. $object = rebuildObjectClass($destdir, $module, $objectname, $newmask);
  1361. if (is_numeric($object) && $object <= 0) {
  1362. $pathoffiletoeditsrc = $destdir.'/class/'.strtolower($objectname).'.class.php';
  1363. setEventMessages($langs->trans('ErrorFailToCreateFile', $pathoffiletoeditsrc), null, 'errors');
  1364. $error++;
  1365. }
  1366. // check if documentation was generate and add table of properties object
  1367. $file = $destdir.'/class/'.strtolower($objectname).'.class.php';
  1368. $destfile = $destdir.'/doc/Documentation.asciidoc';
  1369. if (file_exists($destfile)) {
  1370. writePropsInAsciiDoc($file, $objectname, $destfile);
  1371. }
  1372. }
  1373. if (!$error) {
  1374. // Edit sql with new properties
  1375. $result = rebuildObjectSql($destdir, $module, $objectname, $newmask, '', $object);
  1376. if ($result <= 0) {
  1377. setEventMessages($langs->trans('ErrorFailToCreateFile', '.sql'), null);
  1378. $error++;
  1379. }
  1380. }
  1381. if (!$error) {
  1382. setEventMessages($langs->trans('FilesForObjectInitialized', $objectname), null);
  1383. $tabobj = $objectname;
  1384. } else {
  1385. $tabobj = 'newobject';
  1386. }
  1387. // check if module is enabled
  1388. if (isModEnabled(strtolower($module))) {
  1389. $result = unActivateModule(strtolower($module));
  1390. dolibarr_set_const($db, "MAIN_IHM_PARAMS_REV", (int) $conf->global->MAIN_IHM_PARAMS_REV + 1, 'chaine', 0, '', $conf->entity);
  1391. if ($result) {
  1392. setEventMessages($result, null, 'errors');
  1393. }
  1394. setEventMessages($langs->trans('WarningModuleNeedRefresh', $langs->transnoentities($module)), null, 'warnings');
  1395. header("Location: ".DOL_URL_ROOT.'/modulebuilder/index.php?tab=objects&module='.$module);
  1396. exit;
  1397. }
  1398. }
  1399. // Add a dictionary
  1400. if ($dirins && $action == 'initdic' && $module && empty($cancel)) {
  1401. $pathtofile = $listofmodules[strtolower($module)]['moduledescriptorrelpath'];
  1402. $destdir = $dirins.'/'.strtolower($module);
  1403. $moduledescriptorfile = $dirins.'/'.strtolower($module).'/core/modules/mod'.$module.'.class.php';
  1404. if (!GETPOST('dicname')) {
  1405. $error++;
  1406. setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("Table")), null, 'errors');
  1407. }
  1408. if (!GETPOST('label')) {
  1409. $error++;
  1410. setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("Lable")), null, 'errors');
  1411. }
  1412. if (!$error) {
  1413. $newdicname = $dicname;
  1414. if (!preg_match('/^c_/', $newdicname)) {
  1415. $newdicname = 'c_'.$dicname;
  1416. }
  1417. dol_include_once($pathtofile);
  1418. $class = 'mod'.$module;
  1419. if (class_exists($class)) {
  1420. try {
  1421. $moduleobj = new $class($db);
  1422. } catch (Exception $e) {
  1423. $error++;
  1424. dol_print_error($db, $e->getMessage());
  1425. }
  1426. } else {
  1427. $error++;
  1428. $langs->load("errors");
  1429. dol_print_error($db, $langs->trans("ErrorFailedToLoadModuleDescriptorForXXX", $module));
  1430. exit;
  1431. }
  1432. $dictionaries = $moduleobj->dictionaries;
  1433. $checkComment = checkExistComment($moduledescriptorfile, 2);
  1434. if ($checkComment < 0) {
  1435. setEventMessages($langs->trans("WarningCommentNotFound", $langs->trans("Dictionaries"), "mod".$module."class.php"), null, 'warnings');
  1436. } else {
  1437. createNewDictionnary($module, $moduledescriptorfile, $newdicname, $dictionaries);
  1438. if (function_exists('opcache_invalidate')) {
  1439. opcache_reset(); // remove the include cache hell !
  1440. }
  1441. clearstatcache(true);
  1442. header("Location: ".DOL_URL_ROOT.'/modulebuilder/index.php?tab=dictionaries&module='.$module.($forceddirread ? '@'.$dirread : ''));
  1443. exit;
  1444. }
  1445. }
  1446. }
  1447. // Delete a SQL table
  1448. if ($dirins && ($action == 'droptable' || $action == 'droptableextrafields') && !empty($module) && !empty($tabobj)) {
  1449. $objectname = $tabobj;
  1450. $arrayoftables = array();
  1451. if ($action == 'droptable') {
  1452. $arrayoftables[] = MAIN_DB_PREFIX.strtolower($module).'_'.strtolower($tabobj);
  1453. }
  1454. if ($action == 'droptableextrafields') {
  1455. $arrayoftables[] = MAIN_DB_PREFIX.strtolower($module).'_'.strtolower($tabobj).'_extrafields';
  1456. }
  1457. foreach ($arrayoftables as $tabletodrop) {
  1458. $nb = -1;
  1459. $sql = "SELECT COUNT(*) as nb FROM ".$tabletodrop;
  1460. $resql = $db->query($sql);
  1461. if ($resql) {
  1462. $obj = $db->fetch_object($resql);
  1463. if ($obj) {
  1464. $nb = $obj->nb;
  1465. }
  1466. } else {
  1467. if ($db->lasterrno() == 'DB_ERROR_NOSUCHTABLE') {
  1468. setEventMessages($langs->trans("TableDoesNotExists", $tabletodrop), null, 'warnings');
  1469. } else {
  1470. dol_print_error($db);
  1471. }
  1472. }
  1473. if ($nb == 0) {
  1474. $resql = $db->DDLDropTable($tabletodrop);
  1475. //var_dump($resql);
  1476. setEventMessages($langs->trans("TableDropped", $tabletodrop), null, 'mesgs');
  1477. } elseif ($nb > 0) {
  1478. setEventMessages($langs->trans("TableNotEmptyDropCanceled", $tabletodrop), null, 'warnings');
  1479. }
  1480. }
  1481. }
  1482. if ($dirins && $action == 'addproperty' && empty($cancel) && !empty($module) && (!empty($tabobj) || !empty(GETPOST('obj')))) {
  1483. $error = 0;
  1484. $objectname = (GETPOST('obj') ? GETPOST('obj') : $tabobj);
  1485. $dirins = $dirread = $listofmodules[strtolower($module)]['moduledescriptorrootpath'];
  1486. $moduletype = $listofmodules[strtolower($module)]['moduletype'];
  1487. $srcdir = $dirread.'/'.strtolower($module);
  1488. $destdir = $dirins.'/'.strtolower($module);
  1489. dol_mkdir($destdir);
  1490. $objects = dolGetListOfObjectClasses($destdir);
  1491. if (!in_array($objectname, array_values($objects))) {
  1492. $error++;
  1493. setEventMessages($langs->trans("ErrorObjectNotFound", $langs->transnoentities($objectname)), null, 'errors');
  1494. }
  1495. // We click on add property
  1496. if (!GETPOST('regenerateclasssql') && !GETPOST('regeneratemissing')) {
  1497. if (!GETPOST('propname', 'aZ09')) {
  1498. $error++;
  1499. setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("Name")), null, 'errors');
  1500. }
  1501. if (!GETPOST('proplabel', 'alpha')) {
  1502. $error++;
  1503. setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("Label")), null, 'errors');
  1504. }
  1505. if (!GETPOST('proptype', 'alpha')) {
  1506. $error++;
  1507. setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("Type")), null, 'errors');
  1508. }
  1509. if (!$error && !GETPOST('regenerateclasssql') && !GETPOST('regeneratemissing')) {
  1510. $addfieldentry = array(
  1511. 'name'=>GETPOST('propname', 'aZ09'),
  1512. 'label'=>GETPOST('proplabel', 'alpha'),
  1513. 'type'=>strtolower(GETPOST('proptype', 'alpha')),
  1514. 'arrayofkeyval'=>GETPOST('proparrayofkeyval', 'alphawithlgt'), // Example json string '{"0":"Draft","1":"Active","-1":"Cancel"}'
  1515. 'visible'=>GETPOST('propvisible', 'alphanohtml'),
  1516. 'enabled'=>GETPOST('propenabled', 'alphanohtml'),
  1517. 'position'=>GETPOST('propposition', 'int'),
  1518. 'notnull'=>GETPOST('propnotnull', 'int'),
  1519. 'index'=>GETPOST('propindex', 'int'),
  1520. 'searchall'=>GETPOST('propsearchall', 'int'),
  1521. 'isameasure'=>GETPOST('propisameasure', 'int'),
  1522. 'comment'=>GETPOST('propcomment', 'alpha'),
  1523. 'help'=>GETPOST('prophelp', 'alpha'),
  1524. 'css'=>GETPOST('propcss', 'alpha'), // Can be 'maxwidth500 widthcentpercentminusxx' for example
  1525. 'cssview'=>GETPOST('propcssview', 'alpha'),
  1526. 'csslist'=>GETPOST('propcsslist', 'alpha'),
  1527. 'default'=>GETPOST('propdefault', 'restricthtml'),
  1528. 'noteditable'=>intval(GETPOST('propnoteditable', 'int')),
  1529. //'alwayseditable'=>intval(GETPOST('propalwayseditable', 'int')),
  1530. 'validate' => GETPOST('propvalidate', 'int')
  1531. );
  1532. if (!empty($addfieldentry['arrayofkeyval']) && !is_array($addfieldentry['arrayofkeyval'])) {
  1533. $tmpdecode = json_decode($addfieldentry['arrayofkeyval'], true);
  1534. if ($tmpdecode) { // If string is already a json
  1535. $addfieldentry['arrayofkeyval'] = $tmpdecode;
  1536. } else { // If string is a list of lines with "key,value"
  1537. $tmparray = dolExplodeIntoArray($addfieldentry['arrayofkeyval'], "\n", ",");
  1538. $addfieldentry['arrayofkeyval'] = $tmparray;
  1539. }
  1540. }
  1541. }
  1542. } else {
  1543. $addfieldentry = array();
  1544. }
  1545. /*if (GETPOST('regeneratemissing'))
  1546. {
  1547. setEventMessages($langs->trans("FeatureNotYetAvailable"), null, 'warnings');
  1548. $error++;
  1549. }*/
  1550. $moduletype = $listofmodules[strtolower($module)]['moduletype'];
  1551. // Edit the class file to write properties
  1552. if (!$error) {
  1553. $object = rebuildObjectClass($destdir, $module, $objectname, $newmask, $srcdir, $addfieldentry, $moduletype);
  1554. if (is_numeric($object) && $object <= 0) {
  1555. $pathoffiletoeditsrc = $destdir.'/class/'.strtolower($objectname).'.class.php';
  1556. setEventMessages($langs->trans('ErrorFailToCreateFile', $pathoffiletoeditsrc), null, 'errors');
  1557. $error++;
  1558. }
  1559. }
  1560. // Edit sql with new properties
  1561. if (!$error) {
  1562. $result = rebuildObjectSql($destdir, $module, $objectname, $newmask, $srcdir, $object, $moduletype);
  1563. if ($result <= 0) {
  1564. setEventMessages($langs->trans('ErrorFailToCreateFile', '.sql'), null, 'errors');
  1565. $error++;
  1566. }
  1567. }
  1568. if (!$error) {
  1569. clearstatcache(true);
  1570. setEventMessages($langs->trans('FilesForObjectUpdated', $objectname), null);
  1571. setEventMessages($langs->trans('WarningDatabaseIsNotUpdated'), null);
  1572. // Make a redirect to reload all data
  1573. header("Location: ".DOL_URL_ROOT.'/modulebuilder/index.php?tab=objects&module='.$module.($forceddirread ? '@'.$dirread : '').'&tabobj='.$objectname.'&nocache='.time());
  1574. exit;
  1575. }
  1576. }
  1577. if ($dirins && $action == 'confirm_deleteproperty' && $propertykey) {
  1578. $objectname = $tabobj;
  1579. $dirins = $dirread = $listofmodules[strtolower($module)]['moduledescriptorrootpath'];
  1580. $moduletype = $listofmodules[strtolower($module)]['moduletype'];
  1581. $srcdir = $dirread.'/'.strtolower($module);
  1582. $destdir = $dirins.'/'.strtolower($module);
  1583. dol_mkdir($destdir);
  1584. // Edit the class file to write properties
  1585. if (!$error) {
  1586. $object = rebuildObjectClass($destdir, $module, $objectname, $newmask, $srcdir, array(), $propertykey);
  1587. if (is_numeric($object) && $object <= 0) {
  1588. $pathoffiletoeditsrc = $destdir.'/class/'.strtolower($objectname).'.class.php';
  1589. setEventMessages($langs->trans('ErrorFailToCreateFile', $pathoffiletoeditsrc), null, 'errors');
  1590. $error++;
  1591. }
  1592. }
  1593. // Edit sql with new properties
  1594. if (!$error) {
  1595. $result = rebuildObjectSql($destdir, $module, $objectname, $newmask, $srcdir, $object);
  1596. if ($result <= 0) {
  1597. setEventMessages($langs->trans('ErrorFailToCreateFile', '.sql'), null, 'errors');
  1598. $error++;
  1599. }
  1600. }
  1601. if (!$error) {
  1602. setEventMessages($langs->trans('FilesForObjectUpdated', $objectname), null);
  1603. clearstatcache(true);
  1604. // Make a redirect to reload all data
  1605. header("Location: ".DOL_URL_ROOT.'/modulebuilder/index.php?tab=objects&module='.$module.($forceddirread ? '@'.$dirread : '').'&tabobj='.$objectname);
  1606. exit;
  1607. }
  1608. }
  1609. if ($dirins && $action == 'confirm_deletemodule') {
  1610. if (preg_match('/[^a-z0-9_]/i', $module)) {
  1611. $error++;
  1612. setEventMessages($langs->trans("SpaceOrSpecialCharAreNotAllowed"), null, 'errors');
  1613. }
  1614. if (!$error) {
  1615. $modulelowercase = strtolower($module);
  1616. // Dir for module
  1617. $dir = $dirins.'/'.$modulelowercase;
  1618. $pathtofile = $listofmodules[strtolower($module)]['moduledescriptorrelpath'];
  1619. // Dir for module
  1620. $dir = dol_buildpath($modulelowercase, 0);
  1621. // Zip file to build
  1622. $FILENAMEZIP = '';
  1623. // Load module
  1624. dol_include_once($pathtofile);
  1625. $class = 'mod'.$module;
  1626. if (class_exists($class)) {
  1627. try {
  1628. $moduleobj = new $class($db);
  1629. } catch (Exception $e) {
  1630. $error++;
  1631. dol_print_error($db, $e->getMessage());
  1632. }
  1633. } else {
  1634. $error++;
  1635. $langs->load("errors");
  1636. dol_print_error($db, $langs->trans("ErrorFailedToLoadModuleDescriptorForXXX", $module));
  1637. exit;
  1638. }
  1639. $moduleobj->remove();
  1640. $result = dol_delete_dir_recursive($dir);
  1641. if ($result > 0) {
  1642. setEventMessages($langs->trans("DirWasRemoved", $modulelowercase), null);
  1643. clearstatcache(true);
  1644. if (function_exists('opcache_invalidate')) {
  1645. opcache_reset(); // remove the include cache hell !
  1646. }
  1647. header("Location: ".$_SERVER["PHP_SELF"].'?module=deletemodule');
  1648. exit;
  1649. } else {
  1650. setEventMessages($langs->trans("PurgeNothingToDelete"), null, 'warnings');
  1651. }
  1652. }
  1653. $action = '';
  1654. $module = 'deletemodule';
  1655. }
  1656. if ($dirins && $action == 'confirm_deleteobject' && $objectname) {
  1657. if (preg_match('/[^a-z0-9_]/i', $objectname)) {
  1658. $error++;
  1659. setEventMessages($langs->trans("SpaceOrSpecialCharAreNotAllowed"), null, 'errors');
  1660. }
  1661. if (!$error) {
  1662. $modulelowercase = strtolower($module);
  1663. $objectlowercase = strtolower($objectname);
  1664. // Dir for module
  1665. $dir = $dirins.'/'.$modulelowercase;
  1666. // Delete some files
  1667. $filetodelete = array(
  1668. 'myobject_card.php'=>strtolower($objectname).'_card.php',
  1669. 'myobject_note.php'=>strtolower($objectname).'_note.php',
  1670. 'myobject_contact.php'=>strtolower($objectname).'_contact.php',
  1671. 'myobject_document.php'=>strtolower($objectname).'_document.php',
  1672. 'myobject_agenda.php'=>strtolower($objectname).'_agenda.php',
  1673. 'myobject_list.php'=>strtolower($objectname).'_list.php',
  1674. 'admin/myobject_extrafields.php'=>'admin/'.strtolower($objectname).'_extrafields.php',
  1675. 'lib/mymodule_myobject.lib.php'=>'lib/'.strtolower($module).'_'.strtolower($objectname).'.lib.php',
  1676. 'test/phpunit/MyObjectTest.php'=>'test/phpunit/'.strtolower($objectname).'Test.php',
  1677. 'sql/llx_mymodule_myobject.sql'=>'sql/llx_'.strtolower($module).'_'.strtolower($objectname).'.sql',
  1678. 'sql/llx_mymodule_myobject_extrafields.sql'=>'sql/llx_'.strtolower($module).'_'.strtolower($objectname).'_extrafields.sql',
  1679. 'sql/llx_mymodule_myobject.key.sql'=>'sql/llx_'.strtolower($module).'_'.strtolower($objectname).'.key.sql',
  1680. 'sql/llx_mymodule_myobject_extrafields.key.sql'=>'sql/llx_'.strtolower($module).'_'.strtolower($objectname).'_extrafields.key.sql',
  1681. 'scripts/myobject.php'=>'scripts/'.strtolower($objectname).'.php',
  1682. 'class/myobject.class.php'=>'class/'.strtolower($objectname).'.class.php',
  1683. 'class/api_myobject.class.php'=>'class/api_'.strtolower($module).'.class.php',
  1684. 'core/modules/mymodule/mod_myobject_advanced.php'=>'core/modules/'.strtolower($module).'/mod_'.strtolower($objectname).'_advanced.php',
  1685. 'core/modules/mymodule/mod_myobject_standard.php'=>'core/modules/'.strtolower($module).'/mod_'.strtolower($objectname).'_standard.php',
  1686. 'core/modules/mymodule/modules_myobject.php'=>'core/modules/'.strtolower($module).'/modules_'.strtolower($objectname).'.php',
  1687. 'core/modules/mymodule/doc/doc_generic_myobject_odt.modules.php'=>'core/modules/'.strtolower($module).'/doc/doc_generic_'.strtolower($objectname).'_odt.modules.php',
  1688. 'core/modules/mymodule/doc/pdf_standard_myobject.modules.php'=>'core/modules/'.strtolower($module).'/doc/pdf_standard_'.strtolower($objectname).'.modules.php'
  1689. );
  1690. //menu for the object selected
  1691. // load class and check if menu,permission,documentation exist for this object
  1692. $pathtofile = $listofmodules[strtolower($module)]['moduledescriptorrelpath'];
  1693. dol_include_once($pathtofile);
  1694. $class = 'mod'.$module;
  1695. if (class_exists($class)) {
  1696. try {
  1697. $moduleobj = new $class($db);
  1698. } catch (Exception $e) {
  1699. $error++;
  1700. dol_print_error($db, $e->getMessage());
  1701. }
  1702. }
  1703. $moduledescriptorfile = $dirins.'/'.strtolower($module).'/core/modules/mod'.$module.'.class.php';
  1704. // delete menus linked to the object
  1705. $menus = $moduleobj->menu;
  1706. $rewriteMenu = checkExistComment($moduledescriptorfile, 0);
  1707. if ($rewriteMenu < 0) {
  1708. setEventMessages($langs->trans("WarningCommentNotFound", $langs->trans("Menus"), "mod".$module."class.php"), null, 'warnings');
  1709. } else {
  1710. reWriteAllMenus($moduledescriptorfile, $menus, $objectname, null, -1);
  1711. }
  1712. // regenerate permissions and delete them
  1713. $permissions = $moduleobj->rights;
  1714. $rewritePerms = checkExistComment($moduledescriptorfile, 1);
  1715. if ($rewritePerms < 0) {
  1716. setEventMessages($langs->trans("WarningCommentNotFound", $langs->trans("Permissions"), "mod".$module."class.php"), null, 'warnings');
  1717. } else {
  1718. reWriteAllPermissions($moduledescriptorfile, $permissions, null, null, $objectname, '', -1);
  1719. }
  1720. if ($rewritePerms && $rewriteMenu) {
  1721. // check if documentation has been generated
  1722. $file_doc = $dirins.'/'.strtolower($module).'/doc/Documentation.asciidoc';
  1723. deletePropsAndPermsFromDoc($file_doc, $objectname);
  1724. clearstatcache(true);
  1725. if (function_exists('opcache_invalidate')) {
  1726. opcache_reset(); // remove the include cache hell !
  1727. }
  1728. $resultko = 0;
  1729. foreach ($filetodelete as $tmpfiletodelete) {
  1730. $resulttmp = dol_delete_file($dir.'/'.$tmpfiletodelete, 0, 0, 1);
  1731. $resulttmp = dol_delete_file($dir.'/'.$tmpfiletodelete.'.back', 0, 0, 1);
  1732. if (!$resulttmp) {
  1733. $resultko++;
  1734. }
  1735. }
  1736. if ($resultko == 0) {
  1737. setEventMessages($langs->trans("FilesDeleted"), null);
  1738. } else {
  1739. setEventMessages($langs->trans("ErrorSomeFilesCouldNotBeDeleted"), null, 'warnings');
  1740. }
  1741. }
  1742. }
  1743. $action = '';
  1744. if (! $error) {
  1745. $tabobj = 'newobject';
  1746. } else {
  1747. $tabobj = 'deleteobject';
  1748. }
  1749. // check if module is enabled
  1750. if (isModEnabled(strtolower($module))) {
  1751. $result = unActivateModule(strtolower($module));
  1752. dolibarr_set_const($db, "MAIN_IHM_PARAMS_REV", (int) $conf->global->MAIN_IHM_PARAMS_REV + 1, 'chaine', 0, '', $conf->entity);
  1753. if ($result) {
  1754. setEventMessages($result, null, 'errors');
  1755. }
  1756. setEventMessages($langs->trans('WarningModuleNeedRefresh', $langs->transnoentities($module)), null, 'warnings');
  1757. header("Location: ".DOL_URL_ROOT.'/modulebuilder/index.php?tab=objects&tabobj=deleteobject&module='.urlencode($module));
  1758. exit;
  1759. }
  1760. }
  1761. if (($dirins && $action == 'confirm_deletedictionary' && $dicname) || ($dirins && $action == 'confirm_deletedictionary' && GETPOST('dictionnarykey'))) {
  1762. $pathtofile = $listofmodules[strtolower($module)]['moduledescriptorrelpath'];
  1763. $destdir = $dirins.'/'.strtolower($module);
  1764. $moduledescriptorfile = $dirins.'/'.strtolower($module).'/core/modules/mod'.$module.'.class.php';
  1765. if (preg_match('/[^a-z0-9_]/i', $dicname)) {
  1766. $error++;
  1767. setEventMessages($langs->trans("SpaceOrSpecialCharAreNotAllowed"), null, 'errors');
  1768. }
  1769. if (!empty($dicname)) {
  1770. $newdicname = $dicname;
  1771. if (!preg_match('/^c_/', $newdicname)) {
  1772. $newdicname = 'c_'.strtolower($dicname);
  1773. }
  1774. }
  1775. dol_include_once($pathtofile);
  1776. $class = 'mod'.$module;
  1777. if (class_exists($class)) {
  1778. try {
  1779. $moduleobj = new $class($db);
  1780. } catch (Exception $e) {
  1781. $error++;
  1782. dol_print_error($db, $e->getMessage());
  1783. }
  1784. } else {
  1785. $error++;
  1786. $langs->load("errors");
  1787. dol_print_error($db, $langs->trans("ErrorFailedToLoadModuleDescriptorForXXX", $module));
  1788. exit;
  1789. }
  1790. $dicts = $moduleobj->dictionaries;
  1791. $checkComment = checkExistComment($moduledescriptorfile, 2);
  1792. if ($checkComment < 0) {
  1793. $error++;
  1794. setEventMessages($langs->trans("WarningCommentNotFound", $langs->trans("Dictionaries"), "mod".$module."class.php"), null, 'warnings');
  1795. }
  1796. if (!empty(GETPOST('dictionnarykey'))) {
  1797. $newdicname = $dicts['tabname'][GETPOST('dictionnarykey')-1];
  1798. }
  1799. //chercher la table dicname
  1800. $query = "SHOW TABLES LIKE '" . MAIN_DB_PREFIX.strtolower($newdicname) . "'";
  1801. $checkTable = $db->query($query);
  1802. if ($checkTable && $db->num_rows($checkTable) <= 0) {
  1803. $error++;
  1804. }
  1805. // search the key by name
  1806. $keyToDelete = null;
  1807. foreach ($dicts['tabname'] as $key => $table) {
  1808. //var_dump($table." /////// ".$newdicname);exit;
  1809. if (strtolower($table) === $newdicname) {
  1810. $keyToDelete = $key;
  1811. break;
  1812. }
  1813. }
  1814. // delete all dicname's key values from the dictionary
  1815. if ($keyToDelete !== null) {
  1816. $keysToDelete = ['tabname', 'tablib', 'tabsql', 'tabsqlsort', 'tabfield', 'tabfieldvalue', 'tabfieldinsert', 'tabrowid', 'tabcond', 'tabhelp'];
  1817. foreach ($keysToDelete as $key) {
  1818. unset($dicts[$key][$keyToDelete]);
  1819. }
  1820. } else {
  1821. $error++;
  1822. setEventMessages($langs->trans("ErrorDictionaryNotFound", ucfirst($dicname)), null, 'errors');
  1823. }
  1824. if (!$error) {
  1825. // delete table
  1826. $_results = $db->DDLDropTable(MAIN_DB_PREFIX.strtolower($newdicname));
  1827. if ($_results < 0) {
  1828. dol_print_error($db);
  1829. $langs->load("errors");
  1830. setEventMessages($langs->trans("ErrorTableNotFound", $newdicname), null, 'errors');
  1831. }
  1832. // rebuild file after update dictionaries
  1833. $result = updateDictionaryInFile($module, $moduledescriptorfile, $dicts);
  1834. if ($result > 0) {
  1835. setEventMessages($langs->trans("DictionaryDeleted", ucfirst(substr($newdicname, 2))), null);
  1836. }
  1837. if (function_exists('opcache_invalidate')) {
  1838. opcache_reset(); // remove the include cache hell !
  1839. }
  1840. clearstatcache(true);
  1841. header("Location: ".DOL_URL_ROOT.'/modulebuilder/index.php?tab=dictionaries&module='.$module.($forceddirread ? '@'.$dirread : ''));
  1842. exit;
  1843. }
  1844. }
  1845. if ($dirins && $action == 'updatedictionary' && GETPOST('dictionnarykey')) {
  1846. $keydict = GETPOST('dictionnarykey') - 1 ;
  1847. $pathtofile = $listofmodules[strtolower($module)]['moduledescriptorrelpath'];
  1848. $destdir = $dirins.'/'.strtolower($module);
  1849. $moduledescriptorfile = $dirins.'/'.strtolower($module).'/core/modules/mod'.$module.'.class.php';
  1850. dol_include_once($pathtofile);
  1851. $class = 'mod'.$module;
  1852. if (class_exists($class)) {
  1853. try {
  1854. $moduleobj = new $class($db);
  1855. } catch (Exception $e) {
  1856. $error++;
  1857. dol_print_error($db, $e->getMessage());
  1858. }
  1859. } else {
  1860. $error++;
  1861. $langs->load("errors");
  1862. dol_print_error($db, $langs->trans("ErrorFailedToLoadModuleDescriptorForXXX", $module));
  1863. exit;
  1864. }
  1865. $dicts = $moduleobj->dictionaries;
  1866. if (!empty(GETPOST('tablib')) && GETPOST('tablib') !== $dicts['tablib'][$keydict]) {
  1867. $dicts['tablib'][$keydict] = ucfirst(strtolower(GETPOST('tablib')));
  1868. $checkComment = checkExistComment($moduledescriptorfile, 2);
  1869. if ($checkComment < 0) {
  1870. setEventMessages($langs->trans("WarningCommentNotFound", $langs->trans("Dictionaries"), "mod".$module."class.php"), null, 'warnings');
  1871. } else {
  1872. $updateDict = updateDictionaryInFile($module, $moduledescriptorfile, $dicts);
  1873. if ($updateDict > 0) {
  1874. setEventMessages($langs->trans("DictionaryNameUpdated", ucfirst(GETPOST('tablib'))), null);
  1875. }
  1876. if (function_exists('opcache_invalidate')) {
  1877. opcache_reset(); // remove the include cache hell !
  1878. }
  1879. clearstatcache(true);
  1880. header("Location: ".DOL_URL_ROOT.'/modulebuilder/index.php?tab=dictionaries&module='.$module.($forceddirread ? '@'.$dirread : ''));
  1881. exit;
  1882. }
  1883. }
  1884. //var_dump(GETPOST('tablib'));exit;
  1885. }
  1886. if ($dirins && $action == 'generatedoc') {
  1887. $modulelowercase = strtolower($module);
  1888. // Dir for module
  1889. $dirofmodule = dol_buildpath($modulelowercase, 0).'/doc';
  1890. $FILENAMEDOC = strtolower($module).'.html';
  1891. $util = new Utils($db);
  1892. $result = $util->generateDoc($module);
  1893. if ($result > 0) {
  1894. setEventMessages($langs->trans("DocFileGeneratedInto", $dirofmodule), null);
  1895. } else {
  1896. setEventMessages($util->error, $util->errors, 'errors');
  1897. }
  1898. }
  1899. if ($dirins && $action == 'generatepackage') {
  1900. $modulelowercase = strtolower($module);
  1901. $pathtofile = $listofmodules[strtolower($module)]['moduledescriptorrelpath'];
  1902. // Dir for module
  1903. $dir = dol_buildpath($modulelowercase, 0);
  1904. // Zip file to build
  1905. $FILENAMEZIP = '';
  1906. // Load module
  1907. dol_include_once($pathtofile);
  1908. $class = 'mod'.$module;
  1909. if (class_exists($class)) {
  1910. try {
  1911. $moduleobj = new $class($db);
  1912. } catch (Exception $e) {
  1913. $error++;
  1914. dol_print_error($db, $e->getMessage());
  1915. }
  1916. } else {
  1917. $error++;
  1918. $langs->load("errors");
  1919. dol_print_error($db, $langs->trans("ErrorFailedToLoadModuleDescriptorForXXX", $module));
  1920. exit;
  1921. }
  1922. $arrayversion = explode('.', $moduleobj->version, 3);
  1923. if (count($arrayversion)) {
  1924. $FILENAMEZIP = "module_".$modulelowercase.'-'.$arrayversion[0].(empty($arrayversion[1]) ? '.0' : '.'.$arrayversion[1]).(empty($arrayversion[2]) ? '' : '.'.$arrayversion[2]).'.zip';
  1925. $dirofmodule = dol_buildpath($modulelowercase, 0).'/bin';
  1926. $outputfilezip = $dirofmodule.'/'.$FILENAMEZIP;
  1927. if ($dirofmodule) {
  1928. if (!dol_is_dir($dirofmodule)) {
  1929. dol_mkdir($dirofmodule);
  1930. }
  1931. // Note: We exclude /bin/ to not include the already generated zip
  1932. $result = dol_compress_dir($dir, $outputfilezip, 'zip', '/\/bin\/|\.git|\.old|\.back|\.ssh/', $modulelowercase);
  1933. } else {
  1934. $result = -1;
  1935. }
  1936. if ($result > 0) {
  1937. setEventMessages($langs->trans("ZipFileGeneratedInto", $outputfilezip), null);
  1938. } else {
  1939. $error++;
  1940. $langs->load("errors");
  1941. setEventMessages($langs->trans("ErrorFailToGenerateFile", $outputfilezip), null, 'errors');
  1942. }
  1943. } else {
  1944. $error++;
  1945. $langs->load("errors");
  1946. setEventMessages($langs->trans("ErrorCheckVersionIsDefined"), null, 'errors');
  1947. }
  1948. }
  1949. // Add permission
  1950. if ($dirins && $action == 'addright' && !empty($module) && empty($cancel)) {
  1951. $error = 0;
  1952. // load class and check if right exist
  1953. $pathtofile = $listofmodules[strtolower($module)]['moduledescriptorrelpath'];
  1954. dol_include_once($pathtofile);
  1955. $class = 'mod'.$module;
  1956. if (class_exists($class)) {
  1957. try {
  1958. $moduleobj = new $class($db);
  1959. } catch (Exception $e) {
  1960. $error++;
  1961. dol_print_error($db, $e->getMessage());
  1962. }
  1963. }
  1964. // verify informations entred
  1965. if (!GETPOST('label', 'alpha')) {
  1966. $error++;
  1967. setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("Label")), null, 'errors');
  1968. }
  1969. if (!GETPOST('permissionObj', 'alpha')) {
  1970. $error++;
  1971. setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("Rights")), null, 'errors');
  1972. }
  1973. $id = GETPOST('id', 'alpha');
  1974. $label = GETPOST('label', 'alpha');
  1975. $objectForPerms = strtolower(GETPOST('permissionObj', 'alpha'));
  1976. $crud = GETPOST('crud', 'alpha');
  1977. //check existing object permission
  1978. $counter = 0;
  1979. $permsForObject =array();
  1980. $permissions = $moduleobj->rights;
  1981. $allObject = array();
  1982. $countPerms = count($permissions);
  1983. for ($i =0; $i<$countPerms; $i++) {
  1984. if ($permissions[$i][4] == $objectForPerms) {
  1985. $counter++;
  1986. if (count($permsForObject) < 3) {
  1987. $permsForObject[] = $permissions[$i];
  1988. }
  1989. }
  1990. $allObject[] = $permissions[$i][4];
  1991. }
  1992. // check if label of object already exists
  1993. $countPermsObj = count($permsForObject);
  1994. for ($j = 0; $j<$countPermsObj; $j++) {
  1995. if (in_array($crud, $permsForObject[$j])) {
  1996. $error++;
  1997. setEventMessages($langs->trans("ErrorExistingPermission", $langs->transnoentities($crud), $langs->transnoentities($objectForPerms)), null, 'errors');
  1998. }
  1999. }
  2000. if (!$error) {
  2001. $key = $countPerms + 1;
  2002. //prepare right to add
  2003. $rightToAdd = [
  2004. 0=> $id,
  2005. 1=>$label,
  2006. 4=>$objectForPerms,
  2007. 5=>$crud
  2008. ];
  2009. if (isModEnabled(strtolower($module))) {
  2010. $result = unActivateModule(strtolower($module));
  2011. dolibarr_set_const($db, "MAIN_IHM_PARAMS_REV", (int) $conf->global->MAIN_IHM_PARAMS_REV + 1, 'chaine', 0, '', $conf->entity);
  2012. if ($result) {
  2013. setEventMessages($result, null, 'errors');
  2014. }
  2015. setEventMessages($langs->trans('WarningModuleNeedRefresh', $langs->transnoentities($module)), null, 'warnings');
  2016. }
  2017. }
  2018. $moduledescriptorfile = $dirins.'/'.strtolower($module).'/core/modules/mod'.$module.'.class.php';
  2019. //rewriting all permissions after add a right
  2020. $rewrite = checkExistComment($moduledescriptorfile, 1);
  2021. if ($rewrite < 0) {
  2022. setEventMessages($langs->trans("WarningCommentNotFound", $langs->trans("Permissions"), "mod".$module."class.php"), null, 'warnings');
  2023. } else {
  2024. reWriteAllPermissions($moduledescriptorfile, $permissions, $key, $rightToAdd, '', '', 1);
  2025. setEventMessages($langs->trans('PermissionAddedSuccesfuly'), null);
  2026. clearstatcache(true);
  2027. if (function_exists('opcache_invalidate')) {
  2028. opcache_reset(); // remove the include cache hell !
  2029. }
  2030. header("Location: ".DOL_URL_ROOT.'/modulebuilder/index.php?tab=permissions&module='.$module);
  2031. exit;
  2032. }
  2033. }
  2034. // Update permission
  2035. if ($dirins && GETPOST('action') == 'update_right' && GETPOST('modifyright')&& empty($cancel)) {
  2036. $error = 0;
  2037. // load class and check if right exist
  2038. $pathtofile = $listofmodules[strtolower($module)]['moduledescriptorrelpath'];
  2039. dol_include_once($pathtofile);
  2040. $class = 'mod'.$module;
  2041. if (class_exists($class)) {
  2042. try {
  2043. $moduleobj = new $class($db);
  2044. } catch (Exception $e) {
  2045. $error++;
  2046. dol_print_error($db, $e->getMessage());
  2047. }
  2048. }
  2049. // verify informations entred
  2050. if (!GETPOST('label', 'alpha')) {
  2051. $error++;
  2052. setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("Label")), null, 'errors');
  2053. }
  2054. if (!GETPOST('permissionObj', 'alpha')) {
  2055. $error++;
  2056. setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("Rights")), null, 'errors');
  2057. }
  2058. $label = GETPOST('label', 'alpha');
  2059. $objectForPerms = strtolower(GETPOST('permissionObj', 'alpha'));
  2060. $crud = GETPOST('crud', 'alpha');
  2061. if ($label == "Read objects of $module" && $crud != "read") {
  2062. $crud = "read";
  2063. $label == "Read objects of $module";
  2064. }
  2065. if ($label == "Create/Update objects of $module" && $crud != "write") {
  2066. $crud = "write";
  2067. $label == "Create/Update objects of $module";
  2068. }
  2069. if ($label == "Delete objects of $module" && $crud != "delete") {
  2070. $crud = "delete";
  2071. $label == "Delete objects of $module";
  2072. }
  2073. $permissions = $moduleobj->rights;
  2074. $key =(int) GETPOST('counter')-1;
  2075. //get permission want to delete from permissions array
  2076. $x1 = $permissions[$key][1];
  2077. $x2 = $permissions[$key][4];
  2078. $x3 = $permissions[$key][5];
  2079. //check existing object permission
  2080. $counter = 0;
  2081. $permsForObject =array();
  2082. $permissions = $moduleobj->rights;
  2083. $firstRight = 0;
  2084. $existRight = 0;
  2085. $allObject = array();
  2086. $countPerms = count($permissions);
  2087. for ($i =0; $i<$countPerms; $i++) {
  2088. if ($permissions[$i][4] == $objectForPerms) {
  2089. $counter++;
  2090. if (count($permsForObject) < 3) {
  2091. $permsForObject[] = $permissions[$i];
  2092. }
  2093. }
  2094. $allObject[] = $permissions[$i][4];
  2095. }
  2096. if ($label != $x1 && $crud != $x3) {
  2097. $countPermsObj = count($permsForObject);
  2098. for ($j = 0; $j<$countPermsObj; $j++) {
  2099. if (in_array($label, $permsForObject[$j])) {
  2100. $error++;
  2101. setEventMessages($langs->trans("ErrorExistingPermission", $langs->transnoentities($label), $langs->transnoentities($objectForPerms)), null, 'errors');
  2102. }
  2103. }
  2104. }
  2105. if (!$error) {
  2106. if (isModEnabled(strtolower($module))) {
  2107. $result = unActivateModule(strtolower($module));
  2108. dolibarr_set_const($db, "MAIN_IHM_PARAMS_REV", (int) $conf->global->MAIN_IHM_PARAMS_REV + 1, 'chaine', 0, '', $conf->entity);
  2109. if ($result) {
  2110. setEventMessages($result, null, 'errors');
  2111. }
  2112. setEventMessages($langs->trans('WarningModuleNeedRefresh', $langs->transnoentities($module)), null, 'warnings');
  2113. }
  2114. $moduledescriptorfile = $dirins.'/'.strtolower($module).'/core/modules/mod'.$module.'.class.php';
  2115. // rewriting all permissions after update permission needed
  2116. $rewrite = checkExistComment($moduledescriptorfile, 1);
  2117. if ($rewrite < 0) {
  2118. setEventMessages($langs->trans("WarningCommentNotFound", $langs->trans("Permissions"), "mod".$module."class.php"), null, 'warnings');
  2119. } else {
  2120. reWriteAllPermissions($moduledescriptorfile, $permissions, $key, $rightUpdated, '', '', 2);
  2121. setEventMessages($langs->trans('PermissionUpdatedSuccesfuly'), null);
  2122. clearstatcache(true);
  2123. if (function_exists('opcache_invalidate')) {
  2124. opcache_reset(); // remove the include cache hell !
  2125. }
  2126. header("Location: ".DOL_URL_ROOT.'/modulebuilder/index.php?tab=permissions&module='.$module);
  2127. exit;
  2128. }
  2129. }
  2130. }
  2131. // Delete permission
  2132. if ($dirins && $action == 'confirm_deleteright' && !empty($module) && GETPOST('permskey', 'int')) {
  2133. $error = 0;
  2134. // load class and check if right exist
  2135. $pathtofile = $listofmodules[strtolower($module)]['moduledescriptorrelpath'];
  2136. dol_include_once($pathtofile);
  2137. $class = 'mod'.$module;
  2138. if (class_exists($class)) {
  2139. try {
  2140. $moduleobj = new $class($db);
  2141. } catch (Exception $e) {
  2142. $error++;
  2143. dol_print_error($db, $e->getMessage());
  2144. }
  2145. }
  2146. $permissions = $moduleobj->rights;
  2147. $key = (int) GETPOST('permskey', 'int')-1;
  2148. if (!$error) {
  2149. // check if module is enabled
  2150. if (isModEnabled(strtolower($module))) {
  2151. $result = unActivateModule(strtolower($module));
  2152. dolibarr_set_const($db, "MAIN_IHM_PARAMS_REV", (int) $conf->global->MAIN_IHM_PARAMS_REV + 1, 'chaine', 0, '', $conf->entity);
  2153. if ($result) {
  2154. setEventMessages($result, null, 'errors');
  2155. }
  2156. setEventMessages($langs->trans('WarningModuleNeedRefresh', $langs->transnoentities($module)), null, 'warnings');
  2157. header("Location: ".DOL_URL_ROOT.'/modulebuilder/index.php?tab=permissions&module='.$module);
  2158. exit;
  2159. }
  2160. // rewriting all permissions
  2161. $moduledescriptorfile = $dirins.'/'.strtolower($module).'/core/modules/mod'.$module.'.class.php';
  2162. $rewrite = checkExistComment($moduledescriptorfile, 1);
  2163. if ($rewrite < 0) {
  2164. setEventMessages($langs->trans("WarningCommentNotFound", $langs->trans("Permissions"), "mod".$module."class.php"), null, 'warnings');
  2165. } else {
  2166. reWriteAllPermissions($moduledescriptorfile, $permissions, $key, null, '', '', 0);
  2167. setEventMessages($langs->trans('PermissionDeletedSuccesfuly'), null);
  2168. clearstatcache(true);
  2169. if (function_exists('opcache_invalidate')) {
  2170. opcache_reset(); // remove the include cache hell !
  2171. }
  2172. header("Location: ".DOL_URL_ROOT.'/modulebuilder/index.php?tab=permissions&module='.$module);
  2173. exit;
  2174. }
  2175. }
  2176. }
  2177. // Save file
  2178. if ($action == 'savefile' && empty($cancel)) {
  2179. $relofcustom = basename($dirins);
  2180. if ($relofcustom) {
  2181. // Check that relative path ($file) start with name 'custom'
  2182. if (!preg_match('/^'.$relofcustom.'/', $file)) {
  2183. $file = $relofcustom.'/'.$file;
  2184. }
  2185. $pathoffile = dol_buildpath($file, 0);
  2186. $pathoffilebackup = dol_buildpath($file.'.back', 0);
  2187. // Save old version
  2188. if (dol_is_file($pathoffile)) {
  2189. dol_copy($pathoffile, $pathoffilebackup, 0, 1);
  2190. }
  2191. $check = 'restricthtml';
  2192. $srclang = dol_mimetype($pathoffile, '', 3);
  2193. if ($srclang == 'md') {
  2194. $check = 'restricthtml';
  2195. }
  2196. if ($srclang == 'lang') {
  2197. $check = 'restricthtml';
  2198. }
  2199. if ($srclang == 'php') {
  2200. $check = 'none';
  2201. }
  2202. $content = GETPOST('editfilecontent', $check);
  2203. // Save file on disk
  2204. if ($content) {
  2205. dol_delete_file($pathoffile);
  2206. $result = file_put_contents($pathoffile, $content);
  2207. if ($result) {
  2208. dolChmod($pathoffile, $newmask);
  2209. setEventMessages($langs->trans("FileSaved"), null);
  2210. } else {
  2211. setEventMessages($langs->trans("ErrorFailedToSaveFile"), null, 'errors');
  2212. }
  2213. } else {
  2214. setEventMessages($langs->trans("ContentCantBeEmpty"), null, 'errors');
  2215. //$action='editfile';
  2216. $error++;
  2217. }
  2218. }
  2219. }
  2220. // Enable module
  2221. if ($action == 'set' && $user->admin) {
  2222. $param = '';
  2223. if ($module) {
  2224. $param .= '&module='.urlencode($module);
  2225. }
  2226. if ($tab) {
  2227. $param .= '&tab='.urlencode($tab);
  2228. }
  2229. if ($tabobj) {
  2230. $param .= '&tabobj='.urlencode($tabobj);
  2231. }
  2232. $value = GETPOST('value', 'alpha');
  2233. $resarray = activateModule($value);
  2234. if (!empty($resarray['errors'])) {
  2235. setEventMessages('', $resarray['errors'], 'errors');
  2236. } else {
  2237. //var_dump($resarray);exit;
  2238. if ($resarray['nbperms'] > 0) {
  2239. $tmpsql = "SELECT COUNT(rowid) as nb FROM ".MAIN_DB_PREFIX."user WHERE admin <> 1";
  2240. $resqltmp = $db->query($tmpsql);
  2241. if ($resqltmp) {
  2242. $obj = $db->fetch_object($resqltmp);
  2243. //var_dump($obj->nb);exit;
  2244. if ($obj && $obj->nb > 1) {
  2245. $msg = $langs->trans('ModuleEnabledAdminMustCheckRights');
  2246. setEventMessages($msg, null, 'warnings');
  2247. }
  2248. } else {
  2249. dol_print_error($db);
  2250. }
  2251. }
  2252. }
  2253. header("Location: ".$_SERVER["PHP_SELF"]."?".$param);
  2254. exit;
  2255. }
  2256. // Disable module
  2257. if ($action == 'reset' && $user->admin) {
  2258. $param = '';
  2259. if ($module) {
  2260. $param .= '&module='.urlencode($module);
  2261. }
  2262. if ($tab) {
  2263. $param .= '&tab='.urlencode($tab);
  2264. }
  2265. if ($tabobj) {
  2266. $param .= '&tabobj='.urlencode($tabobj);
  2267. }
  2268. $value = GETPOST('value', 'alpha');
  2269. $result = unActivateModule($value);
  2270. if ($result) {
  2271. setEventMessages($result, null, 'errors');
  2272. }
  2273. header("Location: ".$_SERVER["PHP_SELF"]."?".$param);
  2274. exit;
  2275. }
  2276. // delete menu
  2277. if ($dirins && $action == 'confirm_deletemenu' && GETPOST('menukey', 'int')) {
  2278. // check if module is enabled
  2279. if (isModEnabled(strtolower($module))) {
  2280. $result = unActivateModule(strtolower($module));
  2281. dolibarr_set_const($db, "MAIN_IHM_PARAMS_REV", (int) $conf->global->MAIN_IHM_PARAMS_REV + 1, 'chaine', 0, '', $conf->entity);
  2282. if ($result) {
  2283. setEventMessages($result, null, 'errors');
  2284. }
  2285. header("Location: ".DOL_URL_ROOT.'/modulebuilder/index.php?tab=menus&module='.$module);
  2286. setEventMessages($langs->trans('WarningModuleNeedRefresh', $langs->transnoentities($module)), null, 'warnings');
  2287. }
  2288. // load class and check if menu exist
  2289. $pathtofile = $listofmodules[strtolower($module)]['moduledescriptorrelpath'];
  2290. dol_include_once($pathtofile);
  2291. $class = 'mod'.$module;
  2292. if (class_exists($class)) {
  2293. try {
  2294. $moduleobj = new $class($db);
  2295. } catch (Exception $e) {
  2296. $error++;
  2297. dol_print_error($db, $e->getMessage());
  2298. }
  2299. }
  2300. // get all objects and convert value to lower case for compare
  2301. $dir = $listofmodules[strtolower($module)]['moduledescriptorrootpath'];
  2302. $destdir = $dir.'/'.strtolower($module);
  2303. $objects = dolGetListOfObjectClasses($destdir);
  2304. $result = array_map('strtolower', $objects);
  2305. $menus = $moduleobj->menu;
  2306. $key = (int) GETPOST('menukey', 'int');
  2307. $moduledescriptorfile = $dirins.'/'.strtolower($module).'/core/modules/mod'.$module.'.class.php';
  2308. $checkcomment = checkExistComment($moduledescriptorfile, 0);
  2309. if ($checkcomment < 0) {
  2310. setEventMessages($langs->trans("WarningCommentNotFound", $langs->trans("Menus"), "mod".$module."class.php"), null, 'warnings');
  2311. } else {
  2312. if ($menus[$key]['fk_menu'] === 'fk_mainmenu='.strtolower($module)) {
  2313. if (in_array(strtolower($menus[$key]['leftmenu']), $result)) {
  2314. reWriteAllMenus($moduledescriptorfile, $menus, $menus[$key]['leftmenu'], $key, -1);
  2315. } else {
  2316. reWriteAllMenus($moduledescriptorfile, $menus, null, $key, 0);
  2317. }
  2318. } else {
  2319. reWriteAllMenus($moduledescriptorfile, $menus, null, $key, 0);
  2320. }
  2321. clearstatcache(true);
  2322. if (function_exists('opcache_invalidate')) {
  2323. opcache_reset(); // remove the include cache hell !
  2324. }
  2325. setEventMessages($langs->trans('MenuDeletedSuccessfuly'), null);
  2326. header("Location: ".DOL_URL_ROOT.'/modulebuilder/index.php?tab=menus&module='.$module);
  2327. exit;
  2328. }
  2329. }
  2330. // Add menu in module without initial object
  2331. if ($dirins && $action == 'addmenu' && empty($cancel)) {
  2332. // check if module is enabled
  2333. if (isModEnabled(strtolower($module))) {
  2334. $result = unActivateModule(strtolower($module));
  2335. dolibarr_set_const($db, "MAIN_IHM_PARAMS_REV", (int) $conf->global->MAIN_IHM_PARAMS_REV + 1, 'chaine', 0, '', $conf->entity);
  2336. if ($result) {
  2337. setEventMessages($result, null, 'errors');
  2338. }
  2339. header("Location: ".DOL_URL_ROOT.'/modulebuilder/index.php?tab=menus&module='.$module);
  2340. setEventMessages($langs->trans('WarningModuleNeedRefresh', $langs->transnoentities($module)), null, 'warnings');
  2341. }
  2342. $error = 0;
  2343. // load class and check if right exist
  2344. $pathtofile = $listofmodules[strtolower($module)]['moduledescriptorrelpath'];
  2345. dol_include_once($pathtofile);
  2346. $class = 'mod'.$module;
  2347. if (class_exists($class)) {
  2348. try {
  2349. $moduleobj = new $class($db);
  2350. } catch (Exception $e) {
  2351. $error++;
  2352. dol_print_error($db, $e->getMessage());
  2353. }
  2354. }
  2355. // get all menus
  2356. $menus = $moduleobj->menu;
  2357. //verify fields required
  2358. if (!GETPOST('type', 'alpha')) {
  2359. $error++;
  2360. setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("Type")), null, 'errors');
  2361. }
  2362. if (!GETPOST('titre', 'alpha')) {
  2363. $error++;
  2364. setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("Title")), null, 'errors');
  2365. }
  2366. if (!GETPOST('user', 'alpha')) {
  2367. $error++;
  2368. setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("DetailUser")), null, 'errors');
  2369. }
  2370. if (!GETPOST('url', 'alpha')) {
  2371. $error++;
  2372. setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("Url")), null, 'errors');
  2373. }
  2374. if (!empty(GETPOST('target'))) {
  2375. $targets = array('_blank','_self','_parent','_top','');
  2376. if (!in_array(GETPOST('target'), $targets)) {
  2377. $error++;
  2378. setEventMessages($langs->trans("ErrorFieldValue", $langs->transnoentities("target")), null, 'errors');
  2379. }
  2380. }
  2381. // check if title or url already exist in menus
  2382. foreach ($menus as $menu) {
  2383. if (!empty(GETPOST('url')) && GETPOST('url') == $menu['url']) {
  2384. $error++;
  2385. setEventMessages($langs->trans("ErrorFieldExist", $langs->transnoentities("url")), null, 'errors');
  2386. break;
  2387. }
  2388. if (strtolower(GETPOST('titre')) == strtolower($menu['titre'])) {
  2389. $error++;
  2390. setEventMessages($langs->trans("ErrorFieldExist", $langs->transnoentities("titre")), null, 'errors');
  2391. break;
  2392. }
  2393. }
  2394. if (GETPOST('type', 'alpha') == 'left' && !empty(GETPOST('lefmenu', 'alpha'))) {
  2395. if (!str_contains(GETPOST('leftmenu'), strtolower($module))) {
  2396. $error++;
  2397. setEventMessages($langs->trans("WarningFieldsMustContains", $langs->transnoentities("leftmenu")), null, 'errors');
  2398. }
  2399. }
  2400. $dirins = $listofmodules[strtolower($module)]['moduledescriptorrootpath'];
  2401. $destdir = $dirins.'/'.strtolower($module);
  2402. $objects = dolGetListOfObjectClasses($destdir);
  2403. if (GETPOST('type', 'alpha') == 'left') {
  2404. if (empty(GETPOST('leftmenu')) && count($objects) >0) {
  2405. $error++;
  2406. setEventMessages($langs->trans("ErrorCoherenceMenu", $langs->transnoentities("leftmenu"), $langs->transnoentities("type")), null, 'errors');
  2407. }
  2408. }
  2409. if (GETPOST('type', 'alpha') == 'top') {
  2410. $error++;
  2411. setEventMessages($langs->trans("ErrorTypeMenu", $langs->transnoentities("type")), null, 'errors');
  2412. }
  2413. $moduledescriptorfile = $dirins.'/'.strtolower($module).'/core/modules/mod'.$module.'.class.php';
  2414. if (!$error) {
  2415. //stock forms in array
  2416. $menuToAdd = array(
  2417. 'fk_menu' => GETPOST('fk_menu', 'alpha'),
  2418. 'type' => GETPOST('type', 'alpha'),
  2419. 'titre' => ucfirst(GETPOST('titre', 'alpha')),
  2420. 'prefix' => '',
  2421. 'mainmenu' => GETPOST('mainmenu', 'alpha'),
  2422. 'leftmenu' => GETPOST('leftmenu', 'alpha'),
  2423. 'url' => GETPOST('url', 'alpha'),
  2424. 'langs' => strtolower($module)."@".strtolower($module),
  2425. 'position' => '',
  2426. 'enabled' => GETPOST('enabled', 'alpha'),
  2427. 'perms' => '$user->hasRight("'.strtolower($module).'", "'.GETPOST('objects', 'alpha').'", "'.GETPOST('perms', 'alpha').'")',
  2428. 'target' => GETPOST('target', 'alpha'),
  2429. 'user' => GETPOST('user', 'alpha'),
  2430. );
  2431. if (GETPOST('type') == 'left') {
  2432. unset($menuToAdd['prefix']);
  2433. if (empty(GETPOST('fk_menu'))) {
  2434. $menuToAdd['fk_menu'] = 'fk_mainmenu='.GETPOST('mainmenu', 'alpha');
  2435. } else {
  2436. $menuToAdd['fk_menu'] = 'fk_mainmenu='.GETPOST('mainmenu', 'alpha').',fk_leftmenu='.GETPOST('fk_menu');
  2437. }
  2438. }
  2439. if (GETPOST('enabled') == '1') {
  2440. $menuToAdd['enabled'] = "\$conf->".strtolower($module)."->enabled";
  2441. } else {
  2442. $menuToAdd['enabled'] = "0";
  2443. }
  2444. if (empty(GETPOST('objects'))) {
  2445. $menuToAdd['perms'] = '1';
  2446. }
  2447. $checkcomment = checkExistComment($moduledescriptorfile, 0);
  2448. if ($checkcomment < 0) {
  2449. setEventMessages($langs->trans("WarningCommentNotFound", $langs->trans("Menus"), "mod".$module."class.php"), null, 'warnings');
  2450. } else {
  2451. reWriteAllMenus($moduledescriptorfile, $menus, $menuToAdd, null, 1);
  2452. clearstatcache(true);
  2453. if (function_exists('opcache_invalidate')) {
  2454. opcache_reset();
  2455. }
  2456. header("Location: ".DOL_URL_ROOT.'/modulebuilder/index.php?tab=menus&module='.$module);
  2457. setEventMessages($langs->trans('MenuAddedSuccesfuly'), null);
  2458. exit;
  2459. }
  2460. }
  2461. }
  2462. // modify a menu
  2463. if ($dirins && $action == "modify_menu" && GETPOST('menukey', 'int') && GETPOST('tabobj')) {
  2464. $objectname = GETPOST('tabobj');
  2465. $dirins = $listofmodules[strtolower($module)]['moduledescriptorrootpath'];
  2466. $destdir = $dirins.'/'.strtolower($module);
  2467. $objects = dolGetListOfObjectClasses($destdir);
  2468. if (empty($cancel)) {
  2469. if (isModEnabled(strtolower($module))) {
  2470. $result = unActivateModule(strtolower($module));
  2471. dolibarr_set_const($db, "MAIN_IHM_PARAMS_REV", (int) $conf->global->MAIN_IHM_PARAMS_REV + 1, 'chaine', 0, '', $conf->entity);
  2472. if ($result) {
  2473. setEventMessages($result, null, 'errors');
  2474. }
  2475. header("Location: ".DOL_URL_ROOT.'/modulebuilder/index.php?tab=menus&module='.$module);
  2476. setEventMessages($langs->trans('WarningModuleNeedRefresh', $langs->transnoentities($module)), null, 'warnings');
  2477. }
  2478. $error = 0;
  2479. // for loading class and the menu wants to modify
  2480. $pathtofile = $listofmodules[strtolower($module)]['moduledescriptorrelpath'];
  2481. dol_include_once($pathtofile);
  2482. $class = 'mod'.$module;
  2483. if (class_exists($class)) {
  2484. try {
  2485. $moduleobj = new $class($db);
  2486. } catch (Exception $e) {
  2487. $error++;
  2488. dol_print_error($db, $e->getMessage());
  2489. }
  2490. }
  2491. $menus = $moduleobj->menu;
  2492. $key = (int) GETPOST('menukey', 'int') - 1;
  2493. $moduledescriptorfile = $dirins.'/'.strtolower($module).'/core/modules/mod'.$module.'.class.php';
  2494. //stock forms in array
  2495. $menuModify = array(
  2496. 'fk_menu' => GETPOST('fk_menu', 'alpha'),
  2497. 'type' => GETPOST('type', 'alpha'),
  2498. 'titre' => ucfirst(GETPOST('titre', 'alpha')),
  2499. 'mainmenu' => GETPOST('mainmenu', 'alpha'),
  2500. 'leftmenu' => $menus[$key]['leftmenu'],
  2501. 'url' => GETPOST('url', 'alpha'),
  2502. 'langs' => strtolower($module)."@".strtolower($module),
  2503. 'position' => '',
  2504. 'enabled' => GETPOST('enabled', 'alpha'),
  2505. 'perms' => '',
  2506. 'target' => GETPOST('target', 'alpha'),
  2507. 'user' => GETPOST('user', 'alpha'),
  2508. );
  2509. if (!empty(GETPOST('fk_menu')) && GETPOST('fk_menu') != $menus[$key]['fk_menu']) {
  2510. $menuModify['fk_menu'] = 'fk_mainmenu='.GETPOST('mainmenu').',fk_leftmenu='.GETPOST('fk_menu');
  2511. } elseif (GETPOST('fk_menu') == $menus[$key]['fk_menu']) {
  2512. $menuModify['fk_menu'] = $menus[$key]['fk_menu'];
  2513. } else {
  2514. $menuModify['fk_menu'] = 'fk_mainmenu='.GETPOST('mainmenu');
  2515. }
  2516. if (GETPOST('enabled') != '0') {
  2517. $menuModify['enabled'] = "\$conf->".strtolower($module)."->enabled";
  2518. } else {
  2519. $menuModify['enabled'] = '0';
  2520. }
  2521. if (!empty(GETPOST('perms')) && !empty(GETPOST('objects'))) {
  2522. $menuModify['perms'] = '$user->hasRight("'.strtolower($module).'", "'.GETPOST('objects', 'alpha').'", "'.GETPOST('perms', 'alpha').'")';
  2523. }
  2524. if (empty(GETPOST('objects'))) {
  2525. $menuModify['perms'] = '1';
  2526. }
  2527. if (GETPOST('type', 'alpha') == 'top') {
  2528. $error++;
  2529. setEventMessages($langs->trans("ErrorTypeMenu", $langs->transnoentities("type")), null, 'errors');
  2530. }
  2531. if (!$error) {
  2532. //update menu
  2533. $checkComment = checkExistComment($moduledescriptorfile, 0);
  2534. if ($checkComment < 0) {
  2535. setEventMessages($langs->trans("WarningCommentNotFound", $langs->trans("Menus"), "mod".$module."class.php"), null, 'warnings');
  2536. } else {
  2537. $result = reWriteAllMenus($moduledescriptorfile, $menus, $menuModify, $key, 2);
  2538. clearstatcache(true);
  2539. if (function_exists('opcache_invalidate')) {
  2540. opcache_reset();
  2541. }
  2542. if ($result < 0) {
  2543. setEventMessages($langs->trans('ErrorMenuExistValue'), null, 'errors');
  2544. header("Location: ".$_SERVER["PHP_SELF"].'?action=editmenu&token='.newToken().'&menukey='.urlencode($key+1).'&tab='.urlencode($tab).'&module='.urlencode($module).'&tabobj='.($key+1));
  2545. exit;
  2546. }
  2547. setEventMessages($langs->trans('MenuUpdatedSuccessfuly'), null);
  2548. header("Location: ".DOL_URL_ROOT.'/modulebuilder/index.php?tab=menus&module='.$module);
  2549. exit;
  2550. }
  2551. }
  2552. } else {
  2553. $_POST['type'] = '';
  2554. $_POST['titre'] = '';
  2555. $_POST['fk_menu'] = '';
  2556. $_POST['leftmenu'] = '';
  2557. $_POST['url'] = '';
  2558. }
  2559. }
  2560. // update properties description of module
  2561. if ($dirins && $action == "update_props_module" && !empty(GETPOST('keydescription', 'alpha')) && empty($cancel)) {
  2562. if (isModEnabled(strtolower($module))) {
  2563. $result = unActivateModule(strtolower($module));
  2564. dolibarr_set_const($db, "MAIN_IHM_PARAMS_REV", (int) $conf->global->MAIN_IHM_PARAMS_REV + 1, 'chaine', 0, '', $conf->entity);
  2565. if ($result) {
  2566. setEventMessages($result, null, 'errors');
  2567. }
  2568. header("Location: ".DOL_URL_ROOT.'/modulebuilder/index.php?tab=menus&module='.$module);
  2569. setEventMessages($langs->trans('WarningModuleNeedRefresh', $langs->transnoentities($module)), null, 'warnings');
  2570. }
  2571. $pathtofile = $listofmodules[strtolower($module)]['moduledescriptorrelpath'];
  2572. $moduledescriptorfile = $dirins.'/'.strtolower($module).'/core/modules/mod'.$module.'.class.php';
  2573. $modulelogfile = $dirins.'/'.strtolower($module).'/ChangeLog.md';
  2574. dol_include_once($pathtofile);
  2575. $class = 'mod'.$module;
  2576. if (class_exists($class)) {
  2577. try {
  2578. $moduleobj = new $class($db);
  2579. } catch (Exception $e) {
  2580. $error++;
  2581. dol_print_error($db, $e->getMessage());
  2582. }
  2583. }
  2584. $keydescription = GETPOST('keydescription', 'alpha');
  2585. switch ($keydescription) {
  2586. case 'desc':
  2587. $propertyToUpdate = 'description';
  2588. break;
  2589. case 'version':
  2590. case 'family':
  2591. case 'picto':
  2592. case 'editor_name':
  2593. case 'editor_url':
  2594. $propertyToUpdate = $keydescription;
  2595. break;
  2596. default:
  2597. $error = GETPOST('keydescription');
  2598. break;
  2599. }
  2600. if (isset($propertyToUpdate) && !empty(GETPOST('propsmodule'))) {
  2601. $newValue = GETPOST('propsmodule');
  2602. $lineToReplace = "\t\t\$this->$propertyToUpdate = ";
  2603. $newLine = "\t\t\$this->$propertyToUpdate = '$newValue';\n";
  2604. //for change version in log file
  2605. if ($propertyToUpdate === 'version') {
  2606. dolReplaceInFile($modulelogfile, array("## ".$moduleobj->$propertyToUpdate => $newValue));
  2607. }
  2608. $fileLines = file($moduledescriptorfile);
  2609. foreach ($fileLines as &$line) {
  2610. if (strpos($line, $lineToReplace) === 0) {
  2611. dolReplaceInFile($moduledescriptorfile, array($line => $newLine));
  2612. break;
  2613. }
  2614. }
  2615. clearstatcache(true);
  2616. if (function_exists('opcache_invalidate')) {
  2617. opcache_reset();
  2618. }
  2619. setEventMessages($langs->trans('PropertyModuleUpdated', $propertyToUpdate), null);
  2620. header("Location: ".DOL_URL_ROOT.'/modulebuilder/index.php?tab=description&module='.$module);
  2621. exit;
  2622. }
  2623. }
  2624. /*
  2625. * View
  2626. */
  2627. $form = new Form($db);
  2628. $formadmin = new FormAdmin($db);
  2629. // Set dir where external modules are installed
  2630. if (!dol_is_dir($dirins)) {
  2631. dol_mkdir($dirins);
  2632. }
  2633. $dirins_ok = (dol_is_dir($dirins));
  2634. $help_url = '';
  2635. $morejs = array(
  2636. '/includes/ace/src/ace.js',
  2637. '/includes/ace/src/ext-statusbar.js',
  2638. '/includes/ace/src/ext-language_tools.js',
  2639. //'/includes/ace/src/ext-chromevox.js'
  2640. );
  2641. $morecss = array();
  2642. llxHeader('', $langs->trans("ModuleBuilder"), $help_url, '', 0, 0, $morejs, $morecss, '', 'classforhorizontalscrolloftabs');
  2643. $text = $langs->trans("ModuleBuilder");
  2644. print load_fiche_titre($text, '', 'title_setup');
  2645. print '<span class="opacitymedium hideonsmartphone">'.$langs->trans("ModuleBuilderDesc", 'https://wiki.dolibarr.org/index.php/Module_development#Create_your_module').'</span>';
  2646. print '<br class="hideonsmartphone">';
  2647. //print $textforlistofdirs;
  2648. //print '<br>';
  2649. $message = '';
  2650. if (!$dirins) {
  2651. $message = info_admin($langs->trans("ConfFileMustContainCustom", DOL_DOCUMENT_ROOT.'/custom', DOL_DOCUMENT_ROOT));
  2652. $allowfromweb = -1;
  2653. } else {
  2654. if ($dirins_ok) {
  2655. if (!is_writable(dol_osencode($dirins))) {
  2656. $langs->load("errors");
  2657. $message = info_admin($langs->trans("ErrorFailedToWriteInDir", $dirins));
  2658. $allowfromweb = 0;
  2659. }
  2660. } else {
  2661. $message = info_admin($langs->trans("NotExistsDirect", $dirins).$langs->trans("InfDirAlt").$langs->trans("InfDirExample"));
  2662. $allowfromweb = 0;
  2663. }
  2664. }
  2665. if ($message) {
  2666. print $message;
  2667. }
  2668. //print $langs->trans("ModuleBuilderDesc3", count($listofmodules), $FILEFLAG).'<br>';
  2669. $infomodulesfound = '<div style="padding: 12px 9px 12px">'.$form->textwithpicto('', $langs->trans("ModuleBuilderDesc3", count($listofmodules)).'<br><br>'.$langs->trans("ModuleBuilderDesc4", $FILEFLAG).'<br>'.$textforlistofdirs).'</div>';
  2670. $dolibarrdataroot = preg_replace('/([\\/]+)$/i', '', DOL_DATA_ROOT);
  2671. $allowonlineinstall = true;
  2672. if (dol_is_file($dolibarrdataroot.'/installmodules.lock')) {
  2673. $allowonlineinstall = false;
  2674. }
  2675. if (empty($allowonlineinstall)) {
  2676. if (getDolGlobalString('MAIN_MESSAGE_INSTALL_MODULES_DISABLED_CONTACT_US')) {
  2677. // Show clean message
  2678. $message = info_admin($langs->trans('InstallModuleFromWebHasBeenDisabledContactUs'));
  2679. } else {
  2680. // Show technical message
  2681. $message = info_admin($langs->trans("InstallModuleFromWebHasBeenDisabledByFile", $dolibarrdataroot.'/installmodules.lock'), 0, 0, 1, 'warning');
  2682. }
  2683. print $message;
  2684. llxFooter();
  2685. exit(0);
  2686. }
  2687. // Load module descriptor
  2688. $error = 0;
  2689. $moduleobj = null;
  2690. if (!empty($module) && $module != 'initmodule' && $module != 'deletemodule') {
  2691. $modulelowercase = strtolower($module);
  2692. $loadclasserrormessage = '';
  2693. // Load module
  2694. try {
  2695. $fullpathdirtodescriptor = $listofmodules[strtolower($module)]['moduledescriptorrelpath'];
  2696. //throw(new Exception());
  2697. dol_include_once($fullpathdirtodescriptor);
  2698. $class = 'mod'.$module;
  2699. } catch (Throwable $e) { // This is called in PHP 7 only (includes Error and Exception)
  2700. $loadclasserrormessage = $e->getMessage()."<br>\n";
  2701. $loadclasserrormessage .= 'File: '.$e->getFile()."<br>\n";
  2702. $loadclasserrormessage .= 'Line: '.$e->getLine()."<br>\n";
  2703. }
  2704. if (class_exists($class)) {
  2705. try {
  2706. $moduleobj = new $class($db);
  2707. } catch (Exception $e) {
  2708. $error++;
  2709. print $e->getMessage();
  2710. }
  2711. } else {
  2712. if (empty($forceddirread)) {
  2713. $error++;
  2714. }
  2715. $langs->load("errors");
  2716. print '<!-- ErrorFailedToLoadModuleDescriptorForXXX -->';
  2717. print img_warning('').' '.$langs->trans("ErrorFailedToLoadModuleDescriptorForXXX", $module).'<br>';
  2718. print $loadclasserrormessage;
  2719. }
  2720. }
  2721. print '<br>';
  2722. // Tabs for all modules
  2723. $head = array();
  2724. $h = 0;
  2725. $head[$h][0] = $_SERVER["PHP_SELF"].'?module=initmodule';
  2726. $head[$h][1] = '<span class="valignmiddle text-plus-circle">'.$langs->trans("NewModule").'</span><span class="fa fa-plus-circle valignmiddle paddingleft"></span>';
  2727. $head[$h][2] = 'initmodule';
  2728. $h++;
  2729. $linktoenabledisable = '';
  2730. if (is_array($listofmodules) && count($listofmodules) > 0) {
  2731. // Define $linktoenabledisable
  2732. $modulelowercase = strtolower($module);
  2733. $const_name = 'MAIN_MODULE_'.strtoupper($module);
  2734. $param = '';
  2735. if ($tab) {
  2736. $param .= '&tab='.urlencode($tab);
  2737. }
  2738. if ($module) {
  2739. $param .= '&module='.urlencode($module);
  2740. }
  2741. if ($tabobj) {
  2742. $param .= '&tabobj='.urlencode($tabobj);
  2743. }
  2744. $urltomodulesetup = '<a href="'.DOL_URL_ROOT.'/admin/modules.php?search_keyword='.urlencode($module).'">'.$langs->trans('Home').'-'.$langs->trans("Setup").'-'.$langs->trans("Modules").'</a>';
  2745. // Define $linktoenabledisable to show after module title
  2746. if (isModEnabled($modulelowercase)) { // If module is already activated
  2747. $linktoenabledisable .= '<a class="reposition asetresetmodule valignmiddle" href="'.$_SERVER["PHP_SELF"].'?id='.$moduleobj->numero.'&action=reset&token='.newToken().'&value=mod'.$module.$param.'">';
  2748. $linktoenabledisable .= img_picto($langs->trans("Activated"), 'switch_on', '', false, 0, 0, '', '', 1);
  2749. $linktoenabledisable .= '</a>';
  2750. $linktoenabledisable .= $form->textwithpicto('', $langs->trans("Warning").' : '.$langs->trans("ModuleIsLive"), -1, 'warning');
  2751. $objMod = $moduleobj;
  2752. $backtourlparam = '';
  2753. $backtourlparam .= ($backtourlparam ? '&' : '?').'module='.$module; // No urlencode here, done later
  2754. if ($tab) {
  2755. $backtourlparam .= ($backtourlparam ? '&' : '?').'tab='.$tab; // No urlencode here, done later
  2756. }
  2757. $backtourl = $_SERVER["PHP_SELF"].$backtourlparam;
  2758. $regs = array();
  2759. if (is_array($objMod->config_page_url)) {
  2760. $i = 0;
  2761. foreach ($objMod->config_page_url as $page) {
  2762. $urlpage = $page;
  2763. if ($i++) {
  2764. $linktoenabledisable .= ' <a href="'.$urlpage.'" title="'.$langs->trans($page).'">'.img_picto(ucfirst($page), "setup").'</a>';
  2765. // print '<a href="'.$page.'">'.ucfirst($page).'</a>&nbsp;';
  2766. } else {
  2767. if (preg_match('/^([^@]+)@([^@]+)$/i', $urlpage, $regs)) {
  2768. $urltouse = dol_buildpath('/'.$regs[2].'/admin/'.$regs[1], 1);
  2769. $linktoenabledisable .= ' <a href="'.$urltouse.(preg_match('/\?/', $urltouse) ? '&' : '?').'save_lastsearch_values=1&backtopage='.urlencode($backtourl).'" title="'.$langs->trans("Setup").'">'.img_picto($langs->trans("Setup"), "setup", 'style="padding-right: 8px"').'</a>';
  2770. } else {
  2771. // Case standard admin page (not a page provided by the
  2772. // module but a page provided by dolibarr)
  2773. $urltouse = DOL_URL_ROOT.'/admin/'.$urlpage;
  2774. $linktoenabledisable .= ' <a href="'.$urltouse.(preg_match('/\?/', $urltouse) ? '&' : '?').'save_lastsearch_values=1&backtopage='.urlencode($backtourl).'" title="'.$langs->trans("Setup").'">'.img_picto($langs->trans("Setup"), "setup", 'style="padding-right: 8px"').'</a>';
  2775. }
  2776. }
  2777. }
  2778. } elseif (preg_match('/^([^@]+)@([^@]+)$/i', $objMod->config_page_url, $regs)) {
  2779. $linktoenabledisable .= ' &nbsp; <a href="'.dol_buildpath('/'.$regs[2].'/admin/'.$regs[1], 1).'?save_lastsearch_values=1&backtopage='.urlencode($backtourl).'" title="'.$langs->trans("Setup").'">'.img_picto($langs->trans("Setup"), "setup", 'style="padding-right: 8px"').'</a>';
  2780. }
  2781. } else {
  2782. if (!empty($moduleobj)) {
  2783. $linktoenabledisable .= '<a class="reposition asetresetmodule valignmiddle" href="'.$_SERVER["PHP_SELF"].'?id='.$moduleobj->numero.'&action=set&token='.newToken().'&value=mod'.$module.$param.'">';
  2784. $linktoenabledisable .= img_picto($langs->trans("ModuleIsNotActive", $urltomodulesetup), 'switch_off', 'style="padding-right: 8px"', false, 0, 0, '', 'classfortooltip', 1);
  2785. $linktoenabledisable .= "</a>\n";
  2786. }
  2787. }
  2788. // Loop to show tab of each module
  2789. foreach ($listofmodules as $tmpmodule => $tmpmodulearray) {
  2790. $head[$h][0] = $_SERVER["PHP_SELF"].'?module='.$tmpmodulearray['modulenamewithcase'].($forceddirread ? '@'.$dirread : '');
  2791. $head[$h][1] = $tmpmodulearray['modulenamewithcase'];
  2792. $head[$h][2] = $tmpmodulearray['modulenamewithcase'];
  2793. if ($tmpmodulearray['modulenamewithcase'] == $module) {
  2794. $head[$h][4] = '<span class="inline-block">'.$linktoenabledisable.'</span>';
  2795. }
  2796. $h++;
  2797. }
  2798. }
  2799. $head[$h][0] = $_SERVER["PHP_SELF"].'?module=deletemodule';
  2800. $head[$h][1] = img_picto('', 'delete', 'class="pictofixedwidth"').$langs->trans("DangerZone");
  2801. $head[$h][2] = 'deletemodule';
  2802. $h++;
  2803. print dol_get_fiche_head($head, $module, '', -1, '', 0, $infomodulesfound, '', 8); // Modules
  2804. if ($module == 'initmodule') {
  2805. // New module
  2806. print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
  2807. print '<input type="hidden" name="token" value="'.newToken().'">';
  2808. print '<input type="hidden" name="action" value="initmodule">';
  2809. print '<input type="hidden" name="module" value="initmodule">';
  2810. //print '<span class="opacitymedium">'.$langs->trans("ModuleBuilderDesc2", 'conf/conf.php', $newdircustom).'</span><br>';
  2811. print '<br>';
  2812. print '<div class="tagtable">';
  2813. print '<div class="tagtr"><div class="tagtd paddingright">';
  2814. print '<span class="opacitymedium">'.$langs->trans("IdModule").'</span>';
  2815. print '</div><div class="tagtd">';
  2816. print '<input type="text" name="idmodule" class="width75" value="500000" placeholder="'.dol_escape_htmltag($langs->trans("IdModule")).'">';
  2817. print '<span class="opacitymedium">';
  2818. print ' &nbsp; (';
  2819. print dolButtonToOpenUrlInDialogPopup('popup_modules_id', $langs->transnoentitiesnoconv("SeeIDsInUse"), $langs->transnoentitiesnoconv("SeeIDsInUse"), '/admin/system/modules.php?mainmenu=home&leftmenu=admintools_info', '', '');
  2820. print ' - ';
  2821. print '<a href="https://wiki.dolibarr.org/index.php/List_of_modules_id" target="_blank" rel="noopener noreferrer external">'.$langs->trans("SeeReservedIDsRangeHere").'</a>';
  2822. print ')';
  2823. print '</span>';
  2824. print '</div></div>';
  2825. print '<div class="tagtr"><div class="tagtd paddingright">';
  2826. print '<span class="opacitymedium fieldrequired">'.$langs->trans("ModuleName").'</span>';
  2827. print '</div><div class="tagtd">';
  2828. print '<input type="text" name="modulename" value="'.dol_escape_htmltag($modulename).'" autofocus>';
  2829. print ' '.$form->textwithpicto('', $langs->trans("EnterNameOfModuleDesc"));
  2830. print '</div></div>';
  2831. print '<div class="tagtr"><div class="tagtd paddingright">';
  2832. print '<span class="opacitymedium">'.$langs->trans("Description").'</span>';
  2833. print '</div><div class="tagtd">';
  2834. print '<input type="text" name="description" value="" class="minwidth500"><br>';
  2835. print '</div></div>';
  2836. print '<div class="tagtr"><div class="tagtd paddingright">';
  2837. print '<span class="opacitymedium">'.$langs->trans("Version").'</span>';
  2838. print '</div><div class="tagtd">';
  2839. print '<input type="text" name="version" class="width75" value="'.(GETPOSTISSET('version') ? GETPOST('version') : getDolGlobalString('MODULEBUILDER_SPECIFIC_VERSION', '1.0')).'" placeholder="'.dol_escape_htmltag($langs->trans("Version")).'">';
  2840. print '</div></div>';
  2841. print '<div class="tagtr"><div class="tagtd paddingright">';
  2842. print '<span class="opacitymedium">'.$langs->trans("Family").'</span>';
  2843. print '</div><div class="tagtd">';
  2844. print '<select name="family" id="family" class="minwidth400">';
  2845. $arrayoffamilies = array(
  2846. 'hr' => "ModuleFamilyHr",
  2847. 'crm' => "ModuleFamilyCrm",
  2848. 'srm' => "ModuleFamilySrm",
  2849. 'financial' => 'ModuleFamilyFinancial',
  2850. 'products' => 'ModuleFamilyProducts',
  2851. 'projects' => 'ModuleFamilyProjects',
  2852. 'ecm' => 'ModuleFamilyECM',
  2853. 'technic' => 'ModuleFamilyTechnic',
  2854. 'portal' => 'ModuleFamilyPortal',
  2855. 'interface' => 'ModuleFamilyInterface',
  2856. 'base' => 'ModuleFamilyBase',
  2857. 'other' => 'ModuleFamilyOther'
  2858. );
  2859. foreach ($arrayoffamilies as $key => $value) {
  2860. print '<option value="hr"'.($key == getDolGlobalString('MODULEBUILDER_SPECIFIC_FAMILY', 'other') ? ' selected="selected"' : '').' data-html="'.dol_escape_htmltag($langs->trans($value).' <span class="opacitymedium">- '.$key.'</span>').'">'.$langs->trans($value).'</option>';
  2861. }
  2862. print '</select>';
  2863. print ajax_combobox("family");
  2864. print '</div></div>';
  2865. print '<div class="tagtr"><div class="tagtd paddingright">';
  2866. print '<span class="opacitymedium">'.$langs->trans("Picto").'</span>';
  2867. print '</div><div class="tagtd">';
  2868. print '<input type="text" name="idpicto" value="'.(GETPOSTISSET('idpicto') ? GETPOST('idpicto') : getDolGlobalString('MODULEBUILDER_DEFAULTPICTO', 'fa-file-o')).'" placeholder="'.dol_escape_htmltag($langs->trans("Picto")).'">';
  2869. print $form->textwithpicto('', $langs->trans("Example").': fa-file-o, fa-globe, ... any font awesome code.<br>Advanced syntax is fa-fakey[_faprefix[_facolor[_fasize]]]');
  2870. print '</div></div>';
  2871. print '<div class="tagtr"><div class="tagtd paddingright">';
  2872. print '<span class="opacitymedium">'.$langs->trans("EditorName").'</span>';
  2873. print '</div><div class="tagtd">';
  2874. print '<input type="text" name="editorname" value="'.(GETPOSTISSET('editorname') ? GETPOST('editorname') : getDolGlobalString('MODULEBUILDER_SPECIFIC_EDITOR_NAME', $mysoc->name)).'" placeholder="'.dol_escape_htmltag($langs->trans("EditorName")).'"><br>';
  2875. print '</div></div>';
  2876. print '<div class="tagtr"><div class="tagtd paddingright">';
  2877. print '<span class="opacitymedium">'.$langs->trans("EditorUrl").'</span>';
  2878. print '</div><div class="tagtd">';
  2879. print '<input type="text" name="editorurl" value="'.(GETPOSTISSET('editorurl') ? GETPOST('editorurl') : getDolGlobalString('MODULEBUILDER_SPECIFIC_EDITOR_URL', $mysoc->url)).'" placeholder="'.dol_escape_htmltag($langs->trans("EditorUrl")).'"><br>';
  2880. print '</div></div>';
  2881. print '<br><input type="submit" class="button" name="create" value="'.dol_escape_htmltag($langs->trans("Create")).'"'.($dirins ? '' : ' disabled="disabled"').'>';
  2882. print '</form>';
  2883. } elseif ($module == 'deletemodule') {
  2884. print '<!-- Form to init a module -->'."\n";
  2885. print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST" name="delete">';
  2886. print '<input type="hidden" name="token" value="'.newToken().'">';
  2887. print '<input type="hidden" name="action" value="confirm_deletemodule">';
  2888. print '<input type="hidden" name="module" value="deletemodule">';
  2889. print $langs->trans("EnterNameOfModuleToDeleteDesc").'<br><br>';
  2890. print '<input type="text" name="module" placeholder="'.dol_escape_htmltag($langs->trans("ModuleKey")).'" value="">';
  2891. print '<input type="submit" class="button smallpaddingimp" value="'.$langs->trans("Delete").'"'.($dirins ? '' : ' disabled="disabled"').'>';
  2892. print '</form>';
  2893. } elseif (!empty($module)) {
  2894. // Tabs for module
  2895. if (!$error) {
  2896. $dirread = $listofmodules[strtolower($module)]['moduledescriptorrootpath'];
  2897. $destdir = $dirread.'/'.strtolower($module);
  2898. $objects = dolGetListOfObjectClasses($destdir);
  2899. $diroflang = dol_buildpath($modulelowercase, 0)."/langs";
  2900. $countLangs = countItemsInDirectory($diroflang, 2);
  2901. $countDictionaries = (!empty($moduleobj->dictionaries) ? count($moduleobj->dictionaries['tabname']) : 0);
  2902. $countRights = count($moduleobj->rights);
  2903. $countMenus = count($moduleobj->menu);
  2904. $countTriggers = countItemsInDirectory(dol_buildpath($modulelowercase, 0)."/core/triggers");
  2905. $countWidgets = countItemsInDirectory(dol_buildpath($modulelowercase, 0)."/core/boxes");
  2906. $countCss = countItemsInDirectory(dol_buildpath($modulelowercase, 0)."/css");
  2907. $countJs = countItemsInDirectory(dol_buildpath($modulelowercase, 0)."/js");
  2908. $countCLI = countItemsInDirectory(dol_buildpath($modulelowercase, 0)."/scripts");
  2909. $hasDoc = countItemsInDirectory(dol_buildpath($modulelowercase, 0)."/doc");
  2910. //var_dump($moduleobj->dictionaries);exit;
  2911. $head2 = array();
  2912. $h = 0;
  2913. $head2[$h][0] = $_SERVER["PHP_SELF"].'?tab=description&module='.$module.($forceddirread ? '@'.$dirread : '');
  2914. $head2[$h][1] = $langs->trans("Description");
  2915. $head2[$h][2] = 'description';
  2916. $h++;
  2917. $head2[$h][0] = $_SERVER["PHP_SELF"].'?tab=objects&module='.$module.($forceddirread ? '@'.$dirread : '');
  2918. $head2[$h][1] = ((!is_array($objects) || count($objects) <= 0) ? $langs->trans("Objects") : $langs->trans("Objects").'<span class="marginleftonlyshort badge">'.count($objects)."</span>");
  2919. $head2[$h][2] = 'objects';
  2920. $h++;
  2921. $head2[$h][0] = $_SERVER["PHP_SELF"].'?tab=languages&module='.$module.($forceddirread ? '@'.$dirread : '');
  2922. $head2[$h][1] = ($countLangs <= 0 ? $langs->trans("Languages") : $langs->trans("Languages").'<span class="marginleftonlyshort badge">'.$countLangs."</span>");
  2923. $head2[$h][2] = 'languages';
  2924. $h++;
  2925. $head2[$h][0] = $_SERVER["PHP_SELF"].'?tab=dictionaries&module='.$module.($forceddirread ? '@'.$dirread : '');
  2926. $head2[$h][1] = ($countDictionaries == 0 ? $langs->trans("Dictionaries") : $langs->trans('Dictionaries').'<span class="marginleftonlyshort badge">'.$countDictionaries."</span>");
  2927. $head2[$h][2] = 'dictionaries';
  2928. $h++;
  2929. $head2[$h][0] = $_SERVER["PHP_SELF"].'?tab=permissions&module='.$module.($forceddirread ? '@'.$dirread : '');
  2930. $head2[$h][1] = ($countRights <= 0 ? $langs->trans("Permissions") : $langs->trans("Permissions").'<span class="marginleftonlyshort badge">'.$countRights."</span>");
  2931. $head2[$h][2] = 'permissions';
  2932. $h++;
  2933. $head2[$h][0] = $_SERVER["PHP_SELF"].'?tab=tabs&module='.$module.($forceddirread ? '@'.$dirread : '');
  2934. $head2[$h][1] = $langs->trans("Tabs");
  2935. $head2[$h][2] = 'tabs';
  2936. $h++;
  2937. $head2[$h][0] = $_SERVER["PHP_SELF"].'?tab=menus&module='.$module.($forceddirread ? '@'.$dirread : '');
  2938. $head2[$h][1] = ($countMenus <= 0 ? $langs->trans("Menus") : $langs->trans("Menus").'<span class="marginleftonlyshort badge">'.$countMenus."</span>");
  2939. $head2[$h][2] = 'menus';
  2940. $h++;
  2941. $head2[$h][0] = $_SERVER["PHP_SELF"].'?tab=hooks&module='.$module.($forceddirread ? '@'.$dirread : '');
  2942. $head2[$h][1] = $langs->trans("Hooks");
  2943. $head2[$h][2] = 'hooks';
  2944. $h++;
  2945. $head2[$h][0] = $_SERVER["PHP_SELF"].'?tab=triggers&module='.$module.($forceddirread ? '@'.$dirread : '');
  2946. $head2[$h][1] = ($countTriggers <= 0 ? $langs->trans("Triggers") : $langs->trans("Triggers").'<span class="marginleftonlyshort badge">'.$countTriggers."</span>");
  2947. $head2[$h][2] = 'triggers';
  2948. $h++;
  2949. $head2[$h][0] = $_SERVER["PHP_SELF"].'?tab=widgets&module='.$module.($forceddirread ? '@'.$dirread : '');
  2950. $head2[$h][1] = ($countWidgets <= 0 ? $langs->trans("Widgets") : $langs->trans("Widgets").'<span class="marginleftonlyshort badge">'.$countWidgets."</span>");
  2951. $head2[$h][2] = 'widgets';
  2952. $h++;
  2953. $head2[$h][0] = $_SERVER["PHP_SELF"].'?tab=exportimport&module='.$module.($forceddirread ? '@'.$dirread : '');
  2954. $head2[$h][1] = $langs->trans("Export").'-'.$langs->trans("Import");
  2955. $head2[$h][2] = 'exportimport';
  2956. $h++;
  2957. $head2[$h][0] = $_SERVER["PHP_SELF"].'?tab=css&module='.$module.($forceddirread ? '@'.$dirread : '');
  2958. $head2[$h][1] = ($countCss <= 0 ? $langs->trans("CSS") : $langs->trans("CSS")." (".$countCss.")");
  2959. $head2[$h][2] = 'css';
  2960. $h++;
  2961. $head2[$h][0] = $_SERVER["PHP_SELF"].'?tab=js&module='.$module.($forceddirread ? '@'.$dirread : '');
  2962. $head2[$h][1] = ($countJs <= 0 ? $langs->trans("JS") : $langs->trans("JS").'<span class="marginleftonlyshort badge">'.$countJs."</span>");
  2963. $head2[$h][2] = 'js';
  2964. $h++;
  2965. $head2[$h][0] = $_SERVER["PHP_SELF"].'?tab=cli&module='.$module.($forceddirread ? '@'.$dirread : '');
  2966. $head2[$h][1] = ($countCLI <= 0 ? $langs->trans("CLI") : $langs->trans("CLI").'<span class="marginleftonlyshort badge">'.$countCLI."</span>");
  2967. $head2[$h][2] = 'cli';
  2968. $h++;
  2969. $head2[$h][0] = $_SERVER["PHP_SELF"].'?tab=cron&module='.$module.($forceddirread ? '@'.$dirread : '');
  2970. $head2[$h][1] = $langs->trans("CronList");
  2971. $head2[$h][2] = 'cron';
  2972. $h++;
  2973. $head2[$h][0] = $_SERVER["PHP_SELF"].'?tab=specifications&module='.$module.($forceddirread ? '@'.$dirread : '');
  2974. $head2[$h][1] = ($hasDoc <= 0 ? $langs->trans("Documentation") : $langs->trans("Documentation").'<span class="paddingleft badge">'.$hasDoc."</span>");
  2975. $head2[$h][2] = 'specifications';
  2976. $h++;
  2977. $head2[$h][0] = $_SERVER["PHP_SELF"].'?tab=buildpackage&module='.$module.($forceddirread ? '@'.$dirread : '');
  2978. $head2[$h][1] = $langs->trans("BuildPackage");
  2979. $head2[$h][2] = 'buildpackage';
  2980. $h++;
  2981. $MAXTABFOROBJECT = 15;
  2982. print '<!-- Section for a given module -->';
  2983. // Note module is inside $dirread
  2984. if ($tab == 'description') {
  2985. print '<!-- tab=description -->'."\n";
  2986. $pathtofile = $listofmodules[strtolower($module)]['moduledescriptorrelpath'];
  2987. $pathtofilereadme = $modulelowercase.'/README.md';
  2988. $pathtochangelog = $modulelowercase.'/ChangeLog.md';
  2989. if ($action != 'editfile' || empty($file)) {
  2990. $morehtmlright = '';
  2991. if (realpath($dirread.'/'.$modulelowercase) != $dirread.'/'.$modulelowercase) {
  2992. $morehtmlright = '<div style="padding: 12px 9px 12px">'.$form->textwithpicto('', '<span class="opacitymedium">'.$langs->trans("RealPathOfModule").' :</span> <strong class="wordbreak">'.realpath($dirread.'/'.$modulelowercase).'</strong>').'</div>';
  2993. }
  2994. print dol_get_fiche_head($head2, $tab, '', -1, '', 0, $morehtmlright, '', $MAXTABFOROBJECT, 'formodulesuffix'); // Description - level 2
  2995. print '<span class="opacitymedium">'.$langs->trans("ModuleBuilderDesc".$tab).'</span>';
  2996. print '<br><br>';
  2997. print '<table>';
  2998. print '<tr><td>';
  2999. print '<span class="fa fa-file-o"></span> '.$langs->trans("DescriptorFile").' : <strong class="wordbreak">'.$pathtofile.'</strong>';
  3000. print '</td><td><a class="editfielda" href="'.$_SERVER['PHP_SELF'].'?tab='.urlencode($tab).'&module='.$module.($forceddirread ? '@'.$dirread : '').'&action=editfile&token='.newToken().'&format=php&file='.urlencode($pathtofile).'">'.img_picto($langs->trans("Edit"), 'edit').'</a>';
  3001. print '</td></tr>';
  3002. print '<tr><td><span class="fa fa-file-o"></span> '.$langs->trans("ReadmeFile").' : <strong class="wordbreak">'.$pathtofilereadme.'</strong>';
  3003. print '</td><td><a class="editfielda" href="'.$_SERVER['PHP_SELF'].'?tab='.urlencode($tab).'&module='.$module.($forceddirread ? '@'.$dirread : '').'&action=editfile&token='.newToken().'&format=markdown&file='.urlencode($pathtofilereadme).'">'.img_picto($langs->trans("Edit"), 'edit').'</a>';
  3004. print '</td></tr>';
  3005. print '<tr><td><span class="fa fa-file-o"></span> '.$langs->trans("ChangeLog").' : <strong class="wordbreak">'.$pathtochangelog.'</strong>';
  3006. print '</td><td><a class="editfielda" href="'.$_SERVER['PHP_SELF'].'?tab='.urlencode($tab).'&module='.$module.($forceddirread ? '@'.$dirread : '').'&action=editfile&token='.newToken().'&format=markdown&file='.urlencode($pathtochangelog).'">'.img_picto($langs->trans("Edit"), 'edit').'</a>';
  3007. print '</td></tr>';
  3008. print '</table>';
  3009. print '<br>';
  3010. print load_fiche_titre($form->textwithpicto($langs->trans("DescriptorFile"), $langs->transnoentitiesnoconv("File").' '.$pathtofile), '', '');
  3011. if (!empty($moduleobj)) {
  3012. print '<div class="underbanner clearboth"></div>';
  3013. print '<div class="fichecenter">';
  3014. print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
  3015. print '<input type="hidden" name="token" value="'.newToken().'">';
  3016. print '<input type="hidden" name="action" value="update_props_module">';
  3017. print '<input type="hidden" name="module" value="'.dol_escape_htmltag($module).'">';
  3018. print '<input type="hidden" name="tab" value="'.dol_escape_htmltag($tab).'">';
  3019. print '<input type="hidden" name="keydescription" value="'.dol_escape_htmltag(GETPOST('keydescription', 'alpha')).'">';
  3020. print '<table class="border centpercent">';
  3021. print '<tr class="liste_titre"><td class="titlefield">';
  3022. print $langs->trans("Parameter");
  3023. print '</td><td>';
  3024. print $langs->trans("Value");
  3025. print '</td></tr>';
  3026. print '<tr><td>';
  3027. print $langs->trans("IdModule");
  3028. print '</td><td>';
  3029. print $moduleobj->numero;
  3030. print '<span class="opacitymedium">';
  3031. print ' &nbsp; (';
  3032. print dolButtonToOpenUrlInDialogPopup('popup_modules_id', $langs->transnoentitiesnoconv("SeeIDsInUse"), $langs->transnoentitiesnoconv("SeeIDsInUse"), '/admin/system/modules.php?mainmenu=home&leftmenu=admintools_info', '', '');
  3033. print ' - <a href="https://wiki.dolibarr.org/index.php/List_of_modules_id" target="_blank" rel="noopener noreferrer external">'.$langs->trans("SeeReservedIDsRangeHere").'</a>)';
  3034. print '</span>';
  3035. print '</td></tr>';
  3036. print '<tr><td>';
  3037. print $langs->trans("ModuleName");
  3038. print '</td><td>';
  3039. print $moduleobj->getName();
  3040. print '</td></tr>';
  3041. print '<tr><td>';
  3042. print $langs->trans("Description");
  3043. print '</td><td>';
  3044. if ($action == 'edit_moduledescription' && GETPOST('keydescription', 'alpha') === 'desc') {
  3045. print '<input class="minwidth500" name="propsmodule" value="'.dol_escape_htmltag($moduleobj->description).'">';
  3046. print '<input class="reposition button smallpaddingimp" type="submit" name="modifydesc" value="'.$langs->trans("Modify").'"/>';
  3047. print '<input class="reposition button button-cancel smallpaddingimp" type="submit" name="cancel" value="'.$langs->trans("Cancel").'"/>';
  3048. } else {
  3049. print $moduleobj->getDesc();
  3050. print '<a class="editfielda reposition marginleftonly marginrighttonly paddingright paddingleft" href="'.$_SERVER["PHP_SELF"].'?action=edit_moduledescription&token='.newToken().'&tab='.urlencode($tab).'&module='.urlencode($module).'&keydescription=desc">'.img_edit().'</a>';
  3051. }
  3052. print '</td></tr>';
  3053. print '<tr><td>';
  3054. print $langs->trans("Version");
  3055. print '</td><td>';
  3056. if ($action == 'edit_moduledescription' && GETPOST('keydescription', 'alpha') === 'version') {
  3057. print '<input name="propsmodule" value="'.dol_escape_htmltag($moduleobj->getVersion()).'">';
  3058. print '<input class="reposition button smallpaddingimp" type="submit" name="modifyversion" value="'.$langs->trans("Modify").'"/>';
  3059. print '<input class="reposition button button-cancel smallpaddingimp" type="submit" name="cancel" value="'.$langs->trans("Cancel").'"/>';
  3060. } else {
  3061. print $moduleobj->getVersion();
  3062. print '<a class="editfielda reposition marginleftonly marginrighttonly paddingright paddingleft" href="'.$_SERVER["PHP_SELF"].'?action=edit_moduledescription&token='.newToken().'&tab='.urlencode($tab).'&module='.urlencode($module).'&keydescription=version">'.img_edit().'</a>';
  3063. }
  3064. print '</td></tr>';
  3065. print '<tr><td>';
  3066. print $langs->trans("Family");
  3067. //print "<br>'crm','financial','hr','projects','products','ecm','technic','interface','other'";
  3068. print '</td><td>';
  3069. if ($action == 'edit_moduledescription' && GETPOST('keydescription', 'alpha') === 'family') {
  3070. print '<select name="propsmodule" id="family" class="minwidth400">';
  3071. $arrayoffamilies = array(
  3072. 'hr' => "ModuleFamilyHr",
  3073. 'crm' => "ModuleFamilyCrm",
  3074. 'srm' => "ModuleFamilySrm",
  3075. 'financial' => 'ModuleFamilyFinancial',
  3076. 'products' => 'ModuleFamilyProducts',
  3077. 'projects' => 'ModuleFamilyProjects',
  3078. 'ecm' => 'ModuleFamilyECM',
  3079. 'technic' => 'ModuleFamilyTechnic',
  3080. 'portal' => 'ModuleFamilyPortal',
  3081. 'interface' => 'ModuleFamilyInterface',
  3082. 'base' => 'ModuleFamilyBase',
  3083. 'other' => 'ModuleFamilyOther'
  3084. );
  3085. print '<option value="'.$moduleobj->family.'" data-html="'.dol_escape_htmltag($langs->trans($arrayoffamilies[$moduleobj->family]).' <span class="opacitymedium">- '.$moduleobj->family.'</span>').'">'.$langs->trans($arrayoffamilies[$moduleobj->family]).'</option>';
  3086. foreach ($arrayoffamilies as $key => $value) {
  3087. if ($key != $moduleobj->family) {
  3088. print '<option value="'.$key.'" data-html="'.dol_escape_htmltag($langs->trans($value).' <span class="opacitymedium">- '.$key.'</span>').'">'.$langs->trans($value).'</option>';
  3089. }
  3090. }
  3091. print '</select>';
  3092. print '<input class="reposition button smallpaddingimp" type="submit" name="modifyfamily" value="'.$langs->trans("Modify").'"/>';
  3093. print '<input class="reposition button button-cancel smallpaddingimp" type="submit" name="cancel" value="'.$langs->trans("Cancel").'"/>';
  3094. } else {
  3095. print $moduleobj->family;
  3096. print '<a class="editfielda reposition marginleftonly marginrighttonly paddingright paddingleft" href="'.$_SERVER["PHP_SELF"].'?action=edit_moduledescription&token='.newToken().'&tab='.urlencode($tab).'&module='.urlencode($module).'&keydescription=family">'.img_edit().'</a>';
  3097. }
  3098. print '</td></tr>';
  3099. print '<tr><td>';
  3100. print $langs->trans("Picto");
  3101. print '</td><td>';
  3102. if ($action == 'edit_modulepicto' && GETPOST('keydescription', 'alpha') === 'picto') {
  3103. print '<input class="minwidth500" name="propsmodule" value="'.dol_escape_htmltag($moduleobj->picto).'">';
  3104. print '<input class="reposition button smallpaddingimp" type="submit" name="modifypicto" value="'.$langs->trans("Modify").'"/>';
  3105. print '<input class="reposition button button-cancel smallpaddingimp" type="submit" name="cancel" value="'.$langs->trans("Cancel").'"/>';
  3106. } else {
  3107. print $moduleobj->picto;
  3108. print ' &nbsp; '.img_picto('', $moduleobj->picto, 'class="valignmiddle pictomodule paddingrightonly"');
  3109. print '<a class="editfielda reposition marginleftonly marginrighttonly paddingright paddingleft" href="'.$_SERVER["PHP_SELF"].'?action=edit_modulepicto&token='.newToken().'&tab='.urlencode($tab).'&module='.urlencode($module).'&keydescription=picto">'.img_edit().'</a>';
  3110. }
  3111. print '</td></tr>';
  3112. print '<tr><td>';
  3113. print $langs->trans("EditorName");
  3114. print '</td><td>';
  3115. if ($action == 'edit_moduledescription' && GETPOST('keydescription', 'alpha') === 'editor_name') {
  3116. print '<input name="propsmodule" value="'.dol_escape_htmltag($moduleobj->editor_name).'">';
  3117. print '<input class="reposition button smallpaddingimp" type="submit" name="modifyname" value="'.$langs->trans("Modify").'"/>';
  3118. print '<input class="reposition button button-cancel smallpaddingimp" type="submit" name="cancel" value="'.$langs->trans("Cancel").'"/>';
  3119. } else {
  3120. print $moduleobj->editor_name;
  3121. print '<a class="editfielda reposition marginleftonly marginrighttonly paddingright paddingleft" href="'.$_SERVER["PHP_SELF"].'?action=edit_moduledescription&token='.newToken().'&tab='.urlencode($tab).'&module='.urlencode($module).'&keydescription=editor_name">'.img_edit().'</a>';
  3122. }
  3123. print '</td></tr>';
  3124. print '<tr><td>';
  3125. print $langs->trans("EditorUrl");
  3126. print '</td><td>';
  3127. if ($action == 'edit_moduledescription' && GETPOST('keydescription', 'alpha') === 'editor_url') {
  3128. print '<input name="propsmodule" value="'.dol_escape_htmltag($moduleobj->editor_url).'">';
  3129. print '<input class="reposition button smallpaddingimp" type="submit" name="modifyeditorurl" value="'.$langs->trans("Modify").'"/>';
  3130. print '<input class="reposition button button-cancel smallpaddingimp" type="submit" name="cancel" value="'.$langs->trans("Cancel").'"/>';
  3131. } else {
  3132. if (!empty($moduleobj->editor_url)) {
  3133. print '<a href="'.$moduleobj->editor_url.'" target="_blank" rel="noopener">'.$moduleobj->editor_url.' '.img_picto('', 'globe').'</a>';
  3134. }
  3135. print '<a class="editfielda reposition marginleftonly marginrighttonly paddingright paddingleft" href="'.$_SERVER["PHP_SELF"].'?action=edit_moduledescription&token='.newToken().'&tab='.urlencode($tab).'&module='.urlencode($module).'&keydescription=editor_url">'.img_edit().'</a>';
  3136. }
  3137. print '</td></tr>';
  3138. print '</table>';
  3139. print '</form>';
  3140. } else {
  3141. print $langs->trans("ErrorFailedToLoadModuleDescriptorForXXX", $module).'<br>';
  3142. }
  3143. if (!empty($moduleobj)) {
  3144. print '<br><br>';
  3145. // Readme file
  3146. print load_fiche_titre($form->textwithpicto($langs->trans("ReadmeFile"), $langs->transnoentitiesnoconv("File").' '.$pathtofilereadme), '', '');
  3147. print '<!-- readme file -->';
  3148. if (dol_is_file($dirread.'/'.$pathtofilereadme)) {
  3149. print '<div class="underbanner clearboth"></div><div class="fichecenter">'.$moduleobj->getDescLong().'</div>';
  3150. } else {
  3151. print '<span class="opacitymedium">'.$langs->trans("ErrorFileNotFound", $pathtofilereadme).'</span>';
  3152. }
  3153. print '<br><br>';
  3154. // ChangeLog
  3155. print load_fiche_titre($form->textwithpicto($langs->trans("ChangeLog"), $langs->transnoentitiesnoconv("File").' '.$pathtochangelog), '', '');
  3156. print '<!-- changelog file -->';
  3157. if (dol_is_file($dirread.'/'.$pathtochangelog)) {
  3158. print '<div class="underbanner clearboth"></div><div class="fichecenter">'.$moduleobj->getChangeLog().'</div>';
  3159. } else {
  3160. print '<span class="opacitymedium">'.$langs->trans("ErrorFileNotFound", $pathtochangelog).'</span>';
  3161. }
  3162. }
  3163. print dol_get_fiche_end();
  3164. } else { // Edit text file
  3165. $fullpathoffile = dol_buildpath($file, 0, 1); // Description - level 2
  3166. if ($fullpathoffile) {
  3167. $content = file_get_contents($fullpathoffile);
  3168. }
  3169. // New module
  3170. print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
  3171. print '<input type="hidden" name="token" value="'.newToken().'">';
  3172. print '<input type="hidden" name="action" value="savefile">';
  3173. print '<input type="hidden" name="file" value="'.dol_escape_htmltag($file).'">';
  3174. print '<input type="hidden" name="tab" value="'.$tab.'">';
  3175. print '<input type="hidden" name="module" value="'.$module.'">';
  3176. print dol_get_fiche_head($head2, $tab, '', -1, '', 0, '', '', 0, 'formodulesuffix');
  3177. $doleditor = new DolEditor('editfilecontent', $content, '', '300', 'Full', 'In', true, false, 'ace', 0, '99%', '');
  3178. print $doleditor->Create(1, '', false, $langs->trans("File").' : '.$file, (GETPOST('format', 'aZ09') ?GETPOST('format', 'aZ09') : 'html'));
  3179. print dol_get_fiche_end();
  3180. print '<center>';
  3181. print '<input type="submit" class="button buttonforacesave button-save" id="savefile" name="savefile" value="'.dol_escape_htmltag($langs->trans("Save")).'">';
  3182. print ' &nbsp; ';
  3183. print '<input type="submit" class="button button-cancel" name="cancel" value="'.dol_escape_htmltag($langs->trans("Cancel")).'">';
  3184. print '</center>';
  3185. print '</form>';
  3186. }
  3187. } else {
  3188. print dol_get_fiche_head($head2, $tab, '', -1, '', 0, '', '', $MAXTABFOROBJECT, 'formodulesuffix'); // Level 2
  3189. }
  3190. if ($tab == 'languages') {
  3191. print '<!-- tab=languages -->'."\n";
  3192. if ($action != 'editfile' || empty($file)) {
  3193. print '<span class="opacitymedium">'.$langs->trans("LanguageDefDesc").'</span><br>';
  3194. print '<br>';
  3195. print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
  3196. print '<input type="hidden" name="token" value="'.newToken().'">';
  3197. print '<input type="hidden" name="action" value="addlanguage">';
  3198. print '<input type="hidden" name="file" value="'.dol_escape_htmltag($file).'">';
  3199. print '<input type="hidden" name="tab" value="'.$tab.'">';
  3200. print '<input type="hidden" name="module" value="'.$module.'">';
  3201. print $formadmin->select_language($conf->global->MAIN_LANG_DEFAULT, 'newlangcode', 0, 0, 1, 0, 0, 'minwidth300', 1);
  3202. print '<input type="submit" name="addlanguage" class="button smallpaddingimp" value="'.dol_escape_htmltag($langs->trans("AddLanguageFile")).'"><br>';
  3203. print '</form>';
  3204. print '<br>';
  3205. print '<br>';
  3206. $modulelowercase = strtolower($module);
  3207. // Dir for module
  3208. $diroflang = dol_buildpath($modulelowercase, 0);
  3209. $diroflang .= '/langs';
  3210. $langfiles = dol_dir_list($diroflang, 'files', 1, '\.lang$');
  3211. if (!preg_match('/custom/', $dirread)) {
  3212. // If this is not a module into custom
  3213. $diroflang = $dirread;
  3214. $diroflang .= '/langs';
  3215. $langfiles = dol_dir_list($diroflang, 'files', 1, $modulelowercase.'\.lang$');
  3216. }
  3217. print '<table class="none">';
  3218. foreach ($langfiles as $langfile) {
  3219. $pathtofile = $modulelowercase.'/langs/'.$langfile['relativename'];
  3220. if (!preg_match('/custom/', $dirread)) { // If this is not a module into custom
  3221. $pathtofile = 'langs/'.$langfile['relativename'];
  3222. }
  3223. print '<tr><td><span class="fa fa-file-o"></span> '.$langs->trans("LanguageFile").' '.basename(dirname($pathtofile)).' : <strong class="wordbreak">'.$pathtofile.'</strong>';
  3224. print '</td><td><a class="editfielda" href="'.$_SERVER['PHP_SELF'].'?tab='.urlencode($tab).'&module='.$module.($forceddirread ? '@'.$dirread : '').'&action=editfile&token='.newToken().'&format=ini&file='.urlencode($pathtofile).'">'.img_picto($langs->trans("Edit"), 'edit').'</a>';
  3225. print '</td><td><a class="editfielda" href="'.$_SERVER['PHP_SELF'].'?tab='.urlencode($tab).'&module='.$module.($forceddirread ? '@'.$dirread : '').'&action=confirm_removefile&token='.newToken().'&file='.urlencode($pathtofile).'">'.img_picto($langs->trans("Delete"), 'delete').'</a>';
  3226. print '</td>';
  3227. }
  3228. print '</table>';
  3229. } else {
  3230. // Edit text language file
  3231. //print $langs->trans("UseAsciiDocFormat").'<br>';
  3232. $fullpathoffile = dol_buildpath($file, 0);
  3233. $content = file_get_contents($fullpathoffile);
  3234. // New module
  3235. print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
  3236. print '<input type="hidden" name="token" value="'.newToken().'">';
  3237. print '<input type="hidden" name="action" value="savefile">';
  3238. print '<input type="hidden" name="file" value="'.dol_escape_htmltag($file).'">';
  3239. print '<input type="hidden" name="tab" value="'.$tab.'">';
  3240. print '<input type="hidden" name="module" value="'.$module.'">';
  3241. $doleditor = new DolEditor('editfilecontent', $content, '', '300', 'Full', 'In', true, false, 'ace', 0, '99%');
  3242. print $doleditor->Create(1, '', false, $langs->trans("File").' : '.$file, (GETPOST('format', 'aZ09') ?GETPOST('format', 'aZ09') : 'text'));
  3243. print '<br>';
  3244. print '<center>';
  3245. print '<input type="submit" class="button buttonforacesave button-save" id="savefile" name="savefile" value="'.dol_escape_htmltag($langs->trans("Save")).'">';
  3246. print ' &nbsp; ';
  3247. print '<input type="submit" class="button button-cancel" name="cancel" value="'.dol_escape_htmltag($langs->trans("Cancel")).'">';
  3248. print '</center>';
  3249. print '</form>';
  3250. }
  3251. }
  3252. if ($tab == 'objects') {
  3253. print '<!-- tab=objects -->'."\n";
  3254. $head3 = array();
  3255. $h = 0;
  3256. // Dir for module
  3257. $dir = $dirread.'/'.$modulelowercase.'/class';
  3258. $head3[$h][0] = $_SERVER["PHP_SELF"].'?tab=objects&module='.$module.($forceddirread ? '@'.$dirread : '').'&tabobj=newobject';
  3259. $head3[$h][1] = '<span class="valignmiddle text-plus-circle">'.$langs->trans("NewObjectInModulebuilder").'</span><span class="fa fa-plus-circle valignmiddle paddingleft"></span>';
  3260. $head3[$h][2] = 'newobject';
  3261. $h++;
  3262. // Scan for object class files
  3263. $listofobject = dol_dir_list($dir, 'files', 0, '\.class\.php$');
  3264. $firstobjectname = '';
  3265. foreach ($listofobject as $fileobj) {
  3266. if (preg_match('/^api_/', $fileobj['name'])) {
  3267. continue;
  3268. }
  3269. if (preg_match('/^actions_/', $fileobj['name'])) {
  3270. continue;
  3271. }
  3272. $tmpcontent = file_get_contents($fileobj['fullname']);
  3273. if (preg_match('/class\s+([^\s]*)\s+extends\s+CommonObject/ims', $tmpcontent, $reg)) {
  3274. //$objectname = preg_replace('/\.txt$/', '', $fileobj['name']);
  3275. $objectname = $reg[1];
  3276. if (empty($firstobjectname)) {
  3277. $firstobjectname = $objectname;
  3278. }
  3279. $pictoname = 'generic';
  3280. if (preg_match('/\$picto\s*=\s*["\']([^"\']+)["\']/', $tmpcontent, $reg)) {
  3281. $pictoname = $reg[1];
  3282. }
  3283. $head3[$h][0] = $_SERVER["PHP_SELF"].'?tab=objects&module='.$module.($forceddirread ? '@'.$dirread : '').'&tabobj='.$objectname;
  3284. $head3[$h][1] = img_picto('', $pictoname, 'class="pictofixedwidth valignmiddle"').$objectname;
  3285. $head3[$h][2] = $objectname;
  3286. $h++;
  3287. }
  3288. }
  3289. if ($h > 1) {
  3290. $head3[$h][0] = $_SERVER["PHP_SELF"].'?tab=objects&module='.$module.($forceddirread ? '@'.$dirread : '').'&tabobj=deleteobject';
  3291. $head3[$h][1] = img_picto('', 'delete', 'class="pictofixedwidth"').$langs->trans("DangerZone");
  3292. $head3[$h][2] = 'deleteobject';
  3293. $h++;
  3294. }
  3295. // If tabobj was not defined, then we check if there is one obj. If yes, we force on it, if no, we will show tab to create new objects.
  3296. if ($tabobj == 'newobjectifnoobj') {
  3297. if ($firstobjectname) {
  3298. $tabobj = $firstobjectname;
  3299. } else {
  3300. $tabobj = 'newobject';
  3301. }
  3302. }
  3303. print dol_get_fiche_head($head3, $tabobj, '', -1, '', 0, '', '', 0, 'forobjectsuffix'); // Level 3
  3304. if ($tabobj == 'newobject') {
  3305. // New object tab
  3306. print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
  3307. print '<input type="hidden" name="token" value="'.newToken().'">';
  3308. print '<input type="hidden" name="action" value="initobject">';
  3309. print '<input type="hidden" name="tab" value="objects">';
  3310. print '<input type="hidden" name="module" value="'.dol_escape_htmltag($module).'">';
  3311. print '<span class="opacitymedium">'.$langs->trans("EnterNameOfObjectDesc").'</span><br><br>';
  3312. print '<div class="tagtable">';
  3313. print '<div class="tagtr"><div class="tagtd">';
  3314. print '<span class="opacitymedium">'.$langs->trans("ObjectKey").'</span> &nbsp; ';
  3315. print '</div><div class="tagtd">';
  3316. print '<input type="text" name="objectname" maxlength="64" value="'.dol_escape_htmltag(GETPOSTISSET('objectname', 'alpha') ? GETPOST('objectname', 'alpha') : $modulename).'" autofocus>';
  3317. print $form->textwithpicto('', $langs->trans("Example").': MyObject, ACamelCaseName, ...');
  3318. print '</div></div>';
  3319. print '<div class="tagtr"><div class="tagtd">';
  3320. print '<span class="opacitymedium">'.$langs->trans("Picto").'</span> &nbsp; ';
  3321. print '</div><div class="tagtd">';
  3322. print '<input type="text" name="idpicto" value="fa-file-o" placeholder="'.dol_escape_htmltag($langs->trans("Picto")).'">';
  3323. print $form->textwithpicto('', $langs->trans("Example").': fa-file-o, fa-globe, ... any font awesome code.<br>Advanced syntax is fa-fakey[_faprefix[_facolor[_fasize]]]');
  3324. print '</div></div>';
  3325. print '<div class="tagtr"><div class="tagtd">';
  3326. print '<span class="opacitymedium">'.$langs->trans("DefinePropertiesFromExistingTable").'</span> &nbsp; ';
  3327. print '</div><div class="tagtd">';
  3328. print '<input type="text" name="initfromtablename" value="'.GETPOST('initfromtablename').'" placeholder="'.$langs->trans("TableName").'">';
  3329. print $form->textwithpicto('', $langs->trans("DefinePropertiesFromExistingTableDesc").'<br>'.$langs->trans("DefinePropertiesFromExistingTableDesc2"));
  3330. print '</div></div>';
  3331. print '</div>';
  3332. print '<br>';
  3333. print '<input type="checkbox" name="includerefgeneration" id="includerefgeneration" value="includerefgeneration"> <label class="margintoponly" for="includerefgeneration">'.$form->textwithpicto($langs->trans("IncludeRefGeneration"), $langs->trans("IncludeRefGenerationHelp")).'</label><br>';
  3334. print '<input type="checkbox" name="includedocgeneration" id="includedocgeneration" value="includedocgeneration"> <label for="includedocgeneration">'.$form->textwithpicto($langs->trans("IncludeDocGeneration"), $langs->trans("IncludeDocGenerationHelp")).'</label><br>';
  3335. print '<input type="checkbox" name="generatepermissions" id="generatepermissions" value="generatepermissions"> <label for="generatepermissions">'.$form->textwithpicto($langs->trans("GeneratePermissions"), $langs->trans("GeneratePermissionsHelp")).'</label><br>';
  3336. print '<br>';
  3337. print '<input type="submit" class="button small" name="create" value="'.dol_escape_htmltag($langs->trans("GenerateCode")).'"'.($dirins ? '' : ' disabled="disabled"').'>';
  3338. print '<br>';
  3339. print '<br>';
  3340. /*
  3341. print '<br>';
  3342. print '<span class="opacitymedium">'.$langs->trans("or").'</span>';
  3343. print '<br>';
  3344. print '<br>';
  3345. //print '<input type="checkbox" name="initfromtablecheck"> ';
  3346. print $langs->trans("InitStructureFromExistingTable");
  3347. print '<input type="text" name="initfromtablename" value="" placeholder="'.$langs->trans("TableName").'">';
  3348. print '<input type="submit" class="button smallpaddingimp" name="createtablearray" value="'.dol_escape_htmltag($langs->trans("GenerateCode")).'"'.($dirins ? '' : ' disabled="disabled"').'>';
  3349. print '<br>';
  3350. */
  3351. print '</form>';
  3352. } elseif ($tabobj == 'createproperty') {
  3353. $attributesUnique = array (
  3354. 'proplabel' => $form->textwithpicto($langs->trans("Label"), $langs->trans("YouCanUseTranslationKey")),
  3355. 'propname' => $form->textwithpicto($langs->trans("Code"), $langs->trans("PropertyDesc"), 1, 'help', 'extracss', 0, 3, 'propertyhelp'),
  3356. 'proptype' => $form->textwithpicto($langs->trans("Type"), $langs->trans("TypeOfFieldsHelpIntro").'<br><br>'.$langs->trans("TypeOfFieldsHelp"), 1, 'help', 'extracss', 0, 3, 'typehelp'),
  3357. 'proparrayofkeyval' => $form->textwithpicto($langs->trans("ArrayOfKeyValues"), $langs->trans("ArrayOfKeyValuesDesc")),
  3358. 'propnotnull' => $form->textwithpicto($langs->trans("NotNull"), $langs->trans("NotNullDesc")),
  3359. 'propdefault' => $langs->trans("DefaultValue"),
  3360. 'propindex' => $langs->trans("DatabaseIndex"),
  3361. 'propforeignkey' => $form->textwithpicto($langs->trans("ForeignKey"), $langs->trans("ForeignKeyDesc"), 1, 'help', 'extracss', 0, 3, 'foreignkeyhelp'),
  3362. 'propposition' => $langs->trans("Position"),
  3363. 'propenabled' => $form->textwithpicto($langs->trans("Enabled"), $langs->trans("EnabledDesc"), 1, 'help', 'extracss', 0, 3, 'enabledhelp'),
  3364. 'propvisible' => $form->textwithpicto($langs->trans("Visibility"), $langs->trans("VisibleDesc").'<br><br>'.$langs->trans("ItCanBeAnExpression"), 1, 'help', 'extracss', 0, 3, 'visiblehelp'),
  3365. 'propnoteditable' => $langs->trans("NotEditable"),
  3366. //'propalwayseditable' => $langs->trans("AlwaysEditable"),
  3367. 'propsearchall' => $form->textwithpicto($langs->trans("SearchAll"), $langs->trans("SearchAllDesc")),
  3368. 'propisameasure' => $form->textwithpicto($langs->trans("IsAMeasure"), $langs->trans("IsAMeasureDesc")),
  3369. 'propcss' => $langs->trans("CSSClass"),
  3370. 'propcssview' => $langs->trans("CSSViewClass"),
  3371. 'propcsslist' => $langs->trans("CSSListClass"),
  3372. 'prophelp' => $langs->trans("KeyForTooltip"),
  3373. 'propshowoncombobox' => $langs->trans("ShowOnCombobox"),
  3374. //'propvalidate' => $form->textwithpicto($langs->trans("Validate"), $langs->trans("ValidateModBuilderDesc")),
  3375. 'propcomment' => $langs->trans("Comment"),
  3376. );
  3377. print '<form action="'.$_SERVER["PHP_SELF"].'?tab=objects&module='.urlencode($module).'&tabobj=createproperty&obj='.urlencode(GETPOST('obj')).'" method="POST">';
  3378. print '<input type="hidden" name="token" value="'.newToken().'">';
  3379. print '<input type="hidden" name="action" value="addproperty">';
  3380. print '<input type="hidden" name="tab" value="objects">';
  3381. print '<input type="hidden" name="module" value="'.dol_escape_htmltag($module).'">';
  3382. print '<input type="hidden" name="obj" value="'.dol_escape_htmltag(GETPOST('obj')).'">';
  3383. print '<table class="border centpercent tableforfieldcreate">'."\n";
  3384. $counter = 0;
  3385. foreach ($attributesUnique as $key => $attribute) {
  3386. if ($counter % 2 === 0) {
  3387. print '<tr>';
  3388. }
  3389. if ($key == 'propname' || $key == 'proplabel') {
  3390. print '<td class="titlefieldcreate fieldrequired">'.$attribute.'</td><td class="valuefieldcreate maxwidth50"><input class="maxwidth200" id="'.$key.'" type="text" name="'.$key.'" value="'.dol_escape_htmltag(GETPOST($key, 'alpha')).'"></td>';
  3391. } elseif ($key == 'proptype') {
  3392. print '<td class="titlefieldcreate fieldrequired">'.$attribute.'</td><td class="valuefieldcreate maxwidth50">';
  3393. print '<input class="maxwidth200" id="'.$key.'" list="datalist'.$key.'" type="text" name="'.$key.'" value="'.dol_escape_htmltag(GETPOST($key, 'alpha')).'">';
  3394. //print '<div id="suggestions"></div>';
  3395. print '<datalist id="datalist'.$key.'">';
  3396. print '<option>varchar(128)</option>';
  3397. print '<option>email</option>';
  3398. print '<option>phone</option>';
  3399. print '<option>ip</option>';
  3400. print '<option>url</option>';
  3401. print '<option>password</option>';
  3402. print '<option>text</option>';
  3403. print '<option>html</option>';
  3404. print '<option>date</option>';
  3405. print '<option>datetime</option>';
  3406. print '<option>integer</option>';
  3407. print '<option>double(28,4)</option>';
  3408. print '<option>real</option>';
  3409. print '<option>integer:ClassName:RelativePath/To/ClassFile.class.php[:1[:FILTER]]</option>';
  3410. // Combo with list of fields
  3411. /*
  3412. if (empty($formadmin)) {
  3413. include_once DOL_DOCUMENT_ROOT.'/core/class/html.formadmin.class.php';
  3414. $formadmin = new FormAdmin($db);
  3415. }
  3416. print $formadmin->selectTypeOfFields($key, GETPOST($key, 'alpha'));
  3417. */
  3418. print '</datalist>';
  3419. print '</td>';
  3420. //} elseif ($key == 'propvalidate') {
  3421. // print '<td class="titlefieldcreate">'.$attribute.'</td><td class="valuefieldcreate maxwidth50"><input type="number" step="1" min="0" max="1" class="text maxwidth100" value="'.dol_escape_htmltag(GETPOST($key, 'alpha')).'"></td>';
  3422. } elseif ($key == 'propvisible') {
  3423. print '<td class="titlefieldcreate">'.$attribute.'</td><td class="valuefieldcreate"><input class="maxwidth200" type="text" name="'.$key.'" value="'.dol_escape_htmltag(GETPOSTISSET($key) ? GETPOST($key, 'alpha') : "1").'"></td>';
  3424. } elseif ($key == 'propenabled') {
  3425. //$default = "isModEnabled('".strtolower($module)."')";
  3426. $default = 1;
  3427. print '<td class="titlefieldcreate">'.$attribute.'</td><td class="valuefieldcreate"><input class="maxwidth200" type="text" name="'.$key.'" value="'.dol_escape_htmltag(GETPOSTISSET($key) ? GETPOST($key, 'alpha') : $default).'"></td>';
  3428. } elseif ($key == 'proparrayofkeyval') {
  3429. print '<td class="titlefieldcreate tdproparrayofkeyval">'.$attribute.'</td><td class="valuefieldcreate"><textarea class="maxwidth200" name="'.$key.'">'.dol_escape_htmltag(GETPOSTISSET($key) ? GETPOST($key, 'alpha') : "").'</textarea></td>';
  3430. } else {
  3431. print '<td class="titlefieldcreate">'.$attribute.'</td><td class="valuefieldcreate"><input class="maxwidth200" type="text" name="'.$key.'" value="'.dol_escape_htmltag(GETPOSTISSET($key) ? GETPOST($key, 'alpha') : '').'"></td>';
  3432. }
  3433. $counter++;
  3434. if ($counter % 2 === 0) {
  3435. print '</tr>';
  3436. }
  3437. }
  3438. if ($counter % 2 !== 0) {
  3439. while ($counter % 2 !== 0) {
  3440. print '<td></td>';
  3441. $counter++;
  3442. }
  3443. print '</tr>';
  3444. }
  3445. print '</table><br>'."\n";
  3446. print '<div class="center">';
  3447. print '<input type="submit" class="button button-save" name="add" value="' . dol_escape_htmltag($langs->trans('Create')) . '">';
  3448. print '<input type="button" class="button button-cancel" name="cancel" value="' . dol_escape_htmltag($langs->trans('Cancel')) . '" onclick="goBack()">';
  3449. print '</div>';
  3450. print '</form>';
  3451. // javascript
  3452. print '<script>
  3453. function goBack() {
  3454. var url = "'.$_SERVER["PHP_SELF"].'?tab=objects&module='.urlencode($module).'";
  3455. window.location.href = url;
  3456. }
  3457. $(document).ready(function() {
  3458. $("#proplabel").on("keyup", function() {
  3459. console.log("key up on label");
  3460. s = cleanString($("#proplabel").val());
  3461. $("#propname").val(s);
  3462. });
  3463. function cleanString( stringtoclean )
  3464. {
  3465. // allow "a-z", "A-Z", "0-9" and "_"
  3466. stringtoclean = stringtoclean.replace(/[^a-z0-9_]+/ig, "");
  3467. stringtoclean = stringtoclean.toLowerCase();
  3468. if (!isNaN(stringtoclean)) {
  3469. return ""
  3470. }
  3471. while ( stringtoclean.length > 1 && !isNaN( stringtoclean.charAt(0)) ){
  3472. stringtoclean = stringtoclean.substr(1)
  3473. }
  3474. if (stringtoclean.length > 28) {
  3475. stringtoclean = stringtoclean.substring(0, 27);
  3476. }
  3477. return stringtoclean;
  3478. }
  3479. });';
  3480. print '</script>';
  3481. } elseif ($tabobj == 'deleteobject') {
  3482. // Delete object tab
  3483. print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
  3484. print '<input type="hidden" name="token" value="'.newToken().'">';
  3485. print '<input type="hidden" name="action" value="confirm_deleteobject">';
  3486. print '<input type="hidden" name="tab" value="objects">';
  3487. print '<input type="hidden" name="tabobj" value="deleteobject">';
  3488. print '<input type="hidden" name="module" value="'.dol_escape_htmltag($module).'">';
  3489. print $langs->trans("EnterNameOfObjectToDeleteDesc").'<br><br>';
  3490. print '<input type="text" name="objectname" value="'.dol_escape_htmltag($modulename).'" placeholder="'.dol_escape_htmltag($langs->trans("ObjectKey")).'">';
  3491. print '<input type="submit" class="button smallpaddingimp" name="delete" value="'.dol_escape_htmltag($langs->trans("Delete")).'"'.($dirins ? '' : ' disabled="disabled"').'>';
  3492. print '</form>';
  3493. } else {
  3494. // tabobj = module
  3495. if ($action == 'deleteproperty') {
  3496. $formconfirm = $form->formconfirm(
  3497. $_SERVER["PHP_SELF"].'?propertykey='.urlencode(GETPOST('propertykey', 'alpha')).'&objectname='.urlencode($objectname).'&tab='.urlencode($tab).'&module='.urlencode($module).'&tabobj='.urlencode($tabobj),
  3498. $langs->trans('Delete'),
  3499. $langs->trans('ConfirmDeleteProperty', GETPOST('propertykey', 'alpha')),
  3500. 'confirm_deleteproperty',
  3501. '',
  3502. 0,
  3503. 1
  3504. );
  3505. // Print form confirm
  3506. print $formconfirm;
  3507. }
  3508. if ($action != 'editfile' || empty($file) ) {
  3509. try {
  3510. //$pathtofile = $listofmodules[strtolower($module)]['moduledescriptorrelpath'];
  3511. $pathtoclass = strtolower($module).'/class/'.strtolower($tabobj).'.class.php';
  3512. $pathtoapi = strtolower($module).'/class/api_'.strtolower($module).'.class.php';
  3513. $pathtoagenda = strtolower($module).'/'.strtolower($tabobj).'_agenda.php';
  3514. $pathtocard = strtolower($module).'/'.strtolower($tabobj).'_card.php';
  3515. $pathtodocument = strtolower($module).'/'.strtolower($tabobj).'_document.php';
  3516. $pathtolist = strtolower($module).'/'.strtolower($tabobj).'_list.php';
  3517. $pathtonote = strtolower($module).'/'.strtolower($tabobj).'_note.php';
  3518. $pathtocontact = strtolower($module).'/'.strtolower($tabobj).'_contact.php';
  3519. $pathtophpunit = strtolower($module).'/test/phpunit/'.strtolower($tabobj).'Test.php';
  3520. // Try to load object class file
  3521. clearstatcache(true);
  3522. if (function_exists('opcache_invalidate')) {
  3523. opcache_invalidate($dirread.'/'.$pathtoclass, true); // remove the include cache hell !
  3524. }
  3525. if (empty($forceddirread) && empty($dirread)) {
  3526. $result = dol_include_once($pathtoclass);
  3527. $stringofinclude = "dol_include_once(".$pathtoclass.")";
  3528. } else {
  3529. $result = @include_once $dirread.'/'.$pathtoclass;
  3530. $stringofinclude = "@include_once ".$dirread.'/'.$pathtoclass;
  3531. }
  3532. if (class_exists($tabobj)) {
  3533. try {
  3534. $tmpobject = @new $tabobj($db);
  3535. } catch (Exception $e) {
  3536. dol_syslog('Failed to load Constructor of class: '.$e->getMessage(), LOG_WARNING);
  3537. }
  3538. } else {
  3539. print '<span class="warning">'.$langs->trans('Failed to find the class '.$tabobj.' despite the '.$stringofinclude).'</span><br><br>';
  3540. }
  3541. // Define path for sql file
  3542. $pathtosql = strtolower($module).'/sql/llx_'.strtolower($module).'_'.strtolower($tabobj).'-'.strtolower($module).'.sql';
  3543. $result = dol_buildpath($pathtosql);
  3544. if (! dol_is_file($result)) {
  3545. $pathtosql = strtolower($module).'/sql/llx_'.strtolower($module).'_'.strtolower($tabobj).'.sql';
  3546. $result = dol_buildpath($pathtosql);
  3547. if (! dol_is_file($result)) {
  3548. $pathtosql = 'install/mysql/tables/llx_'.strtolower($module).'_'.strtolower($tabobj).'-'.strtolower($module).'.sql';
  3549. $result = dol_buildpath($pathtosql);
  3550. if (! dol_is_file($result)) {
  3551. $pathtosql = 'install/mysql/tables/llx_'.strtolower($module).'-'.strtolower($module).'.sql';
  3552. $result = dol_buildpath($pathtosql);
  3553. if (! dol_is_file($result)) {
  3554. $pathtosql = 'install/mysql/tables/llx_'.strtolower($module).'.sql';
  3555. $pathtosqlextra = 'install/mysql/tables/llx_'.strtolower($module).'_extrafields.sql';
  3556. $result = dol_buildpath($pathtosql);
  3557. } else {
  3558. $pathtosqlextra = 'install/mysql/tables/llx_'.strtolower($module).'_extrafields-'.strtolower($module).'.sql';
  3559. }
  3560. } else {
  3561. $pathtosqlextra = 'install/mysql/tables/llx_'.strtolower($module).'_'.strtolower($tabobj).'_extrafields-'.strtolower($module).'.sql';
  3562. }
  3563. } else {
  3564. $pathtosqlextra = strtolower($module).'/sql/llx_'.strtolower($module).'_'.strtolower($tabobj).'_extrafields.sql';
  3565. }
  3566. } else {
  3567. $pathtosqlextra = strtolower($module).'/sql/llx_'.strtolower($module).'_'.strtolower($tabobj).'_extrafields-'.strtolower($module).'.sql';
  3568. }
  3569. $pathtosqlroot = preg_replace('/\/llx_.*$/', '', $pathtosql);
  3570. $pathtosqlkey = preg_replace('/\.sql$/', '.key.sql', $pathtosql);
  3571. $pathtosqlextrakey = preg_replace('/\.sql$/', '.key.sql', $pathtosqlextra);
  3572. $pathtolib = strtolower($module).'/lib/'.strtolower($module).'.lib.php';
  3573. $pathtoobjlib = strtolower($module).'/lib/'.strtolower($module).'_'.strtolower($tabobj).'.lib.php';
  3574. if (is_object($tmpobject) && property_exists($tmpobject, 'picto')) {
  3575. $pathtopicto = $tmpobject->picto;
  3576. $realpathtopicto = '';
  3577. } else {
  3578. $pathtopicto = strtolower($module).'/img/object_'.strtolower($tabobj).'.png';
  3579. $realpathtopicto = $dirread.'/'.$pathtopicto;
  3580. }
  3581. //var_dump($pathtoclass);
  3582. //var_dump($dirread);
  3583. $realpathtoclass = $dirread.'/'.$pathtoclass;
  3584. $realpathtoapi = $dirread.'/'.$pathtoapi;
  3585. $realpathtoagenda = $dirread.'/'.$pathtoagenda;
  3586. $realpathtocard = $dirread.'/'.$pathtocard;
  3587. $realpathtodocument = $dirread.'/'.$pathtodocument;
  3588. $realpathtolist = $dirread.'/'.$pathtolist;
  3589. $realpathtonote = $dirread.'/'.$pathtonote;
  3590. $realpathtocontact = $dirread.'/'.$pathtocontact;
  3591. $realpathtophpunit = $dirread.'/'.$pathtophpunit;
  3592. $realpathtosql = $dirread.'/'.$pathtosql;
  3593. $realpathtosqlextra = $dirread.'/'.$pathtosqlextra;
  3594. $realpathtosqlkey = $dirread.'/'.$pathtosqlkey;
  3595. $realpathtosqlextrakey = $dirread.'/'.$pathtosqlextrakey;
  3596. $realpathtolib = $dirread.'/'.$pathtolib;
  3597. $realpathtoobjlib = $dirread.'/'.$pathtoobjlib;
  3598. if (empty($realpathtoapi)) { // For compatibility with some old modules
  3599. $pathtoapi = strtolower($module).'/class/api_'.strtolower($module).'s.class.php';
  3600. $realpathtoapi = $dirread.'/'.$pathtoapi;
  3601. }
  3602. $urloflist = dol_buildpath('/'.$pathtolist, 1);
  3603. $urlofcard = dol_buildpath('/'.$pathtocard, 1);
  3604. $objs = array();
  3605. print '<!-- section for object -->';
  3606. print '<div class="fichehalfleft smallxxx">';
  3607. // Main DAO class file
  3608. print '<span class="fa fa-file-o"></span> '.$langs->trans("ClassFile").' : <strong>'.(dol_is_file($realpathtoclass) ? '' : '<strike>').preg_replace('/^'.strtolower($module).'\//', '', $pathtoclass).(dol_is_file($realpathtoclass) ? '' : '</strike>').'</strong>';
  3609. print ' <a class="editfielda" href="'.$_SERVER['PHP_SELF'].'?tab='.urlencode($tab).'&tabobj='.$tabobj.'&module='.$module.($forceddirread ? '@'.$dirread : '').'&action=editfile&token='.newToken().'&format=php&file='.urlencode($pathtoclass).'">'.img_picto($langs->trans("Edit"), 'edit').'</a>';
  3610. print '<br>';
  3611. // Image
  3612. if ($realpathtopicto && dol_is_file($realpathtopicto)) {
  3613. print '<span class="fa fa-file-image-o"></span> '.$langs->trans("Image").' : <strong>'.(dol_is_file($realpathtopicto) ? '' : '<strike>').preg_replace('/^'.strtolower($module).'\//', '', $pathtopicto).(dol_is_file($realpathtopicto) ? '' : '</strike>').'</strong>';
  3614. //print ' <a href="'.$_SERVER['PHP_SELF'].'?tab='.urlencode($tab).'&tabobj='.$tabobj.'&module='.$module.($forceddirread?'@'.$dirread:'').'&action=editfile&token='.newToken().'&format=php&file='.urlencode($pathtopicto).'">'.img_picto($langs->trans("Edit"), 'edit').'</a>';
  3615. print '<br>';
  3616. } elseif (!empty($tmpobject)) {
  3617. print '<span class="fa fa-file-image-o"></span> '.$langs->trans("Image").' : '.img_picto('', $tmpobject->picto, 'class="pictofixedwidth valignmiddle"').$tmpobject->picto;
  3618. print '<br>';
  3619. }
  3620. // API file
  3621. print '<br>';
  3622. print '<span class="fa fa-file-o"></span> '.$langs->trans("ApiClassFile").' : <strong class="wordbreak">'.(dol_is_file($realpathtoapi) ? '' : '<strike><span class="opacitymedium">').preg_replace('/^'.strtolower($module).'\//', '', $pathtoapi).(dol_is_file($realpathtoapi)?'':'</span></strike>').'</strong>';
  3623. if (dol_is_file($realpathtoapi)) {
  3624. $file = file_get_contents($realpathtoapi);
  3625. if (preg_match('/var '.$tabobj.'\s+([^\s]*)\s/ims', $file, $objs)) {
  3626. print ' <a class="editfielda" href="'.$_SERVER['PHP_SELF'].'?tab='.urlencode($tab).'&tabobj='.$tabobj.'&module='.$module.($forceddirread ? '@'.$dirread : '').'&action=editfile&token='.newToken().'&format=php&file='.urlencode($pathtoapi).'">'.img_picto($langs->trans("Edit"), 'edit').'</a>';
  3627. print ' ';
  3628. print '<a class="reposition editfielda" href="'.$_SERVER['PHP_SELF'].'?tab='.urlencode($tab).'&tabobj='.$tabobj.'&module='.$module.($forceddirread ? '@'.$dirread : '').'&action=confirm_removefile&token='.newToken().'&file='.urlencode($pathtoapi).'">'.img_picto($langs->trans("Delete"), 'delete').'</a>';
  3629. print $form->textwithpicto('', $langs->trans("InfoForApiFile"), 1, 'warning');
  3630. print ' &nbsp; ';
  3631. if (!isModEnabled(strtolower($const_name))) { // If module is not activated
  3632. print '<a href="#" class="classfortooltip" target="apiexplorer" title="'.$langs->trans("ModuleMustBeEnabled", $module).'"><strike>'.$langs->trans("ApiExplorer").'</strike></a>';
  3633. } else {
  3634. print '<a href="'.DOL_URL_ROOT.'/api/index.php/explorer/" target="apiexplorer">'.$langs->trans("ApiExplorer").'</a>';
  3635. }
  3636. } else {
  3637. print '<a class="editfielda" href="'.$_SERVER['PHP_SELF'].'?tab='.urlencode($tab).'&tabobj='.$tabobj.'&module='.$module.($forceddirread ? '@'.$dirread : '').'&action=initapi&token='.newToken().'&format=php&file='.urlencode($pathtoapi).'">'.img_picto('AddAPIsForThisObject', 'generate', 'class="paddingleft"').'</a>';
  3638. }
  3639. } else {
  3640. print '<a class="editfielda" href="'.$_SERVER['PHP_SELF'].'?tab='.urlencode($tab).'&tabobj='.$tabobj.'&module='.$module.($forceddirread ? '@'.$dirread : '').'&action=initapi&token='.newToken().'&format=php&file='.urlencode($pathtoapi).'">'.img_picto('Generate', 'generate', 'class="paddingleft"').'</a>';
  3641. }
  3642. // PHPUnit
  3643. print '<br>';
  3644. print '<span class="fa fa-file-o"></span> '.$langs->trans("TestClassFile").' : <strong class="wordbreak">'.(dol_is_file($realpathtophpunit) ? '' : '<strike><span class="opacitymedium">').preg_replace('/^'.strtolower($module).'\//', '', $pathtophpunit).(dol_is_file($realpathtophpunit)?'':'</span></strike>').'</strong>';
  3645. if (dol_is_file($realpathtophpunit)) {
  3646. print ' <a class="editfielda" href="'.$_SERVER['PHP_SELF'].'?tab='.urlencode($tab).'&tabobj='.$tabobj.'&module='.$module.($forceddirread ? '@'.$dirread : '').'&action=editfile&token='.newToken().'&format=php&file='.urlencode($pathtophpunit).'">'.img_picto($langs->trans("Edit"), 'edit').'</a>';
  3647. print ' ';
  3648. print '<a class="reposition editfielda" href="'.$_SERVER['PHP_SELF'].'?tab='.urlencode($tab).'&tabobj='.$tabobj.'&module='.$module.($forceddirread ? '@'.$dirread : '').'&action=confirm_removefile&token='.newToken().'&file='.urlencode($pathtophpunit).'">'.img_picto($langs->trans("Delete"), 'delete').'</a>';
  3649. } else {
  3650. print '<a class="editfielda" href="'.$_SERVER['PHP_SELF'].'?tab='.urlencode($tab).'&tabobj='.$tabobj.'&module='.$module.($forceddirread ? '@'.$dirread : '').'&action=initphpunit&token='.newToken().'&format=php&file='.urlencode($pathtophpunit).'">'.img_picto('Generate', 'generate', 'class="paddingleft"').'</a>';
  3651. }
  3652. print '<br>';
  3653. print '<br>';
  3654. print '<span class="fa fa-file-o"></span> '.$langs->trans("PageForLib").' : <strong class="wordbreak">'.(dol_is_file($realpathtolib) ? '' : '<strike>').preg_replace('/^'.strtolower($module).'\//', '', $pathtolib).(dol_is_file($realpathtolib) ? '' : '</strike>').'</strong>';
  3655. print ' <a class="editfielda" href="'.$_SERVER['PHP_SELF'].'?tab='.urlencode($tab).'&tabobj='.$tabobj.'&module='.$module.($forceddirread ? '@'.$dirread : '').'&action=editfile&token='.newToken().'&format=php&file='.urlencode($pathtolib).'">'.img_picto($langs->trans("Edit"), 'edit').'</a>';
  3656. print '<br>';
  3657. print '<span class="fa fa-file-o"></span> '.$langs->trans("PageForObjLib").' : <strong class="wordbreak">'.(dol_is_file($realpathtoobjlib) ? '' : '<strike>').preg_replace('/^'.strtolower($module).'\//', '', $pathtoobjlib).(dol_is_file($realpathtoobjlib) ? '' : '</strike>').'</strong>';
  3658. print ' <a class="editfielda" href="'.$_SERVER['PHP_SELF'].'?tab='.urlencode($tab).'&tabobj='.$tabobj.'&module='.$module.($forceddirread ? '@'.$dirread : '').'&action=editfile&token='.newToken().'&format=php&file='.urlencode($pathtoobjlib).'">'.img_picto($langs->trans("Edit"), 'edit').'</a>';
  3659. print '<br>';
  3660. print '<br>';
  3661. print '<span class="fa fa-file-o"></span> '.$langs->trans("SqlFile").' : <strong class="wordbreak">'.(dol_is_file($realpathtosql) ? '' : '<strike>').preg_replace('/^'.strtolower($module).'\//', '', $pathtosql).(dol_is_file($realpathtosql) ? '' : '</strike>').'</strong>';
  3662. print ' <a class="editfielda" href="'.$_SERVER['PHP_SELF'].'?tab='.urlencode($tab).'&tabobj='.$tabobj.'&module='.$module.($forceddirread ? '@'.$dirread : '').'&action=editfile&token='.newToken().'&format=sql&file='.urlencode($pathtosql).'">'.img_picto($langs->trans("Edit"), 'edit').'</a>';
  3663. print ' &nbsp; <a class="reposition" href="'.$_SERVER["PHP_SELF"].'?tab='.urlencode($tab).'&tabobj='.$tabobj.'&module='.$module.($forceddirread ? '@'.$dirread : '').'&action=droptable&token='.newToken().'">'.$langs->trans("DropTableIfEmpty").'</a>';
  3664. //print ' &nbsp; <a href="'.$_SERVER["PHP_SELF"].'">'.$langs->trans("RunSql").'</a>';
  3665. print '<br>';
  3666. print '<span class="fa fa-file-o"></span> '.$langs->trans("SqlFileKey").' : <strong class="wordbreak">'.(dol_is_file($realpathtosqlkey) ? '' : '<strike>').preg_replace('/^'.strtolower($module).'\//', '', $pathtosqlkey).(dol_is_file($realpathtosqlkey) ? '' : '</strike>').'</strong>';
  3667. print ' <a class="editfielda" href="'.$_SERVER['PHP_SELF'].'?tab='.urlencode($tab).'&tabobj='.$tabobj.'&module='.$module.($forceddirread ? '@'.$dirread : '').'&action=editfile&token='.newToken().'&format=sql&file='.urlencode($pathtosqlkey).'">'.img_picto($langs->trans("Edit"), 'edit').'</a>';
  3668. //print ' &nbsp; <a href="'.$_SERVER["PHP_SELF"].'">'.$langs->trans("RunSql").'</a>';
  3669. print '<br>';
  3670. print '<span class="fa fa-file-o"></span> '.$langs->trans("SqlFileExtraFields").' : <strong class="wordbreak">'.(dol_is_file($realpathtosqlextra) ? '' : '<strike><span class="opacitymedium">').preg_replace('/^'.strtolower($module).'\//', '', $pathtosqlextra).(dol_is_file($realpathtosqlextra) && dol_is_file($realpathtosqlextrakey) ? '' : '</span></strike>').'</strong>';
  3671. if (dol_is_file($realpathtosqlextra) && dol_is_file($realpathtosqlextrakey)) {
  3672. print ' <a class="editfielda" href="'.$_SERVER['PHP_SELF'].'?tab='.urlencode($tab).'&tabobj='.$tabobj.'&module='.$module.($forceddirread ? '@'.$dirread : '').'&action=editfile&token='.newToken().'&file='.urlencode($pathtosqlextra).'">'.img_picto($langs->trans("Edit"), 'edit').'</a>';
  3673. print ' ';
  3674. print '<a class="reposition editfielda" href="'.$_SERVER['PHP_SELF'].'?tab='.urlencode($tab).'&tabobj='.$tabobj.'&module='.$module.($forceddirread ? '@'.$dirread : '').'&action=confirm_removefile&token='.newToken().'&file='.urlencode($pathtosqlextra).'">'.img_picto($langs->trans("Delete"), 'delete').'</a>';
  3675. print ' &nbsp; ';
  3676. print '<a class="reposition editfielda" href="'.$_SERVER["PHP_SELF"].'?tab='.urlencode($tab).'&tabobj='.$tabobj.'&module='.$module.($forceddirread ? '@'.$dirread : '').'&action=droptableextrafields&token='.newToken().'">'.$langs->trans("DropTableIfEmpty").'</a>';
  3677. } else {
  3678. print '<a class="editfielda" href="'.$_SERVER['PHP_SELF'].'?tab='.urlencode($tab).'&tabobj='.$tabobj.'&module='.$module.($forceddirread ? '@'.$dirread : '').'&action=initsqlextrafields&token='.newToken().'&format=sql&file='.urlencode($pathtosqlextra).'">'.img_picto('Generate', 'generate', 'class="paddingleft"').'</a>';
  3679. }
  3680. //print ' &nbsp; <a href="'.$_SERVER["PHP_SELF"].'">'.$langs->trans("RunSql").'</a>';
  3681. print '<br>';
  3682. print '<span class="fa fa-file-o"></span> '.$langs->trans("SqlFileKeyExtraFields").' : <strong class="wordbreak">'.(dol_is_file($realpathtosqlextrakey) ? '' : '<strike><span class="opacitymedium">').preg_replace('/^'.strtolower($module).'\//', '', $pathtosqlextrakey).(dol_is_file($realpathtosqlextra) && dol_is_file($realpathtosqlextrakey) ? '' : '</span></strike>').'</strong>';
  3683. if (dol_is_file($realpathtosqlextra) && dol_is_file($realpathtosqlextrakey)) {
  3684. print ' <a class="editfielda" href="'.$_SERVER['PHP_SELF'].'?tab='.urlencode($tab).'&tabobj='.$tabobj.'&module='.$module.($forceddirread ? '@'.$dirread : '').'&action=editfile&token='.newToken().'&format=sql&file='.urlencode($pathtosqlextrakey).'">'.img_picto($langs->trans("Edit"), 'edit').'</a>';
  3685. print ' ';
  3686. print '<a class="reposition editfielda" href="'.$_SERVER['PHP_SELF'].'?tab='.urlencode($tab).'&tabobj='.$tabobj.'&module='.$module.($forceddirread ? '@'.$dirread : '').'&action=confirm_removefile&token='.newToken().'&file='.urlencode($pathtosqlextrakey).'">'.img_picto($langs->trans("Delete"), 'delete').'</a>';
  3687. } else {
  3688. print '<a class="editfielda" href="'.$_SERVER['PHP_SELF'].'?tab='.urlencode($tab).'&tabobj='.$tabobj.'&module='.$module.($forceddirread ? '@'.$dirread : '').'&action=initsqlextrafields&token='.newToken().'&format=sql&file='.urlencode($pathtosqlextra).'">'.img_picto('Generate', 'generate', 'class="paddingleft"').'</a>';
  3689. }
  3690. print '<br>';
  3691. print '</div>';
  3692. print '<div class="fichehalfleft smallxxxx">';
  3693. print '<span class="fa fa-file-o"></span> '.$langs->trans("PageForList").' : <strong class="wordbreak"><a href="'.$urloflist.'" target="_test">'.(dol_is_file($realpathtolist) ? '' : '<strike><span class="opacitymedium">').preg_replace('/^'.strtolower($module).'\//', '', $pathtolist).(dol_is_file($realpathtolist) ? '' : '</span></strike>').'</a></strong>';
  3694. print ' <a class="editfielda" href="'.$_SERVER['PHP_SELF'].'?tab='.urlencode($tab).'&tabobj='.$tabobj.'&module='.$module.($forceddirread ? '@'.$dirread : '').'&action=editfile&token='.newToken().'&format=php&file='.urlencode($pathtolist).'">'.img_picto($langs->trans("Edit"), 'edit').'</a>';
  3695. print '<br>';
  3696. print '<span class="fa fa-file-o"></span> '.$langs->trans("PageForCreateEditView").' : <strong class="wordbreak"><a href="'.$urlofcard.'?action=create" target="_test">'.(dol_is_file($realpathtocard) ? '' : '<strike>').preg_replace('/^'.strtolower($module).'\//', '', $pathtocard).(dol_is_file($realpathtocard) ? '' : '</strike>').'?action=create</a></strong>';
  3697. print ' <a class="editfielda" href="'.$_SERVER['PHP_SELF'].'?tab='.urlencode($tab).'&tabobj='.$tabobj.'&module='.$module.($forceddirread ? '@'.$dirread : '').'&action=editfile&token='.newToken().'&format=php&file='.urlencode($pathtocard).'">'.img_picto($langs->trans("Edit"), 'edit').'</a>';
  3698. print '<br>';
  3699. // Page contact
  3700. print '<span class="fa fa-file-o"></span> '.$langs->trans("PageForContactTab").' : <strong class="wordbreak">'.(dol_is_file($realpathtocontact) ? '' : '<strike><span class="opacitymedium">').preg_replace('/^'.strtolower($module).'\//', '', $pathtocontact).(dol_is_file($realpathtocontact) ? '' : '</span></strike>').'</strong>';
  3701. print ' <a class="editfielda" href="'.$_SERVER['PHP_SELF'].'?tab='.urlencode($tab).'&tabobj='.$tabobj.'&module='.$module.($forceddirread ? '@'.$dirread : '').'&action=editfile&token='.newToken().'&format=php&file='.urlencode($pathtocontact).'">'.img_picto($langs->trans("Edit"), 'edit').'</a>';
  3702. if (dol_is_file($realpathtocontact)) {
  3703. print ' ';
  3704. print '<a class="reposition editfielda" href="'.$_SERVER['PHP_SELF'].'?tab='.urlencode($tab).'&tabobj='.$tabobj.'&module='.$module.($forceddirread ? '@'.$dirread : '').'&action=confirm_removefile&token='.newToken().'&file='.urlencode($pathtocontact).'">'.img_picto($langs->trans("Delete"), 'delete').'</a>';
  3705. } else {
  3706. print '<a class="editfielda" href="'.$_SERVER['PHP_SELF'].'?tab='.urlencode($tab).'&tabobj='.$tabobj.'&module='.$module.($forceddirread ? '@'.$dirread : '').'&action=initpagecontact&token='.newToken().'&format=php&file='.urlencode($pathtocontact).'">'.img_picto('Generate', 'generate', 'class="paddingleft"').'</a>';
  3707. }
  3708. print '<br>';
  3709. // Page document
  3710. print '<span class="fa fa-file-o"></span> '.$langs->trans("PageForDocumentTab").' : <strong class="wordbreak">'.(dol_is_file($realpathtodocument) ? '' : '<strike><span class="opacitymedium">').preg_replace('/^'.strtolower($module).'\//', '', $pathtodocument).(dol_is_file($realpathtodocument) ? '' : '</span></strike>').'</strong>';
  3711. print ' <a class="editfielda" href="'.$_SERVER['PHP_SELF'].'?tab='.urlencode($tab).'&tabobj='.$tabobj.'&module='.$module.($forceddirread ? '@'.$dirread : '').'&action=editfile&token='.newToken().'&format=php&file='.urlencode($pathtodocument).'">'.img_picto($langs->trans("Edit"), 'edit').'</a>';
  3712. if (dol_is_file($realpathtodocument)) {
  3713. print ' ';
  3714. print '<a class="reposition editfielda" href="'.$_SERVER['PHP_SELF'].'?tab='.urlencode($tab).'&tabobj='.$tabobj.'&module='.$module.($forceddirread ? '@'.$dirread : '').'&action=confirm_removefile&token='.newToken().'&file='.urlencode($pathtodocument).'">'.img_picto($langs->trans("Delete"), 'delete').'</a>';
  3715. } else {
  3716. print '<a class="editfielda" href="'.$_SERVER['PHP_SELF'].'?tab='.urlencode($tab).'&tabobj='.$tabobj.'&module='.$module.($forceddirread ? '@'.$dirread : '').'&action=initpagedocument&token='.newToken().'&format=php&file='.urlencode($pathtocontact).'">'.img_picto('Generate', 'generate', 'class="paddingleft"').'</a>';
  3717. }
  3718. print '<br>';
  3719. // Page notes
  3720. print '<span class="fa fa-file-o"></span> '.$langs->trans("PageForNoteTab").' : <strong class="wordbreak">'.(dol_is_file($realpathtonote) ? '' : '<strike><span class="opacitymedium">').preg_replace('/^'.strtolower($module).'\//', '', $pathtonote).(dol_is_file($realpathtonote) ? '' : '</span></strike>').'</strong>';
  3721. print ' <a class="editfielda" href="'.$_SERVER['PHP_SELF'].'?tab='.urlencode($tab).'&tabobj='.$tabobj.'&module='.$module.($forceddirread ? '@'.$dirread : '').'&action=editfile&token='.newToken().'&format=php&file='.urlencode($pathtonote).'">'.img_picto($langs->trans("Edit"), 'edit').'</a>';
  3722. if (dol_is_file($realpathtonote)) {
  3723. print ' ';
  3724. print '<a class="reposition editfielda" href="'.$_SERVER['PHP_SELF'].'?tab='.urlencode($tab).'&tabobj='.$tabobj.'&module='.$module.($forceddirread ? '@'.$dirread : '').'&action=confirm_removefile&token='.newToken().'&file='.urlencode($pathtonote).'">'.img_picto($langs->trans("Delete"), 'delete').'</a>';
  3725. } else {
  3726. print '<a class="editfielda" href="'.$_SERVER['PHP_SELF'].'?tab='.urlencode($tab).'&tabobj='.$tabobj.'&module='.$module.($forceddirread ? '@'.$dirread : '').'&action=initpagenote&token='.newToken().'&format=php&file='.urlencode($pathtocontact).'">'.img_picto('Generate', 'generate', 'class="paddingleft"').'</a>';
  3727. }
  3728. print '<br>';
  3729. // Page agenda
  3730. print '<span class="fa fa-file-o"></span> '.$langs->trans("PageForAgendaTab").' : <strong class="wordbreak">'.(dol_is_file($realpathtoagenda) ? '' : '<strike><span class="opacitymedium">').preg_replace('/^'.strtolower($module).'\//', '', $pathtoagenda).(dol_is_file($realpathtoagenda) ? '' : '</span></strike>').'</strong>';
  3731. print ' <a class="editfielda" href="'.$_SERVER['PHP_SELF'].'?tab='.urlencode($tab).'&tabobj='.$tabobj.'&module='.$module.($forceddirread ? '@'.$dirread : '').'&action=editfile&format=php&token='.newToken().'&file='.urlencode($pathtoagenda).'">'.img_picto($langs->trans("Edit"), 'edit').'</a>';
  3732. if (dol_is_file($realpathtoagenda)) {
  3733. print ' ';
  3734. print '<a class="reposition editfielda" href="'.$_SERVER['PHP_SELF'].'?tab='.urlencode($tab).'&tabobj='.$tabobj.'&module='.$module.($forceddirread ? '@'.$dirread : '').'&action=confirm_removefile&token='.newToken().'&file='.urlencode($pathtoagenda).'">'.img_picto($langs->trans("Delete"), 'delete').'</a>';
  3735. } else {
  3736. print '<a class="editfielda" href="'.$_SERVER['PHP_SELF'].'?tab='.urlencode($tab).'&tabobj='.$tabobj.'&module='.$module.($forceddirread ? '@'.$dirread : '').'&action=initpageagenda&token='.newToken().'&format=php&file='.urlencode($pathtocontact).'">'.img_picto('Generate', 'generate', 'class="paddingleft"').'</a>';
  3737. }
  3738. print '<br>';
  3739. print '<br>';
  3740. print '</div>';
  3741. print '<br><br><br>';
  3742. if (!empty($tmpobject)) {
  3743. $reflector = new ReflectionClass($tabobj);
  3744. $reflectorproperties = $reflector->getProperties(); // Can also use get_object_vars
  3745. $reflectorpropdefault = $reflector->getDefaultProperties(); // Can also use get_object_vars
  3746. //$propstat = $reflector->getStaticProperties();
  3747. //var_dump($reflectorpropdefault);
  3748. print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
  3749. print '<input type="hidden" name="token" value="'.newToken().'">';
  3750. print '<input type="hidden" name="action" value="addproperty">';
  3751. print '<input type="hidden" name="tab" value="objects">';
  3752. print '<input type="hidden" name="page_y" value="">';
  3753. print '<input type="hidden" name="module" value="'.dol_escape_htmltag($module.($forceddirread ? '@'.$dirread : '')).'">';
  3754. print '<input type="hidden" name="tabobj" value="'.dol_escape_htmltag($tabobj).'">';
  3755. print '<input class="button smallpaddingimp" type="submit" name="regenerateclasssql" value="'.$langs->trans("RegenerateClassAndSql").'">';
  3756. print '<br><br>';
  3757. $mod = strtolower($module);
  3758. $obj = strtolower($tabobj);
  3759. $newproperty = dolGetButtonTitle($langs->trans('NewProperty'), '', 'fa fa-plus-circle', DOL_URL_ROOT.'/modulebuilder/index.php?tab=objects&module='.urlencode($module).'&tabobj=createproperty&obj='.urlencode($tabobj));
  3760. print_barre_liste($langs->trans("ObjectProperties"), 0, $_SERVER["PHP_SELF"], '', '', '', '', '', 0, '', 0, $newproperty, '', '', 0, 0, 1);
  3761. //var_dump($reflectorpropdefault);exit;
  3762. print '<!-- Table with properties of object -->'."\n";
  3763. print '<div class="div-table-responsive">';
  3764. print '<table class="noborder small">';
  3765. print '<tr class="liste_titre">';
  3766. print '<th class="tdsticky tdstickygray">';
  3767. $htmltext = $langs->trans("PropertyDesc").'<br><br><a class="" href="https://wiki.dolibarr.org/index.php/Language_and_development_rules#Table_and_fields_structures" target="_blank" rel="noopener noreferrer external">'.$langs->trans("SeeExamples").'</a>';
  3768. print $form->textwithpicto($langs->trans("Code"), $htmltext, 1, 'help', 'extracss', 0, 3, 'propertyhelp');
  3769. print '</th>';
  3770. print '<th>';
  3771. print $form->textwithpicto($langs->trans("Label"), $langs->trans("YouCanUseTranslationKey"));
  3772. print '</th>';
  3773. print '<th>'.$form->textwithpicto($langs->trans("Type"), $langs->trans("TypeOfFieldsHelpIntro").'<br><br>'.$langs->trans("TypeOfFieldsHelp"), 1, 'help', 'extracss', 0, 3, 'typehelp').'</th>';
  3774. print '<th>'.$form->textwithpicto($langs->trans("ArrayOfKeyValues"), $langs->trans("ArrayOfKeyValuesDesc")).'</th>';
  3775. print '<th class="center">'.$form->textwithpicto($langs->trans("NotNull"), $langs->trans("NotNullDesc")).'</th>';
  3776. print '<th class="center">'.$langs->trans("DefaultValue").'</th>';
  3777. print '<th class="center">'.$langs->trans("DatabaseIndex").'</th>';
  3778. print '<th class="center">'.$form->textwithpicto($langs->trans("ForeignKey"), $langs->trans("ForeignKeyDesc"), 1, 'help', 'extracss', 0, 3, 'foreignkeyhelp').'</th>';
  3779. print '<th class="right">'.$langs->trans("Position").'</th>';
  3780. print '<th class="center">'.$form->textwithpicto($langs->trans("Enabled"), $langs->trans("EnabledDesc"), 1, 'help', 'extracss', 0, 3, 'enabledhelp').'</th>';
  3781. print '<th class="center">'.$form->textwithpicto($langs->trans("Visibility"), $langs->trans("VisibleDesc").'<br><br>'.$langs->trans("ItCanBeAnExpression"), 1, 'help', 'extracss', 0, 3, 'visiblehelp').'</th>';
  3782. print '<th class="center">'.$langs->trans("NotEditable").'</th>';
  3783. //print '<th class="center">'.$langs->trans("AlwaysEditable").'</th>';
  3784. print '<th class="center">'.$form->textwithpicto($langs->trans("SearchAll"), $langs->trans("SearchAllDesc")).'</th>';
  3785. print '<th class="center">'.$form->textwithpicto($langs->trans("IsAMeasure"), $langs->trans("IsAMeasureDesc")).'</th>';
  3786. print '<th class="center">'.$langs->trans("CSSClass").'</th>';
  3787. print '<th class="center">'.$langs->trans("CSSViewClass").'</th>';
  3788. print '<th class="center">'.$langs->trans("CSSListClass").'</th>';
  3789. print '<th>'.$langs->trans("KeyForTooltip").'</th>';
  3790. print '<th class="center">'.$langs->trans("ShowOnCombobox").'</th>';
  3791. //print '<th class="center">'.$langs->trans("Disabled").'</th>';
  3792. print '<th>'.$form->textwithpicto($langs->trans("Validate"), $langs->trans("ValidateModBuilderDesc")).'</th>';
  3793. print '<th>'.$langs->trans("Comment").'</th>';
  3794. print '<th class="tdstickyright tdstickyghostwhite"></th>';
  3795. print '</tr>';
  3796. // We must use $reflectorpropdefault['fields'] to get list of fields because $tmpobject->fields may have been
  3797. // modified during the constructor and we want value into head of class before constructor is called.
  3798. //$properties = dol_sort_array($tmpobject->fields, 'position');
  3799. $properties = dol_sort_array($reflectorpropdefault['fields'], 'position');
  3800. if (!empty($properties)) {
  3801. // List of existing properties
  3802. foreach ($properties as $propkey => $propval) {
  3803. /* If from Reflection
  3804. if ($propval->class == $tabobj)
  3805. {
  3806. $propname=$propval->getName();
  3807. $comment=$propval->getDocComment();
  3808. $type=gettype($tmpobject->$propname);
  3809. $default=$propdefault[$propname];
  3810. // Discard generic properties
  3811. if (in_array($propname, array('element', 'childtables', 'table_element', 'table_element_line', 'class_element_line', 'ismultientitymanaged'))) continue;
  3812. // Keep or not lines
  3813. if (in_array($propname, array('fk_element', 'lines'))) continue;
  3814. }*/
  3815. $propname = $propkey;
  3816. $proplabel = $propval['label'];
  3817. $proptype = $propval['type'];
  3818. $proparrayofkeyval = !empty($propval['arrayofkeyval'])?$propval['arrayofkeyval']:'';
  3819. $propnotnull = !empty($propval['notnull']) ? $propval['notnull'] : '0';
  3820. $propdefault = !empty($propval['default'])?$propval['default']:'';
  3821. $propindex = !empty($propval['index'])?$propval['index']:'';
  3822. $propforeignkey = !empty($propval['foreignkey'])?$propval['foreignkey']:'';
  3823. $propposition = $propval['position'];
  3824. $propenabled = $propval['enabled'];
  3825. $propvisible = $propval['visible'];
  3826. $propnoteditable = !empty($propval['noteditable'])?$propval['noteditable']:0;
  3827. //$propalwayseditable = !empty($propval['alwayseditable'])?$propval['alwayseditable']:0;
  3828. $propsearchall = !empty($propval['searchall'])?$propval['searchall']:0;
  3829. $propisameasure = !empty($propval['isameasure'])?$propval['isameasure']:0;
  3830. $propcss = !empty($propval['css'])?$propval['css']:'';
  3831. $propcssview = !empty($propval['cssview'])?$propval['cssview']:'';
  3832. $propcsslist = !empty($propval['csslist'])?$propval['csslist']:'';
  3833. $prophelp = !empty($propval['help'])?$propval['help']:'';
  3834. $propshowoncombobox = !empty($propval['showoncombobox'])?$propval['showoncombobox']:0;
  3835. //$propdisabled=$propval['disabled'];
  3836. $propvalidate = !empty($propval['validate'])?$propval['validate']:0;
  3837. $propcomment = !empty($propval['comment'])?$propval['comment']:'';
  3838. print '<!-- line for object property -->'."\n";
  3839. print '<tr class="oddeven">';
  3840. print '<td class="tdsticky tdstickygray">';
  3841. print dol_escape_htmltag($propname);
  3842. print '</td>';
  3843. print '<td>';
  3844. print dol_escape_htmltag($proplabel);
  3845. print '</td>';
  3846. if ($action == 'editproperty' && $propname == $propertykey) {
  3847. print '<td class="tdoverflowmax200">';
  3848. print '<input type="hidden" name="propname" value="'.dol_escape_htmltag($propname).'">';
  3849. print '<input type="hidden" name="proplabel" value="'.dol_escape_htmltag($proplabel).'">';
  3850. print '<input name="proptype" value="'.dol_escape_htmltag($proptype).'"></input>';
  3851. print '</td>';
  3852. print '<td class="tdoverflowmax200">';
  3853. print '<textarea name="proparrayofkeyval">';
  3854. if (isset($proparrayofkeyval)) {
  3855. if (is_array($proparrayofkeyval) || $proparrayofkeyval != '') {
  3856. print dol_escape_htmltag(json_encode($proparrayofkeyval, JSON_UNESCAPED_UNICODE));
  3857. }
  3858. }
  3859. print '</textarea>';
  3860. print '</td>';
  3861. print '<td>';
  3862. print '<input class="center width50" name="propnotnull" value="'.dol_escape_htmltag($propnotnull).'">';
  3863. print '</td>';
  3864. print '<td>';
  3865. print '<input class="maxwidth50" name="propdefault" value="'.dol_escape_htmltag($propdefault).'">';
  3866. print '</td>';
  3867. print '<td class="center">';
  3868. print '<input class="center maxwidth50" name="propindex" value="'.dol_escape_htmltag($propindex).'">';
  3869. print '</td>';
  3870. print '<td>';
  3871. print '<input class="center maxwidth100" name="propforeignkey" value="'.dol_escape_htmltag($propforeignkey).'">';
  3872. print '</td>';
  3873. print '<td>';
  3874. print '<input class="right width50" name="propposition" value="'.dol_escape_htmltag($propposition).'">';
  3875. print '</td>';
  3876. print '<td>';
  3877. print '<input class="center width75" name="propenabled" value="'.dol_escape_htmltag($propenabled).'">';
  3878. print '</td>';
  3879. print '<td>';
  3880. print '<input class="center width75" name="propvisible" value="'.dol_escape_htmltag($propvisible).'">';
  3881. print '</td>';
  3882. print '<td>';
  3883. print '<input class="center width50" name="propnoteditable" size="2" value="'.dol_escape_htmltag($propnoteditable).'">';
  3884. print '</td>';
  3885. /*print '<td>';
  3886. print '<input class="center" name="propalwayseditable" size="2" value="'.dol_escape_htmltag($propalwayseditable).'">';
  3887. print '</td>';*/
  3888. print '<td>';
  3889. print '<input class="center width50" name="propsearchall" value="'.dol_escape_htmltag($propsearchall).'">';
  3890. print '</td>';
  3891. print '<td>';
  3892. print '<input class="center width50" name="propisameasure" value="'.dol_escape_htmltag($propisameasure).'">';
  3893. print '</td>';
  3894. print '<td>';
  3895. print '<input class="center maxwidth50" name="propcss" value="'.dol_escape_htmltag($propcss).'">';
  3896. print '</td>';
  3897. print '<td>';
  3898. print '<input class="center maxwidth50" name="propcssview" value="'.dol_escape_htmltag($propcssview).'">';
  3899. print '</td>';
  3900. print '<td>';
  3901. print '<input class="center maxwidth50" name="propcsslist" value="'.dol_escape_htmltag($propcsslist).'">';
  3902. print '</td>';
  3903. print '<td>';
  3904. print '<input class="maxwidth100" name="prophelp" value="'.dol_escape_htmltag($prophelp).'">';
  3905. print '</td>';
  3906. print '<td>';
  3907. print '<input class="center maxwidth50" name="propshowoncombobox" value="'.dol_escape_htmltag($propshowoncombobox).'">';
  3908. print '</td>';
  3909. print '<td>';
  3910. print '<input type="number" step="1" min="0" max="1" class="text maxwidth100" name="propvalidate" value="'.dol_escape_htmltag($propvalidate).'">';
  3911. print '</td>';
  3912. print '<td>';
  3913. print '<input class="maxwidth100" name="propcomment" value="'.dol_escape_htmltag($propcomment).'">';
  3914. print '</td>';
  3915. print '<td class="center minwidth75 tdstickyright tdstickyghostwhite">';
  3916. print '<input class="reposition button smallpaddingimp" type="submit" name="edit" value="'.$langs->trans("Save").'">';
  3917. print '<input class="reposition button button-cancel smallpaddingimp" type="submit" name="cancel" value="'.$langs->trans("Cancel").'">';
  3918. print '</td>';
  3919. } else {
  3920. print '<td class="tdoverflowmax200">';
  3921. $pictoType = '';
  3922. $matches = array();
  3923. if (preg_match('/^varchar/', $proptype, $matches)) {
  3924. $pictoType = 'varchar';
  3925. } elseif (preg_match('/^integer:/', $proptype, $matches)) {
  3926. $pictoType = 'link';
  3927. } elseif (strpos($proptype, 'integer') === 0) {
  3928. $pictoType = substr($proptype, 0, 3);
  3929. } elseif (strpos($proptype, 'timestamp') === 0) {
  3930. $pictoType = 'datetime';
  3931. } elseif (strpos($proptype, 'real') === 0) {
  3932. $pictoType = 'double';
  3933. }
  3934. print (!empty($pictoType) ? getPictoForType($pictoType) : getPictoForType($proptype)).'<span title="'.dol_escape_htmltag($proptype).'">'.dol_escape_htmltag($proptype).'</span>';
  3935. print '</td>';
  3936. print '<td class="tdoverflowmax200">';
  3937. if ($proparrayofkeyval) {
  3938. print '<span title="'.dol_escape_htmltag(json_encode($proparrayofkeyval, JSON_UNESCAPED_UNICODE)).'">';
  3939. print dol_escape_htmltag(json_encode($proparrayofkeyval, JSON_UNESCAPED_UNICODE));
  3940. print '</span>';
  3941. }
  3942. print '</td>';
  3943. print '<td class="center">';
  3944. print dol_escape_htmltag($propnotnull);
  3945. print '</td>';
  3946. print '<td>';
  3947. print dol_escape_htmltag($propdefault);
  3948. print '</td>';
  3949. print '<td class="center">';
  3950. print $propindex ? '1' : '';
  3951. print '</td>';
  3952. print '<td class="center">';
  3953. print $propforeignkey ? dol_escape_htmltag($propforeignkey) : '';
  3954. print '</td>';
  3955. print '<td class="right">';
  3956. print dol_escape_htmltag($propposition);
  3957. print '</td>';
  3958. print '<td class="center tdoverflowmax100" title="'.($propnoteditable ? dol_escape_htmltag($propnoteditable) : '').'">';
  3959. print $propenabled ? dol_escape_htmltag($propenabled) : '';
  3960. print '</td>';
  3961. // Visibility
  3962. print '<td class="center tdoverflowmax100" title="'.($propvisible ? dol_escape_htmltag($propvisible) : '0').'">';
  3963. print $propvisible ? dol_escape_htmltag($propvisible) : '0';
  3964. print '</td>';
  3965. // Readonly
  3966. print '<td class="center tdoverflowmax100" title="'.($propnoteditable ? dol_escape_htmltag($propnoteditable) : '').'">';
  3967. print $propnoteditable ? dol_escape_htmltag($propnoteditable) : '';
  3968. print '</td>';
  3969. /*print '<td class="center">';
  3970. print $propalwayseditable ? dol_escape_htmltag($propalwayseditable) : '';
  3971. print '</td>';*/
  3972. print '<td class="center">';
  3973. print $propsearchall ? '1' : '';
  3974. print '</td>';
  3975. print '<td class="center">';
  3976. print $propisameasure ? dol_escape_htmltag($propisameasure) : '';
  3977. print '</td>';
  3978. print '<td class="center tdoverflowmax100" title="'.($propcss ? dol_escape_htmltag($propcss) : '').'">';
  3979. print $propcss ? dol_escape_htmltag($propcss) : '';
  3980. print '</td>';
  3981. print '<td class="center tdoverflowmax100" title="'.($propcssview ? dol_escape_htmltag($propcssview) : '').'">';
  3982. print $propcssview ? dol_escape_htmltag($propcssview) : '';
  3983. print '</td>';
  3984. print '<td class="center tdoverflowmax100" title="'.($propcsslist ? dol_escape_htmltag($propcsslist) : '').'">';
  3985. print $propcsslist ? dol_escape_htmltag($propcsslist) : '';
  3986. print '</td>';
  3987. // Key for tooltop
  3988. print '<td class="tdoverflowmax150" title="'.($prophelp ? dol_escape_htmltag($prophelp) : '').'">';
  3989. print $prophelp ? dol_escape_htmltag($prophelp) : '';
  3990. print '</td>';
  3991. print '<td class="center">';
  3992. print $propshowoncombobox ? dol_escape_htmltag($propshowoncombobox) : '';
  3993. print '</td>';
  3994. /*print '<td class="center">';
  3995. print $propdisabled?$propdisabled:'';
  3996. print '</td>';*/
  3997. print '<td class="center">';
  3998. print $propvalidate ? dol_escape_htmltag($propvalidate) : '';
  3999. print '</td>';
  4000. print '<td class="tdoverflowmax200">';
  4001. print '<span title="'.dol_escape_htmltag($propcomment).'">';
  4002. print dol_escape_htmltag($propcomment);
  4003. print '</span>';
  4004. print '</td>';
  4005. print '<td class="center minwidth75 tdstickyright tdstickyghostwhite">';
  4006. if ($propname != 'rowid') {
  4007. print '<a class="editfielda reposition marginleftonly marginrighttonly paddingright paddingleft" href="'.$_SERVER["PHP_SELF"].'?action=editproperty&token='.newToken().'&propertykey='.urlencode($propname).'&tab='.urlencode($tab).'&module='.urlencode($module).'&tabobj='.urlencode($tabobj).'">'.img_edit().'</a>';
  4008. print '<a class="reposition marginleftonly marginrighttonly paddingright paddingleft" href="'.$_SERVER["PHP_SELF"].'?action=deleteproperty&token='.newToken().'&propertykey='.urlencode($propname).'&tab='.urlencode($tab).'&module='.urlencode($module).'&tabobj='.urlencode($tabobj).'">'.img_delete().'</a>';
  4009. }
  4010. print '</td>';
  4011. }
  4012. print '</tr>';
  4013. }
  4014. } else {
  4015. if ($tab == 'specifications') {
  4016. if ($action != 'editfile' || empty($file)) {
  4017. print '<span class="opacitymedium">'.$langs->trans("SpecDefDesc").'</span><br>';
  4018. print '<br>';
  4019. $specs = dol_dir_list(dol_buildpath($modulelowercase.'/doc', 0), 'files', 1, '(\.md|\.asciidoc)$', array('\/temp\/'));
  4020. foreach ($specs as $spec) {
  4021. $pathtofile = $modulelowercase.'/doc/'.$spec['relativename'];
  4022. $format = 'asciidoc';
  4023. if (preg_match('/\.md$/i', $spec['name'])) {
  4024. $format = 'markdown';
  4025. }
  4026. print '<span class="fa fa-file-o"></span> '.$langs->trans("SpecificationFile").' : <strong class="wordbreak">'.$pathtofile.'</strong>';
  4027. print ' <a href="'.$_SERVER['PHP_SELF'].'?tab='.urlencode($tab).'&module='.$module.($forceddirread ? '@'.$dirread : '').'&action=editfile&token='.newToken().'&format='.$format.'&file='.urlencode($pathtofile).'">'.img_picto($langs->trans("Edit"), 'edit').'</a>';
  4028. print '<br>';
  4029. }
  4030. } else {
  4031. // Use MD or asciidoc
  4032. //print $langs->trans("UseAsciiDocFormat").'<br>';
  4033. $fullpathoffile = dol_buildpath($file, 0);
  4034. $content = file_get_contents($fullpathoffile);
  4035. // New module
  4036. print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
  4037. print '<input type="hidden" name="token" value="'.newToken().'">';
  4038. print '<input type="hidden" name="action" value="savefile">';
  4039. print '<input type="hidden" name="file" value="'.dol_escape_htmltag($file).'">';
  4040. print '<input type="hidden" name="tab" value="'.$tab.'">';
  4041. print '<input type="hidden" name="module" value="'.$module.'">';
  4042. $doleditor = new DolEditor('editfilecontent', $content, '', '300', 'Full', 'In', true, false, 'ace', 0, '99%');
  4043. print $doleditor->Create(1, '', false, $langs->trans("File").' : '.$file, (GETPOST('format', 'aZ09') ?GETPOST('format', 'aZ09') : 'html'));
  4044. print '<br>';
  4045. print '<center>';
  4046. print '<input type="submit" class="button buttonforacesave button-save" id="savefile" name="savefile" value="'.dol_escape_htmltag($langs->trans("Save")).'">';
  4047. print ' &nbsp; ';
  4048. print '<input type="submit" class="button button-cancel" name="cancel" value="'.dol_escape_htmltag($langs->trans("Cancel")).'">';
  4049. print '</center>';
  4050. print '</form>';
  4051. }
  4052. }
  4053. print '<tr><td><span class="warning">'.$langs->trans('Property $field not found into the class. The class was probably not generated by modulebuilder.').'</warning></td></tr>';
  4054. }
  4055. print '</table>';
  4056. print '</div>';
  4057. print '</form>';
  4058. } else {
  4059. print '<span class="warning">'.$langs->trans('Failed to init the object with the new '.$tabobj.'($db)').'</warning>';
  4060. }
  4061. } catch (Exception $e) {
  4062. print $e->getMessage();
  4063. }
  4064. } else {
  4065. if (empty($forceddirread)) {
  4066. $fullpathoffile = dol_buildpath($file, 0);
  4067. } else {
  4068. $fullpathoffile = $dirread.'/'.$file;
  4069. }
  4070. $content = file_get_contents($fullpathoffile);
  4071. // New module
  4072. print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
  4073. print '<input type="hidden" name="token" value="'.newToken().'">';
  4074. print '<input type="hidden" name="action" value="savefile">';
  4075. print '<input type="hidden" name="file" value="'.dol_escape_htmltag($file).'">';
  4076. print '<input type="hidden" name="tab" value="'.$tab.'">';
  4077. print '<input type="hidden" name="tabobj" value="'.dol_escape_htmltag($tabobj).'">';
  4078. print '<input type="hidden" name="module" value="'.$module.($forceddirread ? '@'.$dirread : '').'">';
  4079. $doleditor = new DolEditor('editfilecontent', $content, '', '300', 'Full', 'In', true, false, 'ace', 0, '99%');
  4080. print $doleditor->Create(1, '', false, $langs->trans("File").' : '.$file, (GETPOST('format', 'aZ09') ?GETPOST('format', 'aZ09') : 'html'));
  4081. print '<br>';
  4082. print '<center>';
  4083. print '<input type="submit" class="button buttonforacesave button-save" id="savefile" name="savefile" value="'.dol_escape_htmltag($langs->trans("Save")).'">';
  4084. print ' &nbsp; ';
  4085. print '<input type="submit" class="button button-cancel" name="cancel" value="'.dol_escape_htmltag($langs->trans("Cancel")).'">';
  4086. print '</center>';
  4087. print '</form>';
  4088. }
  4089. }
  4090. print dol_get_fiche_end(); // Level 3
  4091. }
  4092. if ($tab == 'dictionaries') {
  4093. print '<!-- tab=dictionaries -->'."\n";
  4094. $pathtofile = $listofmodules[strtolower($module)]['moduledescriptorrelpath'];
  4095. $dicts = $moduleobj->dictionaries;
  4096. if ($action == 'deletedict') {
  4097. $formconfirm = $form->formconfirm(
  4098. $_SERVER["PHP_SELF"].'?dictionnarykey='.urlencode(GETPOST('dictionnarykey', 'int')).'&tab='.urlencode($tab).'&module='.urlencode($module),
  4099. $langs->trans('Delete'),
  4100. $langs->trans('Confirm Delete Dictionnary', GETPOST('dictionnarykey', 'alpha')),
  4101. 'confirm_deletedictionary',
  4102. '',
  4103. 0,
  4104. 1
  4105. );
  4106. print $formconfirm;
  4107. }
  4108. if ($action != 'editfile' || empty($file)) {
  4109. print '<span class="opacitymedium">';
  4110. $htmlhelp = $langs->trans("DictionariesDefDescTooltip", '{s1}');
  4111. $htmlhelp = str_replace('{s1}', '<a target="adminbis" class="nofocusvisible" href="'.DOL_URL_ROOT.'/admin/dict.php">'.$langs->trans('Setup').' - '.$langs->trans('Dictionaries').'</a>', $htmlhelp);
  4112. print $form->textwithpicto($langs->trans("DictionariesDefDesc"), $htmlhelp, 1, 'help', '', 0, 2, 'helpondesc').'<br>';
  4113. print '</span>';
  4114. print '<br>';
  4115. print '<span class="fa fa-file-o"></span> '.$langs->trans("DescriptorFile").' : <strong class="wordbreak">'.$pathtofile.'</strong>';
  4116. print ' <a class="editfielda paddingleft paddingright" href="'.$_SERVER['PHP_SELF'].'?tab='.urlencode($tab).'&module='.$module.($forceddirread ? '@'.$dirread : '').'&action=editfile&token='.newToken().'&format=php&file='.urlencode($pathtofile).'">'.img_picto($langs->trans("Edit"), 'edit').'</a>';
  4117. print '<br>';
  4118. if (is_array($dicts) && !empty($dicts)) {
  4119. print '<span class="fa fa-file-o"></span> '.$langs->trans("LanguageFile").' :</span> ';
  4120. print '<strong class="wordbreak">'.$dicts['langs'].'</strong>';
  4121. print '<br>';
  4122. }
  4123. print '<!-- tab=objects -->'."\n";
  4124. $head3 = array();
  4125. $h = 0;
  4126. // Dir for module
  4127. //$dir = $dirread.'/'.$modulelowercase.'/class';
  4128. $head3[$h][0] = $_SERVER["PHP_SELF"].'?tab=dictionaries&module='.$module.($forceddirread ? '@'.$dirread : '').'&tabdic=newdictionary';
  4129. $head3[$h][1] = '<span class="valignmiddle text-plus-circle">'.$langs->trans("NewDictionary").'</span><span class="fa fa-plus-circle valignmiddle paddingleft"></span>';
  4130. $head3[$h][2] = 'newdictionary';
  4131. $h++;
  4132. // Scan for object class files
  4133. //$listofobject = dol_dir_list($dir, 'files', 0, '\.class\.php$');
  4134. $firstdicname = '';
  4135. // if (!empty($dicts['tabname'])) {
  4136. // foreach ($dicts['tabname'] as $key => $dic) {
  4137. // $dicname = $dic;
  4138. // $diclabel = $dicts['tablib'][$key];
  4139. // if (empty($firstdicname)) {
  4140. // $firstdicname = $dicname;
  4141. // }
  4142. // $head3[$h][0] = $_SERVER["PHP_SELF"].'?tab=dictionaries&module='.$module.($forceddirread ? '@'.$dirread : '').'&tabdic='.$dicname;
  4143. // $head3[$h][1] = $diclabel;
  4144. // $head3[$h][2] = $dicname;
  4145. // $h++;
  4146. // }
  4147. // }
  4148. // if ($h > 1) {
  4149. // $head3[$h][0] = $_SERVER["PHP_SELF"].'?tab=dictionaries&module='.$module.($forceddirread ? '@'.$dirread : '').'&tabdic=deletedictionary';
  4150. // $head3[$h][1] = $langs->trans("DangerZone");
  4151. // $head3[$h][2] = 'deletedictionary';
  4152. // $h++;
  4153. // }
  4154. // If tabobj was not defined, then we check if there is one obj. If yes, we force on it, if no, we will show tab to create new objects.
  4155. // if ($tabdic == 'newdicifnodic') {
  4156. // if ($firstdicname) {
  4157. // $tabdic = $firstdicname;
  4158. // } else {
  4159. // $tabdic = 'newdictionary';
  4160. // }
  4161. // }
  4162. //print dol_get_fiche_head($head3, $tabdic, '', -1, ''); // Level 3
  4163. $newdict = dolGetButtonTitle($langs->trans('NewDictionary'), '', 'fa fa-plus-circle', DOL_URL_ROOT.'/modulebuilder/index.php?tab=dictionaries&module='.urlencode($module).'&tabdic=newdictionary');
  4164. print_barre_liste($langs->trans("ListOfDictionariesEntries"), '', $_SERVER["PHP_SELF"], '', '', '', '', '', '', '', 0, $newdict, '', '', 0, 0, 1);
  4165. if ($tabdic != 'newdictionary') {
  4166. print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
  4167. print '<input type="hidden" name="token" value="'.newToken().'">';
  4168. print '<input type="hidden" name="action" value="addDictionary">';
  4169. print '<input type="hidden" name="tab" value="dictionaries">';
  4170. print '<input type="hidden" name="module" value="'.dol_escape_htmltag($module).'">';
  4171. print '<input type="hidden" name="tabdic" value="'.dol_escape_htmltag($tabdic).'">';
  4172. print '<div class="div-table-responsive">';
  4173. print '<table class="noborder">';
  4174. print '<tr class="liste_titre">';
  4175. print_liste_field_titre("#", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder, 'thsticky thstickygrey ');
  4176. print_liste_field_titre("Table", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder);
  4177. print_liste_field_titre("Label", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder);
  4178. print_liste_field_titre("SQL", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder);
  4179. print_liste_field_titre("SQLSort", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder);
  4180. print_liste_field_titre("FieldsView", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder);
  4181. print_liste_field_titre("FieldsEdit", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder);
  4182. print_liste_field_titre("FieldsInsert", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder);
  4183. print_liste_field_titre("Rowid", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder);
  4184. print_liste_field_titre("Condition", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder);
  4185. print_liste_field_titre("", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder);
  4186. print "</tr>\n";
  4187. if (!empty($dicts) && is_array($dicts) && !empty($dicts['tabname']) && is_array($dicts['tabname'])) {
  4188. $i = 0;
  4189. $maxi = count($dicts['tabname']);
  4190. while ($i < $maxi) {
  4191. if ($action == 'editdict' && $i == (int) GETPOST('dictionnarykey', 'int')-1) {
  4192. print '<tr class="oddeven">';
  4193. print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
  4194. print '<input type="hidden" name="token" value="'.newToken().'">';
  4195. print '<input type="hidden" name="tab" value="dictionaries">';
  4196. print '<input type="hidden" name="module" value="'.dol_escape_htmltag($module).'">';
  4197. print '<input type="hidden" name="action" value="updatedictionary">';
  4198. print '<input type="hidden" name="dictionnarykey" value="'.($i+1).'">';
  4199. print '<td class="tdsticky tdstickygray">';
  4200. print ($i + 1);
  4201. print '</td>';
  4202. print '<td>';
  4203. print '<input type="text" name="tabname" value="'.$dicts['tabname'][$i].'" readonly class="tdstickygray">';
  4204. print '</td>';
  4205. print '<td>';
  4206. print '<input type="text" name="tablib" value="'.$dicts['tablib'][$i].'">';
  4207. print '</td>';
  4208. print '<td>';
  4209. print '<input type="text" name="tabsql" value="'.$dicts['tabsql'][$i].'" readonly class="tdstickygray">';
  4210. print '</td>';
  4211. print '<td>';
  4212. print '<select name="tabsqlsort">';
  4213. print '<option value="'.dol_escape_htmltag($dicts['tabsqlsort'][$i]).'">'.$dicts['tabsqlsort'][$i].'</option>';
  4214. print '</select>';
  4215. print '</td>';
  4216. print '<td><select name="tabfield" >';
  4217. print '<option value="'.dol_escape_htmltag($dicts['tabfield'][$i]).'">'.$dicts['tabfield'][$i].'</option>';
  4218. print '</select></td>';
  4219. print '<td><select name="tabfieldvalue" >';
  4220. print '<option value="'.dol_escape_htmltag($dicts['tabfieldvalue'][$i]).'">'.$dicts['tabfieldvalue'][$i].'</option>';
  4221. print '</select></td>';
  4222. print '<td><select name="tabfieldinsert" >';
  4223. print '<option value="'.dol_escape_htmltag($dicts['tabfieldinsert'][$i]).'">'.$dicts['tabfieldinsert'][$i].'</option>';
  4224. print '</select></td>';
  4225. print '<td>';
  4226. print '<input type="text" name="tabrowid" value="'.dol_escape_htmltag($dicts['tabrowid'][$i]).'" readonly class="tdstickygray">';
  4227. print '</td>';
  4228. print '<td>';
  4229. print '<input type="text" name="tabcond" value="'.dol_escape_htmltag((empty($dicts['tabcond'][$i]) ? 'disabled' : 'enabled')).'" readonly class="tdstickygray">';
  4230. print '</td>';
  4231. print '<td class="center minwidth75 tdstickyright tdstickyghostwhite">';
  4232. print '<input id ="updatedict" class="reposition button smallpaddingimp" type="submit" name="updatedict" value="'.$langs->trans("Modify").'"/>';
  4233. print '<br>';
  4234. print '<input class="reposition button button-cancel smallpaddingimp" type="submit" name="cancel" value="'.$langs->trans("Cancel").'"/>';
  4235. print '</td>';
  4236. print '</form>';
  4237. print '</tr>';
  4238. } else {
  4239. print '<tr class="oddeven">';
  4240. print '<td class="tdsticky tdstickygray">';
  4241. print ($i + 1);
  4242. print '</td>';
  4243. print '<td>';
  4244. print $dicts['tabname'][$i];
  4245. print '</td>';
  4246. print '<td>';
  4247. print $dicts['tablib'][$i];
  4248. print '</td>';
  4249. print '<td>';
  4250. print $dicts['tabsql'][$i];
  4251. print '</td>';
  4252. print '<td>';
  4253. print $dicts['tabsqlsort'][$i];
  4254. print '</td>';
  4255. print '<td>';
  4256. print $dicts['tabfield'][$i];
  4257. print '</td>';
  4258. print '<td>';
  4259. print $dicts['tabfieldvalue'][$i];
  4260. print '</td>';
  4261. print '<td>';
  4262. print $dicts['tabfieldinsert'][$i];
  4263. print '</td>';
  4264. print '<td >';
  4265. print $dicts['tabrowid'][$i];
  4266. print '</td>';
  4267. print '<td >';
  4268. print $dicts['tabcond'][$i];
  4269. print '</td>';
  4270. print '<td class="center minwidth75 tdstickyright tdstickyghostwhite">';
  4271. print '<a class="editfielda reposition marginleftonly marginrighttonly paddingright paddingleft" href="'.$_SERVER["PHP_SELF"].'?action=editdict&token='.newToken().'&dictionnarykey='.urlencode($i+1).'&tab='.urlencode($tab).'&module='.urlencode($module).'">'.img_edit().'</a>';
  4272. print '<a class="marginleftonly marginrighttonly paddingright paddingleft" href="'.$_SERVER["PHP_SELF"].'?action=deletedict&token='.newToken().'&dictionnarykey='.urlencode($i+1).'&tab='.urlencode($tab).'&module='.urlencode($module).'">'.img_delete().'</a>';
  4273. print '</td>';
  4274. print '</tr>';
  4275. }
  4276. $i++;
  4277. }
  4278. } else {
  4279. print '<tr><td colspan="10"><span class="opacitymedium">'.$langs->trans("None").'</span></td></tr>';
  4280. }
  4281. print '</table>';
  4282. print '</div>';
  4283. print '</form>';
  4284. }
  4285. if ($tabdic == 'newdictionary') {
  4286. // New dic tab
  4287. print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
  4288. print '<input type="hidden" name="token" value="'.newToken().'">';
  4289. print '<input type="hidden" name="action" value="initdic">';
  4290. print '<input type="hidden" name="tab" value="dictionaries">';
  4291. print '<input type="hidden" name="tabdic" value="'.$tabdic.'">';
  4292. print '<input type="hidden" name="module" value="'.dol_escape_htmltag($module).'">';
  4293. print '<span class="opacitymedium">'.$langs->trans("EnterNameOfDictionaryDesc").'</span><br><br>';
  4294. print dol_get_fiche_head('');
  4295. print '<table class="border centpercent">';
  4296. print '<tbody>';
  4297. print '<tr><td class="titlefieldcreate fieldrequired">'.$langs->trans("Table").'</td><td><input type="text" name="dicname" maxlength="64" value="'.dol_escape_htmltag(GETPOST('dicname', 'alpha') ? GETPOST('dicname', 'alpha') : $modulename).'" placeholder="'.dol_escape_htmltag($langs->trans("DicKey")).'" autofocus></td>';
  4298. print '<tr><td class="titlefieldcreate fieldrequired">'.$langs->trans("Label").'</td><td><input type="text" name="label" value="'.dol_escape_htmltag(GETPOST('label', 'alpha')).'"></td></tr>';
  4299. print '<tr><td class="titlefieldcreate">'.$langs->trans("SQL").'</td><td><input type="text" style="width:50%;" name="sql" value="'.dol_escape_htmltag(GETPOST('sql', 'alpha')).'"></td></tr>';
  4300. print '<tr><td class="titlefieldcreate">'.$langs->trans("SQLSort").'</td><td><input type="text" name="sqlsort" value="'.dol_escape_htmltag(GETPOST('sqlsort', 'alpha')).'" readonly></td></tr>';
  4301. print '<tr><td class="titlefieldcreate">'.$langs->trans("FieldsView").'</td><td><input type="text" name="field" value="'.dol_escape_htmltag(GETPOST('field', 'alpha')).'"></td></tr>';
  4302. print '<tr><td class="titlefieldcreate">'.$langs->trans("FieldsEdit").'</td><td><input type="text" name="fieldvalue" value="'.dol_escape_htmltag(GETPOST('fieldvalue', 'alpha')).'"></td></tr>';
  4303. print '<tr><td class="titlefieldcreate">'.$langs->trans("FieldsInsert").'</td><td><input type="text" name="fieldinsert" value="'.dol_escape_htmltag(GETPOST('fieldinsert', 'alpha')).'"></td></tr>';
  4304. print '<tr><td class="titlefieldcreate">'.$langs->trans("Rowid").'</td><td><input type="text" name="rowid" value="'.dol_escape_htmltag(GETPOST('rowid', 'alpha')).'"></td></tr>';
  4305. print '<tr></tr>';
  4306. print '</tbody></table>';
  4307. print '<input type="submit" class="button" name="create" value="'.dol_escape_htmltag($langs->trans("GenerateCode")).'"'.($dirins ? '' : ' disabled="disabled"').'>';
  4308. print '<input id="cancel" type="submit" class="button" name="cancel" value="'.dol_escape_htmltag($langs->trans("Cancel")).'">';
  4309. print dol_get_fiche_end();
  4310. print '</form>';
  4311. print '<script>
  4312. $(document).ready(function() {
  4313. $("input[name=\'dicname\']").on("blur", function() {
  4314. if ($(this).val().length > 0) {
  4315. $("input[name=\'label\']").val($(this).val());
  4316. $("input[name=\'sql\']").val("SELECT f.rowid as rowid, f.code, f.label, f.active FROM llx_c_" + $(this).val() + " as f");
  4317. $("input[name=\'sqlsort\']").val("label ASC");
  4318. $("input[name=\'field\']").val("code,label");
  4319. $("input[name=\'fieldvalue\']").val("code,label");
  4320. $("input[name=\'fieldinsert\']").val("code,label");
  4321. $("input[name=\'rowid\']").val("rowid");
  4322. } else {
  4323. $("input[name=\'label\']").val("");
  4324. $("input[name=\'sql\']").val("");
  4325. $("input[name=\'sqlsort\']").val("");
  4326. $("input[name=\'field\']").val("");
  4327. $("input[name=\'fieldvalue\']").val("");
  4328. $("input[name=\'fieldinsert\']").val("");
  4329. $("input[name=\'rowid\']").val("");
  4330. }
  4331. });
  4332. $("input[id=\'cancel\']").click(function() {
  4333. window.history.back();
  4334. });
  4335. });
  4336. </script>';
  4337. /*print '<br>';
  4338. print '<br>';
  4339. print '<br>';
  4340. print '<span class="opacitymedium">'.$langs->trans("or").'</span>';
  4341. print '<br>';
  4342. print '<br>';
  4343. //print '<input type="checkbox" name="initfromtablecheck"> ';
  4344. print $langs->trans("InitStructureFromExistingTable");
  4345. print '<input type="text" name="initfromtablename" value="" placeholder="'.$langs->trans("TableName").'">';
  4346. print '<input type="submit" class="button smallpaddingimp" name="createtablearray" value="'.dol_escape_htmltag($langs->trans("GenerateCode")).'"'.($dirins ? '' : ' disabled="disabled"').'>';
  4347. print '<br>';
  4348. */
  4349. } elseif ($tabdic == 'deletedictionary') {
  4350. // Delete dic tab
  4351. print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
  4352. print '<input type="hidden" name="token" value="'.newToken().'">';
  4353. print '<input type="hidden" name="action" value="confirm_deletedictionary">';
  4354. print '<input type="hidden" name="tab" value="dictionaries">';
  4355. print '<input type="hidden" name="module" value="'.dol_escape_htmltag($module).'">';
  4356. print $langs->trans("EnterNameOfDictionnaryToDeleteDesc").'<br><br>';
  4357. print '<input type="text" name="dicname" value="'.dol_escape_htmltag($modulename).'" placeholder="'.dol_escape_htmltag($langs->trans("DicKey")).'">';
  4358. print '<input type="submit" class="button smallpaddingimp" name="delete" value="'.dol_escape_htmltag($langs->trans("Delete")).'"'.($dirins ? '' : ' disabled="disabled"').'>';
  4359. print '</form>';
  4360. }
  4361. print dol_get_fiche_end();
  4362. } else {
  4363. $fullpathoffile = dol_buildpath($file, 0);
  4364. $content = file_get_contents($fullpathoffile);
  4365. // New module
  4366. print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
  4367. print '<input type="hidden" name="token" value="'.newToken().'">';
  4368. print '<input type="hidden" name="action" value="savefile">';
  4369. print '<input type="hidden" name="file" value="'.dol_escape_htmltag($file).'">';
  4370. print '<input type="hidden" name="tab" value="'.$tab.'">';
  4371. print '<input type="hidden" name="module" value="'.$module.'">';
  4372. $doleditor = new DolEditor('editfilecontent', $content, '', '300', 'Full', 'In', true, false, 'ace', 0, '99%');
  4373. print $doleditor->Create(1, '', false, $langs->trans("File").' : '.$file, (GETPOST('format', 'aZ09') ?GETPOST('format', 'aZ09') : 'html'));
  4374. print '<br>';
  4375. print '<center>';
  4376. print '<input type="submit" class="button buttonforacesave button-save" id="savefile" name="savefile" value="'.dol_escape_htmltag($langs->trans("Save")).'">';
  4377. print ' &nbsp; ';
  4378. print '<input type="submit" class="button button-cancel" name="cancel" value="'.dol_escape_htmltag($langs->trans("Cancel")).'">';
  4379. print '</center>';
  4380. print '</form>';
  4381. }
  4382. }
  4383. if ($tab == 'menus') {
  4384. print '<!-- tab=menus -->'."\n";
  4385. $pathtofile = $listofmodules[strtolower($module)]['moduledescriptorrelpath'];
  4386. $dirins = $listofmodules[strtolower($module)]['moduledescriptorrootpath'];
  4387. $destdir = $dirins.'/'.strtolower($module);
  4388. $listofobject = dol_dir_list($destdir.'/class', 'files', 0, '\.class\.php$');
  4389. $objects = dolGetListOfObjectclasses($destdir);
  4390. $leftmenus = array();
  4391. $menus = $moduleobj->menu;
  4392. $permissions = $moduleobj->rights;
  4393. $crud = array('read'=>'CRUDRead', 'write'=>'CRUDCreateWrite', 'delete'=>'Delete');
  4394. //grouped permissions
  4395. $groupedRights = array();
  4396. foreach ($permissions as $right) {
  4397. $key = $right[4];
  4398. if (!isset($groupedRights[$key])) {
  4399. $groupedRights[$key] = array();
  4400. }
  4401. $groupedRights[$key][] = $right;
  4402. }
  4403. $groupedRights_json = json_encode($groupedRights);
  4404. if ($action == 'deletemenu') {
  4405. $formconfirms = $form->formconfirm(
  4406. $_SERVER["PHP_SELF"].'?menukey='.urlencode(GETPOST('menukey', 'int')).'&tab='.urlencode($tab).'&module='.urlencode($module),
  4407. $langs->trans('Delete'),
  4408. ($menus[GETPOST('menukey')]['fk_menu'] === 'fk_mainmenu='.strtolower($module) ? $langs->trans('Warning: you will delete all menus linked to this one.', GETPOST('menukey', 'int')) : $langs->trans('Confirm Delete Menu', GETPOST('menukey', 'int'))),
  4409. 'confirm_deletemenu',
  4410. '',
  4411. 0,
  4412. 1
  4413. );
  4414. print $formconfirms;
  4415. }
  4416. if ($action != 'editfile' || empty($file)) {
  4417. print '<span class="opacitymedium">';
  4418. $htmlhelp = $langs->trans("MenusDefDescTooltip", '{s1}');
  4419. $htmlhelp = str_replace('{s1}', '<a target="adminbis" class="nofocusvisible" href="'.DOL_URL_ROOT.'/admin/menus/index.php">'.$langs->trans('Setup').' - '.$langs->trans('Menus').'</a>', $htmlhelp);
  4420. print $form->textwithpicto($langs->trans("MenusDefDesc"), $htmlhelp, 1, 'help', '', 0, 2, 'helpondesc').'<br>';
  4421. print '</span>';
  4422. print '<br>';
  4423. print '<span class="fa fa-file-o"></span> '.$langs->trans("DescriptorFile").' : <strong class="wordbreak">'.$pathtofile.'</strong>';
  4424. print ' <a class="editfielda paddingleft paddingright" href="'.$_SERVER['PHP_SELF'].'?tab='.urlencode($tab).'&module='.$module.($forceddirread ? '@'.$dirread : '').'&action=editfile&token='.newToken().'&format=php&file='.urlencode($pathtofile).'">'.img_picto($langs->trans("Edit"), 'edit').'</a>';
  4425. print '<br>';
  4426. print '<br>';
  4427. print load_fiche_titre($langs->trans("ListOfMenusEntries"), '', '');
  4428. print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
  4429. print '<input type="hidden" name="token" value="'.newToken().'">';
  4430. print '<input type="hidden" name="action" value="addmenu">';
  4431. print '<input type="hidden" name="tab" value="menus">';
  4432. print '<input type="hidden" name="module" value="'.dol_escape_htmltag($module).'">';
  4433. print '<input type="hidden" name="tabobj" value="'.dol_escape_htmltag($tabobj).'">';
  4434. print '<div class="div-table-responsive">';
  4435. print '<table class="noborder small">';
  4436. print '<tr class="liste_titre">';
  4437. print_liste_field_titre("#", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder, 'center ');
  4438. print_liste_field_titre("Position", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder);
  4439. print_liste_field_titre("Title", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder, 'center');
  4440. print_liste_field_titre("LinkToParentMenu", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder);
  4441. print_liste_field_titre("mainmenu", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder);
  4442. print_liste_field_titre("leftmenu", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder);
  4443. print_liste_field_titre("URL", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder, '', $langs->transnoentitiesnoconv('DetailUrl'));
  4444. print_liste_field_titre("LanguageFile", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder);
  4445. print_liste_field_titre("Position", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder, 'right ');
  4446. print_liste_field_titre("Enabled", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder, 'center ', $langs->trans('DetailEnabled'));
  4447. print_liste_field_titre("Rights", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder, '', $langs->trans('DetailRight'));
  4448. print_liste_field_titre("Target", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder, '', $langs->trans('DetailTarget'));
  4449. print_liste_field_titre("MenuForUsers", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder, 'center ', $langs->trans('DetailUser'));
  4450. print_liste_field_titre("", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder, 'center ', $langs->trans(''));
  4451. print "</tr>\n";
  4452. $r = count($menus)+1;
  4453. // for adding menu on module
  4454. print '<tr>';
  4455. print '<td class="center"><input type="hidden" readonly class="center maxwidth50" name="propenabled" value="#"></td>';
  4456. print '<td class="center">';
  4457. print '<select class="maxwidth50" name="type">';
  4458. print '<option value="">'.$langs->trans("........").'</option><option value="'.dol_escape_htmltag("left").'">left</option><option value="'.dol_escape_htmltag("top").'">top</option>';
  4459. print '</select></td>';
  4460. print '<td class="left"><input type="text" class="left maxwidth100" name="titre" value="'.dol_escape_htmltag(GETPOST('titre', 'alpha')).'"></td>';
  4461. print '<td class="left">';
  4462. print '<select name="fk_menu">';
  4463. print '<option value="">'.$langs->trans("........").'</option>';
  4464. foreach ($menus as $obj) {
  4465. if ($obj['type'] == 'left' && !empty($obj['leftmenu'])) {
  4466. print "<option value=".strtolower($obj['leftmenu']).">".$obj['leftmenu']."</option>";
  4467. }
  4468. }
  4469. print '</select>';
  4470. print '</td>';
  4471. print '<td class="left"><input type="text" class="left maxwidth50" name="mainmenu" value="'.(empty(GETPOST('mainmenu')) ? strtolower($module) : dol_escape_htmltag(GETPOST('mainmenu', 'alpha'))).'"></td>';
  4472. print '<td class="center"><input id="leftmenu" type="text" class="left maxwidth50" name="leftmenu" value="'.dol_escape_htmltag(GETPOST('leftmenu', 'alpha')).'"></td>';
  4473. print '<td class="left"><input id="url" type="text" class="left maxwidth50" name="url" value="'.dol_escape_htmltag(GETPOST('url', 'alpha')).'"></td>';
  4474. print '<td class="left"><input type="text" class="left maxwidth75" name="langs" value="'.strtolower($module).'@'.strtolower($module).'" readonly></td>';
  4475. // Position
  4476. print '<td class="center"><input type="text" class="center maxwidth50 tdstickygray" name="position" value="'.(1000+$r).'" readonly></td>';
  4477. // Enabled
  4478. print '<td class="center">';
  4479. print '<input type="enabled" class="maxwidth125" value="'.dol_escape_htmltag(GETPOSTISSET('enabled') ? GETPOST('enabled') : 'isModEnabled(\''.$module.'\')').'">';
  4480. $htmltext = '<u>'.$langs->trans("Examples").':</u><br>';
  4481. $htmltext .= '1 <span class="opacitymedium">(always enabled)</span><br>';
  4482. $htmltext .= '0 <span class="opacitymedium">(always disabled)</span><br>';
  4483. $htmltext .= 'isModEnabled(\''.dol_escape_htmltag($module).'\') <span class="opacitymedium">(enabled when module is enabled)</span><br>';
  4484. print $form->textwithpicto('', $htmltext);
  4485. /*
  4486. print '<select class="maxwidth" name="enabled">';
  4487. print '<option value="1" selected>'.$langs->trans("Show").'</option>';
  4488. print '<option value="0">'.$langs->trans("Hide").'</option>';
  4489. print '</select>';
  4490. */
  4491. print '</td>';
  4492. // Perms
  4493. print '<td class="left">';
  4494. print '<select class="maxwidth" name="objects" id="objects">';
  4495. print '<option value=""></option>';
  4496. if (is_array($objects)) {
  4497. foreach ($objects as $value) {
  4498. print '<option value="'.strtolower($value).'">'.dol_escape_htmltag(strtolower($value)).'</option>';
  4499. }
  4500. }
  4501. print '</select>';
  4502. print '<select class="maxwidth hideobject" name="perms" id="perms">';
  4503. print '</select>';
  4504. print '</td>';
  4505. print '<td class="center"><input type="text" class="center maxwidth50" name="target" value="'.dol_escape_htmltag(GETPOST('target', 'alpha')).'"></td>';
  4506. print '<td class="center"><select class="maxwidth10" name="user"><option value="2">'.$langs->trans("AllMenus").'</option><option value="0">'.$langs->trans("Internal").'</option><option value="1">'.$langs->trans("External").'</option></select></td>';
  4507. print '<td class="center minwidth75 tdstickyright tdstickyghostwhite">';
  4508. print '<input type="submit" class="button" name="add" value="'.$langs->trans("Add").'">';
  4509. print '</td>';
  4510. print '</tr>';
  4511. // end form for add menu
  4512. //var_dump($menus);
  4513. if (count($menus)) {
  4514. $i = 0;
  4515. foreach ($menus as $menu) {
  4516. $i++;
  4517. //for get parent in menu
  4518. $string = dol_escape_htmltag($menu['fk_menu']);
  4519. $value = substr($string, strpos($string, 'fk_leftmenu=') + strlen('fk_leftmenu='));
  4520. $propFk_menu = !empty($menu['fk_menu']) ? $menu['fk_menu'] : GETPOST('fk_menu');
  4521. $propTitre = !empty($menu['titre']) ? $menu['titre'] : GETPOST('titre');
  4522. $propMainmenu = !empty($menu['mainmenu']) ? $menu['mainmenu'] : GETPOST('mainmenu');
  4523. $propLeftmenu = !empty($menu['leftmenu']) ? $menu['leftmenu'] : GETPOST('leftmenu');
  4524. $propUrl = !empty($menu['url']) ? $menu['url'] : GETPOST('url', 'alpha');
  4525. $propPerms = !empty($menu['perms']) ? $menu['perms'] : GETPOST('perms');
  4526. $propUser = !empty($menu['user']) ? $menu['user'] : GETPOST('user');
  4527. $propTarget = !empty($menu['target']) ? $menu['target'] : GETPOST('target');
  4528. $propEnabled = !empty($menu['enabled']) ? $menu['enabled'] : GETPOST('enabled');
  4529. // Perms
  4530. $propPerms = str_replace(array('$user->hasRight(', ')'), '', $propPerms);
  4531. $arguments = explode(",", $propPerms);
  4532. $objPerms = (empty($arguments[1]) ? '' : trim($arguments[1]));
  4533. $valPerms = (empty($arguments[2]) ? '' : trim($arguments[2]));
  4534. //$tabobject = ''; // We can't know what is $tabobject in most cases
  4535. if ($action == 'editmenu' && GETPOST('menukey', 'int') == $i) {
  4536. //var_dump($propPerms);exit;
  4537. print '<tr class="oddeven">';
  4538. print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
  4539. print '<input type="hidden" name="token" value="'.newToken().'">';
  4540. print '<input type="hidden" name="action" value="modify_menu">';
  4541. print '<input type="hidden" name="tab" value="menus">';
  4542. print '<input type="hidden" name="module" value="'.dol_escape_htmltag($module).'">';
  4543. //print '<input type="hidden" name="tabobject" value="'.dol_escape_htmltag($tabobject).'">';
  4544. print '<td class="tdsticky tdstickygray">';
  4545. print $i;
  4546. print '</td>';
  4547. print '<input type="hidden" name="menukey" value="'.$i.'"/>';
  4548. print '<td class="center">
  4549. <select class="center maxwidth50" name="type">
  4550. <option value="'.dol_escape_htmltag($menu['type']).'">
  4551. '.dol_escape_htmltag($menu['type']).'
  4552. </option>';
  4553. print '<option value="'.($menu['type'] == 'left' ? 'top' : 'left').'">';
  4554. if ($menu['type'] == 'left') {
  4555. print 'top';
  4556. } else {
  4557. print 'left';
  4558. }
  4559. print '</option></select></td>';
  4560. print '<td class="left"><input type="text" class="left maxwidth" name="titre" value="'.dol_escape_htmltag($propTitre).'"></td>';
  4561. print '<td class="left">';
  4562. print '<select name="fk_menu" class="left maxwidth">';
  4563. print '<option value="'.dol_escape_htmltag($propFk_menu).'">'.dol_escape_htmltag($value).'</option>';
  4564. foreach ($menus as $obj) {
  4565. if ($obj['type'] == 'left' && $obj['leftmenu'] != $value && $obj['leftmenu'] != $menu['leftmenu']) {
  4566. print "<option value=".strtolower($obj['leftmenu']).">".$obj['leftmenu']."</option>";
  4567. }
  4568. }
  4569. print '</select>';
  4570. print '</td>';
  4571. print '<td class="left"><input type="text" class="left maxwidth50" name="mainmenu" value="'.dol_escape_htmltag($propMainmenu).'" readonly></td>';
  4572. print '<td class="left"><input type="text" class="left maxwidth50" name="leftmenu" value="'.dol_escape_htmltag($propLeftmenu).'" readonly></td>';
  4573. print '<td class="left"><input type="text" class="left maxwidth50" name="url" value="'.dol_escape_htmltag($propUrl).'"></td>';
  4574. print '<td class="left"><input type="text" class="left maxwidth50" name="langs" value="'.strtolower($module).'@'.strtolower($module).'" readonly></td>';
  4575. // Position
  4576. print '<td class="center"><input type="text" class="center maxwidth50 tdstickygray" name="position" value="'.($menu['position']).'" readonly></td>';
  4577. // Enabled
  4578. print '<td class="nowraponall">';
  4579. print '<input type="text" class="maxwidth125" named="enabled" value="'.dol_escape_htmltag($propEnabled != '' ? $propEnabled : "isModEnabled('".dol_escape_htmltag($module)."')").'">';
  4580. $htmltext = '<u>'.$langs->trans("Examples").':</u><br>';
  4581. $htmltext .= '1 <span class="opacitymedium">(always enabled)</span><br>';
  4582. $htmltext .= '0 <span class="opacitymedium">(always disabled)</span><br>';
  4583. $htmltext .= 'isModEnabled(\''.dol_escape_htmltag($module).'\') <span class="opacitymedium">(enabled when module is enabled)</span><br>';
  4584. print $form->textwithpicto('', $htmltext);
  4585. /*
  4586. print '<select class="maxwidth50" name="enabledselect">';
  4587. print '<option value="1">1 (always enabled)</option>';
  4588. print '<option value="0">0 (always disabled)</option>';
  4589. print '<option value="isModEnabled(\''.dol_escape_htmltag($module).'\')" >isModEnabled(\''.dol_escape_htmltag($module).'\')</option>';
  4590. print '</select>';
  4591. */
  4592. print '</td>';
  4593. // Permissions
  4594. print '<td class="center nowraponall">';
  4595. print '<input type="text" name="perms" value="'.dol_escape_htmltag($propPerms).'">';
  4596. /*
  4597. if (!empty($objPerms)) {
  4598. print '<input type="hidden" name="objects" value="'.$objPerms.'" />';
  4599. print '<select class="center maxwidth50" name="perms">';
  4600. if (!empty($valPerms)) {
  4601. print '<option selected value="'.dol_escape_htmltag($valPerms).'">'.dol_escape_htmltag($langs->trans($crud[$valPerms])).'</option>';
  4602. foreach ($crud as $key => $val) {
  4603. if ($valPerms != $key) {
  4604. print '<option value="'.dol_escape_htmltag($key).'">'.dol_escape_htmltag($langs->trans($val)).'</option>';
  4605. }
  4606. }
  4607. }
  4608. print '</select>';
  4609. } else {
  4610. print '<select class="center maxwidth50" name="objects">';
  4611. print '<option></option>';
  4612. foreach ($objects as $obj) {
  4613. print '<option value="'.dol_escape_htmltag(strtolower($obj)).'">'.dol_escape_htmltag($obj).'</option>';
  4614. }
  4615. print '</select>';
  4616. print '<select class="center maxwidth50" name="perms">';
  4617. foreach ($crud as $key => $val) {
  4618. print '<option value="'.dol_escape_htmltag($key).'">'.dol_escape_htmltag($key).'</option>';
  4619. }
  4620. print '</select>';
  4621. }*/
  4622. print '</td>';
  4623. print '<td class="center"><input type="text" class="center maxwidth50" name="target" value="'.dol_escape_htmltag($propTarget).'"></td>';
  4624. print '<td class="center"><select class="center maxwidth10" name="user"><option value="2">'.$langs->trans("AllMenus").'</option><option value="0">'.$langs->trans("Internal").'</option><option value="1">'.$langs->trans("External").'</option></select></td>';
  4625. print '<td class="center minwidth75 tdstickyright tdstickyghostwhite maxwidth75">';
  4626. print '<input class="reposition button smallpaddingimp" type="submit" name="edit" value="'.$langs->trans("Modify").'">';
  4627. print '<input class="reposition button button-cancel smallpaddingimp" type="submit" name="cancel" value="'.$langs->trans("Cancel").'">';
  4628. print '</td>';
  4629. print '</form>';
  4630. print '</tr>';
  4631. } else {
  4632. print '<tr class="oddeven">';
  4633. print '<td class="tdsticky tdstickygray">';
  4634. print $i;
  4635. print '</td>';
  4636. print '<td>';
  4637. print dol_escape_htmltag($menu['type']);
  4638. print '</td>';
  4639. print '<td>';
  4640. print dol_escape_htmltag($menu['titre']);
  4641. print '</td>';
  4642. print '<td>';
  4643. print ($value == strtolower($module) ? '/' : $value);
  4644. print '</td>';
  4645. print '<td>';
  4646. print dol_escape_htmltag($menu['mainmenu']);
  4647. print '</td>';
  4648. print '<td>';
  4649. print dol_escape_htmltag($menu['leftmenu']);
  4650. print '</td>';
  4651. print '<td class="tdoverflowmax300" title="'.dol_escape_htmltag($menu['url']).'">';
  4652. print dol_escape_htmltag($menu['url']);
  4653. print '</td>';
  4654. print '<td>';
  4655. print dol_escape_htmltag($menu['langs']);
  4656. print '</td>';
  4657. // Position
  4658. print '<td class="center">';
  4659. print dol_escape_htmltag($menu['position']);
  4660. print '</td>';
  4661. // Enabled
  4662. print '<td class="center tdoverflowmax200" title="'.dol_escape_htmltag($menu['enabled']).'">';
  4663. print dol_escape_htmltag($menu['enabled']);
  4664. print '</td>';
  4665. // Perms
  4666. print '<td class="center tdoverflowmax200" title="'.dol_escape_htmltag($menu['perms']).'">';
  4667. if (strpos($menu['perms'], "\$user->hasRight") !== 0) {
  4668. print '';
  4669. } else {
  4670. print (dol_escape_htmltag($langs->trans($crud[$valPerms])) );
  4671. }
  4672. print '</td>';
  4673. print '<td class="center tdoverflowmax200" title="'.dol_escape_htmltag($menu['target']).'">';
  4674. print dol_escape_htmltag($menu['target']);
  4675. print '</td>';
  4676. print '<td class="center">';
  4677. if ($menu['user'] == 2) {
  4678. print $langs->trans("AllMenus");
  4679. } elseif ($menu['user'] == 0) {
  4680. print $langs->trans('Internal');
  4681. } elseif ($menu['user'] == 1) {
  4682. print $langs->trans('External');
  4683. } else {
  4684. print $menu['user']; // should not happen
  4685. }
  4686. print '</td>';
  4687. print '<td class="center minwidth75 tdstickyright tdstickyghostwhite">';
  4688. if ($menu['titre'] != 'Module'.$module.'Name') {
  4689. print '<a class="editfielda reposition marginleftonly marginrighttonly paddingright paddingleft" href="'.$_SERVER["PHP_SELF"].'?action=editmenu&token='.newToken().'&menukey='.urlencode($i).'&tab='.urlencode($tab).'&module='.urlencode($module).'&tabobj='.urlencode($tabobj).'">'.img_edit().'</a>';
  4690. print '<a class="marginleftonly marginrighttonly paddingright paddingleft" href="'.$_SERVER["PHP_SELF"].'?action=deletemenu&token='.newToken().'&menukey='.urlencode($i-1).'&tab='.urlencode($tab).'&module='.urlencode($module).'&tabobj='.urlencode($tabobj).'">'.img_delete().'</a>';
  4691. }
  4692. print '</td>';
  4693. }
  4694. print '</tr>';
  4695. }
  4696. } else {
  4697. print '<tr><td colspan="5"><span class="opacitymedium">'.$langs->trans("None").'</span></td></tr>';
  4698. }
  4699. print '</table>';
  4700. print '</div>';
  4701. print '</form>';
  4702. print '<script>
  4703. $(document).ready(function() {
  4704. //for fill in auto url
  4705. $("#leftmenu").on("input", function() {
  4706. var inputLeftMenu = $("#leftmenu").val();
  4707. if (inputLeftMenu !== "") {
  4708. var url = "/'.strtolower($module).'/"+ inputLeftMenu+".php";
  4709. $("#url").val(url);
  4710. }else {
  4711. $("#url").val("");
  4712. }
  4713. });
  4714. var groupedRights = ' . $groupedRights_json . ';
  4715. var objectsSelect = $("select[id=\'objects\']");
  4716. var permsSelect = $("select[id=\'perms\']");
  4717. objectsSelect.change(function() {
  4718. var selectedObject = $(this).val();
  4719. permsSelect.empty();
  4720. var rights = groupedRights[selectedObject];
  4721. if (rights) {
  4722. for (var i = 0; i < rights.length; i++) {
  4723. var right = rights[i];
  4724. var option = $("<option></option>").attr("value", right[5]).text(right[5]);
  4725. permsSelect.append(option);
  4726. }
  4727. } else {
  4728. var option = $("<option></option>").attr("value", "read").text("read");
  4729. permsSelect.append(option);
  4730. }
  4731. if (selectedObject !== "" && selectedObject !== null && rights) {
  4732. permsSelect.show();
  4733. } else {
  4734. permsSelect.hide();
  4735. }
  4736. if (objectsSelect.val() === "" || objectsSelect.val() === null) {
  4737. permsSelect.hide();
  4738. }
  4739. });
  4740. });
  4741. </scrip>';
  4742. // display permissions for each object
  4743. } else {
  4744. $fullpathoffile = dol_buildpath($file, 0);
  4745. $content = file_get_contents($fullpathoffile);
  4746. // New module
  4747. print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
  4748. print '<input type="hidden" name="token" value="'.newToken().'">';
  4749. print '<input type="hidden" name="action" value="savefile">';
  4750. print '<input type="hidden" name="file" value="'.dol_escape_htmltag($file).'">';
  4751. print '<input type="hidden" name="tab" value="'.$tab.'">';
  4752. print '<input type="hidden" name="module" value="'.$module.'">';
  4753. $doleditor = new DolEditor('editfilecontent', $content, '', '300', 'Full', 'In', true, false, 'ace', 0, '99%');
  4754. print $doleditor->Create(1, '', false, $langs->trans("File").' : '.$file, (GETPOST('format', 'aZ09') ?GETPOST('format', 'aZ09') : 'html'));
  4755. print '<br>';
  4756. print '<center>';
  4757. print '<input type="submit" class="button buttonforacesave button-save" id="savefile" name="savefile" value="'.dol_escape_htmltag($langs->trans("Save")).'">';
  4758. print ' &nbsp; ';
  4759. print '<input type="submit" class="button button-cancel" name="cancel" value="'.dol_escape_htmltag($langs->trans("Cancel")).'">';
  4760. print '</center>';
  4761. print '</form>';
  4762. }
  4763. }
  4764. if ($tab == 'permissions') {
  4765. print '<!-- tab=permissions -->'."\n";
  4766. $pathtofile = $listofmodules[strtolower($module)]['moduledescriptorrelpath'];
  4767. $perms = $moduleobj->rights;
  4768. // Get list of existing objects
  4769. $dir = $dirread.'/'.$modulelowercase.'/class';
  4770. $listofobject = dol_dir_list($dir, 'files', 0, '\.class\.php$');
  4771. $objects = array('myobject');
  4772. $reg =array();
  4773. foreach ($listofobject as $fileobj) {
  4774. $tmpcontent = file_get_contents($fileobj['fullname']);
  4775. if (preg_match('/class\s+([^\s]*)\s+extends\s+CommonObject/ims', $tmpcontent, $reg)) {
  4776. $objects[$fileobj['fullname']] = $reg[1];
  4777. }
  4778. }
  4779. // declared select list for actions and labels permissions
  4780. $crud = array('read'=>'CRUDRead', 'write'=>'CRUDCreateWrite', 'delete'=>'Delete');
  4781. $labels = array("Read objects of ".$module, "Create/Update objects of ".$module, "Delete objects of ".$module);
  4782. $action = GETPOST('action', 'alpha');
  4783. if ($action == 'deleteright') {
  4784. $formconfirm = $form->formconfirm(
  4785. $_SERVER["PHP_SELF"].'?permskey='.urlencode(GETPOST('permskey', 'int')).'&tab='.urlencode($tab).'&module='.urlencode($module).'&tabobj='.urlencode($tabobj),
  4786. $langs->trans('Delete'),
  4787. $langs->trans('Confirm Delete Right', GETPOST('permskey', 'alpha')),
  4788. 'confirm_deleteright',
  4789. '',
  4790. 0,
  4791. 1
  4792. );
  4793. print $formconfirm;
  4794. }
  4795. if ($action != 'editfile' || empty($file)) {
  4796. print '<!-- Tab to manage permissions -->'."\n";
  4797. print '<span class="opacitymedium">';
  4798. $htmlhelp = $langs->trans("PermissionsDefDescTooltip", '{s1}');
  4799. $htmlhelp = str_replace('{s1}', '<a target="adminbis" class="nofocusvisible" href="'.DOL_URL_ROOT.'/admin/perms.php">'.$langs->trans('DefaultRights').'</a>', $htmlhelp);
  4800. print $form->textwithpicto($langs->trans("PermissionsDefDesc"), $htmlhelp, 1, 'help', '', 0, 2, 'helpondesc').'<br>';
  4801. print '</span>';
  4802. print '<br>';
  4803. print '<span class="fa fa-file-o"></span> '.$langs->trans("DescriptorFile").' : <strong class="wordbreak">'.$pathtofile.'</strong>';
  4804. print ' <a class="editfielda paddingleft paddingright" href="'.$_SERVER['PHP_SELF'].'?tab='.urlencode($tab).'&module='.$module.($forceddirread ? '@'.$dirread : '').'&action=editfile&token='.newToken().'&format=php&file='.urlencode($pathtofile).'">'.img_picto($langs->trans("Edit"), 'edit').'</a>';
  4805. print '<br>';
  4806. print '<br>';
  4807. print load_fiche_titre($langs->trans("ListOfPermissionsDefined"), '', '');
  4808. print '<!-- form to add permissions -->'."\n";
  4809. print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
  4810. print '<input type="hidden" name="token" value="'.newToken().'">';
  4811. print '<input type="hidden" name="action" value="addright">';
  4812. print '<input type="hidden" name="tab" value="permissions">';
  4813. print '<input type="hidden" name="module" value="'.dol_escape_htmltag($module).'">';
  4814. print '<input type="hidden" name="tabobj" value="'.dol_escape_htmltag($tabobj).'">';
  4815. print '<div class="div-table-responsive">';
  4816. print '<table class="noborder">';
  4817. print '<tr class="liste_titre">';
  4818. print_liste_field_titre("ID", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder, "center");
  4819. print_liste_field_titre("Object", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder, "center");
  4820. print_liste_field_titre("CRUD", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder, "center");
  4821. print_liste_field_titre("Label", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder, "center");
  4822. print_liste_field_titre("", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder, "center");
  4823. print "</tr>\n";
  4824. //form for add new right
  4825. print '<tr class="small">';
  4826. print '<td><input type="hidden" readonly name="id" class="width75" value="0"></td>';
  4827. print '<td><select class="minwidth100" name="permissionObj" id="permissionObj">';
  4828. print '<option value=""></option>';
  4829. foreach ($objects as $obj) {
  4830. if ($obj != 'myobject') {
  4831. print '<option value="'.$obj.'">'.$obj.'</option>';
  4832. }
  4833. }
  4834. print '</select></td>';
  4835. print '<td><select class="maxwidth75" name="crud" id="crud">';
  4836. print '<option value=""></option>';
  4837. foreach ($crud as $key => $val) {
  4838. print '<option value="'.$key.'">'.$langs->trans($val).'</option>';
  4839. }
  4840. print '</td>';
  4841. print '<td >';
  4842. print '<input type="text" name="label" id="label" class="minwidth200">';
  4843. print '</td>';
  4844. print '<td class="center minwidth75 tdstickyright tdstickyghostwhite">';
  4845. print '<input type="submit" class="button" name="add" value="'.$langs->trans("Add").'">';
  4846. print '</td>';
  4847. print '</tr>';
  4848. if (count($perms)) {
  4849. $i = 0;
  4850. foreach ($perms as $perm) {
  4851. $i++;
  4852. // section for editing right
  4853. if ($action == 'edit_right' && $perm[0] == (int) GETPOST('permskey', 'int')) {
  4854. print '<tr class="oddeven">';
  4855. print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST" name="modifPerms">';
  4856. print '<input type="hidden" name="token" value="'.newToken().'">';
  4857. print '<input type="hidden" name="tab" value="permissions">';
  4858. print '<input type="hidden" name="module" value="'.dol_escape_htmltag($module).'">';
  4859. print '<input type="hidden" name="tabobj" value="'.dol_escape_htmltag($tabobj).'">';
  4860. print '<input type="hidden" name="action" value="update_right">';
  4861. print '<input type="hidden" name="counter" value="'.$i.'">';
  4862. print '<input type="hidden" name="permskey" value="'.$perm[0].'">';
  4863. print '<td class="tdsticky tdstickygray">';
  4864. print '<input class="width75" type="text" readonly value="'.dol_escape_htmltag($perm[0]).'"/>';
  4865. print '</td>';
  4866. print '<td>';
  4867. print '<select name="crud">';
  4868. print '<option value="'.dol_escape_htmltag($perm[5]).'">'.$langs->trans($perm[5]).'</option>';
  4869. foreach ($crud as $i=> $x) {
  4870. if ($perm[5] != $i) {
  4871. print '<option value="'.$i.'">'.$langs->trans(ucfirst($x)).'</option>';
  4872. }
  4873. }
  4874. print '</select>';
  4875. print '</td>';
  4876. print '<td><select name="permissionObj" >';
  4877. print '<option value="'.dol_escape_htmltag($perm[4]).'">'.ucfirst($perm[4]).'</option>';
  4878. print '</select></td>';
  4879. print '<td>';
  4880. print '<input type="text" name="label" value="'.dol_escape_htmltag($perm[1]).'">';
  4881. print '</td>';
  4882. print '<td class="center minwidth75 tdstickyright tdstickyghostwhite">';
  4883. print '<input id ="modifyPerm" class="reposition button smallpaddingimp" type="submit" name="modifyright" value="'.$langs->trans("Modify").'"/>';
  4884. print '<br>';
  4885. print '<input class="reposition button button-cancel smallpaddingimp" type="submit" name="cancel" value="'.$langs->trans("Cancel").'"/>';
  4886. print '</td>';
  4887. print '</form>';
  4888. print '</tr>';
  4889. } else {
  4890. // $perm can be module->object->crud or module->crud
  4891. print '<tr class="oddeven">';
  4892. print '<td>';
  4893. print dol_escape_htmltag($perm[0]);
  4894. print '</td>';
  4895. print '<td>';
  4896. if (in_array($perm[5], array('lire', 'read', 'creer', 'write', 'effacer', 'delete'))) {
  4897. print dol_escape_htmltag(ucfirst($perm[4]));
  4898. } else {
  4899. print ''; // No particular object
  4900. }
  4901. print '</td>';
  4902. print '<td>';
  4903. if (in_array($perm[5], array('lire', 'read', 'creer', 'write', 'effacer', 'delete'))) {
  4904. print ucfirst($langs->trans($perm[5]));
  4905. } else {
  4906. print ucfirst($langs->trans($perm[4]));
  4907. }
  4908. print '</td>';
  4909. print '<td>';
  4910. print $langs->trans($perm[1]);
  4911. print '</td>';
  4912. print '<td class="center minwidth75 tdstickyright tdstickyghostwhite">';
  4913. print '<a class="editfielda reposition marginleftonly marginrighttonly paddingright paddingleft" href="'.$_SERVER["PHP_SELF"].'?action=edit_right&token='.newToken().'&permskey='.urlencode($perm[0]).'&tab='.urlencode($tab).'&module='.urlencode($module).'&tabobj='.urlencode($tabobj).'">'.img_edit().'</a>';
  4914. print '<a class="marginleftonly marginrighttonly paddingright paddingleft" href="'.$_SERVER["PHP_SELF"].'?action=deleteright&token='.newToken().'&permskey='.urlencode($i).'&tab='.urlencode($tab).'&module='.urlencode($module).'&tabobj='.urlencode($tabobj).'">'.img_delete().'</a>';
  4915. print '</td>';
  4916. print '</tr>';
  4917. }
  4918. }
  4919. } else {
  4920. print '<tr><td colspan="5"><span class="opacitymedium">'.$langs->trans("None").'</span></td></tr>';
  4921. }
  4922. print '</table>';
  4923. print '</div>';
  4924. print '</form>';
  4925. print '<script>
  4926. function updateInputField() {
  4927. value1 = $("#crud").val();
  4928. value2 = $("#permissionObj").val();
  4929. // Vérifie si les deux sélections sont faites
  4930. if (value1 && value2) {
  4931. switch(value1.toLowerCase()){
  4932. case "read":
  4933. $("#label").val("Read "+value2+" object of '.ucfirst($module).'")
  4934. break;
  4935. case "write":
  4936. $("#label").val("Create/Update "+value2+" object of '.ucfirst($module).'")
  4937. break;
  4938. case "delete":
  4939. $("#label").val("Delete "+value2+" object of '.ucfirst($module).'")
  4940. break;
  4941. default:
  4942. $("#label").val("")
  4943. }
  4944. }
  4945. }
  4946. $("#crud, #permissionObj").change(function(){
  4947. console.log("We change selection");
  4948. updateInputField();
  4949. });
  4950. </script>';
  4951. } else {
  4952. $fullpathoffile = dol_buildpath($file, 0);
  4953. $content = file_get_contents($fullpathoffile);
  4954. // New module
  4955. print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
  4956. print '<input type="hidden" name="token" value="'.newToken().'">';
  4957. print '<input type="hidden" name="action" value="savefile">';
  4958. print '<input type="hidden" name="file" value="'.dol_escape_htmltag($file).'">';
  4959. print '<input type="hidden" name="tab" value="'.$tab.'">';
  4960. print '<input type="hidden" name="module" value="'.$module.'">';
  4961. $doleditor = new DolEditor('editfilecontent', $content, '', '300', 'Full', 'In', true, false, 'ace', 0, '99%');
  4962. print $doleditor->Create(1, '', false, $langs->trans("File").' : '.$file, (GETPOST('format', 'aZ09') ?GETPOST('format', 'aZ09') : 'html'));
  4963. print '<br>';
  4964. print '<center>';
  4965. print '<input type="submit" class="button buttonforacesave button-save" id="savefile" name="savefile" value="'.dol_escape_htmltag($langs->trans("Save")).'">';
  4966. print ' &nbsp; ';
  4967. print '<input type="submit" class="button button-cancel" name="cancel" value="'.dol_escape_htmltag($langs->trans("Cancel")).'">';
  4968. print '</center>';
  4969. print '</form>';
  4970. }
  4971. }
  4972. if ($tab == 'hooks') {
  4973. print '<!-- tab=hooks -->'."\n";
  4974. if ($action != 'editfile' || empty($file)) {
  4975. print '<span class="opacitymedium">'.$langs->trans("HooksDefDesc").'</span><br>';
  4976. print '<br>';
  4977. print '<table>';
  4978. $pathtofile = $listofmodules[strtolower($module)]['moduledescriptorrelpath'];
  4979. print '<tr><td>';
  4980. print '<span class="fa fa-file-o"></span> '.$langs->trans("DescriptorFile").' : <strong class="wordbreak">'.$pathtofile.'</strong>';
  4981. print '</td><td>';
  4982. print '<a class="editfielda paddingleft paddingright" href="'.$_SERVER['PHP_SELF'].'?tab='.urlencode($tab).'&module='.$module.($forceddirread ? '@'.$dirread : '').'&action=editfile&token='.newToken().'&format=php&file='.urlencode($pathtofile).'">'.img_picto($langs->trans("Edit"), 'edit').'</a>';
  4983. print '</td></tr>';
  4984. print '<tr><td>';
  4985. $pathtohook = strtolower($module).'/class/actions_'.strtolower($module).'.class.php';
  4986. print '<span class="fa fa-file-o"></span> '.$langs->trans("HooksFile").' : ';
  4987. if (dol_is_file($dirins.'/'.$pathtohook)) {
  4988. print '<strong class="wordbreak">'.$pathtohook.'</strong>';
  4989. print '</td>';
  4990. print '<td><a class="editfielda paddingleft paddingright" href="'.$_SERVER['PHP_SELF'].'?tab='.urlencode($tab).'&module='.$module.($forceddirread ? '@'.$dirread : '').'&action=editfile&token='.newToken().'&format=php&file='.urlencode($pathtohook).'">'.img_picto($langs->trans("Edit"), 'edit').'</a> ';
  4991. print '<a class="editfielda" href="'.$_SERVER['PHP_SELF'].'?tab='.urlencode($tab).'&module='.$module.($forceddirread ? '@'.$dirread : '').'&action=confirm_removefile&token='.newToken().'&file='.urlencode($pathtohook).'">'.img_picto($langs->trans("Delete"), 'delete').'</a></td>';
  4992. } else {
  4993. print '<span class="opacitymedium">'.$langs->trans("FileNotYetGenerated").'</span>';
  4994. print '<a href="'.$_SERVER['PHP_SELF'].'?tab='.urlencode($tab).'&module='.$module.($forceddirread ? '@'.$dirread : '').'&action=inithook&format=php&file='.urlencode($pathtohook).'">'.img_picto('Generate', 'generate', 'class="paddingleft"').'</td>';
  4995. print '<td></td>';
  4996. }
  4997. print '</tr>';
  4998. } else {
  4999. $fullpathoffile = dol_buildpath($file, 0);
  5000. $content = file_get_contents($fullpathoffile);
  5001. // New module
  5002. print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
  5003. print '<input type="hidden" name="token" value="'.newToken().'">';
  5004. print '<input type="hidden" name="action" value="savefile">';
  5005. print '<input type="hidden" name="file" value="'.dol_escape_htmltag($file).'">';
  5006. print '<input type="hidden" name="tab" value="'.$tab.'">';
  5007. print '<input type="hidden" name="module" value="'.$module.'">';
  5008. $doleditor = new DolEditor('editfilecontent', $content, '', '300', 'Full', 'In', true, false, 'ace', 0, '99%');
  5009. print $doleditor->Create(1, '', false, $langs->trans("File").' : '.$file, (GETPOST('format', 'aZ09') ?GETPOST('format', 'aZ09') : 'html'));
  5010. print '<br>';
  5011. print '<center>';
  5012. print '<input type="submit" class="button buttonforacesave button-save" id="savefile" name="savefile" value="'.dol_escape_htmltag($langs->trans("Save")).'">';
  5013. print ' &nbsp; ';
  5014. print '<input type="submit" class="button button-cancel" name="cancel" value="'.dol_escape_htmltag($langs->trans("Cancel")).'">';
  5015. print '</center>';
  5016. print '</form>';
  5017. }
  5018. }
  5019. if ($tab == 'triggers') {
  5020. print '<!-- tab=triggers -->'."\n";
  5021. require_once DOL_DOCUMENT_ROOT.'/core/class/interfaces.class.php';
  5022. $interfaces = new Interfaces($db);
  5023. $triggers = $interfaces->getTriggersList(array('/'.strtolower($module).'/core/triggers'));
  5024. if ($action != 'editfile' || empty($file)) {
  5025. print '<span class="opacitymedium">'.$langs->trans("TriggerDefDesc").'</span><br>';
  5026. print '<br>';
  5027. print '<table>';
  5028. $pathtofile = $listofmodules[strtolower($module)]['moduledescriptorrelpath'];
  5029. print '<tr><td>';
  5030. print '<span class="fa fa-file-o"></span> '.$langs->trans("DescriptorFile").' : <strong class="wordbreak">'.$pathtofile.'</strong>';
  5031. print '</td><td>';
  5032. print '<a class="editfielda paddingleft paddingright" href="'.$_SERVER['PHP_SELF'].'?tab='.urlencode($tab).'&module='.$module.($forceddirread ? '@'.$dirread : '').'&action=editfile&token='.newToken().'&format=php&file='.urlencode($pathtofile).'">'.img_picto($langs->trans("Edit"), 'edit').'</a>';
  5033. print '</td></tr>';
  5034. if (!empty($triggers)) {
  5035. foreach ($triggers as $trigger) {
  5036. $pathtofile = $trigger['relpath'];
  5037. print '<tr><td>';
  5038. print '<span class="fa fa-file-o"></span> '.$langs->trans("TriggersFile").' : <strong class="wordbreak">'.$pathtofile.'</strong>';
  5039. print '</td><td><a class="editfielda paddingleft paddingright" href="'.$_SERVER['PHP_SELF'].'?tab='.urlencode($tab).'&module='.$module.($forceddirread ? '@'.$dirread : '').'&action=editfile&token='.newToken().'&format=php&file='.urlencode($pathtofile).'">'.img_picto($langs->trans("Edit"), 'edit').'</a></td>';
  5040. print '<td><a class="editfielda" href="'.$_SERVER['PHP_SELF'].'?tab='.urlencode($tab).'&module='.$module.($forceddirread ? '@'.$dirread : '').'&action=confirm_removefile&token='.newToken().'&file='.urlencode($pathtofile).'">'.img_picto($langs->trans("Delete"), 'delete').'</a></td>';
  5041. print '</tr>';
  5042. }
  5043. } else {
  5044. print '<tr><td>';
  5045. print '<span class="fa fa-file-o"></span> '.$langs->trans("TriggersFile");
  5046. print ' : <span class="opacitymedium">'.$langs->trans("FileNotYetGenerated").'</span>';
  5047. print '<a href="'.$_SERVER['PHP_SELF'].'?tab='.urlencode($tab).'&module='.$module.($forceddirread ? '@'.$dirread : '').'&action=inittrigger&format=php">'.img_picto('Generate', 'generate', 'class="paddingleft"').'</a></td>';
  5048. print '<td></td>';
  5049. print '</tr>';
  5050. }
  5051. print '</table>';
  5052. } else {
  5053. $fullpathoffile = dol_buildpath($file, 0);
  5054. $content = file_get_contents($fullpathoffile);
  5055. // New module
  5056. print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
  5057. print '<input type="hidden" name="token" value="'.newToken().'">';
  5058. print '<input type="hidden" name="action" value="savefile">';
  5059. print '<input type="hidden" name="file" value="'.dol_escape_htmltag($file).'">';
  5060. print '<input type="hidden" name="tab" value="'.$tab.'">';
  5061. print '<input type="hidden" name="module" value="'.$module.'">';
  5062. $doleditor = new DolEditor('editfilecontent', $content, '', '300', 'Full', 'In', true, false, 'ace', 0, '99%');
  5063. print $doleditor->Create(1, '', false, $langs->trans("File").' : '.$file, (GETPOST('format', 'aZ09') ?GETPOST('format', 'aZ09') : 'html'));
  5064. print '<br>';
  5065. print '<center>';
  5066. print '<input type="submit" class="button buttonforacesave button-save" id="savefile" name="savefile" value="'.dol_escape_htmltag($langs->trans("Save")).'">';
  5067. print ' &nbsp; ';
  5068. print '<input type="submit" class="button button-cancel" name="cancel" value="'.dol_escape_htmltag($langs->trans("Cancel")).'">';
  5069. print '</center>';
  5070. print '</form>';
  5071. }
  5072. }
  5073. if ($tab == 'css') {
  5074. print '<!-- tab=css -->'."\n";
  5075. if ($action != 'editfile' || empty($file)) {
  5076. print '<span class="opacitymedium">'.$langs->trans("CSSDesc").'</span><br>';
  5077. print '<br>';
  5078. print '<table>';
  5079. print '<tr><td>';
  5080. $pathtohook = strtolower($module).'/css/'.strtolower($module).'.css.php';
  5081. print '<span class="fa fa-file-o"></span> '.$langs->trans("CSSFile").' : ';
  5082. if (dol_is_file($dirins.'/'.$pathtohook)) {
  5083. print '<strong class="wordbreak">'.$pathtohook.'</strong>';
  5084. print '</td><td><a class="editfielda paddingleft paddingright" href="'.$_SERVER['PHP_SELF'].'?tab='.urlencode($tab).'&module='.$module.($forceddirread ? '@'.$dirread : '').'&action=editfile&token='.newToken().'&format=php&file='.urlencode($pathtohook).'">'.img_picto($langs->trans("Edit"), 'edit').'</a></td>';
  5085. print '</td><td><a class="editfielda" href="'.$_SERVER['PHP_SELF'].'?tab='.urlencode($tab).'&module='.$module.($forceddirread ? '@'.$dirread : '').'&action=confirm_removefile&token='.newToken().'&format='.$format.'&file='.urlencode($pathtohook).'">'.img_picto($langs->trans("Delete"), 'delete').'</a></td>';
  5086. } else {
  5087. print '<span class="opacitymedium">'.$langs->trans("FileNotYetGenerated").'</span>';
  5088. print '</td><td><a href="'.$_SERVER['PHP_SELF'].'?tab='.urlencode($tab).'&module='.$module.($forceddirread ? '@'.$dirread : '').'&action=initcss&format=php&file='.urlencode($pathtohook).'">'.img_picto('Generate', 'generate', 'class="paddingleft"').'</a></td>';
  5089. }
  5090. print '</tr>';
  5091. } else {
  5092. $fullpathoffile = dol_buildpath($file, 0);
  5093. $content = file_get_contents($fullpathoffile);
  5094. // New module
  5095. print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
  5096. print '<input type="hidden" name="token" value="'.newToken().'">';
  5097. print '<input type="hidden" name="action" value="savefile">';
  5098. print '<input type="hidden" name="file" value="'.dol_escape_htmltag($file).'">';
  5099. print '<input type="hidden" name="tab" value="'.$tab.'">';
  5100. print '<input type="hidden" name="module" value="'.$module.'">';
  5101. $doleditor = new DolEditor('editfilecontent', $content, '', '300', 'Full', 'In', true, false, 'ace', 0, '99%');
  5102. print $doleditor->Create(1, '', false, $langs->trans("File").' : '.$file, (GETPOST('format', 'aZ09') ?GETPOST('format', 'aZ09') : 'html'));
  5103. print '<br>';
  5104. print '<center>';
  5105. print '<input type="submit" class="button buttonforacesave button-save" id="savefile" name="savefile" value="'.dol_escape_htmltag($langs->trans("Save")).'">';
  5106. print ' &nbsp; ';
  5107. print '<input type="submit" class="button button-cancel" name="cancel" value="'.dol_escape_htmltag($langs->trans("Cancel")).'">';
  5108. print '</center>';
  5109. print '</form>';
  5110. }
  5111. }
  5112. if ($tab == 'js') {
  5113. print '<!-- tab=js -->'."\n";
  5114. if ($action != 'editfile' || empty($file)) {
  5115. print '<span class="opacitymedium">'.$langs->trans("JSDesc").'</span><br>';
  5116. print '<br>';
  5117. print '<table>';
  5118. print '<tr><td>';
  5119. $pathtohook = strtolower($module).'/js/'.strtolower($module).'.js.php';
  5120. print '<span class="fa fa-file-o"></span> '.$langs->trans("JSFile").' : ';
  5121. if (dol_is_file($dirins.'/'.$pathtohook)) {
  5122. print '<strong class="wordbreak">'.$pathtohook.'</strong>';
  5123. print '</td><td><a class="editfielda paddingleft paddingright" href="'.$_SERVER['PHP_SELF'].'?tab='.urlencode($tab).'&module='.$module.($forceddirread ? '@'.$dirread : '').'&action=editfile&token='.newToken().'&format=php&file='.urlencode($pathtohook).'">'.img_picto($langs->trans("Edit"), 'edit').'</a></td>';
  5124. print '</td><td><a class="editfielda" href="'.$_SERVER['PHP_SELF'].'?tab='.urlencode($tab).'&module='.$module.($forceddirread ? '@'.$dirread : '').'&action=confirm_removefile&token='.newToken().'&file='.urlencode($pathtohook).'">'.img_picto($langs->trans("Delete"), 'delete').'</a></td>';
  5125. } else {
  5126. print '<span class="opacitymedium">'.$langs->trans("FileNotYetGenerated").'</span>';
  5127. print '</td><td><a href="'.$_SERVER['PHP_SELF'].'?tab='.urlencode($tab).'&module='.$module.($forceddirread ? '@'.$dirread : '').'&action=initjs&token='.newToken().'&format=php&file='.urlencode($pathtohook).'">'.img_picto('Generate', 'generate', 'class="paddingleft"').'</a></td>';
  5128. }
  5129. print '</tr>';
  5130. } else {
  5131. $fullpathoffile = dol_buildpath($file, 0);
  5132. $content = file_get_contents($fullpathoffile);
  5133. // New module
  5134. print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
  5135. print '<input type="hidden" name="token" value="'.newToken().'">';
  5136. print '<input type="hidden" name="action" value="savefile">';
  5137. print '<input type="hidden" name="file" value="'.dol_escape_htmltag($file).'">';
  5138. print '<input type="hidden" name="tab" value="'.$tab.'">';
  5139. print '<input type="hidden" name="module" value="'.$module.'">';
  5140. $doleditor = new DolEditor('editfilecontent', $content, '', '300', 'Full', 'In', true, false, 'ace', 0, '99%');
  5141. print $doleditor->Create(1, '', false, $langs->trans("File").' : '.$file, (GETPOST('format', 'aZ09') ?GETPOST('format', 'aZ09') : 'html'));
  5142. print '<br>';
  5143. print '<center>';
  5144. print '<input type="submit" class="button buttonforacesave button-save" id="savefile" name="savefile" value="'.dol_escape_htmltag($langs->trans("Save")).'">';
  5145. print ' &nbsp; ';
  5146. print '<input type="submit" class="button button-cancel" name="cancel" value="'.dol_escape_htmltag($langs->trans("Cancel")).'">';
  5147. print '</center>';
  5148. print '</form>';
  5149. }
  5150. }
  5151. if ($tab == 'widgets') {
  5152. print '<!-- tab=widgets -->'."\n";
  5153. require_once DOL_DOCUMENT_ROOT.'/core/boxes/modules_boxes.php';
  5154. $widgets = ModeleBoxes::getWidgetsList(array('/'.strtolower($module).'/core/boxes'));
  5155. if ($action != 'editfile' || empty($file)) {
  5156. print '<span class="opacitymedium">'.$langs->trans("WidgetDesc").'</span><br>';
  5157. print '<br>';
  5158. print '<table>';
  5159. if (!empty($widgets)) {
  5160. foreach ($widgets as $widget) {
  5161. $pathtofile = $widget['relpath'];
  5162. print '<tr><td><span class="fa fa-file-o"></span> '.$langs->trans("WidgetFile").' : <strong class="wordbreak">'.$pathtofile.'</strong>';
  5163. print '</td><td><a class="editfielda paddingleft paddingright" href="'.$_SERVER['PHP_SELF'].'?tab='.urlencode($tab).'&module='.$module.($forceddirread ? '@'.$dirread : '').'&action=editfile&token='.newToken().'&format=php&file='.urlencode($pathtofile).'">'.img_picto($langs->trans("Edit"), 'edit').'</a>';
  5164. print '</td><td><a class="editfielda" href="'.$_SERVER['PHP_SELF'].'?tab='.urlencode($tab).'&module='.$module.($forceddirread ? '@'.$dirread : '').'&action=confirm_removefile&token='.newToken().'&file='.urlencode($pathtofile).'">'.img_picto($langs->trans("Delete"), 'delete').'</a></td>';
  5165. print '</tr>';
  5166. }
  5167. } else {
  5168. print '<tr><td><span class="fa fa-file-o"></span> '.$langs->trans("WidgetFile").' : <span class="opacitymedium">'.$langs->trans("NoWidget").'</span>';
  5169. print '</td><td><a href="'.$_SERVER['PHP_SELF'].'?tab='.urlencode($tab).'&module='.$module.($forceddirread ? '@'.$dirread : '').'&action=initwidget&token='.newToken().'&format=php">'.img_picto('Generate', 'generate', 'class="paddingleft"').'</a>';
  5170. print '</td></tr>';
  5171. }
  5172. print '</table>';
  5173. } else {
  5174. $fullpathoffile = dol_buildpath($file, 0);
  5175. $content = file_get_contents($fullpathoffile);
  5176. // New module
  5177. print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
  5178. print '<input type="hidden" name="token" value="'.newToken().'">';
  5179. print '<input type="hidden" name="action" value="savefile">';
  5180. print '<input type="hidden" name="file" value="'.dol_escape_htmltag($file).'">';
  5181. print '<input type="hidden" name="tab" value="'.$tab.'">';
  5182. print '<input type="hidden" name="module" value="'.$module.'">';
  5183. $doleditor = new DolEditor('editfilecontent', $content, '', '300', 'Full', 'In', true, false, 'ace', 0, '99%');
  5184. print $doleditor->Create(1, '', false, $langs->trans("File").' : '.$file, (GETPOST('format', 'aZ09') ?GETPOST('format', 'aZ09') : 'html'));
  5185. print '<br>';
  5186. print '<center>';
  5187. print '<input type="submit" class="button buttonforacesave button-save" id="savefile" name="savefile" value="'.dol_escape_htmltag($langs->trans("Save")).'">';
  5188. print ' &nbsp; ';
  5189. print '<input type="submit" class="button button-cancel" name="cancel" value="'.dol_escape_htmltag($langs->trans("Cancel")).'">';
  5190. print '</center>';
  5191. print '</form>';
  5192. }
  5193. }
  5194. if ($tab == 'exportimport') {
  5195. print '<!-- tab=exportimport -->'."\n";
  5196. $pathtofile = $listofmodules[strtolower($module)]['moduledescriptorrelpath'];
  5197. $exportlist = $moduleobj->export_label;
  5198. $importlist = $moduleobj->import_label;
  5199. if ($action != 'editfile' || empty($file)) {
  5200. print '<span class="opacitymedium">'.$langs->transnoentities('ImportExportProfiles').'</span><br>';
  5201. print '<br>';
  5202. print '<span class="fa fa-file-o"></span> '.$langs->trans("DescriptorFile").' : <strong class="wordbreak">'.$pathtofile.'</strong>';
  5203. print ' <a class="editfielda paddingleft paddingright" href="'.$_SERVER['PHP_SELF'].'?tab='.urlencode($tab).'&module='.$module.($forceddirread ? '@'.$dirread : '').'&action=editfile&token='.newToken().'&format=php&file='.urlencode($pathtofile).'">'.img_picto($langs->trans("Edit"), 'edit').'</a>';
  5204. print '<br>';
  5205. } else {
  5206. $fullpathoffile = dol_buildpath($file, 0);
  5207. $content = file_get_contents($fullpathoffile);
  5208. // New module
  5209. print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
  5210. print '<input type="hidden" name="token" value="'.newToken().'">';
  5211. print '<input type="hidden" name="action" value="savefile">';
  5212. print '<input type="hidden" name="file" value="'.dol_escape_htmltag($file).'">';
  5213. print '<input type="hidden" name="tab" value="'.$tab.'">';
  5214. print '<input type="hidden" name="module" value="'.$module.'">';
  5215. $doleditor = new DolEditor('editfilecontent', $content, '', '300', 'Full', 'In', true, false, 'ace', 0, '99%');
  5216. print $doleditor->Create(1, '', false, $langs->trans("File").' : '.$file, (GETPOST('format', 'aZ09') ?GETPOST('format', 'aZ09') : 'html'));
  5217. print '<br>';
  5218. print '<center>';
  5219. print '<input type="submit" class="button buttonforacesave button-save" id="savefile" name="savefile" value="'.dol_escape_htmltag($langs->trans("Save")).'">';
  5220. print ' &nbsp; ';
  5221. print '<input type="submit" class="button button-cancel" name="cancel" value="'.dol_escape_htmltag($langs->trans("Cancel")).'">';
  5222. print '</center>';
  5223. print '</form>';
  5224. }
  5225. }
  5226. if ($tab == 'cli') {
  5227. print '<!-- tab=cli -->'."\n";
  5228. $clifiles = array();
  5229. $i = 0;
  5230. $dircli = array('/'.strtolower($module).'/scripts');
  5231. foreach ($dircli as $reldir) {
  5232. $dir = dol_buildpath($reldir, 0);
  5233. $newdir = dol_osencode($dir);
  5234. // Check if directory exists (we do not use dol_is_dir to avoid loading files.lib.php at each call)
  5235. if (!is_dir($newdir)) {
  5236. continue;
  5237. }
  5238. $handle = opendir($newdir);
  5239. if (is_resource($handle)) {
  5240. while (($tmpfile = readdir($handle)) !== false) {
  5241. if (is_readable($newdir.'/'.$tmpfile) && preg_match('/^(.+)\.php/', $tmpfile, $reg)) {
  5242. if (preg_match('/\.back$/', $tmpfile)) {
  5243. continue;
  5244. }
  5245. $clifiles[$i]['relpath'] = preg_replace('/^\//', '', $reldir).'/'.$tmpfile;
  5246. $i++;
  5247. }
  5248. }
  5249. closedir($handle);
  5250. }
  5251. }
  5252. if ($action != 'editfile' || empty($file)) {
  5253. print '<span class="opacitymedium">'.$langs->trans("CLIDesc").'</span><br>';
  5254. print '<br>';
  5255. print '<table>';
  5256. if (!empty($clifiles)) {
  5257. foreach ($clifiles as $clifile) {
  5258. $pathtofile = $clifile['relpath'];
  5259. print '<tr><td><span class="fa fa-file-o"></span> '.$langs->trans("CLIFile").' : <strong class="wordbreak">'.$pathtofile.'</strong>';
  5260. print '</td><td><a class="editfielda" href="'.$_SERVER['PHP_SELF'].'?tab='.urlencode($tab).'&module='.$module.($forceddirread ? '@'.$dirread : '').'&action=editfile&token='.newToken().'&format=php&file='.urlencode($pathtofile).'">'.img_picto($langs->trans("Edit"), 'edit').'</a></td>';
  5261. print '<td><a class="editfielda" href="'.$_SERVER['PHP_SELF'].'?tab='.urlencode($tab).'&module='.$module.($forceddirread ? '@'.$dirread : '').'&action=confirm_removefile&token='.newToken().'&file='.urlencode($pathtofile).'">'.img_picto($langs->trans("Delete"), 'delete').'</a></td>';
  5262. print '</tr>';
  5263. }
  5264. } else {
  5265. print '<tr><td><span class="fa fa-file-o"></span> '.$langs->trans("CLIFile").' : <span class="opacitymedium">'.$langs->trans("FileNotYetGenerated"); '</span>';
  5266. print '</td><td><a href="'.$_SERVER['PHP_SELF'].'?tab='.urlencode($tab).'&module='.$module.($forceddirread ? '@'.$dirread : '').'&action=initcli&token='.newToken().'&format=php">'.img_picto('Generate', 'generate', 'class="paddingleft"').'</a>';
  5267. print '</td></tr>';
  5268. }
  5269. print '</table>';
  5270. } else {
  5271. $fullpathoffile = dol_buildpath($file, 0);
  5272. $content = file_get_contents($fullpathoffile);
  5273. // New module
  5274. print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
  5275. print '<input type="hidden" name="token" value="'.newToken().'">';
  5276. print '<input type="hidden" name="action" value="savefile">';
  5277. print '<input type="hidden" name="file" value="'.dol_escape_htmltag($file).'">';
  5278. print '<input type="hidden" name="tab" value="'.$tab.'">';
  5279. print '<input type="hidden" name="module" value="'.$module.'">';
  5280. $doleditor = new DolEditor('editfilecontent', $content, '', '300', 'Full', 'In', true, false, 'ace', 0, '99%');
  5281. print $doleditor->Create(1, '', false, $langs->trans("File").' : '.$file, (GETPOST('format', 'aZ09') ?GETPOST('format', 'aZ09') : 'html'));
  5282. print '<br>';
  5283. print '<center>';
  5284. print '<input type="submit" class="button buttonforacesave button-save" id="savefile" name="savefile" value="'.dol_escape_htmltag($langs->trans("Save")).'">';
  5285. print ' &nbsp; ';
  5286. print '<input type="submit" class="button button-cancel" name="cancel" value="'.dol_escape_htmltag($langs->trans("Cancel")).'">';
  5287. print '</center>';
  5288. print '</form>';
  5289. }
  5290. }
  5291. if ($tab == 'cron') {
  5292. print '<!-- tab=cron -->'."\n";
  5293. $pathtofile = $listofmodules[strtolower($module)]['moduledescriptorrelpath'];
  5294. $cronjobs = $moduleobj->cronjobs;
  5295. if ($action != 'editfile' || empty($file)) {
  5296. print '<span class="opacitymedium">'.str_replace('{s1}', '<a target="adminbis" class="nofocusvisible" href="'.DOL_URL_ROOT.'/cron/list.php">'.$langs->transnoentities('CronList').'</a>', $langs->trans("CronJobDefDesc", '{s1}')).'</span><br>';
  5297. print '<br>';
  5298. print '<span class="fa fa-file-o"></span> '.$langs->trans("DescriptorFile").' : <strong class="wordbreak">'.$pathtofile.'</strong>';
  5299. print ' <a class="editfielda paddingleft paddingright" href="'.$_SERVER['PHP_SELF'].'?tab='.urlencode($tab).'&module='.$module.($forceddirread ? '@'.$dirread : '').'&action=editfile&token='.newToken().'&format=php&file='.urlencode($pathtofile).'">'.img_picto($langs->trans("Edit"), 'edit').'</a>';
  5300. print '<br>';
  5301. print '<br>';
  5302. print load_fiche_titre($langs->trans("CronJobProfiles"), '', '');
  5303. print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
  5304. print '<input type="hidden" name="token" value="'.newToken().'">';
  5305. print '<input type="hidden" name="action" value="addproperty">';
  5306. print '<input type="hidden" name="tab" value="objects">';
  5307. print '<input type="hidden" name="module" value="'.dol_escape_htmltag($module).'">';
  5308. print '<input type="hidden" name="tabobj" value="'.dol_escape_htmltag($tabobj).'">';
  5309. print '<div class="div-table-responsive">';
  5310. print '<table class="noborder">';
  5311. print '<tr class="liste_titre">';
  5312. print_liste_field_titre("CronLabel", $_SERVER["PHP_SELF"], "", "", $param, '', $sortfield, $sortorder);
  5313. print_liste_field_titre("CronTask", '', '', "", $param, '', $sortfield, $sortorder);
  5314. print_liste_field_titre("CronFrequency", '', "", "", $param, '', $sortfield, $sortorder);
  5315. print_liste_field_titre("StatusAtInstall", $_SERVER["PHP_SELF"], "", "", $param, '', $sortfield, $sortorder);
  5316. print_liste_field_titre("Comment", $_SERVER["PHP_SELF"], "", "", $param, '', $sortfield, $sortorder);
  5317. print "</tr>\n";
  5318. if (count($cronjobs)) {
  5319. foreach ($cronjobs as $cron) {
  5320. print '<tr class="oddeven">';
  5321. print '<td>';
  5322. print $cron['label'];
  5323. print '</td>';
  5324. print '<td>';
  5325. if ($cron['jobtype'] == 'method') {
  5326. $text = $langs->trans("CronClass");
  5327. $texttoshow = $langs->trans('CronModule').': '.$module.'<br>';
  5328. $texttoshow .= $langs->trans('CronClass').': '.$cron['class'].'<br>';
  5329. $texttoshow .= $langs->trans('CronObject').': '.$cron['objectname'].'<br>';
  5330. $texttoshow .= $langs->trans('CronMethod').': '.$cron['method'];
  5331. $texttoshow .= '<br>'.$langs->trans('CronArgs').': '.$cron['parameters'];
  5332. $texttoshow .= '<br>'.$langs->trans('Comment').': '.$langs->trans($cron['comment']);
  5333. } elseif ($cron['jobtype'] == 'command') {
  5334. $text = $langs->trans('CronCommand');
  5335. $texttoshow = $langs->trans('CronCommand').': '.dol_trunc($cron['command']);
  5336. $texttoshow .= '<br>'.$langs->trans('CronArgs').': '.$cron['parameters'];
  5337. $texttoshow .= '<br>'.$langs->trans('Comment').': '.$langs->trans($cron['comment']);
  5338. }
  5339. print $form->textwithpicto($text, $texttoshow, 1);
  5340. print '</td>';
  5341. print '<td>';
  5342. if ($cron['unitfrequency'] == "60") {
  5343. print $langs->trans('CronEach')." ".($cron['frequency'])." ".$langs->trans('Minutes');
  5344. }
  5345. if ($cron['unitfrequency'] == "3600") {
  5346. print $langs->trans('CronEach')." ".($cron['frequency'])." ".$langs->trans('Hours');
  5347. }
  5348. if ($cron['unitfrequency'] == "86400") {
  5349. print $langs->trans('CronEach')." ".($cron['frequency'])." ".$langs->trans('Days');
  5350. }
  5351. if ($cron['unitfrequency'] == "604800") {
  5352. print $langs->trans('CronEach')." ".($cron['frequency'])." ".$langs->trans('Weeks');
  5353. }
  5354. print '</td>';
  5355. print '<td>';
  5356. print $cron['status'];
  5357. print '</td>';
  5358. print '<td>';
  5359. if (!empty($cron['comment'])) {
  5360. print $cron['comment'];
  5361. }
  5362. print '</td>';
  5363. print '</tr>';
  5364. }
  5365. } else {
  5366. print '<tr><td colspan="5"><span class="opacitymedium">'.$langs->trans("None").'</span></td></tr>';
  5367. }
  5368. print '</table>';
  5369. print '</div>';
  5370. print '</form>';
  5371. } else {
  5372. $fullpathoffile = dol_buildpath($file, 0);
  5373. $content = file_get_contents($fullpathoffile);
  5374. // New module
  5375. print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
  5376. print '<input type="hidden" name="token" value="'.newToken().'">';
  5377. print '<input type="hidden" name="action" value="savefile">';
  5378. print '<input type="hidden" name="file" value="'.dol_escape_htmltag($file).'">';
  5379. print '<input type="hidden" name="tab" value="'.$tab.'">';
  5380. print '<input type="hidden" name="module" value="'.$module.'">';
  5381. $doleditor = new DolEditor('editfilecontent', $content, '', '300', 'Full', 'In', true, false, 'ace', 0, '99%');
  5382. print $doleditor->Create(1, '', false, $langs->trans("File").' : '.$file, (GETPOST('format', 'aZ09') ?GETPOST('format', 'aZ09') : 'html'));
  5383. print '<br>';
  5384. print '<center>';
  5385. print '<input type="submit" class="button buttonforacesave button-save" id="savefile" name="savefile" value="'.dol_escape_htmltag($langs->trans("Save")).'">';
  5386. print ' &nbsp; ';
  5387. print '<input type="submit" class="button button-cancel" name="cancel" value="'.dol_escape_htmltag($langs->trans("Cancel")).'">';
  5388. print '</center>';
  5389. print '</form>';
  5390. }
  5391. }
  5392. if ($tab == 'specifications') {
  5393. print '<!-- tab=specifications -->'."\n";
  5394. $specs = dol_dir_list(dol_buildpath($modulelowercase.'/doc', 0), 'files', 1, '(\.md|\.asciidoc)$', array('\/temp\/'));
  5395. if ($action != 'editfile' || empty($file)) {
  5396. print '<span class="opacitymedium">'.$langs->trans("SpecDefDesc").'</span><br>';
  5397. print '<br>';
  5398. print '<table>';
  5399. if (is_array($specs) && !empty($specs)) {
  5400. foreach ($specs as $spec) {
  5401. $pathtofile = $modulelowercase.'/doc/'.$spec['relativename'];
  5402. $format = 'asciidoc';
  5403. if (preg_match('/\.md$/i', $spec['name'])) {
  5404. $format = 'markdown';
  5405. }
  5406. print '<tr><td>';
  5407. print '<span class="fa fa-file-o"></span> '.$langs->trans("SpecificationFile").' : <strong class="wordbreak">'.$pathtofile.'</strong>';
  5408. print '</td><td><a class="editfielda paddingleft paddingright" href="'.$_SERVER['PHP_SELF'].'?tab='.urlencode($tab).'&module='.$module.($forceddirread ? '@'.$dirread : '').'&action=editfile&token='.newToken().'&format='.$format.'&file='.urlencode($pathtofile).'">'.img_picto($langs->trans("Edit"), 'edit').'</a></td>';
  5409. print '<td><a class="editfielda" href="'.$_SERVER['PHP_SELF'].'?tab='.urlencode($tab).'&module='.$module.($forceddirread ? '@'.$dirread : '').'&action=confirm_removefile&token='.newToken().'&format='.$format.'&file='.urlencode($pathtofile).'">'.img_picto($langs->trans("Delete"), 'delete').'</a></td>';
  5410. print '</tr>';
  5411. }
  5412. } else {
  5413. print '<tr><td>';
  5414. print '<span class="fa fa-file-o"></span> '.$langs->trans("SpecificationFile").' : <span class="opacitymedium">'.$langs->trans("FileNotYetGenerated").'</span>';
  5415. print '</td><td><a href="'.$_SERVER['PHP_SELF'].'?tab='.urlencode($tab).'&module='.$module.($forceddirread ? '@'.$dirread : '').'&action=initdoc&token='.newToken().'&format=php">'.img_picto('Generate', 'generate', 'class="paddingleft"').'</a></td>';
  5416. print '</tr>';
  5417. }
  5418. print '</table>';
  5419. } else {
  5420. // Use MD or asciidoc
  5421. //print $langs->trans("UseAsciiDocFormat").'<br>';
  5422. $fullpathoffile = dol_buildpath($file, 0);
  5423. $content = file_get_contents($fullpathoffile);
  5424. // New module
  5425. print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
  5426. print '<input type="hidden" name="token" value="'.newToken().'">';
  5427. print '<input type="hidden" name="action" value="savefile">';
  5428. print '<input type="hidden" name="file" value="'.dol_escape_htmltag($file).'">';
  5429. print '<input type="hidden" name="tab" value="'.$tab.'">';
  5430. print '<input type="hidden" name="module" value="'.$module.'">';
  5431. $doleditor = new DolEditor('editfilecontent', $content, '', '300', 'Full', 'In', true, false, 'ace', 0, '99%');
  5432. print $doleditor->Create(1, '', false, $langs->trans("File").' : '.$file, (GETPOST('format', 'aZ09') ?GETPOST('format', 'aZ09') : 'html'));
  5433. print '<br>';
  5434. print '<center>';
  5435. print '<input type="submit" class="button buttonforacesave button-save" id="savefile" name="savefile" value="'.dol_escape_htmltag($langs->trans("Save")).'">';
  5436. print ' &nbsp; ';
  5437. print '<input type="submit" class="button button-cancel" name="cancel" value="'.dol_escape_htmltag($langs->trans("Cancel")).'">';
  5438. print '</center>';
  5439. print '</form>';
  5440. }
  5441. print '<br><br><br>';
  5442. $FILENAMEDOC = $modulelowercase.'.html';
  5443. $FILENAMEDOCPDF = $modulelowercase.'.pdf';
  5444. $outputfiledoc = dol_buildpath($modulelowercase, 0).'/doc/'.$FILENAMEDOC;
  5445. $outputfiledocurl = dol_buildpath($modulelowercase, 1).'/doc/'.$FILENAMEDOC;
  5446. $outputfiledocrel = $modulelowercase.'/doc/'.$FILENAMEDOC;
  5447. $outputfiledocpdf = dol_buildpath($modulelowercase, 0).'/doc/'.$FILENAMEDOCPDF;
  5448. $outputfiledocurlpdf = dol_buildpath($modulelowercase, 1).'/doc/'.$FILENAMEDOCPDF;
  5449. $outputfiledocrelpdf = $modulelowercase.'/doc/'.$FILENAMEDOCPDF;
  5450. // HTML
  5451. print '<span class="fa fa-file-o"></span> '.$langs->trans("PathToModuleDocumentation", "HTML").' : ';
  5452. if (!dol_is_file($outputfiledoc)) {
  5453. print '<span class="opacitymedium">'.$langs->trans("FileNotYetGenerated").'</span>';
  5454. } else {
  5455. print '<strong>';
  5456. print '<a href="'.$outputfiledocurl.'" target="_blank" rel="noopener noreferrer">';
  5457. print $outputfiledoc;
  5458. print '</a>';
  5459. print '</strong>';
  5460. print ' <span class="opacitymedium">('.$langs->trans("GeneratedOn").' '.dol_print_date(dol_filemtime($outputfiledoc), 'dayhour').')</span>';
  5461. print ' <a class="editfielda" href="'.$_SERVER['PHP_SELF'].'?tab='.urlencode($tab).'&module='.$module.($forceddirread ? '@'.$dirread : '').'&action=confirm_removefile&token='.newToken().'&format='.$format.'&file='.urlencode($outputfiledocrel).'">'.img_picto($langs->trans("Delete"), 'delete').'</a>';
  5462. }
  5463. print '</strong><br>';
  5464. // PDF
  5465. print '<span class="fa fa-file-o"></span> '.$langs->trans("PathToModuleDocumentation", "PDF").' : ';
  5466. if (!dol_is_file($outputfiledocpdf)) {
  5467. print '<span class="opacitymedium">'.$langs->trans("FileNotYetGenerated").'</span>';
  5468. } else {
  5469. print '<strong>';
  5470. print '<a href="'.$outputfiledocurlpdf.'" target="_blank" rel="noopener noreferrer">';
  5471. print $outputfiledocpdf;
  5472. print '</a>';
  5473. print '</strong>';
  5474. print ' <span class="opacitymedium">('.$langs->trans("GeneratedOn").' '.dol_print_date(dol_filemtime($outputfiledocpdf), 'dayhour').')</span>';
  5475. print ' <a class="editfielda" href="'.$_SERVER['PHP_SELF'].'?tab='.urlencode($tab).'&module='.$module.($forceddirread ? '@'.$dirread : '').'&action=confirm_removefile&token='.newToken().'&format='.$format.'&file='.urlencode($outputfiledocrelpdf).'">'.img_picto($langs->trans("Delete"), 'delete').'</a>';
  5476. }
  5477. print '</strong><br>';
  5478. print '<br>';
  5479. print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST" name="generatedoc">';
  5480. print '<input type="hidden" name="token" value="'.newToken().'">';
  5481. print '<input type="hidden" name="action" value="generatedoc">';
  5482. print '<input type="hidden" name="tab" value="'.dol_escape_htmltag($tab).'">';
  5483. print '<input type="hidden" name="module" value="'.dol_escape_htmltag($module).'">';
  5484. print '<input type="submit" class="button" name="generatedoc" value="'.$langs->trans("BuildDocumentation").'"';
  5485. if (!is_array($specs) || empty($specs)) {
  5486. print ' disabled="disabled"';
  5487. }
  5488. print '>';
  5489. print '</form>';
  5490. }
  5491. if ($tab == 'buildpackage') {
  5492. print '<!-- tab=buildpackage -->'."\n";
  5493. print '<span class="opacitymedium">'.$langs->trans("BuildPackageDesc").'</span>';
  5494. print '<br>';
  5495. if (!class_exists('ZipArchive') && !defined('ODTPHP_PATHTOPCLZIP')) {
  5496. print img_warning().' '.$langs->trans("ErrNoZipEngine");
  5497. print '<br>';
  5498. }
  5499. $modulelowercase = strtolower($module);
  5500. // Zip file to build
  5501. $FILENAMEZIP = '';
  5502. // Load module
  5503. $pathtofile = $listofmodules[strtolower($module)]['moduledescriptorrelpath'];
  5504. dol_include_once($pathtofile);
  5505. $class = 'mod'.$module;
  5506. if (class_exists($class)) {
  5507. try {
  5508. $moduleobj = new $class($db);
  5509. } catch (Exception $e) {
  5510. $error++;
  5511. dol_print_error($db, $e->getMessage());
  5512. }
  5513. } else {
  5514. $error++;
  5515. $langs->load("errors");
  5516. dol_print_error($db, $langs->trans("ErrorFailedToLoadModuleDescriptorForXXX", $module));
  5517. exit;
  5518. }
  5519. $arrayversion = explode('.', $moduleobj->version, 3);
  5520. if (count($arrayversion)) {
  5521. $FILENAMEZIP = "module_".$modulelowercase.'-'.$arrayversion[0].(empty($arrayversion[1]) ? '.0' : '.'.$arrayversion[1]).(empty($arrayversion[2]) ? '' : ".".$arrayversion[2]).".zip";
  5522. $outputfilezip = dol_buildpath($modulelowercase, 0).'/bin/'.$FILENAMEZIP;
  5523. }
  5524. print '<br>';
  5525. print '<span class="fa fa-file-o"></span> '.$langs->trans("PathToModulePackage").' : ';
  5526. if (!dol_is_file($outputfilezip)) {
  5527. print '<span class="opacitymedium">'.$langs->trans("FileNotYetGenerated").'</span>';
  5528. } else {
  5529. $relativepath = $modulelowercase.'/bin/'.$FILENAMEZIP;
  5530. print '<strong><a href="'.DOL_URL_ROOT.'/document.php?modulepart=packages&file='.urlencode($relativepath).'">'.$outputfilezip.'</a></strong>';
  5531. print ' <span class="opacitymedium">('.$langs->trans("GeneratedOn").' '.dol_print_date(dol_filemtime($outputfilezip), 'dayhour').')</span>';
  5532. print ' <a class="editfielda" href="'.$_SERVER['PHP_SELF'].'?tab='.urlencode($tab).'&module='.$module.($forceddirread ? '@'.$dirread : '').'&action=confirm_removefile&token='.newToken().'&file='.urlencode($relativepath).'">'.img_picto($langs->trans("Delete"), 'delete').'</a>';
  5533. }
  5534. print '</strong>';
  5535. print '<br>';
  5536. print '<br>';
  5537. print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST" name="generatepackage">';
  5538. print '<input type="hidden" name="token" value="'.newToken().'">';
  5539. print '<input type="hidden" name="action" value="generatepackage">';
  5540. print '<input type="hidden" name="tab" value="'.dol_escape_htmltag($tab).'">';
  5541. print '<input type="hidden" name="module" value="'.dol_escape_htmltag($module).'">';
  5542. print '<input type="submit" class="button" name="generatepackage" value="'.$langs->trans("BuildPackage").'">';
  5543. print '</form>';
  5544. }
  5545. if ($tab == 'tabs') {
  5546. $pathtofile = $listofmodules[strtolower($module)]['moduledescriptorrelpath'];
  5547. $tabs = $moduleobj->tabs;
  5548. if ($action != 'editfile' || empty($file)) {
  5549. print '<span class="opacitymedium">';
  5550. $htmlhelp = $langs->trans("TabsDefDescTooltip", '{s1}');
  5551. $htmlhelp = str_replace('{s1}', '<a target="adminbis" class="nofocusvisible" href="'.DOL_URL_ROOT.'/admin/menus/index.php">'.$langs->trans('Setup').' - '.$langs->trans('Tabs').'</a>', $htmlhelp);
  5552. print $form->textwithpicto($langs->trans("TabsDefDesc"), $htmlhelp, 1, 'help', '', 0, 2, 'helpondesc').'<br>';
  5553. print '</span>';
  5554. print '<br>';
  5555. print '<span class="fa fa-file-o"></span> '.$langs->trans("DescriptorFile").' : <strong>'.$pathtofile.'</strong>';
  5556. print ' <a class="editfielda paddingleft paddingright" href="'.$_SERVER['PHP_SELF'].'?tab='.urlencode($tab).'&module='.$module.($forceddirread ? '@'.$dirread : '').'&action=editfile&format=php&file='.urlencode($pathtofile).'">'.img_picto($langs->trans("Edit"), 'edit').'</a>';
  5557. print '<br>';
  5558. print '<br>';
  5559. print load_fiche_titre($langs->trans("ListOfTabsEntries"), '', '');
  5560. print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
  5561. print '<input type="hidden" name="token" value="'.newToken().'">';
  5562. print '<input type="hidden" name="action" value="addproperty">';
  5563. print '<input type="hidden" name="tab" value="objects">';
  5564. print '<input type="hidden" name="module" value="'.dol_escape_htmltag($module).'">';
  5565. print '<input type="hidden" name="tabobj" value="'.dol_escape_htmltag($tabobj).'">';
  5566. print '<div class="div-table-responsive">';
  5567. print '<table class="noborder small">';
  5568. print '<tr class="liste_titre">';
  5569. print_liste_field_titre("ObjectType", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder);
  5570. print_liste_field_titre("Tab", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder);
  5571. print_liste_field_titre("Title", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder);
  5572. print_liste_field_titre("LangFile", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder);
  5573. print_liste_field_titre("Condition", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder);
  5574. print_liste_field_titre("Path", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder);
  5575. print "</tr>\n";
  5576. if (count($tabs)) {
  5577. foreach ($tabs as $tab) {
  5578. $parts = explode(':', $tab['data']);
  5579. $objectType = $parts[0];
  5580. $tabName = $parts[1];
  5581. $tabTitle = isset($parts[2]) ? $parts[2] : '';
  5582. $langFile = isset($parts[3]) ? $parts[3] : '';
  5583. $condition = isset($parts[4]) ? $parts[4] : '';
  5584. $path = isset($parts[5]) ? $parts[5] : '';
  5585. // If we want to remove the tab, then the format is 'objecttype:tabname:optionalcondition'
  5586. // See: https://wiki.dolibarr.org/index.php?title=Tabs_system#To_remove_an_existing_tab
  5587. if ($tabName[0] === '-') {
  5588. $tabTitle = '';
  5589. $condition = isset($parts[2]) ? $parts[2] : '';
  5590. }
  5591. print '<tr class="oddeven">';
  5592. print '<td>';
  5593. print dol_escape_htmltag($parts[0]);
  5594. print '</td>';
  5595. print '<td>';
  5596. if ($tabName[0] === "+") {
  5597. print '<span class="badge badge-status4 badge-status">' . dol_escape_htmltag($tabName) . '</span>';
  5598. } else {
  5599. print '<span class="badge badge-status8 badge-status">' . dol_escape_htmltag($tabName) . '</span>';
  5600. }
  5601. print '</td>';
  5602. print '<td>';
  5603. print dol_escape_htmltag($tabTitle);
  5604. print '</td>';
  5605. print '<td>';
  5606. print dol_escape_htmltag($langFile);
  5607. print '</td>';
  5608. print '<td>';
  5609. print dol_escape_htmltag($condition);
  5610. print '</td>';
  5611. print '<td>';
  5612. print dol_escape_htmltag($path);
  5613. print '</td>';
  5614. print '</tr>';
  5615. }
  5616. } else {
  5617. print '<tr><td colspan="5"><span class="opacitymedium">'.$langs->trans("None").'</span></td></tr>';
  5618. }
  5619. print '</table>';
  5620. print '</div>';
  5621. print '</form>';
  5622. } else {
  5623. $fullpathoffile = dol_buildpath($file, 0);
  5624. $content = file_get_contents($fullpathoffile);
  5625. // New module
  5626. print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
  5627. print '<input type="hidden" name="token" value="'.newToken().'">';
  5628. print '<input type="hidden" name="action" value="savefile">';
  5629. print '<input type="hidden" name="file" value="'.dol_escape_htmltag($file).'">';
  5630. print '<input type="hidden" name="tab" value="'.$tab.'">';
  5631. print '<input type="hidden" name="module" value="'.$module.'">';
  5632. $doleditor = new DolEditor('editfilecontent', $content, '', '300', 'Full', 'In', true, false, 'ace', 0, '99%');
  5633. print $doleditor->Create(1, '', false, $langs->trans("File").' : '.$file, (GETPOST('format', 'aZ09') ?GETPOST('format', 'aZ09') : 'html'));
  5634. print '<br>';
  5635. print '<center>';
  5636. print '<input type="submit" class="button buttonforacesave button-save" id="savefile" name="savefile" value="'.dol_escape_htmltag($langs->trans("Save")).'">';
  5637. print ' &nbsp; ';
  5638. print '<input type="submit" class="button button-cancel" name="cancel" value="'.dol_escape_htmltag($langs->trans("Cancel")).'">';
  5639. print '</center>';
  5640. print '</form>';
  5641. }
  5642. }
  5643. if ($tab != 'description') {
  5644. print dol_get_fiche_end();
  5645. }
  5646. }
  5647. }
  5648. print dol_get_fiche_end(); // End modules
  5649. // End of page
  5650. llxFooter();
  5651. $db->close();