Grocery_CRUD.php 162 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628
  1. <?php
  2. /**
  3. * PHP grocery CRUD
  4. *
  5. * A Codeigniter library that creates a CRUD automatically with just few lines of code.
  6. *
  7. * Copyright (C) 2010 - 2014 John Skoumbourdis.
  8. *
  9. * LICENSE
  10. *
  11. * Grocery CRUD is released with dual licensing, using the GPL v3 (license-gpl3.txt) and the MIT license (license-mit.txt).
  12. * You don't have to do anything special to choose one license or the other and you don't have to notify anyone which license you are using.
  13. * Please see the corresponding license file for details of these licenses.
  14. * You are free to use, modify and distribute this software, but all copyright information must remain.
  15. *
  16. * @package grocery CRUD
  17. * @copyright Copyright (c) 2010 through 2014, John Skoumbourdis
  18. * @license https://github.com/scoumbourdis/grocery-crud/blob/master/license-grocery-crud.txt
  19. * @version 1.5.8
  20. * @author John Skoumbourdis <scoumbourdisj@gmail.com>
  21. */
  22. // ------------------------------------------------------------------------
  23. /**
  24. * grocery Field Types
  25. *
  26. * The types of the fields and the default reactions
  27. *
  28. * @package grocery CRUD
  29. * @author John Skoumbourdis <scoumbourdisj@gmail.com>
  30. * @license https://github.com/scoumbourdis/grocery-crud/blob/master/license-grocery-crud.txt
  31. * @link http://www.grocerycrud.com/documentation
  32. */
  33. class grocery_CRUD_Field_Types
  34. {
  35. /**
  36. * Gets the field types of the main table.
  37. * @return array
  38. */
  39. public function get_field_types()
  40. {
  41. if ($this->field_types !== null) {
  42. return $this->field_types;
  43. }
  44. $types = array();
  45. foreach($this->basic_model->get_field_types_basic_table() as $field_info)
  46. {
  47. $field_info->required = !empty($this->required_fields) && in_array($field_info->name,$this->required_fields) ? true : false;
  48. $field_info->display_as =
  49. isset($this->display_as[$field_info->name]) ?
  50. $this->display_as[$field_info->name] :
  51. ucfirst(str_replace("_"," ",$field_info->name));
  52. if($this->change_field_type !== null && isset($this->change_field_type[$field_info->name]))
  53. {
  54. $field_type = $this->change_field_type[$field_info->name];
  55. if (isset($this->relation[$field_info->name])) {
  56. $field_info->crud_type = "relation_".$field_type->type;
  57. }
  58. elseif (isset($this->upload_fields[$field_info->name])) {
  59. $field_info->crud_type = "upload_file_".$field_type->type;
  60. } else {
  61. $field_info->crud_type = $field_type->type;
  62. $field_info->extras = $field_type->extras;
  63. }
  64. $real_type = $field_info->crud_type;
  65. }
  66. elseif(isset($this->relation[$field_info->name]))
  67. {
  68. $real_type = 'relation';
  69. $field_info->crud_type = 'relation';
  70. }
  71. elseif(isset($this->upload_fields[$field_info->name]))
  72. {
  73. $real_type = 'upload_file';
  74. $field_info->crud_type = 'upload_file';
  75. }
  76. else
  77. {
  78. $real_type = $this->get_type($field_info);
  79. $field_info->crud_type = $real_type;
  80. }
  81. switch ($real_type) {
  82. case 'text':
  83. if(!empty($this->unset_texteditor) && in_array($field_info->name,$this->unset_texteditor))
  84. $field_info->extras = false;
  85. else
  86. $field_info->extras = 'text_editor';
  87. break;
  88. case 'relation':
  89. case 'relation_readonly':
  90. $field_info->extras = $this->relation[$field_info->name];
  91. break;
  92. case 'upload_file':
  93. case 'upload_file_readonly':
  94. $field_info->extras = $this->upload_fields[$field_info->name];
  95. break;
  96. default:
  97. if(empty($field_info->extras))
  98. $field_info->extras = false;
  99. break;
  100. }
  101. $types[$field_info->name] = $field_info;
  102. }
  103. if(!empty($this->relation_n_n))
  104. {
  105. foreach($this->relation_n_n as $field_name => $field_extras)
  106. {
  107. $is_read_only = $this->change_field_type !== null
  108. && isset($this->change_field_type[$field_name])
  109. && $this->change_field_type[$field_name]->type == 'readonly'
  110. ? true : false;
  111. $field_info = (object)array();
  112. $field_info->name = $field_name;
  113. $field_info->crud_type = $is_read_only ? 'readonly' : 'relation_n_n';
  114. $field_info->extras = $field_extras;
  115. $field_info->required = !empty($this->required_fields) && in_array($field_name,$this->required_fields) ? true : false;;
  116. $field_info->display_as =
  117. isset($this->display_as[$field_name]) ?
  118. $this->display_as[$field_name] :
  119. ucfirst(str_replace("_"," ",$field_name));
  120. $types[$field_name] = $field_info;
  121. }
  122. }
  123. if(!empty($this->add_fields))
  124. foreach($this->add_fields as $field_object)
  125. {
  126. $field_name = isset($field_object->field_name) ? $field_object->field_name : $field_object;
  127. if(!isset($types[$field_name]))//Doesn't exist in the database? Create it for the CRUD
  128. {
  129. $extras = false;
  130. if($this->change_field_type !== null && isset($this->change_field_type[$field_name]))
  131. {
  132. $field_type = $this->change_field_type[$field_name];
  133. $extras = $field_type->extras;
  134. }
  135. $field_info = (object)array(
  136. 'name' => $field_name,
  137. 'crud_type' => $this->change_field_type !== null && isset($this->change_field_type[$field_name]) ?
  138. $this->change_field_type[$field_name]->type :
  139. 'string',
  140. 'display_as' => isset($this->display_as[$field_name]) ?
  141. $this->display_as[$field_name] :
  142. ucfirst(str_replace("_"," ",$field_name)),
  143. 'required' => !empty($this->required_fields) && in_array($field_name,$this->required_fields) ? true : false,
  144. 'extras' => $extras
  145. );
  146. $types[$field_name] = $field_info;
  147. }
  148. }
  149. if(!empty($this->edit_fields))
  150. foreach($this->edit_fields as $field_object)
  151. {
  152. $field_name = isset($field_object->field_name) ? $field_object->field_name : $field_object;
  153. if(!isset($types[$field_name]))//Doesn't exist in the database? Create it for the CRUD
  154. {
  155. $extras = false;
  156. if($this->change_field_type !== null && isset($this->change_field_type[$field_name]))
  157. {
  158. $field_type = $this->change_field_type[$field_name];
  159. $extras = $field_type->extras;
  160. }
  161. $field_info = (object)array(
  162. 'name' => $field_name,
  163. 'crud_type' => $this->change_field_type !== null && isset($this->change_field_type[$field_name]) ?
  164. $this->change_field_type[$field_name]->type :
  165. 'string',
  166. 'display_as' => isset($this->display_as[$field_name]) ?
  167. $this->display_as[$field_name] :
  168. ucfirst(str_replace("_"," ",$field_name)),
  169. 'required' => in_array($field_name,$this->required_fields) ? true : false,
  170. 'extras' => $extras
  171. );
  172. $types[$field_name] = $field_info;
  173. }
  174. }
  175. $this->field_types = $types;
  176. return $this->field_types;
  177. }
  178. public function get_primary_key()
  179. {
  180. return $this->basic_model->get_primary_key();
  181. }
  182. /**
  183. * Get the html input for the specific field with the
  184. * current value
  185. *
  186. * @param object $field_info
  187. * @param string $value
  188. * @return object
  189. */
  190. protected function get_field_input($field_info, $value = null)
  191. {
  192. $real_type = $field_info->crud_type;
  193. $types_array = array(
  194. 'integer',
  195. 'text',
  196. 'true_false',
  197. 'string',
  198. 'date',
  199. 'datetime',
  200. 'enum',
  201. 'set',
  202. 'relation',
  203. 'relation_readonly',
  204. 'relation_n_n',
  205. 'upload_file',
  206. 'upload_file_readonly',
  207. 'hidden',
  208. 'password',
  209. 'readonly',
  210. 'dropdown',
  211. 'multiselect'
  212. );
  213. if (in_array($real_type,$types_array)) {
  214. /* A quick way to go to an internal method of type $this->get_{type}_input .
  215. * For example if the real type is integer then we will use the method
  216. * $this->get_integer_input
  217. * */
  218. $field_info->input = $this->{"get_".$real_type."_input"}($field_info,$value);
  219. }
  220. else
  221. {
  222. $field_info->input = $this->get_string_input($field_info,$value);
  223. }
  224. return $field_info;
  225. }
  226. protected function change_list_value($field_info, $value = null)
  227. {
  228. $real_type = $field_info->crud_type;
  229. switch ($real_type) {
  230. case 'hidden':
  231. case 'invisible':
  232. case 'integer':
  233. break;
  234. case 'true_false':
  235. if(is_array($field_info->extras) && array_key_exists($value,$field_info->extras)) {
  236. $value = $field_info->extras[$value];
  237. } else if(isset($this->default_true_false_text[$value])) {
  238. $value = $this->default_true_false_text[$value];
  239. }
  240. break;
  241. case 'string':
  242. $value = $this->character_limiter($value,$this->character_limiter,"...");
  243. break;
  244. case 'text':
  245. $value = $this->character_limiter(strip_tags($value),$this->character_limiter,"...");
  246. break;
  247. case 'date':
  248. if(!empty($value) && $value != '0000-00-00' && $value != '1970-01-01')
  249. {
  250. list($year,$month,$day) = explode("-",$value);
  251. $value = date($this->php_date_format, mktime (0, 0, 0, (int)$month , (int)$day , (int)$year));
  252. }
  253. else
  254. {
  255. $value = '';
  256. }
  257. break;
  258. case 'datetime':
  259. if(!empty($value) && $value != '0000-00-00 00:00:00' && $value != '1970-01-01 00:00:00')
  260. {
  261. list($year,$month,$day) = explode("-",$value);
  262. list($hours,$minutes) = explode(":",substr($value,11));
  263. $value = date($this->php_date_format." - H:i", mktime ((int)$hours , (int)$minutes , 0, (int)$month , (int)$day ,(int)$year));
  264. }
  265. else
  266. {
  267. $value = '';
  268. }
  269. break;
  270. case 'enum':
  271. $value = $this->character_limiter($value,$this->character_limiter,"...");
  272. break;
  273. case 'multiselect':
  274. $value_as_array = array();
  275. foreach(explode(",",$value) as $row_value)
  276. {
  277. $value_as_array[] = array_key_exists($row_value,$field_info->extras) ? $field_info->extras[$row_value] : $row_value;
  278. }
  279. $value = implode(",",$value_as_array);
  280. break;
  281. case 'relation_n_n':
  282. $value = $this->character_limiter(str_replace(',',', ',$value),$this->character_limiter,"...");
  283. break;
  284. case 'password':
  285. $value = '******';
  286. break;
  287. case 'dropdown':
  288. $value = array_key_exists($value,$field_info->extras) ? $field_info->extras[$value] : $value;
  289. break;
  290. case 'upload_file':
  291. if(empty($value))
  292. {
  293. $value = "";
  294. }
  295. else
  296. {
  297. $is_image = !empty($value) &&
  298. ( substr($value,-4) == '.jpg'
  299. || substr($value,-4) == '.png'
  300. || substr($value,-5) == '.jpeg'
  301. || substr($value,-4) == '.gif'
  302. || substr($value,-5) == '.tiff')
  303. ? true : false;
  304. $file_url = base_url().$field_info->extras->upload_path."/$value";
  305. $file_url_anchor = '<a href="'.$file_url.'"';
  306. if($is_image)
  307. {
  308. $file_url_anchor .= ' class="image-thumbnail"><img src="'.$file_url.'" height="50px">';
  309. }
  310. else
  311. {
  312. $file_url_anchor .= ' target="_blank">'.$this->character_limiter($value,$this->character_limiter,'...',true);
  313. }
  314. $file_url_anchor .= '</a>';
  315. $value = $file_url_anchor;
  316. }
  317. break;
  318. default:
  319. $value = $this->character_limiter($value,$this->character_limiter,"...");
  320. break;
  321. }
  322. return $value;
  323. }
  324. /**
  325. * Character Limiter of codeigniter (I just don't want to load the helper )
  326. *
  327. * Limits the string based on the character count. Preserves complete words
  328. * so the character count may not be exactly as specified.
  329. *
  330. * @access public
  331. * @param string
  332. * @param integer
  333. * @param string the end character. Usually an ellipsis
  334. * @return string
  335. */
  336. function character_limiter($str, $n = 500, $end_char = '&#8230;')
  337. {
  338. if (strlen($str) < $n)
  339. {
  340. return $str;
  341. }
  342. // a bit complicated, but faster than preg_replace with \s+
  343. $str = preg_replace('/ {2,}/', ' ', str_replace(array("\r", "\n", "\t", "\x0B", "\x0C"), ' ', $str));
  344. if (strlen($str) <= $n)
  345. {
  346. return $str;
  347. }
  348. $out = '';
  349. foreach (explode(' ', trim($str)) as $val)
  350. {
  351. $out .= $val.' ';
  352. if (strlen($out) >= $n)
  353. {
  354. $out = trim($out);
  355. return (strlen($out) === strlen($str)) ? $out : $out.$end_char;
  356. }
  357. }
  358. }
  359. protected function get_type($db_type)
  360. {
  361. $type = false;
  362. if(!empty($db_type->type))
  363. {
  364. switch ($db_type->type) {
  365. case '1':
  366. case '3':
  367. case 'int':
  368. case 'tinyint':
  369. case 'mediumint':
  370. case 'longint':
  371. if( $db_type->db_type == 'tinyint' && $db_type->db_max_length == 1)
  372. $type = 'true_false';
  373. else
  374. $type = 'integer';
  375. break;
  376. case '254':
  377. case 'string':
  378. case 'enum':
  379. if($db_type->db_type != 'enum')
  380. $type = 'string';
  381. else
  382. $type = 'enum';
  383. break;
  384. case 'set':
  385. if($db_type->db_type != 'set')
  386. $type = 'string';
  387. else
  388. $type = 'set';
  389. break;
  390. case '252':
  391. case 'blob':
  392. case 'text':
  393. case 'mediumtext':
  394. case 'longtext':
  395. $type = 'text';
  396. break;
  397. case '10':
  398. case 'date':
  399. $type = 'date';
  400. break;
  401. case '12':
  402. case 'datetime':
  403. case 'timestamp':
  404. $type = 'datetime';
  405. break;
  406. }
  407. }
  408. return $type;
  409. }
  410. }
  411. // ------------------------------------------------------------------------
  412. /**
  413. * Grocery Model Driver
  414. *
  415. * Drives the model - I'ts so easy like you drive a bicycle :-)
  416. *
  417. * @package grocery CRUD
  418. * @author John Skoumbourdis <scoumbourdisj@gmail.com>
  419. * @version 1.5.8
  420. * @link http://www.grocerycrud.com/documentation
  421. */
  422. class grocery_CRUD_Model_Driver extends grocery_CRUD_Field_Types
  423. {
  424. /**
  425. * @var Grocery_crud_model
  426. */
  427. public $basic_model = null;
  428. protected function set_default_Model()
  429. {
  430. $ci = &get_instance();
  431. $ci->load->model('Grocery_crud_model');
  432. $this->basic_model = new Grocery_crud_model();
  433. }
  434. protected function get_total_results()
  435. {
  436. if(!empty($this->where))
  437. foreach($this->where as $where)
  438. $this->basic_model->where($where[0],$where[1],$where[2]);
  439. if(!empty($this->or_where))
  440. foreach($this->or_where as $or_where)
  441. $this->basic_model->or_where($or_where[0],$or_where[1],$or_where[2]);
  442. if(!empty($this->like))
  443. foreach($this->like as $like)
  444. $this->basic_model->like($like[0],$like[1],$like[2]);
  445. if(!empty($this->or_like))
  446. foreach($this->or_like as $or_like)
  447. $this->basic_model->or_like($or_like[0],$or_like[1],$or_like[2]);
  448. if(!empty($this->having))
  449. foreach($this->having as $having)
  450. $this->basic_model->having($having[0],$having[1],$having[2]);
  451. if(!empty($this->or_having))
  452. foreach($this->or_having as $or_having)
  453. $this->basic_model->or_having($or_having[0],$or_having[1],$or_having[2]);
  454. if(!empty($this->relation))
  455. foreach($this->relation as $relation)
  456. $this->basic_model->join_relation($relation[0],$relation[1],$relation[2]);
  457. if(!empty($this->relation_n_n))
  458. {
  459. $columns = $this->get_columns();
  460. foreach($columns as $column)
  461. {
  462. //Use the relation_n_n ONLY if the column is called . The set_relation_n_n are slow and it will make the table slower without any reason as we don't need those queries.
  463. if(isset($this->relation_n_n[$column->field_name]))
  464. {
  465. $this->basic_model->set_relation_n_n_field($this->relation_n_n[$column->field_name]);
  466. }
  467. }
  468. }
  469. return $this->basic_model->get_total_results();
  470. }
  471. protected function filter_data_from_xss($post_data) {
  472. foreach ($post_data as $field_name => $rawData) {
  473. if (!is_array($rawData)) {
  474. $post_data[$field_name] = filter_var(strip_tags($rawData));
  475. }
  476. }
  477. return $post_data;
  478. }
  479. public function set_model($model_name)
  480. {
  481. $ci = &get_instance();
  482. $ci->load->model('Grocery_crud_model');
  483. $ci->load->model($model_name);
  484. $temp = explode('/',$model_name);
  485. krsort($temp);
  486. foreach($temp as $t)
  487. {
  488. $real_model_name = $t;
  489. break;
  490. }
  491. $this->basic_model = $ci->$real_model_name;
  492. }
  493. protected function set_ajax_list_queries($state_info = null)
  494. {
  495. $field_types = $this->get_field_types();
  496. if(!empty($state_info->per_page))
  497. {
  498. if(empty($state_info->page) || !is_numeric($state_info->page) )
  499. $this->limit($state_info->per_page);
  500. else
  501. {
  502. $limit_page = ( ($state_info->page-1) * $state_info->per_page );
  503. $this->limit($state_info->per_page, $limit_page);
  504. }
  505. }
  506. if(!empty($state_info->order_by))
  507. {
  508. $this->order_by($state_info->order_by[0],$state_info->order_by[1]);
  509. }
  510. if(!empty($state_info->search))
  511. {
  512. if (!empty($this->relation)) {
  513. foreach ($this->relation as $relation_name => $relation_values) {
  514. $temp_relation[$this->_unique_field_name($relation_name)] = $this->_get_field_names_to_search($relation_values);
  515. }
  516. }
  517. if (is_array($state_info->search)) {
  518. foreach ($state_info->search as $search_field => $search_text) {
  519. if (isset($temp_relation[$search_field])) {
  520. if (is_array($temp_relation[$search_field])) {
  521. foreach ($temp_relation[$search_field] as $relation_field) {
  522. $this->or_like($relation_field , $search_text);
  523. }
  524. } else {
  525. $this->like($temp_relation[$search_field] , $search_text);
  526. }
  527. } elseif(isset($this->relation_n_n[$search_field])) {
  528. $escaped_text = $this->basic_model->escape_str($search_text);
  529. $this->having($search_field." LIKE '%".$escaped_text."%'");
  530. } else {
  531. $this->like($search_field, $search_text);
  532. }
  533. }
  534. } elseif ($state_info->search->field !== null) {
  535. if (isset($temp_relation[$state_info->search->field])) {
  536. if (is_array($temp_relation[$state_info->search->field])) {
  537. foreach ($temp_relation[$state_info->search->field] as $search_field) {
  538. $this->or_like($search_field , $state_info->search->text);
  539. }
  540. } else {
  541. $this->like($temp_relation[$state_info->search->field] , $state_info->search->text);
  542. }
  543. } elseif(isset($this->relation_n_n[$state_info->search->field])) {
  544. $escaped_text = $this->basic_model->escape_str($state_info->search->text);
  545. $this->having($state_info->search->field." LIKE '%".$escaped_text."%'");
  546. } else {
  547. $this->like($state_info->search->field , $state_info->search->text);
  548. }
  549. }
  550. else
  551. {
  552. $columns = $this->get_columns();
  553. $search_text = $state_info->search->text;
  554. if(!empty($this->where))
  555. foreach($this->where as $where)
  556. $this->basic_model->having($where[0],$where[1],$where[2]);
  557. foreach($columns as $column)
  558. {
  559. if(isset($temp_relation[$column->field_name]))
  560. {
  561. if(is_array($temp_relation[$column->field_name]))
  562. {
  563. foreach($temp_relation[$column->field_name] as $search_field)
  564. {
  565. $this->or_like($search_field, $search_text);
  566. }
  567. }
  568. else
  569. {
  570. $this->or_like($temp_relation[$column->field_name], $search_text);
  571. }
  572. }
  573. elseif(isset($this->relation_n_n[$column->field_name]))
  574. {
  575. //@todo have a where for the relation_n_n statement
  576. }
  577. elseif (isset($field_types[$column->field_name])
  578. && !in_array($field_types[$column->field_name]->type, array('date', 'datetime', 'timestamp')))
  579. {
  580. $this->or_like($column->field_name, $search_text);
  581. }
  582. }
  583. }
  584. }
  585. }
  586. protected function table_exists($table_name = null)
  587. {
  588. if($this->basic_model->db_table_exists($table_name))
  589. return true;
  590. return false;
  591. }
  592. protected function get_relation_array($relation_info, $primary_key_value = null, $limit = null)
  593. {
  594. list($field_name , $related_table , $related_field_title, $where_clause, $order_by) = $relation_info;
  595. if($primary_key_value !== null)
  596. {
  597. $primary_key = $this->basic_model->get_primary_key($related_table);
  598. //A where clause with the primary key is enough to take the selected key row
  599. $where_clause = array($primary_key => $primary_key_value);
  600. }
  601. $relation_array = $this->basic_model->get_relation_array($field_name , $related_table , $related_field_title, $where_clause, $order_by, $limit);
  602. return $relation_array;
  603. }
  604. protected function get_relation_total_rows($relation_info)
  605. {
  606. list($field_name , $related_table , $related_field_title, $where_clause) = $relation_info;
  607. $relation_array = $this->basic_model->get_relation_total_rows($field_name , $related_table , $related_field_title, $where_clause);
  608. return $relation_array;
  609. }
  610. protected function db_insert_validation()
  611. {
  612. $validation_result = (object)array('success'=>false);
  613. $field_types = $this->get_field_types();
  614. $required_fields = $this->required_fields;
  615. $unique_fields = $this->_unique_fields;
  616. $add_fields = $this->get_add_fields();
  617. if(!empty($required_fields))
  618. {
  619. foreach($add_fields as $add_field)
  620. {
  621. $field_name = $add_field->field_name;
  622. if(!isset($this->validation_rules[$field_name]) && in_array( $field_name, $required_fields) )
  623. {
  624. $this->set_rules( $field_name, $field_types[$field_name]->display_as, 'required');
  625. }
  626. }
  627. }
  628. /** Checking for unique fields. If the field value is not unique then
  629. * return a validation error straight away, if not continue... */
  630. if(!empty($unique_fields))
  631. {
  632. $form_validation = $this->form_validation();
  633. foreach($add_fields as $add_field)
  634. {
  635. $field_name = $add_field->field_name;
  636. if(in_array( $field_name, $unique_fields) )
  637. {
  638. $form_validation->set_rules( $field_name,
  639. $field_types[$field_name]->display_as,
  640. 'is_unique['.$this->basic_db_table.'.'.$field_name.']');
  641. }
  642. }
  643. if(!$form_validation->run())
  644. {
  645. $validation_result->error_message = $form_validation->error_string();
  646. $validation_result->error_fields = $form_validation->_error_array;
  647. return $validation_result;
  648. }
  649. }
  650. if(!empty($this->validation_rules))
  651. {
  652. $form_validation = $this->form_validation();
  653. $add_fields = $this->get_add_fields();
  654. foreach($add_fields as $add_field)
  655. {
  656. $field_name = $add_field->field_name;
  657. if(isset($this->validation_rules[$field_name]))
  658. {
  659. $rule = $this->validation_rules[$field_name];
  660. $form_validation->set_rules($rule['field'],$rule['label'],$rule['rules'],$rule['errors']);
  661. }
  662. }
  663. if($form_validation->run())
  664. {
  665. $validation_result->success = true;
  666. }
  667. else
  668. {
  669. $validation_result->error_message = $form_validation->error_string();
  670. $validation_result->error_fields = $form_validation->_error_array;
  671. }
  672. }
  673. else
  674. {
  675. $validation_result->success = true;
  676. }
  677. return $validation_result;
  678. }
  679. protected function form_validation()
  680. {
  681. if($this->form_validation === null)
  682. {
  683. $this->form_validation = new grocery_CRUD_Form_validation();
  684. $ci = &get_instance();
  685. $ci->load->library('form_validation');
  686. $ci->form_validation = $this->form_validation;
  687. }
  688. return $this->form_validation;
  689. }
  690. protected function db_update_validation()
  691. {
  692. $validation_result = (object)array('success'=>false);
  693. $field_types = $this->get_field_types();
  694. $required_fields = $this->required_fields;
  695. $unique_fields = $this->_unique_fields;
  696. $edit_fields = $this->get_edit_fields();
  697. if(!empty($required_fields))
  698. {
  699. foreach($edit_fields as $edit_field)
  700. {
  701. $field_name = $edit_field->field_name;
  702. if(!isset($this->validation_rules[$field_name]) && in_array( $field_name, $required_fields) )
  703. {
  704. $this->set_rules( $field_name, $field_types[$field_name]->display_as, 'required');
  705. }
  706. }
  707. }
  708. /** Checking for unique fields. If the field value is not unique then
  709. * return a validation error straight away, if not continue... */
  710. if(!empty($unique_fields))
  711. {
  712. $form_validation = $this->form_validation();
  713. $form_validation_check = false;
  714. foreach($edit_fields as $edit_field)
  715. {
  716. $field_name = $edit_field->field_name;
  717. if(in_array( $field_name, $unique_fields) )
  718. {
  719. $state_info = $this->getStateInfo();
  720. $primary_key = $this->get_primary_key();
  721. $field_name_value = $_POST[$field_name];
  722. $this->basic_model->where($primary_key,$state_info->primary_key);
  723. $row = $this->basic_model->get_row();
  724. if(!isset($row->$field_name)) {
  725. throw new Exception("The field name doesn't exist in the database. ".
  726. "Please use the unique fields only for fields ".
  727. "that exist in the database");
  728. }
  729. $previous_field_name_value = $row->$field_name;
  730. if(!empty($previous_field_name_value) && $previous_field_name_value != $field_name_value) {
  731. $form_validation->set_rules( $field_name,
  732. $field_types[$field_name]->display_as,
  733. 'is_unique['.$this->basic_db_table.'.'.$field_name.']');
  734. $form_validation_check = true;
  735. }
  736. }
  737. }
  738. if($form_validation_check && !$form_validation->run())
  739. {
  740. $validation_result->error_message = $form_validation->error_string();
  741. $validation_result->error_fields = $form_validation->_error_array;
  742. return $validation_result;
  743. }
  744. }
  745. if(!empty($this->validation_rules))
  746. {
  747. $form_validation = $this->form_validation();
  748. $edit_fields = $this->get_edit_fields();
  749. foreach($edit_fields as $edit_field)
  750. {
  751. $field_name = $edit_field->field_name;
  752. if(isset($this->validation_rules[$field_name]))
  753. {
  754. $rule = $this->validation_rules[$field_name];
  755. $form_validation->set_rules($rule['field'],$rule['label'],$rule['rules'],$rule['errors']);
  756. }
  757. }
  758. if($form_validation->run())
  759. {
  760. $validation_result->success = true;
  761. }
  762. else
  763. {
  764. $validation_result->error_message = $form_validation->error_string();
  765. $validation_result->error_fields = $form_validation->_error_array;
  766. }
  767. }
  768. else
  769. {
  770. $validation_result->success = true;
  771. }
  772. return $validation_result;
  773. }
  774. protected function db_insert($state_info)
  775. {
  776. $validation_result = $this->db_insert_validation();
  777. if($validation_result->success)
  778. {
  779. $post_data = $state_info->unwrapped_data;
  780. if ($this->config->xss_clean) {
  781. $post_data = $this->filter_data_from_xss($post_data);
  782. }
  783. $add_fields = $this->get_add_fields();
  784. if($this->callback_insert === null)
  785. {
  786. if($this->callback_before_insert !== null)
  787. {
  788. $callback_return = call_user_func($this->callback_before_insert, $post_data);
  789. if(!empty($callback_return) && is_array($callback_return))
  790. $post_data = $callback_return;
  791. elseif($callback_return === false)
  792. return false;
  793. }
  794. $insert_data = array();
  795. $types = $this->get_field_types();
  796. foreach($add_fields as $num_row => $field)
  797. {
  798. /* If the multiselect or the set is empty then the browser doesn't send an empty array. Instead it sends nothing */
  799. if(isset($types[$field->field_name]->crud_type) && ($types[$field->field_name]->crud_type == 'set' || $types[$field->field_name]->crud_type == 'multiselect') && !isset($post_data[$field->field_name]))
  800. {
  801. $post_data[$field->field_name] = array();
  802. }
  803. if(isset($post_data[$field->field_name]) && !isset($this->relation_n_n[$field->field_name]))
  804. {
  805. if(isset($types[$field->field_name]->db_null) && $types[$field->field_name]->db_null && is_array($post_data[$field->field_name]) && empty($post_data[$field->field_name]))
  806. {
  807. $insert_data[$field->field_name] = null;
  808. }
  809. elseif(isset($types[$field->field_name]->db_null) && $types[$field->field_name]->db_null && $post_data[$field->field_name] === '')
  810. {
  811. $insert_data[$field->field_name] = null;
  812. }
  813. elseif(isset($types[$field->field_name]->crud_type) && $types[$field->field_name]->crud_type == 'date')
  814. {
  815. $insert_data[$field->field_name] = $this->_convert_date_to_sql_date($post_data[$field->field_name]);
  816. }
  817. elseif(isset($types[$field->field_name]->crud_type) && $types[$field->field_name]->crud_type == 'readonly')
  818. {
  819. //This empty if statement is to make sure that a readonly field will never inserted/updated
  820. }
  821. elseif(isset($types[$field->field_name]->crud_type) && ($types[$field->field_name]->crud_type == 'set' || $types[$field->field_name]->crud_type == 'multiselect'))
  822. {
  823. $insert_data[$field->field_name] = !empty($post_data[$field->field_name]) ? implode(',',$post_data[$field->field_name]) : '';
  824. }
  825. elseif(isset($types[$field->field_name]->crud_type) && $types[$field->field_name]->crud_type == 'datetime'){
  826. $insert_data[$field->field_name] = $this->_convert_date_to_sql_date(substr($post_data[$field->field_name],0,10)).
  827. substr($post_data[$field->field_name],10);
  828. }
  829. else
  830. {
  831. $insert_data[$field->field_name] = $post_data[$field->field_name];
  832. }
  833. }
  834. }
  835. $insert_result = $this->basic_model->db_insert($insert_data);
  836. if($insert_result !== false)
  837. {
  838. $insert_primary_key = $insert_result;
  839. }
  840. else
  841. {
  842. return false;
  843. }
  844. if(!empty($this->relation_n_n))
  845. {
  846. foreach($this->relation_n_n as $field_name => $field_info)
  847. {
  848. $relation_data = isset( $post_data[$field_name] ) ? $post_data[$field_name] : array() ;
  849. $this->db_relation_n_n_update($field_info, $relation_data ,$insert_primary_key);
  850. }
  851. }
  852. if($this->callback_after_insert !== null)
  853. {
  854. $callback_return = call_user_func($this->callback_after_insert, $post_data, $insert_primary_key);
  855. if($callback_return === false)
  856. {
  857. return false;
  858. }
  859. }
  860. }else
  861. {
  862. $callback_return = call_user_func($this->callback_insert, $post_data);
  863. if($callback_return === false)
  864. {
  865. return false;
  866. }
  867. }
  868. if(isset($insert_primary_key))
  869. return $insert_primary_key;
  870. else
  871. return true;
  872. }
  873. return false;
  874. }
  875. protected function db_update($state_info)
  876. {
  877. $validation_result = $this->db_update_validation();
  878. $edit_fields = $this->get_edit_fields();
  879. if($validation_result->success)
  880. {
  881. $post_data = $state_info->unwrapped_data;
  882. $primary_key = $state_info->primary_key;
  883. if ($this->config->xss_clean) {
  884. $post_data = $this->filter_data_from_xss($post_data);
  885. }
  886. if($this->callback_update === null)
  887. {
  888. if($this->callback_before_update !== null)
  889. {
  890. $callback_return = call_user_func($this->callback_before_update, $post_data, $primary_key);
  891. if(!empty($callback_return) && is_array($callback_return))
  892. {
  893. $post_data = $callback_return;
  894. }
  895. elseif($callback_return === false)
  896. {
  897. return false;
  898. }
  899. }
  900. $update_data = array();
  901. $types = $this->get_field_types();
  902. foreach($edit_fields as $num_row => $field)
  903. {
  904. /* If the multiselect or the set is empty then the browser doesn't send an empty array. Instead it sends nothing */
  905. if(isset($types[$field->field_name]->crud_type) && ($types[$field->field_name]->crud_type == 'set' || $types[$field->field_name]->crud_type == 'multiselect') && !isset($post_data[$field->field_name]))
  906. {
  907. $post_data[$field->field_name] = array();
  908. }
  909. if(isset($post_data[$field->field_name]) && !isset($this->relation_n_n[$field->field_name]))
  910. {
  911. if(isset($types[$field->field_name]->db_null) && $types[$field->field_name]->db_null && is_array($post_data[$field->field_name]) && empty($post_data[$field->field_name]))
  912. {
  913. $update_data[$field->field_name] = null;
  914. }
  915. elseif(isset($types[$field->field_name]->db_null) && $types[$field->field_name]->db_null && $post_data[$field->field_name] === '')
  916. {
  917. $update_data[$field->field_name] = null;
  918. }
  919. elseif(isset($types[$field->field_name]->crud_type) && $types[$field->field_name]->crud_type == 'date')
  920. {
  921. $update_data[$field->field_name] = $this->_convert_date_to_sql_date($post_data[$field->field_name]);
  922. }
  923. elseif(isset($types[$field->field_name]->crud_type) && $types[$field->field_name]->crud_type == 'readonly')
  924. {
  925. //This empty if statement is to make sure that a readonly field will never inserted/updated
  926. }
  927. elseif(isset($types[$field->field_name]->crud_type) && ($types[$field->field_name]->crud_type == 'set' || $types[$field->field_name]->crud_type == 'multiselect'))
  928. {
  929. $update_data[$field->field_name] = !empty($post_data[$field->field_name]) ? implode(',',$post_data[$field->field_name]) : '';
  930. }
  931. elseif(isset($types[$field->field_name]->crud_type) && $types[$field->field_name]->crud_type == 'datetime'){
  932. $update_data[$field->field_name] = $this->_convert_date_to_sql_date(substr($post_data[$field->field_name],0,10)).
  933. substr($post_data[$field->field_name],10);
  934. }
  935. else
  936. {
  937. $update_data[$field->field_name] = $post_data[$field->field_name];
  938. }
  939. }
  940. }
  941. if($this->basic_model->db_update($update_data, $primary_key) === false)
  942. {
  943. return false;
  944. }
  945. if(!empty($this->relation_n_n))
  946. {
  947. foreach($this->relation_n_n as $field_name => $field_info)
  948. {
  949. if ( $this->unset_edit_fields !== null
  950. && is_array($this->unset_edit_fields)
  951. && in_array($field_name,$this->unset_edit_fields)
  952. ) {
  953. continue;
  954. }
  955. $relation_data = isset( $post_data[$field_name] ) ? $post_data[$field_name] : array() ;
  956. $this->db_relation_n_n_update($field_info, $relation_data ,$primary_key);
  957. }
  958. }
  959. if($this->callback_after_update !== null)
  960. {
  961. $callback_return = call_user_func($this->callback_after_update, $post_data, $primary_key);
  962. if($callback_return === false)
  963. {
  964. return false;
  965. }
  966. }
  967. }
  968. else
  969. {
  970. $callback_return = call_user_func($this->callback_update, $post_data, $primary_key);
  971. if($callback_return === false)
  972. {
  973. return false;
  974. }
  975. }
  976. return true;
  977. }
  978. else
  979. {
  980. return false;
  981. }
  982. }
  983. protected function _convert_date_to_sql_date($date)
  984. {
  985. $date = substr($date,0,10);
  986. if(preg_match('/\d{4}-\d{2}-\d{2}/',$date))
  987. {
  988. //If it's already a sql-date don't convert it!
  989. return $date;
  990. }elseif(empty($date))
  991. {
  992. return '';
  993. }
  994. $date_array = preg_split( '/[-\.\/ ]/', $date);
  995. if($this->php_date_format == 'd/m/Y')
  996. {
  997. $sql_date = date('Y-m-d',mktime(0,0,0,$date_array[1],$date_array[0],$date_array[2]));
  998. }
  999. elseif($this->php_date_format == 'm/d/Y')
  1000. {
  1001. $sql_date = date('Y-m-d',mktime(0,0,0,$date_array[0],$date_array[1],$date_array[2]));
  1002. }
  1003. else
  1004. {
  1005. $sql_date = $date;
  1006. }
  1007. return $sql_date;
  1008. }
  1009. protected function _get_field_names_to_search(array $relation_values)
  1010. {
  1011. if(!strstr($relation_values[2],'{')) {
  1012. return $this->_unique_join_name($relation_values[0]).'.'.$relation_values[2];
  1013. } else {
  1014. $relation_values[2] = ' '.$relation_values[2].' ';
  1015. $temp1 = explode('{',$relation_values[2]);
  1016. unset($temp1[0]);
  1017. $field_names_array = array();
  1018. foreach($temp1 as $field) {
  1019. list($field_name) = explode('}',$field);
  1020. $field_name = $this->_unique_join_name($relation_values[0]).'.'. $field_name;
  1021. $field_names_array[] = $field_name;
  1022. }
  1023. return $field_names_array;
  1024. }
  1025. }
  1026. protected function _unique_join_name($field_name)
  1027. {
  1028. return 'j'.substr(md5($field_name),0,8); //This j is because is better for a string to begin with a letter and not a number
  1029. }
  1030. protected function _unique_field_name($field_name)
  1031. {
  1032. return 's'.substr(md5($field_name),0,8); //This s is because is better for a string to begin with a letter and not a number
  1033. }
  1034. protected function db_multiple_delete($state_info)
  1035. {
  1036. foreach ($state_info->ids as $delete_id) {
  1037. $result = $this->db_delete((object)array('primary_key' => $delete_id));
  1038. if (!$result) {
  1039. return false;
  1040. }
  1041. }
  1042. return true;
  1043. }
  1044. protected function db_delete($state_info)
  1045. {
  1046. $primary_key_value = $state_info->primary_key;
  1047. if($this->callback_delete === null)
  1048. {
  1049. if($this->callback_before_delete !== null)
  1050. {
  1051. $callback_return = call_user_func($this->callback_before_delete, $primary_key_value);
  1052. if($callback_return === false)
  1053. {
  1054. return false;
  1055. }
  1056. }
  1057. if(!empty($this->relation_n_n))
  1058. {
  1059. foreach($this->relation_n_n as $field_name => $field_info)
  1060. {
  1061. $this->db_relation_n_n_delete( $field_info, $primary_key_value );
  1062. }
  1063. }
  1064. $delete_result = $this->basic_model->db_delete($primary_key_value);
  1065. if($delete_result === false)
  1066. {
  1067. return false;
  1068. }
  1069. if($this->callback_after_delete !== null)
  1070. {
  1071. $callback_return = call_user_func($this->callback_after_delete, $primary_key_value);
  1072. if($callback_return === false)
  1073. {
  1074. return false;
  1075. }
  1076. }
  1077. }
  1078. else
  1079. {
  1080. $callback_return = call_user_func($this->callback_delete, $primary_key_value);
  1081. if($callback_return === false)
  1082. {
  1083. return false;
  1084. }
  1085. }
  1086. return true;
  1087. }
  1088. protected function db_relation_n_n_update($field_info, $post_data , $primary_key_value)
  1089. {
  1090. $this->basic_model->db_relation_n_n_update($field_info, $post_data , $primary_key_value);
  1091. }
  1092. protected function db_relation_n_n_delete($field_info, $primary_key_value)
  1093. {
  1094. $this->basic_model->db_relation_n_n_delete($field_info, $primary_key_value);
  1095. }
  1096. protected function get_list()
  1097. {
  1098. if(!empty($this->order_by))
  1099. $this->basic_model->order_by($this->order_by[0],$this->order_by[1]);
  1100. if(!empty($this->where))
  1101. foreach($this->where as $where)
  1102. $this->basic_model->where($where[0],$where[1],$where[2]);
  1103. if(!empty($this->or_where))
  1104. foreach($this->or_where as $or_where)
  1105. $this->basic_model->or_where($or_where[0],$or_where[1],$or_where[2]);
  1106. if(!empty($this->like))
  1107. foreach($this->like as $like)
  1108. $this->basic_model->like($like[0],$like[1],$like[2]);
  1109. if(!empty($this->or_like))
  1110. foreach($this->or_like as $or_like)
  1111. $this->basic_model->or_like($or_like[0],$or_like[1],$or_like[2]);
  1112. if(!empty($this->having))
  1113. foreach($this->having as $having)
  1114. $this->basic_model->having($having[0],$having[1],$having[2]);
  1115. if(!empty($this->or_having))
  1116. foreach($this->or_having as $or_having)
  1117. $this->basic_model->or_having($or_having[0],$or_having[1],$or_having[2]);
  1118. if(!empty($this->relation))
  1119. foreach($this->relation as $relation)
  1120. $this->basic_model->join_relation($relation[0],$relation[1],$relation[2]);
  1121. if(!empty($this->relation_n_n))
  1122. {
  1123. $columns = $this->get_columns();
  1124. foreach($columns as $column)
  1125. {
  1126. //Use the relation_n_n ONLY if the column is called . The set_relation_n_n are slow and it will make the table slower without any reason as we don't need those queries.
  1127. if(isset($this->relation_n_n[$column->field_name]))
  1128. {
  1129. $this->basic_model->set_relation_n_n_field($this->relation_n_n[$column->field_name]);
  1130. }
  1131. }
  1132. }
  1133. if($this->theme_config['crud_paging'] === true)
  1134. {
  1135. if($this->limit === null)
  1136. {
  1137. $default_per_page = $this->config->default_per_page;
  1138. if(is_numeric($default_per_page) && $default_per_page >1)
  1139. {
  1140. $this->basic_model->limit($default_per_page);
  1141. }
  1142. else
  1143. {
  1144. $this->basic_model->limit(10);
  1145. }
  1146. }
  1147. else
  1148. {
  1149. $this->basic_model->limit($this->limit[0],$this->limit[1]);
  1150. }
  1151. }
  1152. $results = $this->basic_model->get_list();
  1153. return $results;
  1154. }
  1155. protected function get_edit_values($primary_key_value)
  1156. {
  1157. $values = $this->basic_model->get_edit_values($primary_key_value);
  1158. if(!empty($this->relation_n_n))
  1159. {
  1160. foreach($this->relation_n_n as $field_name => $field_info)
  1161. {
  1162. $values->$field_name = $this->get_relation_n_n_selection_array($primary_key_value, $field_info);
  1163. }
  1164. }
  1165. return $values;
  1166. }
  1167. protected function get_relation_n_n_selection_array($primary_key_value, $field_info)
  1168. {
  1169. return $this->basic_model->get_relation_n_n_selection_array($primary_key_value, $field_info);
  1170. }
  1171. protected function get_relation_n_n_unselected_array($field_info, $selected_values)
  1172. {
  1173. return $this->basic_model->get_relation_n_n_unselected_array($field_info, $selected_values);
  1174. }
  1175. protected function set_basic_db_table($table_name = null)
  1176. {
  1177. $this->basic_model->set_basic_table($table_name);
  1178. }
  1179. protected function upload_file($state_info)
  1180. {
  1181. if(isset($this->upload_fields[$state_info->field_name]) )
  1182. {
  1183. if($this->callback_upload === null)
  1184. {
  1185. if($this->callback_before_upload !== null)
  1186. {
  1187. $callback_before_upload_response = call_user_func($this->callback_before_upload, $_FILES, $this->upload_fields[$state_info->field_name]);
  1188. if($callback_before_upload_response === false)
  1189. return false;
  1190. elseif(is_string($callback_before_upload_response))
  1191. return $callback_before_upload_response;
  1192. }
  1193. $upload_info = $this->upload_fields[$state_info->field_name];
  1194. header('Pragma: no-cache');
  1195. header('Cache-Control: private, no-cache');
  1196. header('Content-Disposition: inline; filename="files.json"');
  1197. header('X-Content-Type-Options: nosniff');
  1198. header('Access-Control-Allow-Origin: *');
  1199. header('Access-Control-Allow-Methods: OPTIONS, HEAD, GET, POST, PUT, DELETE');
  1200. header('Access-Control-Allow-Headers: X-File-Name, X-File-Type, X-File-Size');
  1201. $allowed_files = $this->config->file_upload_allow_file_types;
  1202. $reg_exp = '';
  1203. if(!empty($upload_info->allowed_file_types)){
  1204. $reg_exp = '/(\\.|\\/)('.$upload_info->allowed_file_types.')$/i';
  1205. }else{
  1206. $reg_exp = '/(\\.|\\/)('.$allowed_files.')$/i';
  1207. }
  1208. $max_file_size_ui = $this->config->file_upload_max_file_size;
  1209. $max_file_size_bytes = $this->_convert_bytes_ui_to_bytes($max_file_size_ui);
  1210. $options = array(
  1211. 'upload_dir' => $upload_info->upload_path.'/',
  1212. 'param_name' => $this->_unique_field_name($state_info->field_name),
  1213. 'upload_url' => base_url().$upload_info->upload_path.'/',
  1214. 'accept_file_types' => $reg_exp,
  1215. 'max_file_size' => $max_file_size_bytes
  1216. );
  1217. $upload_handler = new UploadHandler($options);
  1218. $upload_handler->default_config_path = $this->default_config_path;
  1219. $uploader_response = $upload_handler->post();
  1220. if(is_array($uploader_response))
  1221. {
  1222. foreach($uploader_response as &$response)
  1223. {
  1224. unset($response->delete_url);
  1225. unset($response->delete_type);
  1226. }
  1227. }
  1228. if($this->callback_after_upload !== null)
  1229. {
  1230. $callback_after_upload_response = call_user_func($this->callback_after_upload, $uploader_response , $this->upload_fields[$state_info->field_name] , $_FILES );
  1231. if($callback_after_upload_response === false)
  1232. return false;
  1233. elseif(is_string($callback_after_upload_response))
  1234. return $callback_after_upload_response;
  1235. elseif(is_array($callback_after_upload_response))
  1236. $uploader_response = $callback_after_upload_response;
  1237. }
  1238. return $uploader_response;
  1239. }
  1240. else
  1241. {
  1242. $upload_response = call_user_func($this->callback_upload, $_FILES, $this->upload_fields[$state_info->field_name] );
  1243. if($upload_response === false)
  1244. {
  1245. return false;
  1246. }
  1247. else
  1248. {
  1249. return $upload_response;
  1250. }
  1251. }
  1252. }
  1253. else
  1254. {
  1255. return false;
  1256. }
  1257. }
  1258. protected function delete_file($state_info)
  1259. {
  1260. if(isset($state_info->field_name) && isset($this->upload_fields[$state_info->field_name]))
  1261. {
  1262. $upload_info = $this->upload_fields[$state_info->field_name];
  1263. if(file_exists("{$upload_info->upload_path}/{$state_info->file_name}"))
  1264. {
  1265. if( unlink("{$upload_info->upload_path}/{$state_info->file_name}") )
  1266. {
  1267. $this->basic_model->db_file_delete($state_info->field_name, $state_info->file_name);
  1268. return true;
  1269. }
  1270. else
  1271. {
  1272. return false;
  1273. }
  1274. }
  1275. else
  1276. {
  1277. $this->basic_model->db_file_delete($state_info->field_name, $state_info->file_name);
  1278. return true;
  1279. }
  1280. }
  1281. else
  1282. {
  1283. return false;
  1284. }
  1285. }
  1286. protected function ajax_relation($state_info)
  1287. {
  1288. if(!isset($this->relation[$state_info->field_name]))
  1289. return false;
  1290. list($field_name, $related_table, $related_field_title, $where_clause, $order_by) = $this->relation[$state_info->field_name];
  1291. return $this->basic_model->get_ajax_relation_array($state_info->search, $field_name, $related_table, $related_field_title, $where_clause, $order_by);
  1292. }
  1293. }
  1294. /**
  1295. * PHP grocery CRUD
  1296. *
  1297. * LICENSE
  1298. *
  1299. * Grocery CRUD is released with dual licensing, using the GPL v3 (license-gpl3.txt) and the MIT license (license-mit.txt).
  1300. * You don't have to do anything special to choose one license or the other and you don't have to notify anyone which license you are using.
  1301. * Please see the corresponding license file for details of these licenses.
  1302. * You are free to use, modify and distribute this software, but all copyright information must remain.
  1303. *
  1304. * @package grocery CRUD
  1305. * @copyright Copyright (c) 2010 through 2014, John Skoumbourdis
  1306. * @license https://github.com/scoumbourdis/grocery-crud/blob/master/license-grocery-crud.txt
  1307. * @author John Skoumbourdis <scoumbourdisj@gmail.com>
  1308. */
  1309. // ------------------------------------------------------------------------
  1310. /**
  1311. * PHP grocery Layout
  1312. *
  1313. * Here you manage all the HTML Layout
  1314. *
  1315. * @package grocery CRUD
  1316. * @author John Skoumbourdis <scoumbourdisj@gmail.com>
  1317. * @version 1.5.8
  1318. */
  1319. class grocery_CRUD_Layout extends grocery_CRUD_Model_Driver
  1320. {
  1321. private $theme_path = null;
  1322. private $views_as_string = '';
  1323. private $echo_and_die = false;
  1324. protected $theme = null;
  1325. protected $default_true_false_text = array('inactive' , 'active');
  1326. protected $css_files = array();
  1327. protected $js_files = array();
  1328. protected $js_lib_files = array();
  1329. protected $js_config_files = array();
  1330. protected function set_basic_Layout()
  1331. {
  1332. if(!file_exists($this->theme_path.$this->theme.'/views/list_template.php'))
  1333. {
  1334. throw new Exception('The template does not exist. Please check your files and try again.', 12);
  1335. die();
  1336. }
  1337. }
  1338. protected function showList($ajax = false, $state_info = null)
  1339. {
  1340. $data = $this->get_common_data();
  1341. $data->order_by = $this->order_by;
  1342. $data->types = $this->get_field_types();
  1343. $data->list = $this->get_list();
  1344. $data->list = $this->change_list($data->list , $data->types);
  1345. $data->list = $this->change_list_add_actions($data->list);
  1346. $data->total_results = $this->get_total_results();
  1347. $data->dialog_forms = $this->config->dialog_forms;
  1348. $data->columns = $this->get_columns();
  1349. $data->success_message = $this->get_success_message_at_list($state_info);
  1350. $data->primary_key = $this->get_primary_key();
  1351. $data->add_url = $this->getAddUrl();
  1352. $data->edit_url = $this->getEditUrl();
  1353. $data->delete_url = $this->getDeleteUrl();
  1354. $data->delete_multiple_url = $this->getDeleteMultipleUrl();
  1355. $data->read_url = $this->getReadUrl();
  1356. $data->ajax_list_url = $this->getAjaxListUrl();
  1357. $data->ajax_list_info_url = $this->getAjaxListInfoUrl();
  1358. $data->export_url = $this->getExportToExcelUrl();
  1359. $data->print_url = $this->getPrintUrl();
  1360. $data->actions = $this->actions;
  1361. $data->unique_hash = $this->get_method_hash();
  1362. $data->order_by = $this->order_by;
  1363. $data->unset_add = $this->unset_add;
  1364. $data->unset_edit = $this->unset_edit;
  1365. $data->unset_read = $this->unset_read;
  1366. $data->unset_delete = $this->unset_delete;
  1367. $data->unset_export = $this->unset_export;
  1368. $data->unset_print = $this->unset_print;
  1369. $default_per_page = $this->config->default_per_page;
  1370. $data->paging_options = $this->config->paging_options;
  1371. $data->default_per_page = is_numeric($default_per_page) && $default_per_page >1 && in_array($default_per_page,$data->paging_options)? $default_per_page : 25;
  1372. if($data->list === false)
  1373. {
  1374. throw new Exception('It is impossible to get data. Please check your model and try again.', 13);
  1375. $data->list = array();
  1376. }
  1377. foreach($data->list as $num_row => $row)
  1378. {
  1379. $data->list[$num_row]->primary_key_value = $row->{$data->primary_key};
  1380. $data->list[$num_row]->edit_url = $data->edit_url.'/'.$row->{$data->primary_key};
  1381. $data->list[$num_row]->delete_url = $data->delete_url.'/'.$row->{$data->primary_key};
  1382. $data->list[$num_row]->read_url = $data->read_url.'/'.$row->{$data->primary_key};
  1383. }
  1384. if(!$ajax)
  1385. {
  1386. $this->_add_js_vars(array('dialog_forms' => $this->config->dialog_forms));
  1387. $data->list_view = $this->_theme_view('list.php',$data,true);
  1388. $this->_theme_view('list_template.php',$data);
  1389. }
  1390. else
  1391. {
  1392. $this->set_echo_and_die();
  1393. $this->_theme_view('list.php',$data);
  1394. }
  1395. }
  1396. protected function exportToExcel($state_info = null)
  1397. {
  1398. $data = $this->get_common_data();
  1399. $data->order_by = $this->order_by;
  1400. $data->types = $this->get_field_types();
  1401. $data->list = $this->get_list();
  1402. $data->list = $this->change_list($data->list , $data->types);
  1403. $data->list = $this->change_list_add_actions($data->list);
  1404. $data->total_results = $this->get_total_results();
  1405. $data->columns = $this->get_columns();
  1406. $data->primary_key = $this->get_primary_key();
  1407. @ob_end_clean();
  1408. $this->_export_to_excel($data);
  1409. }
  1410. protected function _export_to_excel($data)
  1411. {
  1412. /**
  1413. * No need to use an external library here. The only bad thing without using external library is that Microsoft Excel is complaining
  1414. * that the file is in a different format than specified by the file extension. If you press "Yes" everything will be just fine.
  1415. * */
  1416. $string_to_export = "";
  1417. foreach($data->columns as $column){
  1418. $string_to_export .= $column->display_as."\t";
  1419. }
  1420. $string_to_export .= "\n";
  1421. foreach($data->list as $num_row => $row){
  1422. foreach($data->columns as $column){
  1423. $string_to_export .= $this->_trim_export_string($row->{$column->field_name})."\t";
  1424. }
  1425. $string_to_export .= "\n";
  1426. }
  1427. // Convert to UTF-16LE and Prepend BOM
  1428. $string_to_export = "\xFF\xFE" .mb_convert_encoding($string_to_export, 'UTF-16LE', 'UTF-8');
  1429. $filename = "export-".date("Y-m-d_H:i:s").".xls";
  1430. header('Content-type: application/vnd.ms-excel;charset=UTF-16LE');
  1431. header('Content-Disposition: attachment; filename='.$filename);
  1432. header("Cache-Control: no-cache");
  1433. echo $string_to_export;
  1434. die();
  1435. }
  1436. protected function print_webpage($state_info = null)
  1437. {
  1438. $data = $this->get_common_data();
  1439. $data->order_by = $this->order_by;
  1440. $data->types = $this->get_field_types();
  1441. $data->list = $this->get_list();
  1442. $data->list = $this->change_list($data->list , $data->types);
  1443. $data->list = $this->change_list_add_actions($data->list);
  1444. $data->total_results = $this->get_total_results();
  1445. $data->columns = $this->get_columns();
  1446. $data->primary_key = $this->get_primary_key();
  1447. @ob_end_clean();
  1448. $this->_print_webpage($data);
  1449. }
  1450. protected function _print_webpage($data)
  1451. {
  1452. $string_to_print = "<meta charset=\"utf-8\" /><style type=\"text/css\" >
  1453. #print-table{ color: #000; background: #fff; font-family: Verdana,Tahoma,Helvetica,sans-serif; font-size: 13px;}
  1454. #print-table table tr td, #print-table table tr th{ border: 1px solid black; border-bottom: none; border-right: none; padding: 4px 8px 4px 4px}
  1455. #print-table table{ border-bottom: 1px solid black; border-right: 1px solid black}
  1456. #print-table table tr th{text-align: left;background: #ddd}
  1457. #print-table table tr:nth-child(odd){background: #eee}
  1458. </style>";
  1459. $string_to_print .= "<div id='print-table'>";
  1460. $string_to_print .= '<table width="100%" cellpadding="0" cellspacing="0" ><tr>';
  1461. foreach($data->columns as $column){
  1462. $string_to_print .= "<th>".$column->display_as."</th>";
  1463. }
  1464. $string_to_print .= "</tr>";
  1465. foreach($data->list as $num_row => $row){
  1466. $string_to_print .= "<tr>";
  1467. foreach($data->columns as $column){
  1468. $string_to_print .= "<td>".$this->_trim_print_string($row->{$column->field_name})."</td>";
  1469. }
  1470. $string_to_print .= "</tr>";
  1471. }
  1472. $string_to_print .= "</table></div>";
  1473. echo $string_to_print;
  1474. die();
  1475. }
  1476. protected function _trim_export_string($value)
  1477. {
  1478. $value = str_replace(array("&nbsp;","&amp;","&gt;","&lt;"),array(" ","&",">","<"),$value);
  1479. return strip_tags(str_replace(array("\t","\n","\r"),"",$value));
  1480. }
  1481. protected function _trim_print_string($value)
  1482. {
  1483. $value = str_replace(array("&nbsp;","&amp;","&gt;","&lt;"),array(" ","&",">","<"),$value);
  1484. //If the value has only spaces and nothing more then add the whitespace html character
  1485. if(str_replace(" ","",$value) == "")
  1486. $value = "&nbsp;";
  1487. return strip_tags($value);
  1488. }
  1489. protected function set_echo_and_die()
  1490. {
  1491. $this->echo_and_die = true;
  1492. }
  1493. protected function unset_echo_and_die()
  1494. {
  1495. $this->echo_and_die = false;
  1496. }
  1497. protected function showListInfo()
  1498. {
  1499. $this->set_echo_and_die();
  1500. $total_results = (int)$this->get_total_results();
  1501. @ob_end_clean();
  1502. echo json_encode(array('total_results' => $total_results));
  1503. die();
  1504. }
  1505. protected function change_list_add_actions($list)
  1506. {
  1507. if(empty($this->actions))
  1508. return $list;
  1509. $primary_key = $this->get_primary_key();
  1510. foreach($list as $num_row => $row)
  1511. {
  1512. $actions_urls = array();
  1513. foreach($this->actions as $unique_id => $action)
  1514. {
  1515. if(!empty($action->url_callback))
  1516. {
  1517. $actions_urls[$unique_id] = call_user_func($action->url_callback, $row->$primary_key, $row);
  1518. }
  1519. else
  1520. {
  1521. $actions_urls[$unique_id] =
  1522. $action->url_has_http ?
  1523. $action->link_url.$row->$primary_key :
  1524. site_url($action->link_url.'/'.$row->$primary_key);
  1525. }
  1526. }
  1527. $row->action_urls = $actions_urls;
  1528. }
  1529. return $list;
  1530. }
  1531. protected function change_list($list,$types)
  1532. {
  1533. $primary_key = $this->get_primary_key();
  1534. $has_callbacks = !empty($this->callback_column) ? true : false;
  1535. $output_columns = $this->get_columns();
  1536. foreach($list as $num_row => $row)
  1537. {
  1538. foreach($output_columns as $column)
  1539. {
  1540. $field_name = $column->field_name;
  1541. $field_value = isset( $row->{$column->field_name} ) ? $row->{$column->field_name} : null;
  1542. if( $has_callbacks && isset($this->callback_column[$field_name]) )
  1543. $list[$num_row]->$field_name = call_user_func($this->callback_column[$field_name], $field_value, $row);
  1544. elseif(isset($types[$field_name]))
  1545. $list[$num_row]->$field_name = $this->change_list_value($types[$field_name] , $field_value);
  1546. else
  1547. $list[$num_row]->$field_name = $field_value;
  1548. }
  1549. }
  1550. return $list;
  1551. }
  1552. protected function showAddForm()
  1553. {
  1554. $this->set_js_lib($this->default_javascript_path.'/'.grocery_CRUD::JQUERY);
  1555. $data = $this->get_common_data();
  1556. $data->types = $this->get_field_types();
  1557. $data->list_url = $this->getListUrl();
  1558. $data->insert_url = $this->getInsertUrl();
  1559. $data->validation_url = $this->getValidationInsertUrl();
  1560. $data->input_fields = $this->get_add_input_fields();
  1561. $data->fields = $this->get_add_fields();
  1562. $data->hidden_fields = $this->get_add_hidden_fields();
  1563. $data->unset_back_to_list = $this->unset_back_to_list;
  1564. $data->unique_hash = $this->get_method_hash();
  1565. $data->is_ajax = $this->_is_ajax();
  1566. $this->_theme_view('add.php',$data);
  1567. $this->_inline_js("var js_date_format = '".$this->js_date_format."';");
  1568. $this->_get_ajax_results();
  1569. }
  1570. protected function showEditForm($state_info)
  1571. {
  1572. $this->set_js_lib($this->default_javascript_path.'/'.grocery_CRUD::JQUERY);
  1573. $data = $this->get_common_data();
  1574. $data->types = $this->get_field_types();
  1575. $data->field_values = $this->get_edit_values($state_info->primary_key);
  1576. $data->add_url = $this->getAddUrl();
  1577. $data->list_url = $this->getListUrl();
  1578. $data->update_url = $this->getUpdateUrl($state_info);
  1579. $data->delete_url = $this->getDeleteUrl($state_info);
  1580. $data->read_url = $this->getReadUrl($state_info->primary_key);
  1581. $data->input_fields = $this->get_edit_input_fields($data->field_values);
  1582. $data->unique_hash = $this->get_method_hash();
  1583. $data->fields = $this->get_edit_fields();
  1584. $data->hidden_fields = $this->get_edit_hidden_fields();
  1585. $data->unset_back_to_list = $this->unset_back_to_list;
  1586. $data->validation_url = $this->getValidationUpdateUrl($state_info->primary_key);
  1587. $data->is_ajax = $this->_is_ajax();
  1588. $this->_theme_view('edit.php',$data);
  1589. $this->_inline_js("var js_date_format = '".$this->js_date_format."';");
  1590. $this->_get_ajax_results();
  1591. }
  1592. protected function showReadForm($state_info)
  1593. {
  1594. $this->set_js_lib($this->default_javascript_path.'/'.grocery_CRUD::JQUERY);
  1595. $data = $this->get_common_data();
  1596. $data->types = $this->get_field_types();
  1597. $data->field_values = $this->get_edit_values($state_info->primary_key);
  1598. $data->add_url = $this->getAddUrl();
  1599. $data->list_url = $this->getListUrl();
  1600. $data->update_url = $this->getUpdateUrl($state_info);
  1601. $data->delete_url = $this->getDeleteUrl($state_info);
  1602. $data->read_url = $this->getReadUrl($state_info->primary_key);
  1603. $data->input_fields = $this->get_read_input_fields($data->field_values);
  1604. $data->unique_hash = $this->get_method_hash();
  1605. $data->fields = $this->get_read_fields();
  1606. $data->hidden_fields = $this->get_edit_hidden_fields();
  1607. $data->unset_back_to_list = $this->unset_back_to_list;
  1608. $data->validation_url = $this->getValidationUpdateUrl($state_info->primary_key);
  1609. $data->is_ajax = $this->_is_ajax();
  1610. $this->_theme_view('read.php',$data);
  1611. $this->_inline_js("var js_date_format = '".$this->js_date_format."';");
  1612. $this->_get_ajax_results();
  1613. }
  1614. protected function delete_layout($delete_result = true)
  1615. {
  1616. @ob_end_clean();
  1617. if($delete_result === false)
  1618. {
  1619. $error_message = '<p>'.$this->l('delete_error_message').'</p>';
  1620. echo json_encode(array('success' => $delete_result ,'error_message' => $error_message));
  1621. }
  1622. else
  1623. {
  1624. $success_message = '<p>'.$this->l('delete_success_message').'</p>';
  1625. echo json_encode(array('success' => true , 'success_message' => $success_message));
  1626. }
  1627. $this->set_echo_and_die();
  1628. }
  1629. protected function get_success_message_at_list($field_info = null)
  1630. {
  1631. if($field_info !== null && isset($field_info->success_message) && $field_info->success_message)
  1632. {
  1633. if(!empty($field_info->primary_key) && !$this->unset_edit)
  1634. {
  1635. return $this->l('insert_success_message')." <a class='go-to-edit-form' href='".$this->getEditUrl($field_info->primary_key)."'>".$this->l('form_edit')." {$this->subject}</a> ";
  1636. }
  1637. else
  1638. {
  1639. return $this->l('insert_success_message');
  1640. }
  1641. }
  1642. else
  1643. {
  1644. return null;
  1645. }
  1646. }
  1647. protected function insert_layout($insert_result = false)
  1648. {
  1649. @ob_end_clean();
  1650. if($insert_result === false)
  1651. {
  1652. echo json_encode(array('success' => false));
  1653. }
  1654. else
  1655. {
  1656. $success_message = '<p>'.$this->l('insert_success_message');
  1657. if(!$this->unset_back_to_list && !empty($insert_result) && !$this->unset_edit)
  1658. {
  1659. $success_message .= " <a class='go-to-edit-form' href='".$this->getEditUrl($insert_result)."'>".$this->l('form_edit')." {$this->subject}</a> ";
  1660. if (!$this->_is_ajax()) {
  1661. $success_message .= $this->l('form_or');
  1662. }
  1663. }
  1664. if(!$this->unset_back_to_list && !$this->_is_ajax())
  1665. {
  1666. $success_message .= " <a href='".$this->getListUrl()."'>".$this->l('form_go_back_to_list')."</a>";
  1667. }
  1668. $success_message .= '</p>';
  1669. echo json_encode(array(
  1670. 'success' => true ,
  1671. 'insert_primary_key' => $insert_result,
  1672. 'success_message' => $success_message,
  1673. 'success_list_url' => $this->getListSuccessUrl($insert_result)
  1674. ));
  1675. }
  1676. $this->set_echo_and_die();
  1677. }
  1678. protected function validation_layout($validation_result)
  1679. {
  1680. @ob_end_clean();
  1681. echo json_encode($validation_result);
  1682. $this->set_echo_and_die();
  1683. }
  1684. protected function upload_layout($upload_result, $field_name)
  1685. {
  1686. @ob_end_clean();
  1687. if($upload_result !== false && !is_string($upload_result) && empty($upload_result[0]->error))
  1688. {
  1689. echo json_encode(
  1690. (object)array(
  1691. 'success' => true,
  1692. 'files' => $upload_result
  1693. ));
  1694. }
  1695. else
  1696. {
  1697. $result = (object)array('success' => false);
  1698. if(is_string($upload_result))
  1699. $result->message = $upload_result;
  1700. if(!empty($upload_result[0]->error))
  1701. $result->message = $upload_result[0]->error;
  1702. echo json_encode($result);
  1703. }
  1704. $this->set_echo_and_die();
  1705. }
  1706. protected function delete_file_layout($upload_result)
  1707. {
  1708. @ob_end_clean();
  1709. if($upload_result !== false)
  1710. {
  1711. echo json_encode( (object)array( 'success' => true ) );
  1712. }
  1713. else
  1714. {
  1715. echo json_encode((object)array('success' => false));
  1716. }
  1717. $this->set_echo_and_die();
  1718. }
  1719. public function set_css($css_file)
  1720. {
  1721. $this->css_files[sha1($css_file)] = base_url().$css_file;
  1722. }
  1723. public function set_js($js_file)
  1724. {
  1725. $this->js_files[sha1($js_file)] = base_url().$js_file;
  1726. }
  1727. public function set_js_lib($js_file)
  1728. {
  1729. $this->js_lib_files[sha1($js_file)] = base_url().$js_file;
  1730. $this->js_files[sha1($js_file)] = base_url().$js_file;
  1731. }
  1732. public function set_js_config($js_file)
  1733. {
  1734. $this->js_config_files[sha1($js_file)] = base_url().$js_file;
  1735. $this->js_files[sha1($js_file)] = base_url().$js_file;
  1736. }
  1737. public function is_IE7()
  1738. {
  1739. return isset($_SERVER['HTTP_USER_AGENT'])
  1740. && (strpos($_SERVER['HTTP_USER_AGENT'], 'MSIE 7') !== false)
  1741. ? true : false;
  1742. }
  1743. public function get_css_files()
  1744. {
  1745. return $this->css_files;
  1746. }
  1747. public function get_js_files()
  1748. {
  1749. return $this->js_files;
  1750. }
  1751. public function get_js_lib_files()
  1752. {
  1753. return $this->js_lib_files;
  1754. }
  1755. public function get_js_config_files()
  1756. {
  1757. return $this->js_config_files;
  1758. }
  1759. /**
  1760. * Load Javascripts
  1761. **/
  1762. protected function load_js_fancybox()
  1763. {
  1764. $this->set_css($this->default_css_path.'/jquery_plugins/fancybox/jquery.fancybox.css');
  1765. $this->set_js_lib($this->default_javascript_path.'/jquery_plugins/jquery.fancybox-1.3.4.js');
  1766. $this->set_js_lib($this->default_javascript_path.'/jquery_plugins/jquery.easing-1.3.pack.js');
  1767. }
  1768. protected function load_js_chosen()
  1769. {
  1770. $this->set_css($this->default_css_path.'/jquery_plugins/chosen/chosen.css');
  1771. $this->set_js_lib($this->default_javascript_path.'/jquery_plugins/jquery.chosen.min.js');
  1772. }
  1773. protected function load_js_jqueryui()
  1774. {
  1775. $this->set_css($this->default_css_path.'/ui/simple/'.grocery_CRUD::JQUERY_UI_CSS);
  1776. $this->set_js_lib($this->default_javascript_path.'/jquery_plugins/ui/'.grocery_CRUD::JQUERY_UI_JS);
  1777. }
  1778. protected function load_js_uploader()
  1779. {
  1780. $this->set_css($this->default_css_path.'/ui/simple/'.grocery_CRUD::JQUERY_UI_CSS);
  1781. $this->set_css($this->default_css_path.'/jquery_plugins/file_upload/file-uploader.css');
  1782. $this->set_css($this->default_css_path.'/jquery_plugins/file_upload/jquery.fileupload-ui.css');
  1783. $this->set_js_lib($this->default_javascript_path.'/jquery_plugins/ui/'.grocery_CRUD::JQUERY_UI_JS);
  1784. $this->set_js_lib($this->default_javascript_path.'/jquery_plugins/tmpl.min.js');
  1785. $this->set_js_lib($this->default_javascript_path.'/jquery_plugins/load-image.min.js');
  1786. $this->set_js_lib($this->default_javascript_path.'/jquery_plugins/jquery.iframe-transport.js');
  1787. $this->set_js_lib($this->default_javascript_path.'/jquery_plugins/jquery.fileupload.js');
  1788. $this->set_js_config($this->default_javascript_path.'/jquery_plugins/config/jquery.fileupload.config.js');
  1789. }
  1790. protected function get_layout()
  1791. {
  1792. $js_files = $this->get_js_files();
  1793. $css_files = $this->get_css_files();
  1794. $js_lib_files = $this->get_js_lib_files();
  1795. $js_config_files = $this->get_js_config_files();
  1796. if ($this->unset_jquery) {
  1797. unset($js_files[sha1($this->default_javascript_path.'/'.grocery_CRUD::JQUERY)]);
  1798. }
  1799. if ($this->unset_jquery_ui) {
  1800. unset($css_files[sha1($this->default_css_path.'/ui/simple/'.grocery_CRUD::JQUERY_UI_CSS)]);
  1801. unset($js_files[sha1($this->default_javascript_path.'/jquery_plugins/ui/'.grocery_CRUD::JQUERY_UI_JS)]);
  1802. }
  1803. if ($this->unset_bootstrap) {
  1804. unset($js_files[sha1($this->default_theme_path.'/bootstrap/js/bootstrap/dropdown.js')]);
  1805. unset($js_files[sha1($this->default_theme_path.'/bootstrap/js/bootstrap/modal.js')]);
  1806. unset($js_files[sha1($this->default_theme_path.'/bootstrap/js/bootstrap/dropdown.min.js')]);
  1807. unset($js_files[sha1($this->default_theme_path.'/bootstrap/js/bootstrap/modal.min.js')]);
  1808. unset($css_files[sha1($this->default_theme_path.'/bootstrap/css/bootstrap/bootstrap.css')]);
  1809. unset($css_files[sha1($this->default_theme_path.'/bootstrap/css/bootstrap/bootstrap.min.css')]);
  1810. unset($css_files[sha1($this->default_theme_path.'/bootstrap-v4/css/bootstrap/bootstrap.css')]);
  1811. unset($css_files[sha1($this->default_theme_path.'/bootstrap-v4/css/bootstrap/bootstrap.min.css')]);
  1812. }
  1813. if($this->echo_and_die === false)
  1814. {
  1815. /** Initialize JavaScript variables */
  1816. $js_vars = array(
  1817. 'default_javascript_path' => base_url().$this->default_javascript_path,
  1818. 'default_css_path' => base_url().$this->default_css_path,
  1819. 'default_texteditor_path' => base_url().$this->default_texteditor_path,
  1820. 'default_theme_path' => base_url().$this->default_theme_path,
  1821. 'base_url' => base_url()
  1822. );
  1823. $this->_add_js_vars($js_vars);
  1824. return (object)array(
  1825. 'js_files' => $js_files,
  1826. 'js_lib_files' => $js_lib_files,
  1827. 'js_config_files' => $js_config_files,
  1828. 'css_files' => $css_files,
  1829. 'output' => $this->views_as_string,
  1830. );
  1831. }
  1832. elseif($this->echo_and_die === true)
  1833. {
  1834. echo $this->views_as_string;
  1835. die();
  1836. }
  1837. }
  1838. protected function update_layout($update_result = false, $state_info = null)
  1839. {
  1840. @ob_end_clean();
  1841. if($update_result === false)
  1842. {
  1843. echo json_encode(array('success' => $update_result));
  1844. }
  1845. else
  1846. {
  1847. $success_message = '<p>'.$this->l('update_success_message');
  1848. if(!$this->unset_back_to_list && !$this->_is_ajax())
  1849. {
  1850. $success_message .= " <a href='".$this->getListUrl()."'>".$this->l('form_go_back_to_list')."</a>";
  1851. }
  1852. $success_message .= '</p>';
  1853. echo json_encode(array(
  1854. 'success' => true ,
  1855. 'insert_primary_key' => $update_result,
  1856. 'success_message' => $success_message,
  1857. 'success_list_url' => $this->getListSuccessUrl($state_info->primary_key)
  1858. ));
  1859. }
  1860. $this->set_echo_and_die();
  1861. }
  1862. protected function get_integer_input($field_info,$value)
  1863. {
  1864. $this->set_js_lib($this->default_javascript_path.'/jquery_plugins/jquery.numeric.min.js');
  1865. $this->set_js_config($this->default_javascript_path.'/jquery_plugins/config/jquery.numeric.config.js');
  1866. $extra_attributes = '';
  1867. if(!empty($field_info->db_max_length))
  1868. $extra_attributes .= "maxlength='{$field_info->db_max_length}'";
  1869. $input = "<input id='field-{$field_info->name}' name='{$field_info->name}' type='text' value='$value' class='numeric form-control' $extra_attributes />";
  1870. return $input;
  1871. }
  1872. protected function get_true_false_input($field_info,$value)
  1873. {
  1874. $value_is_null = empty($value) && $value !== '0' && $value !== 0 ? true : false;
  1875. $input = "<div class='pretty-radio-buttons'>";
  1876. $true_string = is_array($field_info->extras) && array_key_exists(1,$field_info->extras) ? $field_info->extras[1] : $this->default_true_false_text[1];
  1877. $checked = $value === '1' || ($value_is_null && $field_info->default === '1') ? "checked = 'checked'" : "";
  1878. $input .=
  1879. "<div class=\"radio\"><label>
  1880. <input id='field-{$field_info->name}-true' type=\"radio\" name=\"{$field_info->name}\" value=\"1\" $checked />
  1881. $true_string
  1882. </label> </div>";
  1883. $false_string = is_array($field_info->extras) && array_key_exists(0,$field_info->extras) ? $field_info->extras[0] : $this->default_true_false_text[0];
  1884. $checked = $value === '0' || ($value_is_null && $field_info->default === '0') ? "checked = 'checked'" : "";
  1885. $input .=
  1886. "<div class=\"radio\"><label>
  1887. <input id='field-{$field_info->name}-false' type=\"radio\" name=\"{$field_info->name}\" value=\"0\" $checked />
  1888. $false_string
  1889. </label> </div>";
  1890. $input .= "</div>";
  1891. return $input;
  1892. }
  1893. protected function get_string_input($field_info,$value)
  1894. {
  1895. $value = !is_string($value) ? '' : str_replace('"',"&quot;",$value);
  1896. $extra_attributes = '';
  1897. if (!empty($field_info->db_max_length)) {
  1898. if (in_array($field_info->type, array("decimal", "float"))) {
  1899. $decimal_lentgh = explode(",", $field_info->db_max_length);
  1900. $decimal_lentgh = ((int)$decimal_lentgh[0]) + 1;
  1901. $extra_attributes .= "maxlength='" . $decimal_lentgh . "'";
  1902. } else {
  1903. $extra_attributes .= "maxlength='{$field_info->db_max_length}'";
  1904. }
  1905. }
  1906. $input = "<input id='field-{$field_info->name}' class='form-control' name='{$field_info->name}' type='text' value=\"$value\" $extra_attributes />";
  1907. return $input;
  1908. }
  1909. protected function get_text_input($field_info,$value)
  1910. {
  1911. if($field_info->extras == 'text_editor')
  1912. {
  1913. $editor = $this->config->default_text_editor;
  1914. switch ($editor) {
  1915. case 'ckeditor':
  1916. $this->set_js_lib($this->default_texteditor_path.'/ckeditor/ckeditor.js');
  1917. $this->set_js_lib($this->default_texteditor_path.'/ckeditor/adapters/jquery.js');
  1918. $this->set_js_config($this->default_javascript_path.'/jquery_plugins/config/jquery.ckeditor.config.js');
  1919. break;
  1920. case 'tinymce':
  1921. $this->set_js_lib($this->default_texteditor_path.'/tiny_mce/jquery.tinymce.js');
  1922. $this->set_js_config($this->default_javascript_path.'/jquery_plugins/config/jquery.tine_mce.config.js');
  1923. break;
  1924. case 'markitup':
  1925. $this->set_css($this->default_texteditor_path.'/markitup/skins/markitup/style.css');
  1926. $this->set_css($this->default_texteditor_path.'/markitup/sets/default/style.css');
  1927. $this->set_js_lib($this->default_texteditor_path.'/markitup/jquery.markitup.js');
  1928. $this->set_js_config($this->default_javascript_path.'/jquery_plugins/config/jquery.markitup.config.js');
  1929. break;
  1930. }
  1931. $class_name = $this->config->text_editor_type == 'minimal' ? 'mini-texteditor' : 'texteditor';
  1932. $input = "<textarea id='field-{$field_info->name}' name='{$field_info->name}' class='$class_name' >$value</textarea>";
  1933. }
  1934. else
  1935. {
  1936. $input = "<textarea id='field-{$field_info->name}' name='{$field_info->name}' class='form-control'>$value</textarea>";
  1937. }
  1938. return $input;
  1939. }
  1940. protected function get_datetime_input($field_info,$value)
  1941. {
  1942. $this->set_css($this->default_css_path.'/ui/simple/'.grocery_CRUD::JQUERY_UI_CSS);
  1943. $this->set_css($this->default_css_path.'/jquery_plugins/jquery.ui.datetime.css');
  1944. $this->set_css($this->default_css_path.'/jquery_plugins/jquery-ui-timepicker-addon.css');
  1945. $this->set_js_lib($this->default_javascript_path.'/jquery_plugins/ui/'.grocery_CRUD::JQUERY_UI_JS);
  1946. $this->set_js_lib($this->default_javascript_path.'/jquery_plugins/jquery-ui-timepicker-addon.js');
  1947. if($this->language !== 'english')
  1948. {
  1949. include($this->default_config_path.'/language_alias.php');
  1950. if(array_key_exists($this->language, $language_alias))
  1951. {
  1952. $i18n_date_js_file = $this->default_javascript_path.'/jquery_plugins/ui/i18n/datepicker/jquery.ui.datepicker-'.$language_alias[$this->language].'.js';
  1953. if(file_exists($i18n_date_js_file))
  1954. {
  1955. $this->set_js_lib($i18n_date_js_file);
  1956. }
  1957. $i18n_datetime_js_file = $this->default_javascript_path.'/jquery_plugins/ui/i18n/timepicker/jquery-ui-timepicker-'.$language_alias[$this->language].'.js';
  1958. if(file_exists($i18n_datetime_js_file))
  1959. {
  1960. $this->set_js_lib($i18n_datetime_js_file);
  1961. }
  1962. }
  1963. }
  1964. $this->set_js_config($this->default_javascript_path.'/jquery_plugins/config/jquery-ui-timepicker-addon.config.js');
  1965. if(!empty($value) && $value != '0000-00-00 00:00:00' && $value != '1970-01-01 00:00:00'){
  1966. list($year,$month,$day) = explode('-',substr($value,0,10));
  1967. $date = date($this->php_date_format, mktime(0,0,0,$month,$day,$year));
  1968. $datetime = $date.substr($value,10);
  1969. }
  1970. else
  1971. {
  1972. $datetime = '';
  1973. }
  1974. $input = "<input id='field-{$field_info->name}' name='{$field_info->name}' type='text' value='$datetime' maxlength='19' class='datetime-input form-control' />
  1975. <a class='datetime-input-clear' tabindex='-1'>".$this->l('form_button_clear')."</a>
  1976. ({$this->ui_date_format}) hh:mm:ss";
  1977. return $input;
  1978. }
  1979. protected function get_hidden_input($field_info,$value)
  1980. {
  1981. if($field_info->extras !== null && $field_info->extras != false)
  1982. $value = $field_info->extras;
  1983. $input = "<input id='field-{$field_info->name}' type='hidden' name='{$field_info->name}' value='$value' />";
  1984. return $input;
  1985. }
  1986. protected function get_password_input($field_info,$value)
  1987. {
  1988. $value = !is_string($value) ? '' : $value;
  1989. $extra_attributes = '';
  1990. if(!empty($field_info->db_max_length))
  1991. $extra_attributes .= "maxlength='{$field_info->db_max_length}'";
  1992. $input = "<input id='field-{$field_info->name}' class='form-control' name='{$field_info->name}' type='password' value='$value' $extra_attributes />";
  1993. return $input;
  1994. }
  1995. protected function get_date_input($field_info,$value)
  1996. {
  1997. $this->set_css($this->default_css_path.'/ui/simple/'.grocery_CRUD::JQUERY_UI_CSS);
  1998. $this->set_js_lib($this->default_javascript_path.'/jquery_plugins/ui/'.grocery_CRUD::JQUERY_UI_JS);
  1999. if($this->language !== 'english')
  2000. {
  2001. include($this->default_config_path.'/language_alias.php');
  2002. if(array_key_exists($this->language, $language_alias))
  2003. {
  2004. $i18n_date_js_file = $this->default_javascript_path.'/jquery_plugins/ui/i18n/datepicker/jquery.ui.datepicker-'.$language_alias[$this->language].'.js';
  2005. if(file_exists($i18n_date_js_file))
  2006. {
  2007. $this->set_js_lib($i18n_date_js_file);
  2008. }
  2009. }
  2010. }
  2011. $this->set_js_config($this->default_javascript_path.'/jquery_plugins/config/jquery.datepicker.config.js');
  2012. if(!empty($value) && $value != '0000-00-00' && $value != '1970-01-01')
  2013. {
  2014. list($year,$month,$day) = explode('-',substr($value,0,10));
  2015. $date = date($this->php_date_format, mktime(0,0,0,$month,$day,$year));
  2016. }
  2017. else
  2018. {
  2019. $date = '';
  2020. }
  2021. $input = "<input id='field-{$field_info->name}' name='{$field_info->name}' type='text' value='$date' maxlength='10' class='datepicker-input form-control' />
  2022. <a class='datepicker-input-clear' tabindex='-1'>".$this->l('form_button_clear')."</a> (".$this->ui_date_format.")";
  2023. return $input;
  2024. }
  2025. protected function get_dropdown_input($field_info,$value)
  2026. {
  2027. $this->load_js_chosen();
  2028. $this->set_js_config($this->default_javascript_path.'/jquery_plugins/config/jquery.chosen.config.js');
  2029. $select_title = str_replace('{field_display_as}',$field_info->display_as,$this->l('set_relation_title'));
  2030. $input = "<select id='field-{$field_info->name}' name='{$field_info->name}' class='chosen-select' data-placeholder='".$select_title."'>";
  2031. $options = array('' => '') + $field_info->extras;
  2032. foreach($options as $option_value => $option_label)
  2033. {
  2034. $selected = !empty($value) && $value == $option_value ? "selected='selected'" : '';
  2035. $input .= "<option value='$option_value' $selected >$option_label</option>";
  2036. }
  2037. $input .= "</select>";
  2038. return $input;
  2039. }
  2040. protected function get_enum_input($field_info,$value)
  2041. {
  2042. $this->load_js_chosen();
  2043. $this->set_js_config($this->default_javascript_path.'/jquery_plugins/config/jquery.chosen.config.js');
  2044. $select_title = str_replace('{field_display_as}',$field_info->display_as,$this->l('set_relation_title'));
  2045. $input = "<select id='field-{$field_info->name}' name='{$field_info->name}' class='chosen-select' data-placeholder='".$select_title."'>";
  2046. $options_array = $field_info->extras !== false && is_array($field_info->extras)? $field_info->extras : explode("','",substr($field_info->db_max_length,1,-1));
  2047. $options_array = array('' => '') + $options_array;
  2048. foreach($options_array as $option)
  2049. {
  2050. $selected = !empty($value) && $value == $option ? "selected='selected'" : '';
  2051. $input .= "<option value='$option' $selected >$option</option>";
  2052. }
  2053. $input .= "</select>";
  2054. return $input;
  2055. }
  2056. protected function get_readonly_input($field_info, $value)
  2057. {
  2058. $read_only_value = "&nbsp;";
  2059. if (!empty($value) && !is_array($value)) {
  2060. $read_only_value = $value;
  2061. } elseif (is_array($value)) {
  2062. $all_values = array_values($value);
  2063. $read_only_value = implode(", ",$all_values);
  2064. }
  2065. return '<div id="field-'.$field_info->name.'" class="readonly_label">'.$read_only_value.'</div>';
  2066. }
  2067. protected function get_set_input($field_info,$value)
  2068. {
  2069. $this->load_js_chosen();
  2070. $this->set_js_config($this->default_javascript_path.'/jquery_plugins/config/jquery.chosen.config.js');
  2071. $options_array = $field_info->extras !== false && is_array($field_info->extras)? $field_info->extras : explode("','",substr($field_info->db_max_length,1,-1));
  2072. $selected_values = !empty($value) ? explode(",",$value) : array();
  2073. $select_title = str_replace('{field_display_as}',$field_info->display_as,$this->l('set_relation_title'));
  2074. $input = "<select id='field-{$field_info->name}' name='{$field_info->name}[]' multiple='multiple' size='8' class='chosen-multiple-select' data-placeholder='$select_title' style='width:510px;' >";
  2075. foreach($options_array as $option)
  2076. {
  2077. $selected = !empty($value) && in_array($option,$selected_values) ? "selected='selected'" : '';
  2078. $input .= "<option value='$option' $selected >$option</option>";
  2079. }
  2080. $input .= "</select>";
  2081. return $input;
  2082. }
  2083. protected function get_multiselect_input($field_info,$value)
  2084. {
  2085. $this->load_js_chosen();
  2086. $this->set_js_config($this->default_javascript_path.'/jquery_plugins/config/jquery.chosen.config.js');
  2087. $options_array = $field_info->extras;
  2088. $selected_values = !empty($value) ? explode(",",$value) : array();
  2089. $select_title = str_replace('{field_display_as}',$field_info->display_as,$this->l('set_relation_title'));
  2090. $input = "<select id='field-{$field_info->name}' name='{$field_info->name}[]' multiple='multiple' size='8' class='chosen-multiple-select' data-placeholder='$select_title' style='width:510px;' >";
  2091. foreach($options_array as $option_value => $option_label)
  2092. {
  2093. $selected = !empty($value) && in_array($option_value,$selected_values) ? "selected='selected'" : '';
  2094. $input .= "<option value='$option_value' $selected >$option_label</option>";
  2095. }
  2096. $input .= "</select>";
  2097. return $input;
  2098. }
  2099. protected function get_relation_input($field_info,$value)
  2100. {
  2101. $this->load_js_chosen();
  2102. $this->set_js_config($this->default_javascript_path.'/jquery_plugins/config/jquery.chosen.config.js');
  2103. $ajax_limitation = 10000;
  2104. $total_rows = $this->get_relation_total_rows($field_info->extras);
  2105. //Check if we will use ajax for our queries or just clien-side javascript
  2106. $using_ajax = $total_rows > $ajax_limitation ? true : false;
  2107. //We will not use it for now. It is not ready yet. Probably we will have this functionality at version 1.4
  2108. $using_ajax = false;
  2109. //If total rows are more than the limitation, use the ajax plugin
  2110. $ajax_or_not_class = $using_ajax ? 'chosen-select' : 'chosen-select';
  2111. $this->_inline_js("var ajax_relation_url = '".$this->getAjaxRelationUrl()."';\n");
  2112. $select_title = str_replace('{field_display_as}',$field_info->display_as,$this->l('set_relation_title'));
  2113. $input = "<select id='field-{$field_info->name}' name='{$field_info->name}' class='$ajax_or_not_class' data-placeholder='$select_title' style='width:300px'>";
  2114. $input .= "<option value=''></option>";
  2115. if(!$using_ajax)
  2116. {
  2117. $options_array = $this->get_relation_array($field_info->extras);
  2118. foreach($options_array as $option_value => $option)
  2119. {
  2120. $selected = !empty($value) && $value == $option_value ? "selected='selected'" : '';
  2121. $input .= "<option value='$option_value' $selected >$option</option>";
  2122. }
  2123. }
  2124. elseif(!empty($value) || (is_numeric($value) && $value == '0') ) //If it's ajax then we only need the selected items and not all the items
  2125. {
  2126. $selected_options_array = $this->get_relation_array($field_info->extras, $value);
  2127. foreach($selected_options_array as $option_value => $option)
  2128. {
  2129. $input .= "<option value='$option_value'selected='selected' >$option</option>";
  2130. }
  2131. }
  2132. $input .= "</select>";
  2133. return $input;
  2134. }
  2135. protected function get_relation_readonly_input($field_info,$value)
  2136. {
  2137. $options_array = $this->get_relation_array($field_info->extras);
  2138. $value = isset($options_array[$value]) ? $options_array[$value] : '';
  2139. return $this->get_readonly_input($field_info, $value);
  2140. }
  2141. protected function get_upload_file_readonly_input($field_info,$value)
  2142. {
  2143. $file = $file_url = base_url().$field_info->extras->upload_path.'/'.$value;
  2144. $value = !empty($value) ? '<a href="'.$file.'" target="_blank">'.$value.'</a>' : '';
  2145. return $this->get_readonly_input($field_info, $value);
  2146. }
  2147. protected function get_relation_n_n_input($field_info_type, $selected_values)
  2148. {
  2149. $has_priority_field = !empty($field_info_type->extras->priority_field_relation_table) ? true : false;
  2150. $is_ie_7 = isset($_SERVER['HTTP_USER_AGENT']) && (strpos($_SERVER['HTTP_USER_AGENT'], 'MSIE 7') !== false) ? true : false;
  2151. if($has_priority_field || $is_ie_7)
  2152. {
  2153. $this->set_css($this->default_css_path.'/ui/simple/'.grocery_CRUD::JQUERY_UI_CSS);
  2154. $this->set_css($this->default_css_path.'/jquery_plugins/ui.multiselect.css');
  2155. $this->set_js_lib($this->default_javascript_path.'/jquery_plugins/ui/'.grocery_CRUD::JQUERY_UI_JS);
  2156. $this->set_js_lib($this->default_javascript_path.'/jquery_plugins/ui.multiselect.min.js');
  2157. $this->set_js_config($this->default_javascript_path.'/jquery_plugins/config/jquery.multiselect.js');
  2158. if($this->language !== 'english')
  2159. {
  2160. include($this->default_config_path.'/language_alias.php');
  2161. if(array_key_exists($this->language, $language_alias))
  2162. {
  2163. $i18n_date_js_file = $this->default_javascript_path.'/jquery_plugins/ui/i18n/multiselect/ui-multiselect-'.$language_alias[$this->language].'.js';
  2164. if(file_exists($i18n_date_js_file))
  2165. {
  2166. $this->set_js_lib($i18n_date_js_file);
  2167. }
  2168. }
  2169. }
  2170. }
  2171. else
  2172. {
  2173. $this->set_css($this->default_css_path.'/jquery_plugins/chosen/chosen.css');
  2174. $this->set_js_lib($this->default_javascript_path.'/jquery_plugins/jquery.chosen.min.js');
  2175. $this->set_js_config($this->default_javascript_path.'/jquery_plugins/config/jquery.chosen.config.js');
  2176. }
  2177. $this->_inline_js("var ajax_relation_url = '".$this->getAjaxRelationUrl()."';\n");
  2178. $field_info = $this->relation_n_n[$field_info_type->name]; //As we use this function the relation_n_n exists, so don't need to check
  2179. $unselected_values = $this->get_relation_n_n_unselected_array($field_info, $selected_values);
  2180. if(empty($unselected_values) && empty($selected_values))
  2181. {
  2182. $input = "Please add {$field_info_type->display_as} first";
  2183. }
  2184. else
  2185. {
  2186. $css_class = $has_priority_field || $is_ie_7 ? 'multiselect': 'chosen-multiple-select';
  2187. $width_style = $has_priority_field || $is_ie_7 ? '' : 'width:510px;';
  2188. $select_title = str_replace('{field_display_as}',$field_info_type->display_as,$this->l('set_relation_title'));
  2189. $input = "<select id='field-{$field_info_type->name}' name='{$field_info_type->name}[]' multiple='multiple' size='8' class='$css_class' data-placeholder='$select_title' style='$width_style' >";
  2190. if(!empty($unselected_values))
  2191. foreach($unselected_values as $id => $name)
  2192. {
  2193. $input .= "<option value='$id'>$name</option>";
  2194. }
  2195. if(!empty($selected_values))
  2196. foreach($selected_values as $id => $name)
  2197. {
  2198. $input .= "<option value='$id' selected='selected'>$name</option>";
  2199. }
  2200. $input .= "</select>";
  2201. }
  2202. return $input;
  2203. }
  2204. protected function _convert_bytes_ui_to_bytes($bytes_ui)
  2205. {
  2206. $bytes_ui = str_replace(' ','',$bytes_ui);
  2207. if(strstr($bytes_ui,'MB'))
  2208. $bytes = (int)(str_replace('MB','',$bytes_ui))*1024*1024;
  2209. elseif(strstr($bytes_ui,'KB'))
  2210. $bytes = (int)(str_replace('KB','',$bytes_ui))*1024;
  2211. elseif(strstr($bytes_ui,'B'))
  2212. $bytes = (int)(str_replace('B','',$bytes_ui));
  2213. else
  2214. $bytes = (int)($bytes_ui);
  2215. return $bytes;
  2216. }
  2217. protected function get_upload_file_input($field_info, $value)
  2218. {
  2219. $this->load_js_uploader();
  2220. //Fancybox
  2221. $this->load_js_fancybox();
  2222. $this->set_js_config($this->default_javascript_path.'/jquery_plugins/config/jquery.fancybox.config.js');
  2223. $unique = mt_rand();
  2224. $allowed_files = $this->config->file_upload_allow_file_types;
  2225. $allowed_files_ui = '.'.str_replace('|',',.',$allowed_files);
  2226. $max_file_size_ui = $this->config->file_upload_max_file_size;
  2227. $max_file_size_bytes = $this->_convert_bytes_ui_to_bytes($max_file_size_ui);
  2228. $this->_inline_js('
  2229. var upload_info_'.$unique.' = {
  2230. accepted_file_types: /(\\.|\\/)('.$allowed_files.')$/i,
  2231. accepted_file_types_ui : "'.$allowed_files_ui.'",
  2232. max_file_size: '.$max_file_size_bytes.',
  2233. max_file_size_ui: "'.$max_file_size_ui.'"
  2234. };
  2235. var string_upload_file = "'.$this->l('form_upload_a_file').'";
  2236. var string_delete_file = "'.$this->l('string_delete_file').'";
  2237. var string_progress = "'.$this->l('string_progress').'";
  2238. var error_on_uploading = "'.$this->l('error_on_uploading').'";
  2239. var message_prompt_delete_file = "'.$this->l('message_prompt_delete_file').'";
  2240. var error_max_number_of_files = "'.$this->l('error_max_number_of_files').'";
  2241. var error_accept_file_types = "'.$this->l('error_accept_file_types').'";
  2242. var error_max_file_size = "'.str_replace("{max_file_size}",$max_file_size_ui,$this->l('error_max_file_size')).'";
  2243. var error_min_file_size = "'.$this->l('error_min_file_size').'";
  2244. var base_url = "'.base_url().'";
  2245. var upload_a_file_string = "'.$this->l('form_upload_a_file').'";
  2246. ');
  2247. $uploader_display_none = empty($value) ? "" : "display:none;";
  2248. $file_display_none = empty($value) ? "display:none;" : "";
  2249. $is_image = !empty($value) &&
  2250. ( substr($value,-4) == '.jpg'
  2251. || substr($value,-4) == '.png'
  2252. || substr($value,-5) == '.jpeg'
  2253. || substr($value,-4) == '.gif'
  2254. || substr($value,-5) == '.tiff')
  2255. ? true : false;
  2256. $image_class = $is_image ? 'image-thumbnail' : '';
  2257. $input = '<span class="fileinput-button qq-upload-button" id="upload-button-'.$unique.'" style="'.$uploader_display_none.'">
  2258. <span>'.$this->l('form_upload_a_file').'</span>
  2259. <input type="file" name="'.$this->_unique_field_name($field_info->name).'" class="gc-file-upload" rel="'.$this->getUploadUrl($field_info->name).'" id="'.$unique.'">
  2260. <input class="hidden-upload-input" type="hidden" name="'.$field_info->name.'" value="'.$value.'" rel="'.$this->_unique_field_name($field_info->name).'" />
  2261. </span>';
  2262. $this->set_css($this->default_css_path.'/jquery_plugins/file_upload/fileuploader.css');
  2263. $file_url = base_url().$field_info->extras->upload_path.'/'.$value;
  2264. $input .= "<div id='uploader_$unique' rel='$unique' class='grocery-crud-uploader' style='$uploader_display_none'></div>";
  2265. $input .= "<div id='success_$unique' class='upload-success-url' style='$file_display_none padding-top:7px;'>";
  2266. $input .= "<a href='".$file_url."' id='file_$unique' class='open-file";
  2267. $input .= $is_image ? " $image_class'><img src='".$file_url."' height='50px'>" : "' target='_blank'>$value";
  2268. $input .= "</a> ";
  2269. $input .= "<a href='javascript:void(0)' id='delete_$unique' class='delete-anchor'>".$this->l('form_upload_delete')."</a> ";
  2270. $input .= "</div><div style='clear:both'></div>";
  2271. $input .= "<div id='loading-$unique' style='display:none'><span id='upload-state-message-$unique'></span> <span class='qq-upload-spinner'></span> <span id='progress-$unique'></span></div>";
  2272. $input .= "<div style='display:none'><a href='".$this->getUploadUrl($field_info->name)."' id='url_$unique'></a></div>";
  2273. $input .= "<div style='display:none'><a href='".$this->getFileDeleteUrl($field_info->name)."' id='delete_url_$unique' rel='$value' ></a></div>";
  2274. return $input;
  2275. }
  2276. protected function get_add_hidden_fields()
  2277. {
  2278. return $this->add_hidden_fields;
  2279. }
  2280. protected function get_edit_hidden_fields()
  2281. {
  2282. return $this->edit_hidden_fields;
  2283. }
  2284. protected function get_add_input_fields($field_values = null)
  2285. {
  2286. $fields = $this->get_add_fields();
  2287. $types = $this->get_field_types();
  2288. $input_fields = array();
  2289. foreach($fields as $field_num => $field)
  2290. {
  2291. $field_info = $types[$field->field_name];
  2292. $field_value = !empty($field_values) && isset($field_values->{$field->field_name}) ? $field_values->{$field->field_name} : null;
  2293. if(!isset($this->callback_add_field[$field->field_name]))
  2294. {
  2295. $field_input = $this->get_field_input($field_info, $field_value);
  2296. }
  2297. else
  2298. {
  2299. $field_input = $field_info;
  2300. $field_input->input = call_user_func($this->callback_add_field[$field->field_name], $field_value, null, $field_info);
  2301. }
  2302. switch ($field_info->crud_type) {
  2303. case 'invisible':
  2304. unset($this->add_fields[$field_num]);
  2305. unset($fields[$field_num]);
  2306. continue;
  2307. break;
  2308. case 'hidden':
  2309. $this->add_hidden_fields[] = $field_input;
  2310. unset($this->add_fields[$field_num]);
  2311. unset($fields[$field_num]);
  2312. continue;
  2313. break;
  2314. }
  2315. $input_fields[$field->field_name] = $field_input;
  2316. }
  2317. return $input_fields;
  2318. }
  2319. protected function get_edit_input_fields($field_values = null)
  2320. {
  2321. $fields = $this->get_edit_fields();
  2322. $types = $this->get_field_types();
  2323. $input_fields = array();
  2324. foreach($fields as $field_num => $field)
  2325. {
  2326. $field_info = $types[$field->field_name];
  2327. $field_value = !empty($field_values) && isset($field_values->{$field->field_name}) ? $field_values->{$field->field_name} : null;
  2328. if(!isset($this->callback_edit_field[$field->field_name]))
  2329. {
  2330. $field_input = $this->get_field_input($field_info, $field_value);
  2331. }
  2332. else
  2333. {
  2334. $primary_key = $this->getStateInfo()->primary_key;
  2335. $field_input = $field_info;
  2336. $field_input->input = call_user_func($this->callback_edit_field[$field->field_name], $field_value, $primary_key, $field_info, $field_values);
  2337. }
  2338. switch ($field_info->crud_type) {
  2339. case 'invisible':
  2340. unset($this->edit_fields[$field_num]);
  2341. unset($fields[$field_num]);
  2342. continue;
  2343. break;
  2344. case 'hidden':
  2345. $this->edit_hidden_fields[] = $field_input;
  2346. unset($this->edit_fields[$field_num]);
  2347. unset($fields[$field_num]);
  2348. continue;
  2349. break;
  2350. }
  2351. $input_fields[$field->field_name] = $field_input;
  2352. }
  2353. return $input_fields;
  2354. }
  2355. protected function get_read_input_fields($field_values = null)
  2356. {
  2357. $read_fields = $this->get_read_fields();
  2358. $this->field_types = null;
  2359. $this->required_fields = null;
  2360. $read_inputs = array();
  2361. foreach ($read_fields as $field) {
  2362. if (!empty($this->change_field_type)
  2363. && isset($this->change_field_type[$field->field_name])
  2364. && $this->change_field_type[$field->field_name]->type == 'hidden') {
  2365. continue;
  2366. }
  2367. $this->field_type($field->field_name, 'readonly');
  2368. }
  2369. $fields = $this->get_read_fields();
  2370. $types = $this->get_field_types();
  2371. $input_fields = array();
  2372. foreach($fields as $field_num => $field)
  2373. {
  2374. $field_info = $types[$field->field_name];
  2375. $field_value = !empty($field_values) && isset($field_values->{$field->field_name}) ? $field_values->{$field->field_name} : null;
  2376. if(!isset($this->callback_read_field[$field->field_name]))
  2377. {
  2378. $field_input = $this->get_field_input($field_info, $field_value);
  2379. }
  2380. else
  2381. {
  2382. $primary_key = $this->getStateInfo()->primary_key;
  2383. $field_input = $field_info;
  2384. $field_input->input = call_user_func($this->callback_read_field[$field->field_name], $field_value, $primary_key, $field_info, $field_values);
  2385. }
  2386. switch ($field_info->crud_type) {
  2387. case 'invisible':
  2388. unset($this->read_fields[$field_num]);
  2389. unset($fields[$field_num]);
  2390. continue;
  2391. break;
  2392. case 'hidden':
  2393. $this->read_hidden_fields[] = $field_input;
  2394. unset($this->read_fields[$field_num]);
  2395. unset($fields[$field_num]);
  2396. continue;
  2397. break;
  2398. }
  2399. $input_fields[$field->field_name] = $field_input;
  2400. }
  2401. return $input_fields;
  2402. }
  2403. protected function setThemeBasics()
  2404. {
  2405. $this->theme_path = $this->default_theme_path;
  2406. if(substr($this->theme_path,-1) != '/')
  2407. $this->theme_path = $this->theme_path.'/';
  2408. include($this->theme_path.$this->theme.'/config.php');
  2409. $this->theme_config = $config;
  2410. }
  2411. public function set_theme($theme = null)
  2412. {
  2413. $this->theme = $theme;
  2414. return $this;
  2415. }
  2416. protected function _get_ajax_results()
  2417. {
  2418. //This is a $_POST request rather that $_GET request , because
  2419. //Codeigniter doesn't like the $_GET requests so much!
  2420. if ($this->_is_ajax()) {
  2421. @ob_end_clean();
  2422. $results= (object)array(
  2423. 'output' => $this->views_as_string,
  2424. 'js_files' => array_values($this->get_js_files()),
  2425. 'js_lib_files' => array_values($this->get_js_lib_files()),
  2426. 'js_config_files' => array_values($this->get_js_config_files()),
  2427. 'css_files' => array_values($this->get_css_files())
  2428. );
  2429. echo json_encode($results);
  2430. die;
  2431. }
  2432. //else just continue
  2433. }
  2434. protected function _is_ajax()
  2435. {
  2436. return array_key_exists('is_ajax', $_POST) && $_POST['is_ajax'] == 'true' ? true: false;
  2437. }
  2438. protected function _theme_view($view, $vars = array(), $return = FALSE)
  2439. {
  2440. $vars = (is_object($vars)) ? get_object_vars($vars) : $vars;
  2441. $file_exists = FALSE;
  2442. $ext = pathinfo($view, PATHINFO_EXTENSION);
  2443. $file = ($ext == '') ? $view.'.php' : $view;
  2444. $view_file = $this->theme_path.$this->theme.'/views/';
  2445. if (file_exists($view_file.$file))
  2446. {
  2447. $path = $view_file.$file;
  2448. $file_exists = TRUE;
  2449. }
  2450. if ( ! $file_exists)
  2451. {
  2452. throw new Exception('Unable to load the requested file: '.$file, 16);
  2453. }
  2454. extract($vars);
  2455. #region buffering...
  2456. ob_start();
  2457. include($path);
  2458. $buffer = ob_get_contents();
  2459. @ob_end_clean();
  2460. #endregion
  2461. if ($return === TRUE)
  2462. {
  2463. return $buffer;
  2464. }
  2465. $this->views_as_string .= $buffer;
  2466. }
  2467. protected function _inline_js($inline_js = '')
  2468. {
  2469. $this->views_as_string .= "<script type=\"text/javascript\">\n{$inline_js}\n</script>\n";
  2470. }
  2471. protected function _add_js_vars($js_vars = array())
  2472. {
  2473. $javascript_as_string = "<script type=\"text/javascript\">\n";
  2474. foreach ($js_vars as $js_var => $js_value) {
  2475. $javascript_as_string .= "\tvar $js_var = '$js_value';\n";
  2476. }
  2477. $javascript_as_string .= "\n</script>\n";
  2478. $this->views_as_string .= $javascript_as_string;
  2479. }
  2480. protected function get_views_as_string()
  2481. {
  2482. if(!empty($this->views_as_string))
  2483. return $this->views_as_string;
  2484. else
  2485. return null;
  2486. }
  2487. }
  2488. /**
  2489. * PHP grocery CRUD
  2490. *
  2491. * LICENSE
  2492. *
  2493. * Grocery CRUD is released with dual licensing, using the GPL v3 (license-gpl3.txt) and the MIT license (license-mit.txt).
  2494. * You don't have to do anything special to choose one license or the other and you don't have to notify anyone which license you are using.
  2495. * Please see the corresponding license file for details of these licenses.
  2496. * You are free to use, modify and distribute this software, but all copyright information must remain.
  2497. *
  2498. * @package grocery CRUD
  2499. * @copyright Copyright (c) 2010 through 2014, John Skoumbourdis
  2500. * @license https://github.com/scoumbourdis/grocery-crud/blob/master/license-grocery-crud.txt
  2501. * @author John Skoumbourdis <scoumbourdisj@gmail.com>
  2502. */
  2503. // ------------------------------------------------------------------------
  2504. /**
  2505. * PHP grocery States
  2506. *
  2507. * States of grocery CRUD
  2508. *
  2509. * @package grocery CRUD
  2510. * @author John Skoumbourdis <scoumbourdisj@gmail.com>
  2511. * @version 1.5.8
  2512. */
  2513. class grocery_CRUD_States extends grocery_CRUD_Layout
  2514. {
  2515. const STATE_UNKNOWN = 0;
  2516. const STATE_LIST = 1;
  2517. const STATE_ADD = 2;
  2518. const STATE_EDIT = 3;
  2519. const STATE_DELETE = 4;
  2520. const STATE_INSERT = 5;
  2521. const STATE_READ = 18;
  2522. const STATE_DELETE_MULTIPLE = '19';
  2523. protected $states = array(
  2524. 0 => 'unknown',
  2525. 1 => 'list',
  2526. 2 => 'add',
  2527. 3 => 'edit',
  2528. 4 => 'delete',
  2529. 5 => 'insert',
  2530. 6 => 'update',
  2531. 7 => 'ajax_list',
  2532. 8 => 'ajax_list_info',
  2533. 9 => 'insert_validation',
  2534. 10 => 'update_validation',
  2535. 11 => 'upload_file',
  2536. 12 => 'delete_file',
  2537. 13 => 'ajax_relation',
  2538. 14 => 'ajax_relation_n_n',
  2539. 15 => 'success',
  2540. 16 => 'export',
  2541. 17 => 'print',
  2542. 18 => 'read',
  2543. 19 => 'delete_multiple'
  2544. );
  2545. public function getStateInfo()
  2546. {
  2547. $state_code = $this->getStateCode();
  2548. $segment_object = $this->get_state_info_from_url();
  2549. $first_parameter = $segment_object->first_parameter;
  2550. $second_parameter = $segment_object->second_parameter;
  2551. $state_info = (object)array();
  2552. switch ($state_code) {
  2553. case self::STATE_LIST:
  2554. case self::STATE_ADD:
  2555. //for now... do nothing! Keeping this switch here in case we need any information at the future.
  2556. break;
  2557. case self::STATE_EDIT:
  2558. case self::STATE_READ:
  2559. if ($first_parameter !== null) {
  2560. $state_info = (object) array('primary_key' => $first_parameter);
  2561. } else {
  2562. throw new Exception('On the state "edit" the Primary key cannot be null', 6);
  2563. die();
  2564. }
  2565. break;
  2566. case self::STATE_DELETE:
  2567. if ($first_parameter !== null) {
  2568. $state_info = (object) array('primary_key' => $first_parameter);
  2569. } else {
  2570. throw new Exception('On the state "delete" the Primary key cannot be null',7);
  2571. die();
  2572. }
  2573. break;
  2574. case self::STATE_DELETE_MULTIPLE:
  2575. if (!empty($_POST) && !empty($_POST['ids']) && is_array($_POST['ids'])) {
  2576. $state_info = (object) array('ids' => $_POST['ids']);
  2577. } else {
  2578. throw new Exception('On the state "Delete Multiple" you need send the ids as a post array.');
  2579. die();
  2580. }
  2581. break;
  2582. case self::STATE_INSERT:
  2583. if(!empty($_POST))
  2584. {
  2585. $state_info = (object)array('unwrapped_data' => $_POST);
  2586. }
  2587. else
  2588. {
  2589. throw new Exception('On the state "insert" you must have post data',8);
  2590. die();
  2591. }
  2592. break;
  2593. case 6:
  2594. if(!empty($_POST) && $first_parameter !== null)
  2595. {
  2596. $state_info = (object)array('primary_key' => $first_parameter,'unwrapped_data' => $_POST);
  2597. }
  2598. elseif(empty($_POST))
  2599. {
  2600. throw new Exception('On the state "update" you must have post data',9);
  2601. die();
  2602. }
  2603. else
  2604. {
  2605. throw new Exception('On the state "update" the Primary key cannot be null',10);
  2606. die();
  2607. }
  2608. break;
  2609. case 7:
  2610. case 8:
  2611. case 16: //export to excel
  2612. case 17: //print
  2613. $state_info = (object)array();
  2614. $data = !empty($_POST) ? $_POST : $_GET;
  2615. if(!empty($data['per_page']))
  2616. {
  2617. $state_info->per_page = is_numeric($data['per_page']) ? $data['per_page'] : null;
  2618. }
  2619. if(!empty($data['page']))
  2620. {
  2621. $state_info->page = is_numeric($data['page']) ? $data['page'] : null;
  2622. }
  2623. //If we request an export or a print we don't care about what page we are
  2624. if($state_code === 16 || $state_code === 17)
  2625. {
  2626. $state_info->page = 1;
  2627. $state_info->per_page = 1000000; //a very big number!
  2628. }
  2629. if(!empty($data['order_by'][0]))
  2630. {
  2631. $state_info->order_by = $data['order_by'];
  2632. }
  2633. if(!empty($data['search_text']))
  2634. {
  2635. if(empty($data['search_field']))
  2636. {
  2637. $search_text = strip_tags($data['search_field']);
  2638. $state_info->search = (object)array('field' => null , 'text' => $data['search_text']);
  2639. }
  2640. else
  2641. {
  2642. if (is_array($data['search_field'])) {
  2643. $search_array = array();
  2644. foreach ($data['search_field'] as $search_key => $search_field_name) {
  2645. $search_array[$search_field_name] = !empty($data['search_text'][$search_key]) ? $data['search_text'][$search_key] : '';
  2646. }
  2647. $state_info->search = $search_array;
  2648. } else {
  2649. $state_info->search = (object)array(
  2650. 'field' => strip_tags($data['search_field']) ,
  2651. 'text' => $data['search_text'] );
  2652. }
  2653. }
  2654. }
  2655. break;
  2656. case 9:
  2657. break;
  2658. case 10:
  2659. if($first_parameter !== null)
  2660. {
  2661. $state_info = (object)array('primary_key' => $first_parameter);
  2662. }
  2663. break;
  2664. case 11:
  2665. $state_info->field_name = $first_parameter;
  2666. break;
  2667. case 12:
  2668. $state_info->field_name = $first_parameter;
  2669. $state_info->file_name = $second_parameter;
  2670. break;
  2671. case 13:
  2672. $state_info->field_name = $_POST['field_name'];
  2673. $state_info->search = $_POST['term'];
  2674. break;
  2675. case 14:
  2676. $state_info->field_name = $_POST['field_name'];
  2677. $state_info->search = $_POST['term'];
  2678. break;
  2679. case 15:
  2680. $state_info = (object)array(
  2681. 'primary_key' => $first_parameter,
  2682. 'success_message' => true
  2683. );
  2684. break;
  2685. }
  2686. return $state_info;
  2687. }
  2688. protected function getStateCode()
  2689. {
  2690. $state_string = $this->get_state_info_from_url()->operation;
  2691. if( $state_string != 'unknown' && in_array( $state_string, $this->states ) )
  2692. $state_code = array_search($state_string, $this->states);
  2693. else
  2694. $state_code = 0;
  2695. return $state_code;
  2696. }
  2697. protected function state_url($url = '', $is_list_page = false)
  2698. {
  2699. //Easy scenario, we had set the crud_url_path
  2700. if (!empty($this->crud_url_path)) {
  2701. $state_url = !empty($this->list_url_path) && $is_list_page?
  2702. $this->list_url_path :
  2703. $this->crud_url_path.'/'.$url ;
  2704. } else {
  2705. //Complicated scenario. The crud_url_path is not specified so we are
  2706. //trying to understand what is going on from the URL.
  2707. $ci = &get_instance();
  2708. $segment_object = $this->get_state_info_from_url();
  2709. $method_name = $this->get_method_name();
  2710. $segment_position = $segment_object->segment_position;
  2711. $state_url_array = array();
  2712. if( sizeof($ci->uri->segments) > 0 ) {
  2713. foreach($ci->uri->segments as $num => $value)
  2714. {
  2715. $state_url_array[$num] = $value;
  2716. if($num == ($segment_position - 1))
  2717. break;
  2718. }
  2719. if( $method_name == 'index' && !in_array( 'index', $state_url_array ) ) //there is a scenario that you don't have the index to your url
  2720. $state_url_array[$num+1] = 'index';
  2721. }
  2722. $state_url = site_url(implode('/',$state_url_array).'/'.$url);
  2723. }
  2724. return $state_url;
  2725. }
  2726. protected function get_state_info_from_url()
  2727. {
  2728. $ci = &get_instance();
  2729. $segment_position = count($ci->uri->segments) + 1;
  2730. $operation = 'list';
  2731. $segements = $ci->uri->segments;
  2732. foreach($segements as $num => $value)
  2733. {
  2734. if($value != 'unknown' && in_array($value, $this->states))
  2735. {
  2736. $segment_position = (int)$num;
  2737. $operation = $value; //I don't have a "break" here because I want to ensure that is the LAST segment with name that is in the array.
  2738. }
  2739. }
  2740. $function_name = $this->get_method_name();
  2741. if($function_name == 'index' && !in_array('index',$ci->uri->segments))
  2742. $segment_position++;
  2743. $first_parameter = isset($segements[$segment_position+1]) ? $segements[$segment_position+1] : null;
  2744. $second_parameter = isset($segements[$segment_position+2]) ? $segements[$segment_position+2] : null;
  2745. return (object)array('segment_position' => $segment_position, 'operation' => $operation, 'first_parameter' => $first_parameter, 'second_parameter' => $second_parameter);
  2746. }
  2747. protected function get_method_hash()
  2748. {
  2749. $ci = &get_instance();
  2750. $state_info = $this->get_state_info_from_url();
  2751. $extra_values = $ci->uri->segment($state_info->segment_position - 1) != $this->get_method_name() ? $ci->uri->segment($state_info->segment_position - 1) : '';
  2752. return $this->crud_url_path !== null
  2753. ? md5($this->crud_url_path)
  2754. : md5($this->get_controller_name().$this->get_method_name().$extra_values);
  2755. }
  2756. protected function get_method_name()
  2757. {
  2758. $ci = &get_instance();
  2759. return $ci->router->method;
  2760. }
  2761. protected function get_controller_name()
  2762. {
  2763. $ci = &get_instance();
  2764. return $ci->router->class;
  2765. }
  2766. public function getState()
  2767. {
  2768. return $this->states[$this->getStateCode()];
  2769. }
  2770. protected function getListUrl()
  2771. {
  2772. return $this->state_url('',true);
  2773. }
  2774. protected function getAjaxListUrl()
  2775. {
  2776. return $this->state_url('ajax_list');
  2777. }
  2778. protected function getExportToExcelUrl()
  2779. {
  2780. return $this->state_url('export');
  2781. }
  2782. protected function getPrintUrl()
  2783. {
  2784. return $this->state_url('print');
  2785. }
  2786. protected function getAjaxListInfoUrl()
  2787. {
  2788. return $this->state_url('ajax_list_info');
  2789. }
  2790. protected function getAddUrl()
  2791. {
  2792. return $this->state_url('add');
  2793. }
  2794. protected function getInsertUrl()
  2795. {
  2796. return $this->state_url('insert');
  2797. }
  2798. protected function getValidationInsertUrl()
  2799. {
  2800. return $this->state_url('insert_validation');
  2801. }
  2802. protected function getValidationUpdateUrl($primary_key = null)
  2803. {
  2804. if($primary_key === null)
  2805. return $this->state_url('update_validation');
  2806. else
  2807. return $this->state_url('update_validation/'.$primary_key);
  2808. }
  2809. protected function getEditUrl($primary_key = null)
  2810. {
  2811. if($primary_key === null)
  2812. return $this->state_url('edit');
  2813. else
  2814. return $this->state_url('edit/'.$primary_key);
  2815. }
  2816. protected function getReadUrl($primary_key = null)
  2817. {
  2818. if($primary_key === null)
  2819. return $this->state_url('read');
  2820. else
  2821. return $this->state_url('read/'.$primary_key);
  2822. }
  2823. protected function getUpdateUrl($state_info)
  2824. {
  2825. return $this->state_url('update/'.$state_info->primary_key);
  2826. }
  2827. protected function getDeleteUrl($state_info = null)
  2828. {
  2829. if (empty($state_info)) {
  2830. return $this->state_url('delete');
  2831. } else {
  2832. return $this->state_url('delete/'.$state_info->primary_key);
  2833. }
  2834. }
  2835. protected function getDeleteMultipleUrl()
  2836. {
  2837. return $this->state_url('delete_multiple');
  2838. }
  2839. protected function getListSuccessUrl($primary_key = null)
  2840. {
  2841. if(empty($primary_key))
  2842. return $this->state_url('success',true);
  2843. else
  2844. return $this->state_url('success/'.$primary_key,true);
  2845. }
  2846. protected function getUploadUrl($field_name)
  2847. {
  2848. return $this->state_url('upload_file/'.$field_name);
  2849. }
  2850. protected function getFileDeleteUrl($field_name)
  2851. {
  2852. return $this->state_url('delete_file/'.$field_name);
  2853. }
  2854. protected function getAjaxRelationUrl()
  2855. {
  2856. return $this->state_url('ajax_relation');
  2857. }
  2858. protected function getAjaxRelationManytoManyUrl()
  2859. {
  2860. return $this->state_url('ajax_relation_n_n');
  2861. }
  2862. }
  2863. /**
  2864. * PHP grocery CRUD
  2865. *
  2866. * LICENSE
  2867. *
  2868. * Grocery CRUD is released with dual licensing, using the GPL v3 (license-gpl3.txt) and the MIT license (license-mit.txt).
  2869. * You don't have to do anything special to choose one license or the other and you don't have to notify anyone which license you are using.
  2870. * Please see the corresponding license file for details of these licenses.
  2871. * You are free to use, modify and distribute this software, but all copyright information must remain.
  2872. *
  2873. * @package grocery CRUD
  2874. * @copyright Copyright (c) 2010 through 2014, John Skoumbourdis
  2875. * @license https://github.com/scoumbourdis/grocery-crud/blob/master/license-grocery-crud.txt
  2876. * @version 1.5.8
  2877. * @author John Skoumbourdis <scoumbourdisj@gmail.com>
  2878. */
  2879. // ------------------------------------------------------------------------
  2880. /**
  2881. * PHP grocery CRUD
  2882. *
  2883. * Creates a full functional CRUD with few lines of code.
  2884. *
  2885. * @package grocery CRUD
  2886. * @author John Skoumbourdis <scoumbourdisj@gmail.com>
  2887. * @license https://github.com/scoumbourdis/grocery-crud/blob/master/license-grocery-crud.txt
  2888. * @link http://www.grocerycrud.com/documentation
  2889. */
  2890. class Grocery_CRUD extends grocery_CRUD_States
  2891. {
  2892. /**
  2893. * Grocery CRUD version
  2894. *
  2895. * @var string
  2896. */
  2897. const VERSION = "1.5.8";
  2898. const JQUERY = "jquery-1.11.1.min.js";
  2899. const JQUERY_UI_JS = "jquery-ui-1.10.3.custom.min.js";
  2900. const JQUERY_UI_CSS = "jquery-ui-1.10.1.custom.min.css";
  2901. protected $state_code = null;
  2902. protected $state_info = null;
  2903. protected $columns = null;
  2904. private $basic_db_table_checked = false;
  2905. private $columns_checked = false;
  2906. private $add_fields_checked = false;
  2907. private $edit_fields_checked = false;
  2908. private $read_fields_checked = false;
  2909. protected $default_theme = 'flexigrid';
  2910. protected $language = null;
  2911. protected $lang_strings = array();
  2912. protected $php_date_format = null;
  2913. protected $js_date_format = null;
  2914. protected $ui_date_format = null;
  2915. protected $character_limiter = null;
  2916. protected $config = null;
  2917. protected $add_fields = null;
  2918. protected $edit_fields = null;
  2919. protected $read_fields = null;
  2920. protected $add_hidden_fields = array();
  2921. protected $edit_hidden_fields = array();
  2922. protected $field_types = null;
  2923. protected $basic_db_table = null;
  2924. protected $theme_config = array();
  2925. protected $subject = null;
  2926. protected $subject_plural = null;
  2927. protected $display_as = array();
  2928. protected $order_by = null;
  2929. protected $where = array();
  2930. protected $like = array();
  2931. protected $having = array();
  2932. protected $or_having = array();
  2933. protected $limit = null;
  2934. protected $required_fields = array();
  2935. protected $_unique_fields = array();
  2936. protected $validation_rules = array();
  2937. protected $relation = array();
  2938. protected $relation_n_n = array();
  2939. protected $upload_fields = array();
  2940. protected $actions = array();
  2941. protected $form_validation = null;
  2942. protected $change_field_type = null;
  2943. protected $primary_keys = array();
  2944. protected $crud_url_path = null;
  2945. protected $list_url_path = null;
  2946. /* The unsetters */
  2947. protected $unset_texteditor = array();
  2948. protected $unset_add = false;
  2949. protected $unset_edit = false;
  2950. protected $unset_delete = false;
  2951. protected $unset_read = false;
  2952. protected $unset_jquery = false;
  2953. protected $unset_jquery_ui = false;
  2954. protected $unset_bootstrap = false;
  2955. protected $unset_list = false;
  2956. protected $unset_export = false;
  2957. protected $unset_print = false;
  2958. protected $unset_back_to_list = false;
  2959. protected $unset_columns = null;
  2960. protected $unset_add_fields = null;
  2961. protected $unset_edit_fields = null;
  2962. protected $unset_read_fields = null;
  2963. /* Callbacks */
  2964. protected $callback_before_insert = null;
  2965. protected $callback_after_insert = null;
  2966. protected $callback_insert = null;
  2967. protected $callback_before_update = null;
  2968. protected $callback_after_update = null;
  2969. protected $callback_update = null;
  2970. protected $callback_before_delete = null;
  2971. protected $callback_after_delete = null;
  2972. protected $callback_delete = null;
  2973. protected $callback_column = array();
  2974. protected $callback_add_field = array();
  2975. protected $callback_edit_field = array();
  2976. protected $callback_upload = null;
  2977. protected $callback_before_upload = null;
  2978. protected $callback_after_upload = null;
  2979. protected $default_javascript_path = null; //autogenerate, please do not modify
  2980. protected $default_css_path = null; //autogenerate, please do not modify
  2981. protected $default_texteditor_path = null; //autogenerate, please do not modify
  2982. protected $default_theme_path = null; //autogenerate, please do not modify
  2983. protected $default_language_path = 'assets/grocery_crud/languages';
  2984. protected $default_config_path = 'assets/grocery_crud/config';
  2985. protected $default_assets_path = 'assets/grocery_crud';
  2986. /**
  2987. *
  2988. * Constructor
  2989. *
  2990. * @access public
  2991. */
  2992. public function __construct()
  2993. {
  2994. }
  2995. /**
  2996. * The displayed columns that user see
  2997. *
  2998. * @access public
  2999. * @param string
  3000. * @param array
  3001. * @return void
  3002. */
  3003. public function columns()
  3004. {
  3005. $args = func_get_args();
  3006. if(isset($args[0]) && is_array($args[0]))
  3007. {
  3008. $args = $args[0];
  3009. }
  3010. $this->columns = $args;
  3011. return $this;
  3012. }
  3013. /**
  3014. * Set Validation Rules
  3015. *
  3016. * Important note: If the $field is an array then no automated crud fields will take apart
  3017. *
  3018. * @access public
  3019. * @param mixed
  3020. * @param string
  3021. * @oaram array
  3022. * @return void
  3023. */
  3024. function set_rules($field, $label = '', $rules = '', $errors = array())
  3025. {
  3026. if(is_string($field))
  3027. {
  3028. $this->validation_rules[$field] = array('field' => $field, 'label' => $label, 'rules' => $rules, 'errors' => $errors);
  3029. }elseif(is_array($field))
  3030. {
  3031. foreach($field as $num_field => $field_array)
  3032. {
  3033. $this->validation_rules[$field_array['field']] = $field_array;
  3034. }
  3035. }
  3036. return $this;
  3037. }
  3038. /**
  3039. *
  3040. * Changes the default field type
  3041. * @param string $field
  3042. * @param string $type
  3043. * @param array|string $extras
  3044. */
  3045. public function change_field_type($field , $type, $extras = null)
  3046. {
  3047. $field_type = (object)array('type' => $type);
  3048. $field_type->extras = $extras;
  3049. $this->change_field_type[$field] = $field_type;
  3050. return $this;
  3051. }
  3052. /**
  3053. *
  3054. * Just an alias to the change_field_type method
  3055. * @param string $field
  3056. * @param string $type
  3057. * @param array|string $extras
  3058. */
  3059. public function field_type($field , $type, $extras = null)
  3060. {
  3061. return $this->change_field_type($field , $type, $extras);
  3062. }
  3063. /**
  3064. * Change the default primary key for a specific table.
  3065. * If the $table_name is NULL then the primary key is for the default table name that we added at the set_table method
  3066. *
  3067. * @param string $primary_key_field
  3068. * @param string $table_name
  3069. */
  3070. public function set_primary_key($primary_key_field, $table_name = null)
  3071. {
  3072. $this->primary_keys[] = array('field_name' => $primary_key_field, 'table_name' => $table_name);
  3073. return $this;
  3074. }
  3075. /**
  3076. * Unsets the texteditor of the selected fields
  3077. *
  3078. * @access public
  3079. * @param string
  3080. * @param array
  3081. * @return void
  3082. */
  3083. public function unset_texteditor()
  3084. {
  3085. $args = func_get_args();
  3086. if(isset($args[0]) && is_array($args[0]))
  3087. {
  3088. $args = $args[0];
  3089. }
  3090. foreach($args as $arg)
  3091. {
  3092. $this->unset_texteditor[] = $arg;
  3093. }
  3094. return $this;
  3095. }
  3096. /**
  3097. * Unsets just the jquery library from the js. This function can be used if there is already a jquery included
  3098. * in the main template. This will avoid all jquery conflicts.
  3099. *
  3100. * @return void
  3101. */
  3102. public function unset_jquery()
  3103. {
  3104. $this->unset_jquery = true;
  3105. return $this;
  3106. }
  3107. /**
  3108. * Unsets the jquery UI Javascript and CSS. This function is really useful
  3109. * when the jquery UI JavaScript and CSS are already included in the main template.
  3110. * This will avoid all jquery UI conflicts.
  3111. *
  3112. * @return void
  3113. */
  3114. public function unset_jquery_ui()
  3115. {
  3116. $this->unset_jquery_ui = true;
  3117. return $this;
  3118. }
  3119. /**
  3120. * Unsets just the twitter bootstrap libraries from the js and css. This function can be used if there is already twitter bootstrap files included
  3121. * in the main template. If you are already using a bootstrap template then it's not necessary to load the files again.
  3122. *
  3123. * @return void
  3124. */
  3125. public function unset_bootstrap()
  3126. {
  3127. $this->unset_bootstrap = true;
  3128. return $this;
  3129. }
  3130. /**
  3131. * Unsets the add operation from the list
  3132. *
  3133. * @return void
  3134. */
  3135. public function unset_add()
  3136. {
  3137. $this->unset_add = true;
  3138. return $this;
  3139. }
  3140. /**
  3141. * Unsets the edit operation from the list
  3142. *
  3143. * @return void
  3144. */
  3145. public function unset_edit()
  3146. {
  3147. $this->unset_edit = true;
  3148. return $this;
  3149. }
  3150. /**
  3151. * Unsets the delete operation from the list
  3152. *
  3153. * @return void
  3154. */
  3155. public function unset_delete()
  3156. {
  3157. $this->unset_delete = true;
  3158. return $this;
  3159. }
  3160. /**
  3161. * Unsets the read operation from the list
  3162. *
  3163. * @return void
  3164. */
  3165. public function unset_read()
  3166. {
  3167. $this->unset_read = true;
  3168. return $this;
  3169. }
  3170. /**
  3171. * Just an alias to unset_read
  3172. *
  3173. * @return void
  3174. * */
  3175. public function unset_view()
  3176. {
  3177. return unset_read();
  3178. }
  3179. /**
  3180. * Unsets the export button and functionality from the list
  3181. *
  3182. * @return void
  3183. */
  3184. public function unset_export()
  3185. {
  3186. $this->unset_export = true;
  3187. return $this;
  3188. }
  3189. /**
  3190. * Unsets the print button and functionality from the list
  3191. *
  3192. * @return void
  3193. */
  3194. public function unset_print()
  3195. {
  3196. $this->unset_print = true;
  3197. return $this;
  3198. }
  3199. /**
  3200. * Unsets all the operations from the list
  3201. *
  3202. * @return void
  3203. */
  3204. public function unset_operations()
  3205. {
  3206. $this->unset_add = true;
  3207. $this->unset_edit = true;
  3208. $this->unset_delete = true;
  3209. $this->unset_read = true;
  3210. $this->unset_export = true;
  3211. $this->unset_print = true;
  3212. return $this;
  3213. }
  3214. /**
  3215. * Unsets a column from the list
  3216. *
  3217. * @return void.
  3218. */
  3219. public function unset_columns()
  3220. {
  3221. $args = func_get_args();
  3222. if(isset($args[0]) && is_array($args[0]))
  3223. {
  3224. $args = $args[0];
  3225. }
  3226. $this->unset_columns = $args;
  3227. return $this;
  3228. }
  3229. public function unset_list()
  3230. {
  3231. $this->unset_list = true;
  3232. return $this;
  3233. }
  3234. public function unset_fields()
  3235. {
  3236. $args = func_get_args();
  3237. if(isset($args[0]) && is_array($args[0]))
  3238. {
  3239. $args = $args[0];
  3240. }
  3241. $this->unset_add_fields = $args;
  3242. $this->unset_edit_fields = $args;
  3243. $this->unset_read_fields = $args;
  3244. return $this;
  3245. }
  3246. public function unset_add_fields()
  3247. {
  3248. $args = func_get_args();
  3249. if(isset($args[0]) && is_array($args[0]))
  3250. {
  3251. $args = $args[0];
  3252. }
  3253. $this->unset_add_fields = $args;
  3254. return $this;
  3255. }
  3256. public function unset_edit_fields()
  3257. {
  3258. $args = func_get_args();
  3259. if(isset($args[0]) && is_array($args[0]))
  3260. {
  3261. $args = $args[0];
  3262. }
  3263. $this->unset_edit_fields = $args;
  3264. return $this;
  3265. }
  3266. public function unset_read_fields()
  3267. {
  3268. $args = func_get_args();
  3269. if(isset($args[0]) && is_array($args[0]))
  3270. {
  3271. $args = $args[0];
  3272. }
  3273. $this->unset_read_fields = $args;
  3274. return $this;
  3275. }
  3276. /**
  3277. * Unsets everything that has to do with buttons or links with go back to list message
  3278. * @access public
  3279. * @return void
  3280. */
  3281. public function unset_back_to_list()
  3282. {
  3283. $this->unset_back_to_list = true;
  3284. return $this;
  3285. }
  3286. /**
  3287. *
  3288. * The fields that user will see on add/edit
  3289. *
  3290. * @access public
  3291. * @param string
  3292. * @param array
  3293. * @return void
  3294. */
  3295. public function fields()
  3296. {
  3297. $args = func_get_args();
  3298. if(isset($args[0]) && is_array($args[0]))
  3299. {
  3300. $args = $args[0];
  3301. }
  3302. $this->add_fields = $args;
  3303. $this->edit_fields = $args;
  3304. return $this;
  3305. }
  3306. /**
  3307. *
  3308. * The fields that user can see . It is only for the add form
  3309. */
  3310. public function add_fields()
  3311. {
  3312. $args = func_get_args();
  3313. if(isset($args[0]) && is_array($args[0]))
  3314. {
  3315. $args = $args[0];
  3316. }
  3317. $this->add_fields = $args;
  3318. return $this;
  3319. }
  3320. /**
  3321. *
  3322. * The fields that user can see . It is only for the edit form
  3323. */
  3324. public function edit_fields()
  3325. {
  3326. $args = func_get_args();
  3327. if(isset($args[0]) && is_array($args[0]))
  3328. {
  3329. $args = $args[0];
  3330. }
  3331. $this->edit_fields = $args;
  3332. return $this;
  3333. }
  3334. public function set_read_fields()
  3335. {
  3336. $args = func_get_args();
  3337. if(isset($args[0]) && is_array($args[0])) {
  3338. $args = $args[0];
  3339. }
  3340. $this->read_fields = $args;
  3341. return $this;
  3342. }
  3343. /**
  3344. *
  3345. * Changes the displaying label of the field
  3346. * @param $field_name
  3347. * @param $display_as
  3348. * @return void
  3349. */
  3350. public function display_as($field_name, $display_as = null)
  3351. {
  3352. if(is_array($field_name))
  3353. {
  3354. foreach($field_name as $field => $display_as)
  3355. {
  3356. $this->display_as[$field] = $display_as;
  3357. }
  3358. }
  3359. elseif($display_as !== null)
  3360. {
  3361. $this->display_as[$field_name] = $display_as;
  3362. }
  3363. return $this;
  3364. }
  3365. /**
  3366. *
  3367. * Load the language strings array from the language file
  3368. */
  3369. protected function _load_language()
  3370. {
  3371. if($this->language === null)
  3372. {
  3373. $this->language = strtolower($this->config->default_language);
  3374. }
  3375. include($this->default_language_path.'/'.$this->language.'.php');
  3376. foreach($lang as $handle => $lang_string)
  3377. if(!isset($this->lang_strings[$handle]))
  3378. $this->lang_strings[$handle] = $lang_string;
  3379. $this->default_true_false_text = array( $this->l('form_inactive') , $this->l('form_active'));
  3380. $this->subject = $this->subject === null ? $this->l('list_record') : $this->subject;
  3381. }
  3382. protected function _load_date_format()
  3383. {
  3384. list($php_day, $php_month, $php_year) = array('d','m','Y');
  3385. list($js_day, $js_month, $js_year) = array('dd','mm','yy');
  3386. list($ui_day, $ui_month, $ui_year) = array($this->l('ui_day'), $this->l('ui_month'), $this->l('ui_year'));
  3387. $date_format = $this->config->date_format;
  3388. switch ($date_format) {
  3389. case 'uk-date':
  3390. $this->php_date_format = "$php_day/$php_month/$php_year";
  3391. $this->js_date_format = "$js_day/$js_month/$js_year";
  3392. $this->ui_date_format = "$ui_day/$ui_month/$ui_year";
  3393. break;
  3394. case 'us-date':
  3395. $this->php_date_format = "$php_month/$php_day/$php_year";
  3396. $this->js_date_format = "$js_month/$js_day/$js_year";
  3397. $this->ui_date_format = "$ui_month/$ui_day/$ui_year";
  3398. break;
  3399. case 'sql-date':
  3400. default:
  3401. $this->php_date_format = "$php_year-$php_month-$php_day";
  3402. $this->js_date_format = "$js_year-$js_month-$js_day";
  3403. $this->ui_date_format = "$ui_year-$ui_month-$ui_day";
  3404. break;
  3405. }
  3406. }
  3407. /**
  3408. *
  3409. * Set a language string directly
  3410. * @param string $handle
  3411. * @param string $string
  3412. */
  3413. public function set_lang_string($handle, $lang_string){
  3414. $this->lang_strings[$handle] = $lang_string;
  3415. return $this;
  3416. }
  3417. /**
  3418. *
  3419. * Just an alias to get_lang_string method
  3420. * @param string $handle
  3421. */
  3422. public function l($handle)
  3423. {
  3424. return $this->get_lang_string($handle);
  3425. }
  3426. /**
  3427. *
  3428. * Get the language string of the inserted string handle
  3429. * @param string $handle
  3430. */
  3431. public function get_lang_string($handle)
  3432. {
  3433. return $this->lang_strings[$handle];
  3434. }
  3435. /**
  3436. *
  3437. * Simply set the language
  3438. * @example english
  3439. * @param string $language
  3440. */
  3441. public function set_language($language)
  3442. {
  3443. $this->language = $language;
  3444. return $this;
  3445. }
  3446. /**
  3447. *
  3448. * Enter description here ...
  3449. */
  3450. protected function get_columns()
  3451. {
  3452. if($this->columns_checked === false)
  3453. {
  3454. $field_types = $this->get_field_types();
  3455. if(empty($this->columns))
  3456. {
  3457. $this->columns = array();
  3458. foreach($field_types as $field)
  3459. {
  3460. if( !isset($field->db_extra) || $field->db_extra != 'auto_increment' )
  3461. $this->columns[] = $field->name;
  3462. }
  3463. }
  3464. foreach($this->columns as $col_num => $column)
  3465. {
  3466. if(isset($this->relation[$column]))
  3467. {
  3468. $new_column = $this->_unique_field_name($this->relation[$column][0]);
  3469. $this->columns[$col_num] = $new_column;
  3470. if(isset($this->display_as[$column]))
  3471. {
  3472. $display_as = $this->display_as[$column];
  3473. unset($this->display_as[$column]);
  3474. $this->display_as[$new_column] = $display_as;
  3475. }
  3476. else
  3477. {
  3478. $this->display_as[$new_column] = ucfirst(str_replace('_',' ',$column));
  3479. }
  3480. $column = $new_column;
  3481. $this->columns[$col_num] = $new_column;
  3482. }
  3483. else
  3484. {
  3485. if(!empty($this->relation))
  3486. {
  3487. $table_name = $this->get_table();
  3488. foreach($this->relation as $relation)
  3489. {
  3490. if( $relation[2] == $column )
  3491. {
  3492. $new_column = $table_name.'.'.$column;
  3493. if(isset($this->display_as[$column]))
  3494. {
  3495. $display_as = $this->display_as[$column];
  3496. unset($this->display_as[$column]);
  3497. $this->display_as[$new_column] = $display_as;
  3498. }
  3499. else
  3500. {
  3501. $this->display_as[$new_column] = ucfirst(str_replace('_',' ',$column));
  3502. }
  3503. $column = $new_column;
  3504. $this->columns[$col_num] = $new_column;
  3505. }
  3506. }
  3507. }
  3508. }
  3509. if(isset($this->display_as[$column]))
  3510. $this->columns[$col_num] = (object)array('field_name' => $column, 'display_as' => $this->display_as[$column]);
  3511. elseif(isset($field_types[$column]))
  3512. $this->columns[$col_num] = (object)array('field_name' => $column, 'display_as' => $field_types[$column]->display_as);
  3513. else
  3514. $this->columns[$col_num] = (object)array('field_name' => $column, 'display_as' =>
  3515. ucfirst(str_replace('_',' ',$column)));
  3516. if(!empty($this->unset_columns) && in_array($column,$this->unset_columns))
  3517. {
  3518. unset($this->columns[$col_num]);
  3519. }
  3520. }
  3521. $this->columns_checked = true;
  3522. }
  3523. return $this->columns;
  3524. }
  3525. /**
  3526. *
  3527. * Enter description here ...
  3528. */
  3529. protected function get_add_fields()
  3530. {
  3531. if($this->add_fields_checked === false)
  3532. {
  3533. $field_types = $this->get_field_types();
  3534. if(!empty($this->add_fields))
  3535. {
  3536. foreach($this->add_fields as $field_num => $field)
  3537. {
  3538. if(isset($this->display_as[$field]))
  3539. $this->add_fields[$field_num] = (object)array('field_name' => $field, 'display_as' => $this->display_as[$field]);
  3540. elseif(isset($field_types[$field]->display_as))
  3541. $this->add_fields[$field_num] = (object)array('field_name' => $field, 'display_as' => $field_types[$field]->display_as);
  3542. else
  3543. $this->add_fields[$field_num] = (object)array('field_name' => $field, 'display_as' => ucfirst(str_replace('_',' ',$field)));
  3544. }
  3545. }
  3546. else
  3547. {
  3548. $this->add_fields = array();
  3549. foreach($field_types as $field)
  3550. {
  3551. //Check if an unset_add_field is initialize for this field name
  3552. if($this->unset_add_fields !== null && is_array($this->unset_add_fields) && in_array($field->name,$this->unset_add_fields))
  3553. continue;
  3554. if( (!isset($field->db_extra) || $field->db_extra != 'auto_increment') )
  3555. {
  3556. if(isset($this->display_as[$field->name]))
  3557. $this->add_fields[] = (object)array('field_name' => $field->name, 'display_as' => $this->display_as[$field->name]);
  3558. else
  3559. $this->add_fields[] = (object)array('field_name' => $field->name, 'display_as' => $field->display_as);
  3560. }
  3561. }
  3562. }
  3563. $this->add_fields_checked = true;
  3564. }
  3565. return $this->add_fields;
  3566. }
  3567. /**
  3568. *
  3569. * Enter description here ...
  3570. */
  3571. protected function get_edit_fields()
  3572. {
  3573. if($this->edit_fields_checked === false)
  3574. {
  3575. $field_types = $this->get_field_types();
  3576. if(!empty($this->edit_fields))
  3577. {
  3578. foreach($this->edit_fields as $field_num => $field)
  3579. {
  3580. if(isset($this->display_as[$field]))
  3581. $this->edit_fields[$field_num] = (object)array('field_name' => $field, 'display_as' => $this->display_as[$field]);
  3582. else
  3583. $this->edit_fields[$field_num] = (object)array('field_name' => $field, 'display_as' => $field_types[$field]->display_as);
  3584. }
  3585. }
  3586. else
  3587. {
  3588. $this->edit_fields = array();
  3589. foreach($field_types as $field)
  3590. {
  3591. //Check if an unset_edit_field is initialize for this field name
  3592. if($this->unset_edit_fields !== null && is_array($this->unset_edit_fields) && in_array($field->name,$this->unset_edit_fields))
  3593. continue;
  3594. if(!isset($field->db_extra) || $field->db_extra != 'auto_increment')
  3595. {
  3596. if(isset($this->display_as[$field->name]))
  3597. $this->edit_fields[] = (object)array('field_name' => $field->name, 'display_as' => $this->display_as[$field->name]);
  3598. else
  3599. $this->edit_fields[] = (object)array('field_name' => $field->name, 'display_as' => $field->display_as);
  3600. }
  3601. }
  3602. }
  3603. $this->edit_fields_checked = true;
  3604. }
  3605. return $this->edit_fields;
  3606. }
  3607. /**
  3608. *
  3609. * Enter description here ...
  3610. */
  3611. protected function get_read_fields()
  3612. {
  3613. if($this->read_fields_checked === false)
  3614. {
  3615. $field_types = $this->get_field_types();
  3616. if(!empty($this->read_fields))
  3617. {
  3618. foreach($this->read_fields as $field_num => $field)
  3619. {
  3620. if(isset($this->display_as[$field]))
  3621. $this->read_fields[$field_num] = (object)array('field_name' => $field, 'display_as' => $this->display_as[$field]);
  3622. else
  3623. $this->read_fields[$field_num] = (object)array('field_name' => $field, 'display_as' => $field_types[$field]->display_as);
  3624. }
  3625. }
  3626. else
  3627. {
  3628. $this->read_fields = array();
  3629. foreach($field_types as $field)
  3630. {
  3631. //Check if an unset_read_field is initialize for this field name
  3632. if($this->unset_read_fields !== null && is_array($this->unset_read_fields) && in_array($field->name,$this->unset_read_fields))
  3633. continue;
  3634. if(!isset($field->db_extra) || $field->db_extra != 'auto_increment')
  3635. {
  3636. if(isset($this->display_as[$field->name]))
  3637. $this->read_fields[] = (object)array('field_name' => $field->name, 'display_as' => $this->display_as[$field->name]);
  3638. else
  3639. $this->read_fields[] = (object)array('field_name' => $field->name, 'display_as' => $field->display_as);
  3640. }
  3641. }
  3642. }
  3643. $this->read_fields_checked = true;
  3644. }
  3645. return $this->read_fields;
  3646. }
  3647. public function order_by($order_by, $direction = 'asc')
  3648. {
  3649. $this->order_by = array($order_by,$direction);
  3650. return $this;
  3651. }
  3652. public function where($key, $value = NULL, $escape = TRUE)
  3653. {
  3654. $this->where[] = array($key,$value,$escape);
  3655. return $this;
  3656. }
  3657. public function or_where($key, $value = NULL, $escape = TRUE)
  3658. {
  3659. $this->or_where[] = array($key,$value,$escape);
  3660. return $this;
  3661. }
  3662. public function like($field, $match = '', $side = 'both')
  3663. {
  3664. $this->like[] = array($field, $match, $side);
  3665. return $this;
  3666. }
  3667. protected function having($key, $value = '', $escape = TRUE)
  3668. {
  3669. $this->having[] = array($key, $value, $escape);
  3670. return $this;
  3671. }
  3672. protected function or_having($key, $value = '', $escape = TRUE)
  3673. {
  3674. $this->or_having[] = array($key, $value, $escape);
  3675. return $this;
  3676. }
  3677. public function or_like($field, $match = '', $side = 'both')
  3678. {
  3679. $this->or_like[] = array($field, $match, $side);
  3680. return $this;
  3681. }
  3682. public function limit($limit, $offset = '')
  3683. {
  3684. $this->limit = array($limit,$offset);
  3685. return $this;
  3686. }
  3687. protected function _initialize_helpers()
  3688. {
  3689. $ci = &get_instance();
  3690. $ci->load->helper('url');
  3691. $ci->load->helper('form');
  3692. }
  3693. protected function _initialize_variables()
  3694. {
  3695. $ci = &get_instance();
  3696. $ci->load->config('grocery_crud');
  3697. $this->config = (object)array();
  3698. /** Initialize all the config variables into this object */
  3699. $this->config->default_language = $ci->config->item('grocery_crud_default_language');
  3700. $this->config->date_format = $ci->config->item('grocery_crud_date_format');
  3701. $this->config->default_per_page = $ci->config->item('grocery_crud_default_per_page');
  3702. $this->config->file_upload_allow_file_types = $ci->config->item('grocery_crud_file_upload_allow_file_types');
  3703. $this->config->file_upload_max_file_size = $ci->config->item('grocery_crud_file_upload_max_file_size');
  3704. $this->config->default_text_editor = $ci->config->item('grocery_crud_default_text_editor');
  3705. $this->config->text_editor_type = $ci->config->item('grocery_crud_text_editor_type');
  3706. $this->config->character_limiter = $ci->config->item('grocery_crud_character_limiter');
  3707. $this->config->dialog_forms = $ci->config->item('grocery_crud_dialog_forms');
  3708. $this->config->paging_options = $ci->config->item('grocery_crud_paging_options');
  3709. $this->config->default_theme = $ci->config->item('grocery_crud_default_theme');
  3710. $this->config->environment = $ci->config->item('grocery_crud_environment');
  3711. $this->config->xss_clean = $ci->config->item('grocery_crud_xss_clean');
  3712. /** Initialize default paths */
  3713. $this->default_javascript_path = $this->default_assets_path.'/js';
  3714. $this->default_css_path = $this->default_assets_path.'/css';
  3715. $this->default_texteditor_path = $this->default_assets_path.'/texteditor';
  3716. $this->default_theme_path = $this->default_assets_path.'/themes';
  3717. $this->character_limiter = $this->config->character_limiter;
  3718. if ($this->character_limiter === 0 || $this->character_limiter === '0') {
  3719. $this->character_limiter = 1000000; //a very big number
  3720. } elseif($this->character_limiter === null || $this->character_limiter === false) {
  3721. $this->character_limiter = 30; //is better to have the number 30 rather than the 0 value
  3722. }
  3723. if ($this->theme === null && !empty($this->config->default_theme)) {
  3724. $this->set_theme($this->config->default_theme);
  3725. }
  3726. }
  3727. protected function _set_primary_keys_to_model()
  3728. {
  3729. if(!empty($this->primary_keys))
  3730. {
  3731. foreach($this->primary_keys as $primary_key)
  3732. {
  3733. $this->basic_model->set_primary_key($primary_key['field_name'],$primary_key['table_name']);
  3734. }
  3735. }
  3736. }
  3737. /**
  3738. * Initialize all the required libraries and variables before rendering
  3739. */
  3740. protected function pre_render()
  3741. {
  3742. $this->_initialize_variables();
  3743. $this->_initialize_helpers();
  3744. $this->_load_language();
  3745. $this->state_code = $this->getStateCode();
  3746. if($this->basic_model === null)
  3747. $this->set_default_Model();
  3748. $this->set_basic_db_table($this->get_table());
  3749. $this->_load_date_format();
  3750. $this->_set_primary_keys_to_model();
  3751. }
  3752. /**
  3753. *
  3754. * Or else ... make it work! The web application takes decision of what to do and show it to the final user.
  3755. * Without this function nothing works. Here is the core of grocery CRUD project.
  3756. *
  3757. * @access public
  3758. */
  3759. public function render()
  3760. {
  3761. $this->pre_render();
  3762. if( $this->state_code != 0 )
  3763. {
  3764. $this->state_info = $this->getStateInfo();
  3765. }
  3766. else
  3767. {
  3768. throw new Exception('The state is unknown , I don\'t know what I will do with your data!', 4);
  3769. die();
  3770. }
  3771. switch ($this->state_code) {
  3772. case 15://success
  3773. case 1://list
  3774. if($this->unset_list)
  3775. {
  3776. throw new Exception('You don\'t have permissions for this operation', 14);
  3777. die();
  3778. }
  3779. if($this->theme === null)
  3780. $this->set_theme($this->default_theme);
  3781. $this->setThemeBasics();
  3782. $this->set_basic_Layout();
  3783. $state_info = $this->getStateInfo();
  3784. $this->showList(false,$state_info);
  3785. break;
  3786. case 2://add
  3787. if($this->unset_add)
  3788. {
  3789. throw new Exception('You don\'t have permissions for this operation', 14);
  3790. die();
  3791. }
  3792. if($this->theme === null)
  3793. $this->set_theme($this->default_theme);
  3794. $this->setThemeBasics();
  3795. $this->set_basic_Layout();
  3796. $this->showAddForm();
  3797. break;
  3798. case 3://edit
  3799. if($this->unset_edit)
  3800. {
  3801. throw new Exception('You don\'t have permissions for this operation', 14);
  3802. die();
  3803. }
  3804. if($this->theme === null)
  3805. $this->set_theme($this->default_theme);
  3806. $this->setThemeBasics();
  3807. $this->set_basic_Layout();
  3808. $state_info = $this->getStateInfo();
  3809. $this->showEditForm($state_info);
  3810. break;
  3811. case 4://delete
  3812. if($this->unset_delete)
  3813. {
  3814. throw new Exception('This user is not allowed to do this operation', 14);
  3815. die();
  3816. }
  3817. $state_info = $this->getStateInfo();
  3818. $delete_result = $this->db_delete($state_info);
  3819. $this->delete_layout( $delete_result );
  3820. break;
  3821. case 5://insert
  3822. if($this->unset_add)
  3823. {
  3824. throw new Exception('This user is not allowed to do this operation', 14);
  3825. die();
  3826. }
  3827. $state_info = $this->getStateInfo();
  3828. $insert_result = $this->db_insert($state_info);
  3829. $this->insert_layout($insert_result);
  3830. break;
  3831. case 6://update
  3832. if($this->unset_edit)
  3833. {
  3834. throw new Exception('This user is not allowed to do this operation', 14);
  3835. die();
  3836. }
  3837. $state_info = $this->getStateInfo();
  3838. $update_result = $this->db_update($state_info);
  3839. $this->update_layout( $update_result,$state_info);
  3840. break;
  3841. case 7://ajax_list
  3842. if($this->unset_list)
  3843. {
  3844. throw new Exception('You don\'t have permissions for this operation', 14);
  3845. die();
  3846. }
  3847. if($this->theme === null)
  3848. $this->set_theme($this->default_theme);
  3849. $this->setThemeBasics();
  3850. $this->set_basic_Layout();
  3851. $state_info = $this->getStateInfo();
  3852. $this->set_ajax_list_queries($state_info);
  3853. $this->showList(true);
  3854. break;
  3855. case 8://ajax_list_info
  3856. if($this->theme === null)
  3857. $this->set_theme($this->default_theme);
  3858. $this->setThemeBasics();
  3859. $this->set_basic_Layout();
  3860. $state_info = $this->getStateInfo();
  3861. $this->set_ajax_list_queries($state_info);
  3862. $this->showListInfo();
  3863. break;
  3864. case 9://insert_validation
  3865. $validation_result = $this->db_insert_validation();
  3866. $this->validation_layout($validation_result);
  3867. break;
  3868. case 10://update_validation
  3869. $validation_result = $this->db_update_validation();
  3870. $this->validation_layout($validation_result);
  3871. break;
  3872. case 11://upload_file
  3873. $state_info = $this->getStateInfo();
  3874. $upload_result = $this->upload_file($state_info);
  3875. $this->upload_layout($upload_result, $state_info->field_name);
  3876. break;
  3877. case 12://delete_file
  3878. $state_info = $this->getStateInfo();
  3879. $delete_file_result = $this->delete_file($state_info);
  3880. $this->delete_file_layout($delete_file_result);
  3881. break;
  3882. /*
  3883. case 13: //ajax_relation
  3884. $state_info = $this->getStateInfo();
  3885. $ajax_relation_result = $this->ajax_relation($state_info);
  3886. $ajax_relation_result[""] = "";
  3887. echo json_encode($ajax_relation_result);
  3888. die();
  3889. break;
  3890. case 14: //ajax_relation_n_n
  3891. echo json_encode(array("34" => 'Johnny' , "78" => "Test"));
  3892. die();
  3893. break;
  3894. */
  3895. case 16: //export to excel
  3896. //a big number just to ensure that the table characters will not be cutted.
  3897. $this->character_limiter = 1000000;
  3898. if($this->unset_export)
  3899. {
  3900. throw new Exception('You don\'t have permissions for this operation', 15);
  3901. die();
  3902. }
  3903. if($this->theme === null)
  3904. $this->set_theme($this->default_theme);
  3905. $this->setThemeBasics();
  3906. $this->set_basic_Layout();
  3907. $state_info = $this->getStateInfo();
  3908. $this->set_ajax_list_queries($state_info);
  3909. $this->exportToExcel($state_info);
  3910. break;
  3911. case 17: //print
  3912. //a big number just to ensure that the table characters will not be cutted.
  3913. $this->character_limiter = 1000000;
  3914. if($this->unset_print)
  3915. {
  3916. throw new Exception('You don\'t have permissions for this operation', 15);
  3917. die();
  3918. }
  3919. if($this->theme === null)
  3920. $this->set_theme($this->default_theme);
  3921. $this->setThemeBasics();
  3922. $this->set_basic_Layout();
  3923. $state_info = $this->getStateInfo();
  3924. $this->set_ajax_list_queries($state_info);
  3925. $this->print_webpage($state_info);
  3926. break;
  3927. case grocery_CRUD_States::STATE_READ:
  3928. if($this->unset_read)
  3929. {
  3930. throw new Exception('You don\'t have permissions for this operation', 14);
  3931. die();
  3932. }
  3933. if($this->theme === null)
  3934. $this->set_theme($this->default_theme);
  3935. $this->setThemeBasics();
  3936. $this->set_basic_Layout();
  3937. $state_info = $this->getStateInfo();
  3938. $this->showReadForm($state_info);
  3939. break;
  3940. case grocery_CRUD_States::STATE_DELETE_MULTIPLE:
  3941. if($this->unset_delete)
  3942. {
  3943. throw new Exception('This user is not allowed to do this operation');
  3944. die();
  3945. }
  3946. $state_info = $this->getStateInfo();
  3947. $delete_result = $this->db_multiple_delete($state_info);
  3948. $this->delete_layout($delete_result);
  3949. break;
  3950. }
  3951. return $this->get_layout();
  3952. }
  3953. protected function get_common_data()
  3954. {
  3955. $data = (object)array();
  3956. $data->subject = $this->subject;
  3957. $data->subject_plural = $this->subject_plural;
  3958. return $data;
  3959. }
  3960. /**
  3961. *
  3962. * Enter description here ...
  3963. */
  3964. public function callback_before_insert($callback = null)
  3965. {
  3966. $this->callback_before_insert = $callback;
  3967. return $this;
  3968. }
  3969. /**
  3970. *
  3971. * Enter description here ...
  3972. */
  3973. public function callback_after_insert($callback = null)
  3974. {
  3975. $this->callback_after_insert = $callback;
  3976. return $this;
  3977. }
  3978. /**
  3979. *
  3980. * Enter description here ...
  3981. */
  3982. public function callback_insert($callback = null)
  3983. {
  3984. $this->callback_insert = $callback;
  3985. return $this;
  3986. }
  3987. /**
  3988. *
  3989. * Enter description here ...
  3990. */
  3991. public function callback_before_update($callback = null)
  3992. {
  3993. $this->callback_before_update = $callback;
  3994. return $this;
  3995. }
  3996. /**
  3997. *
  3998. * Enter description here ...
  3999. */
  4000. public function callback_after_update($callback = null)
  4001. {
  4002. $this->callback_after_update = $callback;
  4003. return $this;
  4004. }
  4005. /**
  4006. *
  4007. * Enter description here ...
  4008. * @param mixed $callback
  4009. */
  4010. public function callback_update($callback = null)
  4011. {
  4012. $this->callback_update = $callback;
  4013. return $this;
  4014. }
  4015. /**
  4016. *
  4017. * Enter description here ...
  4018. */
  4019. public function callback_before_delete($callback = null)
  4020. {
  4021. $this->callback_before_delete = $callback;
  4022. return $this;
  4023. }
  4024. /**
  4025. *
  4026. * Enter description here ...
  4027. */
  4028. public function callback_after_delete($callback = null)
  4029. {
  4030. $this->callback_after_delete = $callback;
  4031. return $this;
  4032. }
  4033. /**
  4034. *
  4035. * Enter description here ...
  4036. */
  4037. public function callback_delete($callback = null)
  4038. {
  4039. $this->callback_delete = $callback;
  4040. return $this;
  4041. }
  4042. /**
  4043. *
  4044. * Enter description here ...
  4045. * @param string $column
  4046. * @param mixed $callback
  4047. */
  4048. public function callback_column($column ,$callback = null)
  4049. {
  4050. $this->callback_column[$column] = $callback;
  4051. return $this;
  4052. }
  4053. /**
  4054. *
  4055. * Enter description here ...
  4056. * @param string $field
  4057. * @param mixed $callback
  4058. */
  4059. public function callback_field($field, $callback = null)
  4060. {
  4061. $this->callback_add_field[$field] = $callback;
  4062. $this->callback_edit_field[$field] = $callback;
  4063. return $this;
  4064. }
  4065. /**
  4066. *
  4067. * Enter description here ...
  4068. * @param string $field
  4069. * @param mixed $callback
  4070. */
  4071. public function callback_add_field($field, $callback = null)
  4072. {
  4073. $this->callback_add_field[$field] = $callback;
  4074. return $this;
  4075. }
  4076. /**
  4077. *
  4078. * Enter description here ...
  4079. * @param string $field
  4080. * @param mixed $callback
  4081. */
  4082. public function callback_edit_field($field, $callback = null)
  4083. {
  4084. $this->callback_edit_field[$field] = $callback;
  4085. return $this;
  4086. }
  4087. /**
  4088. *
  4089. * Callback that replace the default auto uploader
  4090. *
  4091. * @param mixed $callback
  4092. * @return grocery_CRUD
  4093. */
  4094. public function callback_upload($callback = null)
  4095. {
  4096. $this->callback_upload = $callback;
  4097. return $this;
  4098. }
  4099. /**
  4100. *
  4101. * A callback that triggered before the upload functionality. This callback is suggested for validation checks
  4102. * @param mixed $callback
  4103. * @return grocery_CRUD
  4104. */
  4105. public function callback_before_upload($callback = null)
  4106. {
  4107. $this->callback_before_upload = $callback;
  4108. return $this;
  4109. }
  4110. /**
  4111. *
  4112. * A callback that triggered after the upload functionality
  4113. * @param mixed $callback
  4114. * @return grocery_CRUD
  4115. */
  4116. public function callback_after_upload($callback = null)
  4117. {
  4118. $this->callback_after_upload = $callback;
  4119. return $this;
  4120. }
  4121. /**
  4122. *
  4123. * Gets the basic database table of our crud.
  4124. * @return string
  4125. */
  4126. public function get_table()
  4127. {
  4128. if($this->basic_db_table_checked)
  4129. {
  4130. return $this->basic_db_table;
  4131. }
  4132. elseif( $this->basic_db_table !== null )
  4133. {
  4134. if(!$this->table_exists($this->basic_db_table))
  4135. {
  4136. throw new Exception('The table name does not exist. Please check you database and try again.',11);
  4137. die();
  4138. }
  4139. $this->basic_db_table_checked = true;
  4140. return $this->basic_db_table;
  4141. }
  4142. else
  4143. {
  4144. //Last try , try to find the table from your view / function name!!! Not suggested but it works .
  4145. $last_chance_table_name = $this->get_method_name();
  4146. if($this->table_exists($last_chance_table_name))
  4147. {
  4148. $this->set_table($last_chance_table_name);
  4149. }
  4150. $this->basic_db_table_checked = true;
  4151. return $this->basic_db_table;
  4152. }
  4153. return false;
  4154. }
  4155. /**
  4156. *
  4157. * The field names of the required fields
  4158. */
  4159. public function required_fields()
  4160. {
  4161. $args = func_get_args();
  4162. if(isset($args[0]) && is_array($args[0]))
  4163. {
  4164. $args = $args[0];
  4165. }
  4166. $this->required_fields = $args;
  4167. return $this;
  4168. }
  4169. /**
  4170. * Add the fields that they are as UNIQUE in the database structure
  4171. *
  4172. * @return grocery_CRUD
  4173. */
  4174. public function unique_fields()
  4175. {
  4176. $args = func_get_args();
  4177. if(isset($args[0]) && is_array($args[0]))
  4178. {
  4179. $args = $args[0];
  4180. }
  4181. $this->_unique_fields = $args;
  4182. return $this;
  4183. }
  4184. /**
  4185. *
  4186. * Sets the basic database table that we will get our data.
  4187. * @param string $table_name
  4188. * @return grocery_CRUD
  4189. */
  4190. public function set_table($table_name)
  4191. {
  4192. if(!empty($table_name) && $this->basic_db_table === null)
  4193. {
  4194. $this->basic_db_table = $table_name;
  4195. }
  4196. elseif(!empty($table_name))
  4197. {
  4198. throw new Exception('You have already insert a table name once...', 1);
  4199. }
  4200. else
  4201. {
  4202. throw new Exception('The table name cannot be empty.', 2);
  4203. die();
  4204. }
  4205. return $this;
  4206. }
  4207. /**
  4208. * Set a full URL path to this method.
  4209. *
  4210. * This method is useful when the path is not specified correctly.
  4211. * Especially when we are using routes.
  4212. * For example:
  4213. * Let's say we have the path http://www.example.com/ however the original url path is
  4214. * http://www.example.com/example/index . We have to specify the url so we can have
  4215. * all the CRUD operations correctly.
  4216. * The url path has to be set from this method like this:
  4217. * <code>
  4218. * $crud->set_crud_url_path(site_url('example/index'));
  4219. * </code>
  4220. *
  4221. * @param string $crud_url_path
  4222. * @param string $list_url_path
  4223. * @return grocery_CRUD
  4224. */
  4225. public function set_crud_url_path($crud_url_path, $list_url_path = null)
  4226. {
  4227. $this->crud_url_path = $crud_url_path;
  4228. //If the list_url_path is empty so we are guessing that the list_url_path
  4229. //will be the same with crud_url_path
  4230. $this->list_url_path = !empty($list_url_path) ? $list_url_path : $crud_url_path;
  4231. return $this;
  4232. }
  4233. /**
  4234. *
  4235. * Set a subject to understand what type of CRUD you use.
  4236. * ----------------------------------------------------------------------------------------------
  4237. * Subject_plural: Sets the subject to its plural form. For example the plural
  4238. * of "Customer" is "Customers", "Product" is "Products"... e.t.c.
  4239. * @example In this CRUD we work with the table db_categories. The $subject will be the 'Category'
  4240. * and the $subject_plural will be 'Categories'
  4241. * @param string $subject
  4242. * @param string $subject_plural
  4243. * @return grocery_CRUD
  4244. */
  4245. public function set_subject($subject, $subject_plural = null)
  4246. {
  4247. $this->subject = $subject;
  4248. $this->subject_plural = $subject_plural === null ? $subject : $subject_plural;
  4249. return $this;
  4250. }
  4251. /**
  4252. *
  4253. * Enter description here ...
  4254. * @param $title
  4255. * @param $image_url
  4256. * @param $url
  4257. * @param $css_class
  4258. * @param $url_callback
  4259. */
  4260. public function add_action( $label, $image_url = '', $link_url = '', $css_class = '', $url_callback = null)
  4261. {
  4262. $unique_id = substr($label,0,1).substr(md5($label.$link_url),-8); //The unique id is used for class name so it must begin with a string
  4263. $this->actions[$unique_id] = (object)array(
  4264. 'label' => $label,
  4265. 'image_url' => $image_url,
  4266. 'link_url' => $link_url,
  4267. 'css_class' => $css_class,
  4268. 'url_callback' => $url_callback,
  4269. 'url_has_http' => substr($link_url,0,7) == 'http://' || substr($link_url,0,8) == 'https://' ? true : false
  4270. );
  4271. return $this;
  4272. }
  4273. /**
  4274. *
  4275. * Set a simple 1-n foreign key relation
  4276. * @param string $field_name
  4277. * @param string $related_table
  4278. * @param string $related_title_field
  4279. * @param mixed $where_clause
  4280. * @param string $order_by
  4281. * @return Grocery_CRUD
  4282. */
  4283. public function set_relation($field_name , $related_table, $related_title_field, $where_clause = null, $order_by = null)
  4284. {
  4285. $this->relation[$field_name] = array($field_name, $related_table,$related_title_field, $where_clause, $order_by);
  4286. return $this;
  4287. }
  4288. /**
  4289. *
  4290. * Sets a relation with n-n relationship.
  4291. * @param string $field_name
  4292. * @param string $relation_table
  4293. * @param string $selection_table
  4294. * @param string $primary_key_alias_to_this_table
  4295. * @param string $primary_key_alias_to_selection_table
  4296. * @param string $title_field_selection_table
  4297. * @param string $priority_field_relation_table
  4298. * @param mixed $where_clause
  4299. * @return Grocery_CRUD
  4300. */
  4301. public function set_relation_n_n($field_name, $relation_table, $selection_table, $primary_key_alias_to_this_table, $primary_key_alias_to_selection_table , $title_field_selection_table , $priority_field_relation_table = null, $where_clause = null)
  4302. {
  4303. $this->relation_n_n[$field_name] =
  4304. (object)array(
  4305. 'field_name' => $field_name,
  4306. 'relation_table' => $relation_table,
  4307. 'selection_table' => $selection_table,
  4308. 'primary_key_alias_to_this_table' => $primary_key_alias_to_this_table,
  4309. 'primary_key_alias_to_selection_table' => $primary_key_alias_to_selection_table ,
  4310. 'title_field_selection_table' => $title_field_selection_table ,
  4311. 'priority_field_relation_table' => $priority_field_relation_table,
  4312. 'where_clause' => $where_clause
  4313. );
  4314. return $this;
  4315. }
  4316. /**
  4317. *
  4318. * Transform a field to an upload field
  4319. *
  4320. * @param string $field_name
  4321. * @param string $upload_path
  4322. * @return Grocery_CRUD
  4323. */
  4324. public function set_field_upload($field_name, $upload_dir = '', $allowed_file_types = '')
  4325. {
  4326. $upload_dir = !empty($upload_dir) && substr($upload_dir,-1,1) == '/'
  4327. ? substr($upload_dir,0,-1)
  4328. : $upload_dir;
  4329. $upload_dir = !empty($upload_dir) ? $upload_dir : 'assets/uploads/files';
  4330. /** Check if the upload Url folder exists. If not then throw an exception **/
  4331. if (!is_dir(FCPATH.$upload_dir)) {
  4332. throw new Exception("It seems that the folder \"".FCPATH.$upload_dir."\" for the field name
  4333. \"".$field_name."\" doesn't exists. Please create the folder and try again.");
  4334. }
  4335. $this->upload_fields[$field_name] = (object) array(
  4336. 'field_name' => $field_name,
  4337. 'upload_path' => $upload_dir,
  4338. 'allowed_file_types' => $allowed_file_types,
  4339. 'encrypted_field_name' => $this->_unique_field_name($field_name));
  4340. return $this;
  4341. }
  4342. }
  4343. if(defined('CI_VERSION'))
  4344. {
  4345. $ci = &get_instance();
  4346. $ci->load->library('Form_validation');
  4347. class grocery_CRUD_Form_validation extends CI_Form_validation{
  4348. public $CI;
  4349. public $_field_data = array();
  4350. public $_config_rules = array();
  4351. public $_error_array = array();
  4352. public $_error_messages = array();
  4353. public $_error_prefix = '<p>';
  4354. public $_error_suffix = '</p>';
  4355. public $error_string = '';
  4356. public $_safe_form_data = FALSE;
  4357. }
  4358. }
  4359. /*
  4360. * jQuery File Upload Plugin PHP Example 5.5
  4361. * https://github.com/blueimp/jQuery-File-Upload
  4362. *
  4363. * Copyright 2010, Sebastian Tschan
  4364. * https://blueimp.net
  4365. *
  4366. * Licensed under the MIT license:
  4367. * http://www.opensource.org/licenses/MIT
  4368. */
  4369. class UploadHandler
  4370. {
  4371. private $options;
  4372. public $default_config_path = null;
  4373. function __construct($options=null) {
  4374. $this->options = array(
  4375. 'script_url' => $this->getFullUrl().'/'.basename(__FILE__),
  4376. 'upload_dir' => dirname(__FILE__).'/files/',
  4377. 'upload_url' => $this->getFullUrl().'/files/',
  4378. 'param_name' => 'files',
  4379. // The php.ini settings upload_max_filesize and post_max_size
  4380. // take precedence over the following max_file_size setting:
  4381. 'max_file_size' => null,
  4382. 'min_file_size' => 1,
  4383. 'accept_file_types' => '/.+$/i',
  4384. 'max_number_of_files' => null,
  4385. // Set the following option to false to enable non-multipart uploads:
  4386. 'discard_aborted_uploads' => true,
  4387. // Set to true to rotate images based on EXIF meta data, if available:
  4388. 'orient_image' => false,
  4389. 'image_versions' => array(
  4390. // Uncomment the following version to restrict the size of
  4391. // uploaded images. You can also add additional versions with
  4392. // their own upload directories:
  4393. /*
  4394. 'large' => array(
  4395. 'upload_dir' => dirname(__FILE__).'/files/',
  4396. 'upload_url' => dirname($_SERVER['PHP_SELF']).'/files/',
  4397. 'max_width' => 1920,
  4398. 'max_height' => 1200
  4399. ),
  4400. 'thumbnail' => array(
  4401. 'upload_dir' => dirname(__FILE__).'/thumbnails/',
  4402. 'upload_url' => $this->getFullUrl().'/thumbnails/',
  4403. 'max_width' => 80,
  4404. 'max_height' => 80
  4405. )
  4406. */
  4407. )
  4408. );
  4409. if ($options) {
  4410. // Or else for PHP >= 5.3.0 use: $this->options = array_replace_recursive($this->options, $options);
  4411. foreach($options as $option_name => $option)
  4412. {
  4413. $this->options[$option_name] = $option;
  4414. }
  4415. }
  4416. }
  4417. function getFullUrl() {
  4418. return
  4419. (isset($_SERVER['HTTPS']) ? 'https://' : 'http://').
  4420. (isset($_SERVER['REMOTE_USER']) ? $_SERVER['REMOTE_USER'].'@' : '').
  4421. (isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : ($_SERVER['SERVER_NAME'].
  4422. (isset($_SERVER['HTTPS']) && $_SERVER['SERVER_PORT'] === 443 ||
  4423. $_SERVER['SERVER_PORT'] === 80 ? '' : ':'.$_SERVER['SERVER_PORT']))).
  4424. substr($_SERVER['SCRIPT_NAME'],0, strrpos($_SERVER['SCRIPT_NAME'], '/'));
  4425. }
  4426. private function get_file_object($file_name) {
  4427. $file_path = $this->options['upload_dir'].$file_name;
  4428. if (is_file($file_path) && $file_name[0] !== '.') {
  4429. $file = new stdClass();
  4430. $file->name = $file_name;
  4431. $file->size = filesize($file_path);
  4432. $file->url = $this->options['upload_url'].rawurlencode($file->name);
  4433. foreach($this->options['image_versions'] as $version => $options) {
  4434. if (is_file($options['upload_dir'].$file_name)) {
  4435. $file->{$version.'_url'} = $options['upload_url']
  4436. .rawurlencode($file->name);
  4437. }
  4438. }
  4439. $file->delete_url = $this->options['script_url']
  4440. .'?file='.rawurlencode($file->name);
  4441. $file->delete_type = 'DELETE';
  4442. return $file;
  4443. }
  4444. return null;
  4445. }
  4446. private function get_file_objects() {
  4447. return array_values(array_filter(array_map(
  4448. array($this, 'get_file_object'),
  4449. scandir($this->options['upload_dir'])
  4450. )));
  4451. }
  4452. private function create_scaled_image($file_name, $options) {
  4453. $file_path = $this->options['upload_dir'].$file_name;
  4454. $new_file_path = $options['upload_dir'].$file_name;
  4455. list($img_width, $img_height) = @getimagesize($file_path);
  4456. if (!$img_width || !$img_height) {
  4457. return false;
  4458. }
  4459. $scale = min(
  4460. $options['max_width'] / $img_width,
  4461. $options['max_height'] / $img_height
  4462. );
  4463. if ($scale > 1) {
  4464. $scale = 1;
  4465. }
  4466. $new_width = $img_width * $scale;
  4467. $new_height = $img_height * $scale;
  4468. $new_img = @imagecreatetruecolor($new_width, $new_height);
  4469. switch (strtolower(substr(strrchr($file_name, '.'), 1))) {
  4470. case 'jpg':
  4471. case 'jpeg':
  4472. $src_img = @imagecreatefromjpeg($file_path);
  4473. $write_image = 'imagejpeg';
  4474. break;
  4475. case 'gif':
  4476. @imagecolortransparent($new_img, @imagecolorallocate($new_img, 0, 0, 0));
  4477. $src_img = @imagecreatefromgif($file_path);
  4478. $write_image = 'imagegif';
  4479. break;
  4480. case 'png':
  4481. @imagecolortransparent($new_img, @imagecolorallocate($new_img, 0, 0, 0));
  4482. @imagealphablending($new_img, false);
  4483. @imagesavealpha($new_img, true);
  4484. $src_img = @imagecreatefrompng($file_path);
  4485. $write_image = 'imagepng';
  4486. break;
  4487. default:
  4488. $src_img = $image_method = null;
  4489. }
  4490. $success = $src_img && @imagecopyresampled(
  4491. $new_img,
  4492. $src_img,
  4493. 0, 0, 0, 0,
  4494. $new_width,
  4495. $new_height,
  4496. $img_width,
  4497. $img_height
  4498. ) && $write_image($new_img, $new_file_path);
  4499. // Free up memory (imagedestroy does not delete files):
  4500. @imagedestroy($src_img);
  4501. @imagedestroy($new_img);
  4502. return $success;
  4503. }
  4504. private function has_error($uploaded_file, $file, $error) {
  4505. if ($error) {
  4506. switch($error) {
  4507. case UPLOAD_ERR_INI_SIZE:
  4508. return 'The uploaded file exceeds the upload_max_filesize directive in php.ini.';
  4509. break;
  4510. case UPLOAD_ERR_PARTIAL:
  4511. return 'The uploaded file was only partially uploaded.';
  4512. break;
  4513. case UPLOAD_ERR_NO_FILE:
  4514. return 'No file was uploaded.';
  4515. break;
  4516. case UPLOAD_ERR_CANT_WRITE:
  4517. return 'Failed to write file to disk.';
  4518. break;
  4519. case UPLOAD_ERR_EXTENSION:
  4520. return 'File upload stopped by extension.';
  4521. break;
  4522. default:
  4523. return $error;
  4524. break;
  4525. }
  4526. }
  4527. if (!preg_match($this->options['accept_file_types'], $file->name)) {
  4528. return 'acceptFileTypes';
  4529. }
  4530. if ($uploaded_file && is_uploaded_file($uploaded_file)) {
  4531. $file_size = filesize($uploaded_file);
  4532. } else {
  4533. $file_size = $_SERVER['CONTENT_LENGTH'];
  4534. }
  4535. if ($this->options['max_file_size'] && (
  4536. $file_size > $this->options['max_file_size'] ||
  4537. $file->size > $this->options['max_file_size'])
  4538. ) {
  4539. return 'maxFileSize';
  4540. }
  4541. if ($this->options['min_file_size'] &&
  4542. $file_size < $this->options['min_file_size']) {
  4543. return 'minFileSize';
  4544. }
  4545. if (is_int($this->options['max_number_of_files']) && (
  4546. count($this->get_file_objects()) >= $this->options['max_number_of_files'])
  4547. ) {
  4548. return 'maxNumberOfFiles';
  4549. }
  4550. return $error;
  4551. }
  4552. private function trim_file_name($name, $type) {
  4553. // Remove path information and dots around the filename, to prevent uploading
  4554. // into different directories or replacing hidden system files.
  4555. // Also remove control characters and spaces (\x00..\x20) around the filename:
  4556. $file_name = trim(basename(stripslashes($name)), ".\x00..\x20");
  4557. // Add missing file extension for known image types:
  4558. if (strpos($file_name, '.') === false &&
  4559. preg_match('/^image\/(gif|jpe?g|png)/', $type, $matches)) {
  4560. $file_name .= '.'.$matches[1];
  4561. }
  4562. //Ensure that we don't have disallowed characters and add a unique id just to ensure that the file name will be unique
  4563. $file_name = substr(uniqid(),-5).'-'.$this->_transliterate_characters($file_name);
  4564. //all the characters has to be lowercase
  4565. $file_name = strtolower($file_name);
  4566. return $file_name;
  4567. }
  4568. private function _transliterate_characters($file_name)
  4569. {
  4570. include($this->default_config_path.'/translit_chars.php');
  4571. if ( isset($translit_characters))
  4572. {
  4573. $file_name = preg_replace(array_keys($translit_characters), array_values($translit_characters), $file_name);
  4574. }
  4575. $file_name = preg_replace("/([^a-zA-Z0-9\.\-\_]+?){1}/i", '-', $file_name);
  4576. $file_name = str_replace(" ", "-", $file_name);
  4577. return preg_replace('/\-+/', '-', trim($file_name, '-'));
  4578. }
  4579. private function orient_image($file_path) {
  4580. $exif = exif_read_data($file_path);
  4581. $orientation = intval(@$exif['Orientation']);
  4582. if (!in_array($orientation, array(3, 6, 8))) {
  4583. return false;
  4584. }
  4585. $image = @imagecreatefromjpeg($file_path);
  4586. switch ($orientation) {
  4587. case 3:
  4588. $image = @imagerotate($image, 180, 0);
  4589. break;
  4590. case 6:
  4591. $image = @imagerotate($image, 270, 0);
  4592. break;
  4593. case 8:
  4594. $image = @imagerotate($image, 90, 0);
  4595. break;
  4596. default:
  4597. return false;
  4598. }
  4599. $success = imagejpeg($image, $file_path);
  4600. // Free up memory (imagedestroy does not delete files):
  4601. @imagedestroy($image);
  4602. return $success;
  4603. }
  4604. private function handle_file_upload($uploaded_file, $name, $size, $type, $error) {
  4605. $file = new stdClass();
  4606. $file->name = $this->trim_file_name($name, $type);
  4607. $file->size = intval($size);
  4608. $file->type = $type;
  4609. $error = $this->has_error($uploaded_file, $file, $error);
  4610. if (!$error && $file->name) {
  4611. $file_path = $this->options['upload_dir'].$file->name;
  4612. $append_file = !$this->options['discard_aborted_uploads'] &&
  4613. is_file($file_path) && $file->size > filesize($file_path);
  4614. clearstatcache();
  4615. if ($uploaded_file && is_uploaded_file($uploaded_file)) {
  4616. // multipart/formdata uploads (POST method uploads)
  4617. if ($append_file) {
  4618. file_put_contents(
  4619. $file_path,
  4620. fopen($uploaded_file, 'r'),
  4621. FILE_APPEND
  4622. );
  4623. } else {
  4624. move_uploaded_file($uploaded_file, $file_path);
  4625. }
  4626. } else {
  4627. // Non-multipart uploads (PUT method support)
  4628. file_put_contents(
  4629. $file_path,
  4630. fopen('php://input', 'r'),
  4631. $append_file ? FILE_APPEND : 0
  4632. );
  4633. }
  4634. $file_size = filesize($file_path);
  4635. if ($file_size === $file->size) {
  4636. if ($this->options['orient_image']) {
  4637. $this->orient_image($file_path);
  4638. }
  4639. $file->url = $this->options['upload_url'].rawurlencode($file->name);
  4640. foreach($this->options['image_versions'] as $version => $options) {
  4641. if ($this->create_scaled_image($file->name, $options)) {
  4642. $file->{$version.'_url'} = $options['upload_url']
  4643. .rawurlencode($file->name);
  4644. }
  4645. }
  4646. } else if ($this->options['discard_aborted_uploads']) {
  4647. unlink($file_path);
  4648. $file->error = "It seems that this user doesn't have permissions to upload to this folder";
  4649. }
  4650. $file->size = $file_size;
  4651. $file->delete_url = $this->options['script_url']
  4652. .'?file='.rawurlencode($file->name);
  4653. $file->delete_type = 'DELETE';
  4654. } else {
  4655. $file->error = $error;
  4656. }
  4657. return $file;
  4658. }
  4659. public function get() {
  4660. $file_name = isset($_REQUEST['file']) ?
  4661. basename(stripslashes($_REQUEST['file'])) : null;
  4662. if ($file_name) {
  4663. $info = $this->get_file_object($file_name);
  4664. } else {
  4665. $info = $this->get_file_objects();
  4666. }
  4667. header('Content-type: application/json');
  4668. echo json_encode($info);
  4669. }
  4670. public function post() {
  4671. if (isset($_REQUEST['_method']) && $_REQUEST['_method'] === 'DELETE') {
  4672. return $this->delete();
  4673. }
  4674. $upload = isset($_FILES[$this->options['param_name']]) ?
  4675. $_FILES[$this->options['param_name']] : null;
  4676. $info = array();
  4677. if ($upload && is_array($upload['tmp_name'])) {
  4678. foreach ($upload['tmp_name'] as $index => $value) {
  4679. $info[] = $this->handle_file_upload(
  4680. $upload['tmp_name'][$index],
  4681. isset($_SERVER['HTTP_X_FILE_NAME']) ?
  4682. $_SERVER['HTTP_X_FILE_NAME'] : $upload['name'][$index],
  4683. isset($_SERVER['HTTP_X_FILE_SIZE']) ?
  4684. $_SERVER['HTTP_X_FILE_SIZE'] : $upload['size'][$index],
  4685. isset($_SERVER['HTTP_X_FILE_TYPE']) ?
  4686. $_SERVER['HTTP_X_FILE_TYPE'] : $upload['type'][$index],
  4687. $upload['error'][$index]
  4688. );
  4689. }
  4690. } elseif ($upload || isset($_SERVER['HTTP_X_FILE_NAME'])) {
  4691. $info[] = $this->handle_file_upload(
  4692. isset($upload['tmp_name']) ? $upload['tmp_name'] : null,
  4693. isset($_SERVER['HTTP_X_FILE_NAME']) ?
  4694. $_SERVER['HTTP_X_FILE_NAME'] : $upload['name'],
  4695. isset($_SERVER['HTTP_X_FILE_SIZE']) ?
  4696. $_SERVER['HTTP_X_FILE_SIZE'] : $upload['size'],
  4697. isset($_SERVER['HTTP_X_FILE_TYPE']) ?
  4698. $_SERVER['HTTP_X_FILE_TYPE'] : $upload['type'],
  4699. isset($upload['error']) ? $upload['error'] : null
  4700. );
  4701. }
  4702. header('Vary: Accept');
  4703. $redirect = isset($_REQUEST['redirect']) ?
  4704. stripslashes($_REQUEST['redirect']) : null;
  4705. if ($redirect) {
  4706. header('Location: '.sprintf($redirect, rawurlencode($json)));
  4707. return;
  4708. }
  4709. if (isset($_SERVER['HTTP_ACCEPT']) &&
  4710. (strpos($_SERVER['HTTP_ACCEPT'], 'application/json') !== false)) {
  4711. header('Content-type: application/json');
  4712. } else {
  4713. header('Content-type: text/plain');
  4714. }
  4715. return $info;
  4716. }
  4717. public function delete() {
  4718. $file_name = isset($_REQUEST['file']) ?
  4719. basename(stripslashes($_REQUEST['file'])) : null;
  4720. $file_path = $this->options['upload_dir'].$file_name;
  4721. $success = is_file($file_path) && $file_name[0] !== '.' && unlink($file_path);
  4722. if ($success) {
  4723. foreach($this->options['image_versions'] as $version => $options) {
  4724. $file = $options['upload_dir'].$file_name;
  4725. if (is_file($file)) {
  4726. unlink($file);
  4727. }
  4728. }
  4729. }
  4730. header('Content-type: application/json');
  4731. echo json_encode($success);
  4732. }
  4733. }