DisplayResults.class.php 215 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011501250135014501550165017501850195020502150225023502450255026502750285029503050315032503350345035503650375038503950405041504250435044504550465047504850495050505150525053505450555056505750585059506050615062506350645065506650675068506950705071507250735074507550765077507850795080508150825083508450855086508750885089509050915092509350945095509650975098509951005101510251035104510551065107510851095110511151125113511451155116511751185119512051215122512351245125512651275128512951305131513251335134513551365137513851395140514151425143514451455146514751485149515051515152515351545155515651575158515951605161516251635164516551665167516851695170517151725173517451755176517751785179518051815182518351845185518651875188518951905191519251935194519551965197519851995200520152025203520452055206520752085209521052115212521352145215521652175218521952205221522252235224522552265227522852295230523152325233523452355236523752385239524052415242524352445245524652475248524952505251525252535254525552565257525852595260526152625263526452655266526752685269527052715272527352745275527652775278527952805281528252835284528552865287528852895290529152925293529452955296529752985299530053015302530353045305530653075308530953105311531253135314531553165317531853195320532153225323532453255326532753285329533053315332533353345335533653375338533953405341534253435344534553465347534853495350535153525353535453555356535753585359536053615362536353645365536653675368536953705371537253735374537553765377537853795380538153825383538453855386538753885389539053915392539353945395539653975398539954005401540254035404540554065407540854095410541154125413541454155416541754185419542054215422542354245425542654275428542954305431543254335434543554365437543854395440544154425443544454455446544754485449545054515452545354545455545654575458545954605461546254635464546554665467546854695470547154725473547454755476547754785479548054815482548354845485548654875488548954905491549254935494549554965497549854995500550155025503550455055506550755085509551055115512551355145515551655175518551955205521552255235524552555265527552855295530553155325533553455355536553755385539554055415542554355445545554655475548554955505551555255535554555555565557555855595560556155625563556455655566556755685569557055715572557355745575557655775578557955805581558255835584558555865587558855895590559155925593559455955596559755985599560056015602560356045605560656075608560956105611561256135614561556165617561856195620562156225623562456255626562756285629563056315632563356345635563656375638563956405641564256435644564556465647564856495650565156525653565456555656565756585659566056615662566356645665566656675668566956705671567256735674567556765677567856795680568156825683568456855686568756885689569056915692569356945695569656975698569957005701570257035704570557065707570857095710571157125713571457155716571757185719572057215722572357245725572657275728572957305731573257335734573557365737573857395740574157425743574457455746574757485749575057515752575357545755575657575758575957605761576257635764576557665767576857695770577157725773577457755776577757785779578057815782578357845785578657875788578957905791579257935794579557965797579857995800580158025803580458055806580758085809581058115812581358145815581658175818581958205821582258235824582558265827582858295830583158325833583458355836583758385839584058415842584358445845584658475848584958505851585258535854585558565857585858595860586158625863586458655866586758685869587058715872587358745875587658775878587958805881588258835884588558865887588858895890589158925893589458955896589758985899590059015902590359045905590659075908590959105911591259135914591559165917591859195920592159225923592459255926592759285929593059315932593359345935593659375938593959405941594259435944594559465947594859495950595159525953595459555956595759585959596059615962596359645965596659675968596959705971597259735974597559765977597859795980598159825983598459855986598759885989599059915992599359945995599659975998599960006001600260036004600560066007600860096010601160126013
  1. <?php
  2. /* vim: set expandtab sw=4 ts=4 sts=4: */
  3. /**
  4. * Hold the PMA_DisplayResults class
  5. *
  6. * @package PhpMyAdmin
  7. */
  8. if (! defined('PHPMYADMIN')) {
  9. exit;
  10. }
  11. /**
  12. * Handle all the functionalities related to displaying results
  13. * of sql queries, stored procedure, browsing sql processes or
  14. * displaying binary log.
  15. *
  16. * @package PhpMyAdmin
  17. */
  18. class PMA_DisplayResults
  19. {
  20. // Define constants
  21. const NO_EDIT_OR_DELETE = 'nn';
  22. const UPDATE_ROW = 'ur';
  23. const DELETE_ROW = 'dr';
  24. const KILL_PROCESS = 'kp';
  25. const POSITION_LEFT = 'left';
  26. const POSITION_RIGHT = 'right';
  27. const POSITION_BOTH = 'both';
  28. const POSITION_NONE = 'none';
  29. const PLACE_TOP_DIRECTION_DROPDOWN = 'top_direction_dropdown';
  30. const PLACE_BOTTOM_DIRECTION_DROPDOWN = 'bottom_direction_dropdown';
  31. const DISP_DIR_HORIZONTAL = 'horizontal';
  32. const DISP_DIR_HORIZONTAL_FLIPPED = 'horizontalflipped';
  33. const DISP_DIR_VERTICAL = 'vertical';
  34. const DISPLAY_FULL_TEXT = 'F';
  35. const DISPLAY_PARTIAL_TEXT = 'P';
  36. const HEADER_FLIP_TYPE_AUTO = 'auto';
  37. const HEADER_FLIP_TYPE_CSS = 'css';
  38. const HEADER_FLIP_TYPE_FAKE = 'fake';
  39. const DATE_FIELD = 'date';
  40. const DATETIME_FIELD = 'datetime';
  41. const TIMESTAMP_FIELD = 'timestamp';
  42. const STRING_FIELD = 'string';
  43. const GEOMETRY_FIELD = 'geometry';
  44. const BLOB_FIELD = 'BLOB';
  45. const BINARY_FIELD = 'BINARY';
  46. const RELATIONAL_KEY = 'K';
  47. const RELATIONAL_DISPLAY_COLUMN = 'D';
  48. const GEOMETRY_DISP_GEOM = 'GEOM';
  49. const GEOMETRY_DISP_WKT = 'WKT';
  50. const GEOMETRY_DISP_WKB = 'WKB';
  51. const SMART_SORT_ORDER = 'SMART';
  52. const ASCENDING_SORT_DIR = 'ASC';
  53. const DESCENDING_SORT_DIR = 'DESC';
  54. const TABLE_TYPE_INNO_DB = 'InnoDB';
  55. const ALL_ROWS = 'all';
  56. const QUERY_TYPE_SELECT = 'SELECT';
  57. const ROUTINE_PROCEDURE = 'procedure';
  58. const ROUTINE_FUNCTION = 'function';
  59. // Declare global fields
  60. /** array with properties of the class */
  61. private $_property_array = array(
  62. /** string Database name */
  63. 'db' => null,
  64. /** string Table name */
  65. 'table' => null,
  66. /** string the URL to go back in case of errors */
  67. 'goto' => null,
  68. /** string the SQL query */
  69. 'sql_query' => null,
  70. /**
  71. * integer the total number of rows returned by the SQL query without any
  72. * appended "LIMIT" clause programmatically
  73. */
  74. 'unlim_num_rows' => null,
  75. /** array meta information about fields */
  76. 'fields_meta' => null,
  77. /** boolean */
  78. 'is_count' => null,
  79. /** integer */
  80. 'is_export' => null,
  81. /** boolean */
  82. 'is_func' => null,
  83. /** integer */
  84. 'is_analyse' => null,
  85. /** integer the total number of rows returned by the SQL query */
  86. 'num_rows' => null,
  87. /** integer the total number of fields returned by the SQL query */
  88. 'fields_cnt' => null,
  89. /** double time taken for execute the SQL query */
  90. 'querytime' => null,
  91. /** string path for theme images directory */
  92. 'pma_theme_image' => null,
  93. /** string */
  94. 'text_dir' => null,
  95. /** boolean */
  96. 'is_maint' => null,
  97. /** boolean */
  98. 'is_explain' => null,
  99. /** boolean */
  100. 'is_show' => null,
  101. /** array table definitions */
  102. 'showtable' => null,
  103. /** string */
  104. 'printview' => null,
  105. /** string URL query */
  106. 'url_query' => null,
  107. /** array column names to highlight */
  108. 'highlight_columns' => null,
  109. /** array informations used with vertical display mode */
  110. 'vertical_display' => null,
  111. /** array mime types information of fields */
  112. 'mime_map' => null,
  113. /** boolean */
  114. 'editable' => null
  115. );
  116. /**
  117. * This variable contains the column transformation information
  118. * for some of the system databases.
  119. * One element of this array represent all relavant columns in all tables in
  120. * one specific database
  121. */
  122. public $transformation_info;
  123. /**
  124. * Get any property of this class
  125. *
  126. * @param string $property name of the property
  127. *
  128. * @return if property exist, value of the relavant property
  129. */
  130. public function __get($property)
  131. {
  132. if (array_key_exists($property, $this->_property_array)) {
  133. return $this->_property_array[$property];
  134. }
  135. }
  136. /**
  137. * Set values for any property of this class
  138. *
  139. * @param string $property name of the property
  140. * @param any $value value to set
  141. *
  142. * @return void
  143. */
  144. public function __set($property, $value)
  145. {
  146. if (array_key_exists($property, $this->_property_array)) {
  147. $this->_property_array[$property] = $value;
  148. }
  149. }
  150. /**
  151. * Constructor for PMA_DisplayResults class
  152. *
  153. * @param string $db the database name
  154. * @param string $table the table name
  155. * @param string $goto the URL to go back in case of errors
  156. * @param string $sql_query the SQL query
  157. *
  158. * @access public
  159. */
  160. public function __construct($db, $table, $goto, $sql_query)
  161. {
  162. $this->_setDefaultTransformations();
  163. $this->__set('db', $db);
  164. $this->__set('table', $table);
  165. $this->__set('goto', $goto);
  166. $this->__set('sql_query', $sql_query);
  167. }
  168. /**
  169. * Sets default transformations for some columns
  170. *
  171. * @return void
  172. */
  173. private function _setDefaultTransformations()
  174. {
  175. $sql_highlighting_data = array(
  176. 'libraries/plugins/transformations/Text_Plain_Formatted.class.php',
  177. 'Text_Plain_Formatted',
  178. 'Text_Plain'
  179. );
  180. $this->transformation_info = array(
  181. 'information_schema' => array(
  182. 'events' => array(
  183. 'event_definition' => $sql_highlighting_data
  184. ),
  185. 'processlist' => array(
  186. 'info' => $sql_highlighting_data
  187. ),
  188. 'routines' => array(
  189. 'routine_definition' => $sql_highlighting_data
  190. ),
  191. 'triggers' => array(
  192. 'action_statement' => $sql_highlighting_data
  193. ),
  194. 'views' => array(
  195. 'view_definition' => $sql_highlighting_data
  196. )
  197. )
  198. );
  199. $cfgRelation = PMA_getRelationsParam();
  200. if ($cfgRelation['db']) {
  201. $this->transformation_info[$cfgRelation['db']] = array();
  202. $relDb = &$this->transformation_info[$cfgRelation['db']];
  203. if ($cfgRelation['history']) {
  204. $relDb[$cfgRelation['history']] = array(
  205. 'sqlquery' => $sql_highlighting_data
  206. );
  207. }
  208. if ($cfgRelation['bookmark']) {
  209. $relDb[$cfgRelation['bookmark']] = array(
  210. 'query' => $sql_highlighting_data
  211. );
  212. }
  213. if ($cfgRelation['tracking']) {
  214. $relDb[$cfgRelation['tracking']] = array(
  215. 'schema_sql' => $sql_highlighting_data,
  216. 'data_sql' => $sql_highlighting_data
  217. );
  218. }
  219. }
  220. }
  221. /**
  222. * Set properties which were not initialized at the constructor
  223. *
  224. * @param type $unlim_num_rows integer the total number of rows returned by
  225. * the SQL query without any appended
  226. * "LIMIT" clause programmatically
  227. * @param type $fields_meta array meta information about fields
  228. * @param type $is_count boolean
  229. * @param type $is_export integer
  230. * @param type $is_func boolean
  231. * @param type $is_analyse integer
  232. * @param type $num_rows integer total no. of rows returned by SQL query
  233. * @param type $fields_cnt integer total no.of fields returned by SQL query
  234. * @param type $querytime double time taken for execute the SQL query
  235. * @param type $pmaThemeImage string path for theme images directory
  236. * @param type $text_dir string
  237. * @param type $is_maint boolean
  238. * @param type $is_explain boolean
  239. * @param type $is_show boolean
  240. * @param type $showtable array table definitions
  241. * @param type $printview string
  242. * @param type $url_query string URL query
  243. * @param type $editable boolean whether the resutls set is editable
  244. *
  245. * @return void
  246. *
  247. * @see sql.php
  248. */
  249. public function setProperties(
  250. $unlim_num_rows, $fields_meta, $is_count, $is_export, $is_func,
  251. $is_analyse, $num_rows, $fields_cnt, $querytime, $pmaThemeImage, $text_dir,
  252. $is_maint, $is_explain, $is_show, $showtable, $printview, $url_query,
  253. $editable
  254. ) {
  255. $this->__set('unlim_num_rows', $unlim_num_rows);
  256. $this->__set('fields_meta', $fields_meta);
  257. $this->__set('is_count', $is_count);
  258. $this->__set('is_export', $is_export);
  259. $this->__set('is_func', $is_func);
  260. $this->__set('is_analyse', $is_analyse);
  261. $this->__set('num_rows', $num_rows);
  262. $this->__set('fields_cnt', $fields_cnt);
  263. $this->__set('querytime', $querytime);
  264. $this->__set('pma_theme_image', $pmaThemeImage);
  265. $this->__set('text_dir', $text_dir);
  266. $this->__set('is_maint', $is_maint);
  267. $this->__set('is_explain', $is_explain);
  268. $this->__set('is_show', $is_show);
  269. $this->__set('showtable', $showtable);
  270. $this->__set('printview', $printview);
  271. $this->__set('url_query', $url_query);
  272. $this->__set('editable', $editable);
  273. } // end of the 'setProperties()' function
  274. /**
  275. * Defines the display mode to use for the results of a SQL query
  276. *
  277. * It uses a synthetic string that contains all the required informations.
  278. * In this string:
  279. * - the first two characters stand for the action to do while
  280. * clicking on the "edit" link (e.g. 'ur' for update a row, 'nn' for no
  281. * edit link...);
  282. * - the next two characters stand for the action to do while
  283. * clicking on the "delete" link (e.g. 'kp' for kill a process, 'nn' for
  284. * no delete link...);
  285. * - the next characters are boolean values (1/0) and respectively stand
  286. * for sorting links, navigation bar, "insert a new row" link, the
  287. * bookmark feature, the expand/collapse text/blob fields button and
  288. * the "display printable view" option.
  289. * Of course '0'/'1' means the feature won't/will be enabled.
  290. *
  291. * @param string &$the_disp_mode the synthetic value for display_mode (see a few
  292. * lines above for explanations)
  293. * @param integer &$the_total the total number of rows returned by the SQL
  294. * query without any programmatically appended
  295. * LIMIT clause
  296. * (just a copy of $unlim_num_rows if it exists,
  297. * elsecomputed inside this function)
  298. *
  299. * @return array an array with explicit indexes for all the display
  300. * elements
  301. *
  302. * @access private
  303. *
  304. * @see getTable()
  305. */
  306. private function _setDisplayMode(&$the_disp_mode, &$the_total)
  307. {
  308. // Following variables are needed for use in isset/empty or
  309. // use with array indexes or safe use in foreach
  310. $db = $this->__get('db');
  311. $table = $this->__get('table');
  312. $unlim_num_rows = $this->__get('unlim_num_rows');
  313. $fields_meta = $this->__get('fields_meta');
  314. $printview = $this->__get('printview');
  315. // 1. Initializes the $do_display array
  316. $do_display = array();
  317. $do_display['edit_lnk'] = $the_disp_mode[0] . $the_disp_mode[1];
  318. $do_display['del_lnk'] = $the_disp_mode[2] . $the_disp_mode[3];
  319. $do_display['sort_lnk'] = (string) $the_disp_mode[4];
  320. $do_display['nav_bar'] = (string) $the_disp_mode[5];
  321. $do_display['ins_row'] = (string) $the_disp_mode[6];
  322. $do_display['bkm_form'] = (string) $the_disp_mode[7];
  323. $do_display['text_btn'] = (string) $the_disp_mode[8];
  324. $do_display['pview_lnk'] = (string) $the_disp_mode[9];
  325. // 2. Display mode is not "false for all elements" -> updates the
  326. // display mode
  327. if ($the_disp_mode != 'nnnn000000') {
  328. if (isset($printview) && ($printview == '1')) {
  329. // 2.0 Print view -> set all elements to false!
  330. $do_display['edit_lnk'] = self::NO_EDIT_OR_DELETE; // no edit link
  331. $do_display['del_lnk'] = self::NO_EDIT_OR_DELETE; // no delete link
  332. $do_display['sort_lnk'] = (string) '0';
  333. $do_display['nav_bar'] = (string) '0';
  334. $do_display['ins_row'] = (string) '0';
  335. $do_display['bkm_form'] = (string) '0';
  336. $do_display['text_btn'] = (string) '0';
  337. $do_display['pview_lnk'] = (string) '0';
  338. } elseif ($this->__get('is_count') || $this->__get('is_analyse')
  339. || $this->__get('is_maint') || $this->__get('is_explain')
  340. ) {
  341. // 2.1 Statement is a "SELECT COUNT", a
  342. // "CHECK/ANALYZE/REPAIR/OPTIMIZE", an "EXPLAIN" one or
  343. // contains a "PROC ANALYSE" part
  344. $do_display['edit_lnk'] = self::NO_EDIT_OR_DELETE; // no edit link
  345. $do_display['del_lnk'] = self::NO_EDIT_OR_DELETE; // no delete link
  346. $do_display['sort_lnk'] = (string) '0';
  347. $do_display['nav_bar'] = (string) '0';
  348. $do_display['ins_row'] = (string) '0';
  349. $do_display['bkm_form'] = (string) '1';
  350. if ($this->__get('is_maint')) {
  351. $do_display['text_btn'] = (string) '1';
  352. } else {
  353. $do_display['text_btn'] = (string) '0';
  354. }
  355. $do_display['pview_lnk'] = (string) '1';
  356. } elseif ($this->__get('is_show')) {
  357. // 2.2 Statement is a "SHOW..."
  358. /**
  359. * 2.2.1
  360. * @todo defines edit/delete links depending on show statement
  361. */
  362. $tmp = preg_match(
  363. '@^SHOW[[:space:]]+(VARIABLES|(FULL[[:space:]]+)?'
  364. . 'PROCESSLIST|STATUS|TABLE|GRANTS|CREATE|LOGS|DATABASES|FIELDS'
  365. . ')@i',
  366. $this->__get('sql_query'), $which
  367. );
  368. if (isset($which[1])
  369. && (strpos(' ' . strtoupper($which[1]), 'PROCESSLIST') > 0)
  370. ) {
  371. // no edit link
  372. $do_display['edit_lnk'] = self::NO_EDIT_OR_DELETE;
  373. // "kill process" type edit link
  374. $do_display['del_lnk'] = self::KILL_PROCESS;
  375. } else {
  376. // Default case -> no links
  377. // no edit link
  378. $do_display['edit_lnk'] = self::NO_EDIT_OR_DELETE;
  379. // no delete link
  380. $do_display['del_lnk'] = self::NO_EDIT_OR_DELETE;
  381. }
  382. // 2.2.2 Other settings
  383. $do_display['sort_lnk'] = (string) '0';
  384. $do_display['nav_bar'] = (string) '0';
  385. $do_display['ins_row'] = (string) '0';
  386. $do_display['bkm_form'] = (string) '1';
  387. $do_display['text_btn'] = (string) '1';
  388. $do_display['pview_lnk'] = (string) '1';
  389. } else {
  390. // 2.3 Other statements (ie "SELECT" ones) -> updates
  391. // $do_display['edit_lnk'], $do_display['del_lnk'] and
  392. // $do_display['text_btn'] (keeps other default values)
  393. $prev_table = $fields_meta[0]->table;
  394. $do_display['text_btn'] = (string) '1';
  395. for ($i = 0; $i < $this->__get('fields_cnt'); $i++) {
  396. $is_link = ($do_display['edit_lnk'] != self::NO_EDIT_OR_DELETE)
  397. || ($do_display['del_lnk'] != self::NO_EDIT_OR_DELETE)
  398. || ($do_display['sort_lnk'] != '0')
  399. || ($do_display['ins_row'] != '0');
  400. // 2.3.2 Displays edit/delete/sort/insert links?
  401. if ($is_link
  402. && (($fields_meta[$i]->table == '')
  403. || ($fields_meta[$i]->table != $prev_table))
  404. ) {
  405. // don't display links
  406. $do_display['edit_lnk'] = self::NO_EDIT_OR_DELETE;
  407. $do_display['del_lnk'] = self::NO_EDIT_OR_DELETE;
  408. /**
  409. * @todo May be problematic with same field names
  410. * in two joined table.
  411. */
  412. // $do_display['sort_lnk'] = (string) '0';
  413. $do_display['ins_row'] = (string) '0';
  414. if ($do_display['text_btn'] == '1') {
  415. break;
  416. }
  417. } // end if (2.3.2)
  418. // 2.3.3 Always display print view link
  419. $do_display['pview_lnk'] = (string) '1';
  420. $prev_table = $fields_meta[$i]->table;
  421. } // end for
  422. } // end if..elseif...else (2.1 -> 2.3)
  423. } // end if (2)
  424. // 3. Gets the total number of rows if it is unknown
  425. if (isset($unlim_num_rows) && $unlim_num_rows != '') {
  426. $the_total = $unlim_num_rows;
  427. } elseif ((($do_display['nav_bar'] == '1')
  428. || ($do_display['sort_lnk'] == '1'))
  429. && (strlen($db) && !empty($table))
  430. ) {
  431. $the_total = PMA_Table::countRecords($db, $table);
  432. }
  433. // 4. If navigation bar or sorting fields names URLs should be
  434. // displayed but there is only one row, change these settings to
  435. // false
  436. if ($do_display['nav_bar'] == '1' || $do_display['sort_lnk'] == '1') {
  437. // - Do not display sort links if less than 2 rows.
  438. // - For a VIEW we (probably) did not count the number of rows
  439. // so don't test this number here, it would remove the possibility
  440. // of sorting VIEW results.
  441. if (isset($unlim_num_rows)
  442. && ($unlim_num_rows < 2)
  443. && ! PMA_Table::isView($db, $table)
  444. ) {
  445. // force display of navbar for vertical/horizontal display-choice.
  446. // $do_display['nav_bar'] = (string) '0';
  447. $do_display['sort_lnk'] = (string) '0';
  448. }
  449. } // end if (3)
  450. // 5. Updates the synthetic var
  451. $the_disp_mode = join('', $do_display);
  452. return $do_display;
  453. } // end of the 'setDisplayMode()' function
  454. /**
  455. * Return true if we are executing a query in the form of
  456. * "SELECT * FROM <a table> ..."
  457. *
  458. * @param array $analyzed_sql the analyzed query
  459. *
  460. * @return boolean
  461. *
  462. * @access private
  463. *
  464. * @see _getTableHeaders(), _getColumnParams()
  465. */
  466. private function _isSelect($analyzed_sql)
  467. {
  468. if (!isset($analyzed_sql[0]['select_expr'])) {
  469. $analyzed_sql[0]['select_expr'] = 0;
  470. }
  471. return ! ($this->__get('is_count') || $this->__get('is_export')
  472. || $this->__get('is_func') || $this->__get('is_analyse'))
  473. && (count($analyzed_sql[0]['select_expr']) == 0)
  474. && isset($analyzed_sql[0]['queryflags']['select_from'])
  475. && (count($analyzed_sql[0]['table_ref']) == 1);
  476. }
  477. /**
  478. * Get a navigation button
  479. *
  480. * @param string $caption iconic caption for button
  481. * @param string $title text for button
  482. * @param integer $pos position for next query
  483. * @param string $html_sql_query query ready for display
  484. * @param string $onsubmit optional onsubmit clause
  485. * @param string $input_for_real_end optional hidden field for special treatment
  486. * @param string $onclick optional onclick clause
  487. *
  488. * @return string html content
  489. *
  490. * @access private
  491. *
  492. * @see _getMoveBackwardButtonsForTableNavigation(),
  493. * _getMoveForwardButtonsForTableNavigation()
  494. */
  495. private function _getTableNavigationButton(
  496. $caption, $title, $pos, $html_sql_query, $onsubmit = '',
  497. $input_for_real_end = '', $onclick = ''
  498. ) {
  499. $caption_output = '';
  500. if (in_array(
  501. $GLOBALS['cfg']['TableNavigationLinksMode'],
  502. array('icons', 'both')
  503. )
  504. ) {
  505. $caption_output .= $caption;
  506. }
  507. if (in_array(
  508. $GLOBALS['cfg']['TableNavigationLinksMode'],
  509. array('text', 'both')
  510. )
  511. ) {
  512. $caption_output .= '&nbsp;' . $title;
  513. }
  514. $title_output = ' title="' . $title . '"';
  515. return '<td>'
  516. . '<form action="sql.php" method="post" ' . $onsubmit . '>'
  517. . PMA_generate_common_hidden_inputs(
  518. $this->__get('db'), $this->__get('table')
  519. )
  520. . '<input type="hidden" name="sql_query" value="'
  521. . $html_sql_query . '" />'
  522. . '<input type="hidden" name="pos" value="' . $pos . '" />'
  523. . '<input type="hidden" name="goto" value="' . $this->__get('goto')
  524. . '" />'
  525. . $input_for_real_end
  526. . '<input type="submit" name="navig"'
  527. . ' class="ajax" '
  528. . 'value="' . $caption_output . '" ' . $title_output . $onclick . ' />'
  529. . '</form>'
  530. . '</td>';
  531. } // end function _getTableNavigationButton()
  532. /**
  533. * Get a navigation bar to browse among the results of a SQL query
  534. *
  535. * @param integer $pos_next the offset for the "next" page
  536. * @param integer $pos_prev the offset for the "previous" page
  537. * @param string $id_for_direction_dropdown the id for the direction dropdown
  538. * @param boolean $is_innodb whether its InnoDB or not
  539. *
  540. * @return string html content
  541. *
  542. * @access private
  543. *
  544. * @see _getTable()
  545. */
  546. private function _getTableNavigation(
  547. $pos_next, $pos_prev, $id_for_direction_dropdown, $is_innodb
  548. ) {
  549. $table_navigation_html = '';
  550. $showtable = $this->__get('showtable'); // To use in isset
  551. // here, using htmlentities() would cause problems if the query
  552. // contains accented characters
  553. $html_sql_query = htmlspecialchars($this->__get('sql_query'));
  554. /**
  555. * @todo move this to a central place
  556. * @todo for other future table types
  557. */
  558. $is_innodb = (isset($showtable['Type'])
  559. && $showtable['Type'] == self::TABLE_TYPE_INNO_DB);
  560. // Navigation bar
  561. $table_navigation_html .= '<table class="navigation nospacing nopadding">'
  562. . '<tr>'
  563. . '<td class="navigation_separator"></td>';
  564. // Move to the beginning or to the previous page
  565. if ($_SESSION['tmp_user_values']['pos']
  566. && ($_SESSION['tmp_user_values']['max_rows'] != self::ALL_ROWS)
  567. ) {
  568. $table_navigation_html
  569. .= $this->_getMoveBackwardButtonsForTableNavigation(
  570. $html_sql_query, $pos_prev
  571. );
  572. } // end move back
  573. $nbTotalPage = 1;
  574. //page redirection
  575. // (unless we are showing all records)
  576. if ($_SESSION['tmp_user_values']['max_rows'] != self::ALL_ROWS) { //if1
  577. $pageNow = @floor(
  578. $_SESSION['tmp_user_values']['pos']
  579. / $_SESSION['tmp_user_values']['max_rows']
  580. ) + 1;
  581. $nbTotalPage = @ceil(
  582. $this->__get('unlim_num_rows')
  583. / $_SESSION['tmp_user_values']['max_rows']
  584. );
  585. if ($nbTotalPage > 1) { //if2
  586. $table_navigation_html .= '<td>';
  587. $_url_params = array(
  588. 'db' => $this->__get('db'),
  589. 'table' => $this->__get('table'),
  590. 'sql_query' => $this->__get('sql_query'),
  591. 'goto' => $this->__get('goto'),
  592. );
  593. //<form> to keep the form alignment of button < and <<
  594. // and also to know what to execute when the selector changes
  595. $table_navigation_html .= '<form action="sql.php'
  596. . PMA_generate_common_url($_url_params)
  597. . '" method="post">';
  598. $table_navigation_html .= PMA_Util::pageselector(
  599. 'pos',
  600. $_SESSION['tmp_user_values']['max_rows'],
  601. $pageNow, $nbTotalPage, 200, 5, 5, 20, 10
  602. );
  603. $table_navigation_html .= '</form>'
  604. . '</td>';
  605. } //_if2
  606. } //_if1
  607. // Display the "Show all" button if allowed
  608. if (($this->__get('num_rows') < $this->__get('unlim_num_rows'))
  609. && ($GLOBALS['cfg']['ShowAll']
  610. || ($GLOBALS['cfg']['MaxRows'] * 5 >= $this->__get('unlim_num_rows')))
  611. ) {
  612. $table_navigation_html .= $this->_getShowAllButtonForTableNavigation(
  613. $html_sql_query
  614. );
  615. } // end show all
  616. // Move to the next page or to the last one
  617. $endpos = $_SESSION['tmp_user_values']['pos']
  618. + $_SESSION['tmp_user_values']['max_rows'];
  619. if (($endpos < $this->__get('unlim_num_rows'))
  620. && ($this->__get('num_rows') >= $_SESSION['tmp_user_values']['max_rows'])
  621. && ($_SESSION['tmp_user_values']['max_rows'] != self::ALL_ROWS)
  622. ) {
  623. $table_navigation_html
  624. .= $this->_getMoveForwardButtonsForTableNavigation(
  625. $html_sql_query, $pos_next, $is_innodb
  626. );
  627. } // end move toward
  628. // show separator if pagination happen
  629. if ($nbTotalPage > 1) {
  630. $table_navigation_html
  631. .= '<td><div class="navigation_separator">|</div></td>';
  632. }
  633. $table_navigation_html .= '<td>'
  634. . '<div class="save_edited hide">'
  635. . '<input type="submit" value="' . __('Save edited data') . '" />'
  636. . '<div class="navigation_separator">|</div>'
  637. . '</div>'
  638. . '</td>'
  639. . '<td>'
  640. . '<div class="restore_column hide">'
  641. . '<input type="submit" value="' . __('Restore column order') . '" />'
  642. . '<div class="navigation_separator">|</div>'
  643. . '</div>'
  644. . '</td>';
  645. // if displaying a VIEW, $unlim_num_rows could be zero because
  646. // of $cfg['MaxExactCountViews']; in this case, avoid passing
  647. // the 5th parameter to checkFormElementInRange()
  648. // (this means we can't validate the upper limit
  649. $table_navigation_html .= '<td class="navigation_goto">';
  650. $table_navigation_html .= '<form action="sql.php" method="post" '
  651. . 'onsubmit="return '
  652. . '(checkFormElementInRange('
  653. . 'this, '
  654. . '\'session_max_rows\', '
  655. . '\''
  656. . str_replace('\'', '\\\'', __('%d is not valid row number.'))
  657. . '\', '
  658. . '1)'
  659. . ' &amp;&amp; '
  660. . 'checkFormElementInRange('
  661. . 'this, '
  662. . '\'pos\', '
  663. . '\''
  664. . str_replace('\'', '\\\'', __('%d is not valid row number.'))
  665. . '\', '
  666. . '0'
  667. . (($this->__get('unlim_num_rows') > 0)
  668. ? ', ' . ($this->__get('unlim_num_rows') - 1)
  669. : ''
  670. )
  671. . ')'
  672. . ')'
  673. .'">';
  674. $table_navigation_html .= PMA_generate_common_hidden_inputs(
  675. $this->__get('db'), $this->__get('table')
  676. );
  677. $table_navigation_html .= $this->_getAdditionalFieldsForTableNavigation(
  678. $html_sql_query, $pos_next, $id_for_direction_dropdown
  679. );
  680. $table_navigation_html .= '</form>'
  681. . '</td>'
  682. . '<td class="navigation_separator"></td>'
  683. . '</tr>'
  684. . '</table>';
  685. return $table_navigation_html;
  686. } // end of the '_getTableNavigation()' function
  687. /**
  688. * Prepare move backward buttons - previous and first
  689. *
  690. * @param string $html_sql_query the sql encoded by html special characters
  691. * @param integer $pos_prev the offset for the "previous" page
  692. *
  693. * @return string html content
  694. *
  695. * @access private
  696. *
  697. * @see _getTableNavigation()
  698. */
  699. private function _getMoveBackwardButtonsForTableNavigation(
  700. $html_sql_query, $pos_prev
  701. ) {
  702. return $this->_getTableNavigationButton(
  703. '&lt;&lt;', _pgettext('First page', 'Begin'), 0, $html_sql_query
  704. )
  705. . $this->_getTableNavigationButton(
  706. '&lt;', _pgettext('Previous page', 'Previous'), $pos_prev,
  707. $html_sql_query
  708. );
  709. } // end of the '_getMoveBackwardButtonsForTableNavigation()' function
  710. /**
  711. * Prepare Show All button for table navigation
  712. *
  713. * @param string $html_sql_query the sql encoded by html special characters
  714. *
  715. * @return string html content
  716. *
  717. * @access private
  718. *
  719. * @see _getTableNavigation()
  720. */
  721. private function _getShowAllButtonForTableNavigation($html_sql_query)
  722. {
  723. return "\n"
  724. . '<td>'
  725. . '<form action="sql.php" method="post">'
  726. . PMA_generate_common_hidden_inputs(
  727. $this->__get('db'), $this->__get('table')
  728. )
  729. . '<input type="hidden" name="sql_query" value="'
  730. . $html_sql_query . '" />'
  731. . '<input type="hidden" name="pos" value="0" />'
  732. . '<input type="hidden" name="session_max_rows" value="all" />'
  733. . '<input type="hidden" name="goto" value="' . $this->__get('goto')
  734. . '" />'
  735. . '<input type="submit" name="navig" value="' . __('Show all') . '" />'
  736. . '</form>'
  737. . '</td>';
  738. } // end of the '_getShowAllButtonForTableNavigation()' function
  739. /**
  740. * Prepare move farward buttons - next and last
  741. *
  742. * @param string $html_sql_query the sql encoded by html special characters
  743. * @param integer $pos_next the offset for the "next" page
  744. * @param boolean $is_innodb whether its InnoDB or not
  745. *
  746. * @return string $buttons_html html content
  747. *
  748. * @access private
  749. *
  750. * @see _getTableNavigation()
  751. */
  752. private function _getMoveForwardButtonsForTableNavigation(
  753. $html_sql_query, $pos_next, $is_innodb
  754. ) {
  755. // display the Next button
  756. $buttons_html = $this->_getTableNavigationButton(
  757. '&gt;',
  758. _pgettext('Next page', 'Next'),
  759. $pos_next,
  760. $html_sql_query
  761. );
  762. // prepare some options for the End button
  763. if ($is_innodb
  764. && $this->__get('unlim_num_rows') > $GLOBALS['cfg']['MaxExactCount']
  765. ) {
  766. $input_for_real_end = '<input id="real_end_input" type="hidden" '
  767. . 'name="find_real_end" value="1" />';
  768. // no backquote around this message
  769. $onclick = '';
  770. } else {
  771. $input_for_real_end = $onclick = '';
  772. }
  773. $onsubmit = 'onsubmit="return '
  774. . ($_SESSION['tmp_user_values']['pos']
  775. + $_SESSION['tmp_user_values']['max_rows']
  776. < $this->__get('unlim_num_rows')
  777. && $this->__get('num_rows') >= $_SESSION['tmp_user_values']['max_rows'])
  778. ? 'true'
  779. : 'false' . '"';
  780. // display the End button
  781. $buttons_html .= $this->_getTableNavigationButton(
  782. '&gt;&gt;',
  783. _pgettext('Last page', 'End'),
  784. @((ceil(
  785. $this->__get('unlim_num_rows')
  786. / $_SESSION['tmp_user_values']['max_rows']
  787. )- 1) * $_SESSION['tmp_user_values']['max_rows']),
  788. $html_sql_query, $onsubmit, $input_for_real_end, $onclick
  789. );
  790. return $buttons_html;
  791. } // end of the '_getMoveForwardButtonsForTableNavigation()' function
  792. /**
  793. * Prepare feilds followed by Show button for table navigation
  794. * Start row, Number of rows, Headers every
  795. *
  796. * @param string $html_sql_query the sql encoded by html special
  797. * characters
  798. * @param integer $pos_next the offset for the "next" page
  799. * @param string $id_for_direction_dropdown the id for the direction dropdown
  800. *
  801. * @return string $additional_fields_html html content
  802. *
  803. * @access private
  804. *
  805. * @see _getTableNavigation()
  806. */
  807. private function _getAdditionalFieldsForTableNavigation(
  808. $html_sql_query, $pos_next, $id_for_direction_dropdown
  809. ) {
  810. $additional_fields_html = '';
  811. $additional_fields_html .= '<input type="hidden" name="sql_query" '
  812. . 'value="' . $html_sql_query . '" />'
  813. . '<input type="hidden" name="goto" value="' . $this->__get('goto')
  814. . '" />'
  815. . '<input type="submit" name="navig"'
  816. . ' class="ajax"'
  817. . ' value="' . __('Show') . ' :" />'
  818. . __('Start row') . ': ' . "\n"
  819. . '<input type="text" name="pos" size="3" value="'
  820. . (($pos_next >= $this->__get('unlim_num_rows')) ? 0 : $pos_next)
  821. . '" class="textfield" onfocus="this.select()" />'
  822. . __('Number of rows') . ': ' . "\n"
  823. . '<input type="text" name="session_max_rows" size="3" value="'
  824. . (($_SESSION['tmp_user_values']['max_rows'] != self::ALL_ROWS)
  825. ? $_SESSION['tmp_user_values']['max_rows']
  826. : $GLOBALS['cfg']['MaxRows'])
  827. . '" class="textfield" onfocus="this.select()" />';
  828. if ($GLOBALS['cfg']['ShowDisplayDirection']) {
  829. // Display mode (horizontal/vertical and repeat headers)
  830. $additional_fields_html .= __('Mode') . ': ' . "\n";
  831. $choices = array(
  832. 'horizontal' => __('horizontal'),
  833. 'horizontalflipped' => __('horizontal (rotated headers)'),
  834. 'vertical' => __('vertical')
  835. );
  836. $additional_fields_html .= PMA_Util::getDropdown(
  837. 'disp_direction', $choices,
  838. $_SESSION['tmp_user_values']['disp_direction'],
  839. $id_for_direction_dropdown
  840. );
  841. unset($choices);
  842. }
  843. $additional_fields_html .= sprintf(
  844. __('Headers every %s rows'),
  845. '<input type="text" size="3" name="repeat_cells" value="'
  846. . $_SESSION['tmp_user_values']['repeat_cells']
  847. . '" class="textfield" /> '
  848. );
  849. return $additional_fields_html;
  850. } // end of the '_getAdditionalFieldsForTableNavigation()' function
  851. /**
  852. * Get the headers of the results table
  853. *
  854. * @param array &$is_display which elements to display
  855. * @param array $analyzed_sql the analyzed query
  856. * @param string $sort_expression sort expression
  857. * @param string $sort_expression_nodirection sort expression without direction
  858. * @param string $sort_direction sort direction
  859. * @param boolean $is_limited_display with limited operations or not
  860. *
  861. * @return string html content
  862. *
  863. * @access private
  864. *
  865. * @see getTable()
  866. */
  867. private function _getTableHeaders(
  868. &$is_display, $analyzed_sql = '',
  869. $sort_expression = '', $sort_expression_nodirection = '',
  870. $sort_direction = '', $is_limited_display = false
  871. ) {
  872. $table_headers_html = '';
  873. // Following variable are needed for use in isset/empty or
  874. // use with array indexes/safe use in foreach
  875. $fields_meta = $this->__get('fields_meta');
  876. $highlight_columns = $this->__get('highlight_columns');
  877. $printview = $this->__get('printview');
  878. $vertical_display = $this->__get('vertical_display');
  879. // required to generate sort links that will remember whether the
  880. // "Show all" button has been clicked
  881. $sql_md5 = md5($this->__get('sql_query'));
  882. $session_max_rows = $is_limited_display
  883. ? 0
  884. : $_SESSION['tmp_user_values']['query'][$sql_md5]['max_rows'];
  885. $direction = isset($_SESSION['tmp_user_values']['disp_direction'])
  886. ? $_SESSION['tmp_user_values']['disp_direction']
  887. : '';
  888. if ($analyzed_sql == '') {
  889. $analyzed_sql = array();
  890. }
  891. $directionCondition = ($direction == self::DISP_DIR_HORIZONTAL)
  892. || ($direction == self::DISP_DIR_HORIZONTAL_FLIPPED);
  893. // can the result be sorted?
  894. if ($is_display['sort_lnk'] == '1') {
  895. list($unsorted_sql_query, $drop_down_html)
  896. = $this->_getUnsortedSqlAndSortByKeyDropDown(
  897. $analyzed_sql, $sort_expression
  898. );
  899. $table_headers_html .= $drop_down_html;
  900. }
  901. // Output data needed for grid editing
  902. $table_headers_html .= '<input id="save_cells_at_once" type="hidden" value="'
  903. . $GLOBALS['cfg']['SaveCellsAtOnce'] . '" />'
  904. . '<div class="common_hidden_inputs">'
  905. . PMA_generate_common_hidden_inputs(
  906. $this->__get('db'), $this->__get('table')
  907. )
  908. . '</div>';
  909. // Output data needed for column reordering and show/hide column
  910. if ($this->_isSelect($analyzed_sql)) {
  911. $table_headers_html .= $this->_getDataForResettingColumnOrder();
  912. }
  913. $vertical_display['emptypre'] = 0;
  914. $vertical_display['emptyafter'] = 0;
  915. $vertical_display['textbtn'] = '';
  916. $full_or_partial_text_link = null;
  917. $this->__set('vertical_display', $vertical_display);
  918. // Display options (if we are not in print view)
  919. if (! (isset($printview) && ($printview == '1')) && ! $is_limited_display) {
  920. $table_headers_html .= $this->_getOptionsBlock();
  921. // prepare full/partial text button or link
  922. $full_or_partial_text_link = $this->_getFullOrPartialTextButtonOrLink();
  923. }
  924. // Start of form for multi-rows edit/delete/export
  925. $table_headers_html .= $this->_getFormForMultiRowOperations(
  926. $is_display['del_lnk']
  927. );
  928. // 1. Set $colspan or $rowspan and generate html with full/partial
  929. // text button or link
  930. list($colspan, $rowspan, $button_html)
  931. = $this->_getFieldVisibilityParams(
  932. $directionCondition, $is_display, $full_or_partial_text_link
  933. );
  934. $table_headers_html .= $button_html;
  935. // 2. Displays the fields' name
  936. // 2.0 If sorting links should be used, checks if the query is a "JOIN"
  937. // statement (see 2.1.3)
  938. // 2.0.1 Prepare Display column comments if enabled
  939. // ($GLOBALS['cfg']['ShowBrowseComments']).
  940. // Do not show comments, if using horizontalflipped mode,
  941. // because of space usage
  942. $comments_map = $this->_getTableCommentsArray($direction, $analyzed_sql);
  943. if ($GLOBALS['cfgRelation']['commwork']
  944. && $GLOBALS['cfgRelation']['mimework']
  945. && $GLOBALS['cfg']['BrowseMIME']
  946. && ! $_SESSION['tmp_user_values']['hide_transformation']
  947. ) {
  948. include_once './libraries/transformations.lib.php';
  949. $this->__set(
  950. 'mime_map',
  951. PMA_getMIME($this->__get('db'), $this->__get('table'))
  952. );
  953. }
  954. // See if we have to highlight any header fields of a WHERE query.
  955. // Uses SQL-Parser results.
  956. $this->_setHighlightedColumnGlobalField($analyzed_sql);
  957. list($col_order, $col_visib) = $this->_getColumnParams($analyzed_sql);
  958. for ($j = 0; $j < $this->__get('fields_cnt'); $j++) {
  959. // assign $i with appropriate column order
  960. $i = $col_order ? $col_order[$j] : $j;
  961. // See if this column should get highlight because it's used in the
  962. // where-query.
  963. $condition_field = (isset($highlight_columns[$fields_meta[$i]->name])
  964. || isset($highlight_columns[PMA_Util::backquote($fields_meta[$i]->name)]))
  965. ? true
  966. : false;
  967. // 2.0 Prepare comment-HTML-wrappers for each row, if defined/enabled.
  968. $comments = $this->_getCommentForRow($comments_map, $fields_meta[$i]);
  969. $vertical_display = $this->__get('vertical_display');
  970. if (($is_display['sort_lnk'] == '1') && ! $is_limited_display) {
  971. list($order_link, $sorted_headrer_html)
  972. = $this->_getOrderLinkAndSortedHeaderHtml(
  973. $fields_meta[$i], $sort_expression,
  974. $sort_expression_nodirection, $i, $unsorted_sql_query,
  975. $session_max_rows, $direction, $comments,
  976. $sort_direction, $directionCondition, $col_visib,
  977. $col_visib[$j], $condition_field
  978. );
  979. $table_headers_html .= $sorted_headrer_html;
  980. $vertical_display['desc'][] = ' <th '
  981. . 'class="draggable'
  982. . ($condition_field ? ' condition' : '')
  983. . '" data-column="' . htmlspecialchars($fields_meta[$i]->name)
  984. . '">' . "\n" . $order_link . $comments . ' </th>' . "\n";
  985. } else {
  986. // 2.2 Results can't be sorted
  987. if ($directionCondition) {
  988. $table_headers_html
  989. .= $this->_getDraggableClassForNonSortableColumns(
  990. $col_visib, $col_visib[$j], $condition_field,
  991. $direction, $fields_meta[$i], $comments
  992. );
  993. }
  994. $vertical_display['desc'][] = ' <th '
  995. . 'class="draggable'
  996. . ($condition_field ? ' condition"' : '')
  997. . '" data-column="' . htmlspecialchars($fields_meta[$i]->name)
  998. . '">' . "\n" . ' '
  999. . htmlspecialchars($fields_meta[$i]->name)
  1000. . "\n" . $comments . ' </th>';
  1001. } // end else (2.2)
  1002. $this->__set('vertical_display', $vertical_display);
  1003. } // end for
  1004. // Display column at rightside - checkboxes or empty column
  1005. $table_headers_html .= $this->_getColumnAtRightSide(
  1006. $is_display, $directionCondition, $full_or_partial_text_link,
  1007. $colspan, $rowspan
  1008. );
  1009. if ($directionCondition) {
  1010. $table_headers_html .= '</tr>'
  1011. . '</thead>';
  1012. }
  1013. return $table_headers_html;
  1014. } // end of the '_getTableHeaders()' function
  1015. /**
  1016. * Prepare unsorted sql query and sort by key drop down
  1017. *
  1018. * @param array $analyzed_sql the analyzed query
  1019. * @param string $sort_expression sort expression
  1020. *
  1021. * @return array two element array - $unsorted_sql_query, $drop_down_html
  1022. *
  1023. * @access private
  1024. *
  1025. * @see _getTableHeaders()
  1026. */
  1027. private function _getUnsortedSqlAndSortByKeyDropDown(
  1028. $analyzed_sql, $sort_expression
  1029. ) {
  1030. $drop_down_html = '';
  1031. // Just as fallback
  1032. $unsorted_sql_query = $this->__get('sql_query');
  1033. if (isset($analyzed_sql[0]['unsorted_query'])) {
  1034. $unsorted_sql_query = $analyzed_sql[0]['unsorted_query'];
  1035. }
  1036. // Handles the case of multiple clicks on a column's header
  1037. // which would add many spaces before "ORDER BY" in the
  1038. // generated query.
  1039. $unsorted_sql_query = trim($unsorted_sql_query);
  1040. // sorting by indexes, only if it makes sense (only one table ref)
  1041. if (isset($analyzed_sql)
  1042. && isset($analyzed_sql[0])
  1043. && isset($analyzed_sql[0]['querytype'])
  1044. && ($analyzed_sql[0]['querytype'] == self::QUERY_TYPE_SELECT)
  1045. && isset($analyzed_sql[0]['table_ref'])
  1046. && (count($analyzed_sql[0]['table_ref']) == 1)
  1047. ) {
  1048. // grab indexes data:
  1049. $indexes = PMA_Index::getFromTable(
  1050. $this->__get('table'),
  1051. $this->__get('db')
  1052. );
  1053. // do we have any index?
  1054. if ($indexes) {
  1055. $drop_down_html = $this->_getSortByKeyDropDown(
  1056. $indexes, $sort_expression,
  1057. $unsorted_sql_query
  1058. );
  1059. }
  1060. }
  1061. return array($unsorted_sql_query, $drop_down_html);
  1062. } // end of the '_getUnsortedSqlAndSortByKeyDropDown()' function
  1063. /**
  1064. * Prepare sort by key dropdown - html code segment
  1065. *
  1066. * @param array $indexes the indexes of the table for sort criteria
  1067. * @param string $sort_expression the sort expression
  1068. * @param string $unsorted_sql_query the unsorted sql query
  1069. *
  1070. * @return string $drop_down_html html content
  1071. *
  1072. * @access private
  1073. *
  1074. * @see _getTableHeaders()
  1075. */
  1076. private function _getSortByKeyDropDown(
  1077. $indexes, $sort_expression, $unsorted_sql_query
  1078. ) {
  1079. $drop_down_html = '';
  1080. $drop_down_html .= '<form action="sql.php" method="post">' . "\n"
  1081. . PMA_generate_common_hidden_inputs(
  1082. $this->__get('db'), $this->__get('table')
  1083. )
  1084. . __('Sort by key')
  1085. . ': <select name="sql_query" class="autosubmit">' . "\n";
  1086. $used_index = false;
  1087. $local_order = (isset($sort_expression) ? $sort_expression : '');
  1088. foreach ($indexes as $index) {
  1089. $asc_sort = '`'
  1090. . implode('` ASC, `', array_keys($index->getColumns()))
  1091. . '` ASC';
  1092. $desc_sort = '`'
  1093. . implode('` DESC, `', array_keys($index->getColumns()))
  1094. . '` DESC';
  1095. $used_index = $used_index
  1096. || ($local_order == $asc_sort)
  1097. || ($local_order == $desc_sort);
  1098. if (preg_match(
  1099. '@(.*)([[:space:]](LIMIT (.*)|PROCEDURE (.*)|'
  1100. . 'FOR UPDATE|LOCK IN SHARE MODE))@is',
  1101. $unsorted_sql_query, $my_reg
  1102. )) {
  1103. $unsorted_sql_query_first_part = $my_reg[1];
  1104. $unsorted_sql_query_second_part = $my_reg[2];
  1105. } else {
  1106. $unsorted_sql_query_first_part = $unsorted_sql_query;
  1107. $unsorted_sql_query_second_part = '';
  1108. }
  1109. $drop_down_html .= '<option value="'
  1110. . htmlspecialchars(
  1111. $unsorted_sql_query_first_part . "\n"
  1112. . ' ORDER BY ' . $asc_sort
  1113. . $unsorted_sql_query_second_part
  1114. )
  1115. . '"' . ($local_order == $asc_sort
  1116. ? ' selected="selected"'
  1117. : '')
  1118. . '>' . htmlspecialchars($index->getName()) . ' ('
  1119. . __('Ascending') . ')</option>';
  1120. $drop_down_html .= '<option value="'
  1121. . htmlspecialchars(
  1122. $unsorted_sql_query_first_part . "\n"
  1123. . ' ORDER BY ' . $desc_sort
  1124. . $unsorted_sql_query_second_part
  1125. )
  1126. . '"' . ($local_order == $desc_sort
  1127. ? ' selected="selected"'
  1128. : '')
  1129. . '>' . htmlspecialchars($index->getName()) . ' ('
  1130. . __('Descending') . ')</option>';
  1131. }
  1132. $drop_down_html .= '<option value="' . htmlspecialchars($unsorted_sql_query)
  1133. . '"' . ($used_index ? '' : ' selected="selected"') . '>' . __('None')
  1134. . '</option>'
  1135. . '</select>' . "\n"
  1136. . '</form>' . "\n";
  1137. return $drop_down_html;
  1138. } // end of the '_getSortByKeyDropDown()' function
  1139. /**
  1140. * Set column span, row span and prepare html with full/partial
  1141. * text button or link
  1142. *
  1143. * @param boolean $directionCondition display direction horizontal or
  1144. * horizontalflipped
  1145. * @param array &$is_display which elements to display
  1146. * @param string $full_or_partial_text_link full/partial link or text button
  1147. *
  1148. * @return array 3 element array - $colspan, $rowspan, $button_html
  1149. *
  1150. * @access private
  1151. *
  1152. * @see _getTableHeaders()
  1153. */
  1154. private function _getFieldVisibilityParams(
  1155. $directionCondition, &$is_display, $full_or_partial_text_link
  1156. ) {
  1157. $button_html = '';
  1158. $colspan = $rowspan = null;
  1159. $vertical_display = $this->__get('vertical_display');
  1160. // 1. Displays the full/partial text button (part 1)...
  1161. if ($directionCondition) {
  1162. $button_html .= '<thead><tr>' . "\n";
  1163. $colspan = (($is_display['edit_lnk'] != self::NO_EDIT_OR_DELETE)
  1164. && ($is_display['del_lnk'] != self::NO_EDIT_OR_DELETE))
  1165. ? ' colspan="4"'
  1166. : '';
  1167. } else {
  1168. $rowspan = (($is_display['edit_lnk'] != self::NO_EDIT_OR_DELETE)
  1169. && ($is_display['del_lnk'] != self::NO_EDIT_OR_DELETE))
  1170. ? ' rowspan="4"'
  1171. : '';
  1172. }
  1173. // ... before the result table
  1174. if ((($is_display['edit_lnk'] == self::NO_EDIT_OR_DELETE)
  1175. && ($is_display['del_lnk'] == self::NO_EDIT_OR_DELETE))
  1176. && ($is_display['text_btn'] == '1')
  1177. ) {
  1178. $vertical_display['emptypre']
  1179. = (($is_display['edit_lnk'] != self::NO_EDIT_OR_DELETE)
  1180. && ($is_display['del_lnk'] != self::NO_EDIT_OR_DELETE)) ? 4 : 0;
  1181. if ($directionCondition) {
  1182. $button_html .= '<th colspan="' . $this->__get('fields_cnt') . '">'
  1183. . '</th>'
  1184. . '</tr>'
  1185. . '<tr>';
  1186. // end horizontal/horizontalflipped mode
  1187. } else {
  1188. $span = $this->__get('num_rows') + 1 + floor(
  1189. $this->__get('num_rows')
  1190. / $_SESSION['tmp_user_values']['repeat_cells']
  1191. );
  1192. $button_html .= '<tr><th colspan="' . $span . '"></th></tr>';
  1193. } // end vertical mode
  1194. } elseif ((($GLOBALS['cfg']['RowActionLinks'] == self::POSITION_LEFT)
  1195. || ($GLOBALS['cfg']['RowActionLinks'] == self::POSITION_BOTH))
  1196. && ($is_display['text_btn'] == '1')
  1197. ) {
  1198. // ... at the left column of the result table header if possible
  1199. // and required
  1200. $vertical_display['emptypre']
  1201. = (($is_display['edit_lnk'] != self::NO_EDIT_OR_DELETE)
  1202. && ($is_display['del_lnk'] != self::NO_EDIT_OR_DELETE)) ? 4 : 0;
  1203. if ($directionCondition) {
  1204. $button_html .= '<th ' . $colspan . '>'
  1205. . $full_or_partial_text_link . '</th>';
  1206. // end horizontal/horizontalflipped mode
  1207. } else {
  1208. $vertical_display['textbtn']
  1209. = ' <th ' . $rowspan . ' class="vmiddle">' . "\n"
  1210. . ' ' . "\n"
  1211. . ' </th>' . "\n";
  1212. } // end vertical mode
  1213. } elseif ((($GLOBALS['cfg']['RowActionLinks'] == self::POSITION_LEFT)
  1214. || ($GLOBALS['cfg']['RowActionLinks'] == self::POSITION_BOTH))
  1215. && (($is_display['edit_lnk'] != self::NO_EDIT_OR_DELETE)
  1216. || ($is_display['del_lnk'] != self::NO_EDIT_OR_DELETE))
  1217. ) {
  1218. // ... elseif no button, displays empty(ies) col(s) if required
  1219. $vertical_display['emptypre']
  1220. = (($is_display['edit_lnk'] != self::NO_EDIT_OR_DELETE)
  1221. && ($is_display['del_lnk'] != self::NO_EDIT_OR_DELETE)) ? 4 : 0;
  1222. if ($directionCondition) {
  1223. $button_html .= '<td ' . $colspan . '></td>';
  1224. // end horizontal/horizontalfipped mode
  1225. } else {
  1226. $vertical_display['textbtn'] = ' <td' . $rowspan .
  1227. '></td>' . "\n";
  1228. } // end vertical mode
  1229. } elseif (($GLOBALS['cfg']['RowActionLinks'] == self::POSITION_NONE)
  1230. && ($directionCondition)
  1231. ) {
  1232. // ... elseif display an empty column if the actions links are
  1233. // disabled to match the rest of the table
  1234. $button_html .= '<th></th>';
  1235. }
  1236. $this->__set('vertical_display', $vertical_display);
  1237. return array($colspan, $rowspan, $button_html);
  1238. } // end of the '_getFieldVisibilityParams()' function
  1239. /**
  1240. * Get table comments as array
  1241. *
  1242. * @param boolean $direction display direction, horizontal
  1243. * or horizontalflipped
  1244. * @param array $analyzed_sql the analyzed query
  1245. *
  1246. * @return array $comments_map table comments when condition true
  1247. * null when condition falls
  1248. *
  1249. * @access private
  1250. *
  1251. * @see _getTableHeaders()
  1252. */
  1253. private function _getTableCommentsArray($direction, $analyzed_sql)
  1254. {
  1255. $comments_map = null;
  1256. if ($GLOBALS['cfg']['ShowBrowseComments']
  1257. && ($direction != self::DISP_DIR_HORIZONTAL_FLIPPED)
  1258. ) {
  1259. $comments_map = array();
  1260. if (isset($analyzed_sql[0])
  1261. && is_array($analyzed_sql[0])
  1262. && isset($analyzed_sql[0]['table_ref'])
  1263. ) {
  1264. foreach ($analyzed_sql[0]['table_ref'] as $tbl) {
  1265. $tb = $tbl['table_true_name'];
  1266. $comments_map[$tb] = PMA_getComments($this->__get('db'), $tb);
  1267. unset($tb);
  1268. }
  1269. }
  1270. }
  1271. return $comments_map;
  1272. } // end of the '_getTableCommentsArray()' function
  1273. /**
  1274. * Set global array for store highlighted header fields
  1275. *
  1276. * @param array $analyzed_sql the analyzed query
  1277. *
  1278. * @return void
  1279. *
  1280. * @access private
  1281. *
  1282. * @see _getTableHeaders()
  1283. */
  1284. private function _setHighlightedColumnGlobalField($analyzed_sql)
  1285. {
  1286. $highlight_columns = array();
  1287. if (isset($analyzed_sql) && isset($analyzed_sql[0])
  1288. && isset($analyzed_sql[0]['where_clause_identifiers'])
  1289. ) {
  1290. $wi = 0;
  1291. if (isset($analyzed_sql[0]['where_clause_identifiers'])
  1292. && is_array($analyzed_sql[0]['where_clause_identifiers'])
  1293. ) {
  1294. foreach ($analyzed_sql[0]['where_clause_identifiers']
  1295. as $wci_nr => $wci
  1296. ) {
  1297. $highlight_columns[$wci] = 'true';
  1298. }
  1299. }
  1300. }
  1301. $this->__set('highlight_columns', $highlight_columns);
  1302. } // end of the '_setHighlightedColumnGlobalField()' function
  1303. /**
  1304. * Prepare data for column restoring and show/hide
  1305. *
  1306. * @return string $data_html html content
  1307. *
  1308. * @access private
  1309. *
  1310. * @see _getTableHeaders()
  1311. */
  1312. private function _getDataForResettingColumnOrder()
  1313. {
  1314. $data_html = '';
  1315. // generate the column order, if it is set
  1316. $pmatable = new PMA_Table($this->__get('table'), $this->__get('db'));
  1317. $col_order = $pmatable->getUiProp(PMA_Table::PROP_COLUMN_ORDER);
  1318. if ($col_order) {
  1319. $data_html .= '<input id="col_order" type="hidden" value="'
  1320. . implode(',', $col_order) . '" />';
  1321. }
  1322. $col_visib = $pmatable->getUiProp(PMA_Table::PROP_COLUMN_VISIB);
  1323. if ($col_visib) {
  1324. $data_html .= '<input id="col_visib" type="hidden" value="'
  1325. . implode(',', $col_visib) . '" />';
  1326. }
  1327. // generate table create time
  1328. if (! PMA_Table::isView($this->__get('db'), $this->__get('table'))) {
  1329. $data_html .= '<input id="table_create_time" type="hidden" value="'
  1330. . PMA_Table::sGetStatusInfo(
  1331. $this->__get('db'), $this->__get('table'), 'Create_time'
  1332. ) . '" />';
  1333. }
  1334. return $data_html;
  1335. } // end of the '_getDataForResettingColumnOrder()' function
  1336. /**
  1337. * Prepare option fields block
  1338. *
  1339. * @return string $options_html html content
  1340. *
  1341. * @access private
  1342. *
  1343. * @see _getTableHeaders()
  1344. */
  1345. private function _getOptionsBlock()
  1346. {
  1347. $options_html = '';
  1348. $options_html .= '<form method="post" action="sql.php" '
  1349. . 'name="displayOptionsForm" '
  1350. . 'id="displayOptionsForm"';
  1351. $options_html .= ' class="ajax" ';
  1352. $options_html .= '>';
  1353. $url_params = array(
  1354. 'db' => $this->__get('db'),
  1355. 'table' => $this->__get('table'),
  1356. 'sql_query' => $this->__get('sql_query'),
  1357. 'goto' => $this->__get('goto'),
  1358. 'display_options_form' => 1
  1359. );
  1360. $options_html .= PMA_generate_common_hidden_inputs($url_params)
  1361. . '<br />'
  1362. . PMA_Util::getDivForSliderEffect(
  1363. 'displayoptions', __('Options')
  1364. )
  1365. . '<fieldset>';
  1366. $options_html .= '<div class="formelement">';
  1367. $choices = array(
  1368. 'P' => __('Partial texts'),
  1369. 'F' => __('Full texts')
  1370. );
  1371. $options_html .= PMA_Util::getRadioFields(
  1372. 'display_text', $choices,
  1373. $_SESSION['tmp_user_values']['display_text']
  1374. )
  1375. . '</div>';
  1376. if ($GLOBALS['cfgRelation']['relwork']
  1377. && $GLOBALS['cfgRelation']['displaywork']
  1378. ) {
  1379. $options_html .= '<div class="formelement">';
  1380. $choices = array(
  1381. 'K' => __('Relational key'),
  1382. 'D' => __('Relational display column')
  1383. );
  1384. $options_html .= PMA_Util::getRadioFields(
  1385. 'relational_display', $choices,
  1386. $_SESSION['tmp_user_values']['relational_display']
  1387. )
  1388. . '</div>';
  1389. }
  1390. $options_html .= '<div class="formelement">'
  1391. . PMA_Util::getCheckbox(
  1392. 'display_binary', __('Show binary contents'),
  1393. ! empty($_SESSION['tmp_user_values']['display_binary']), false
  1394. )
  1395. . '<br />'
  1396. . PMA_Util::getCheckbox(
  1397. 'display_blob', __('Show BLOB contents'),
  1398. ! empty($_SESSION['tmp_user_values']['display_blob']), false
  1399. )
  1400. . '<br />'
  1401. . PMA_Util::getCheckbox(
  1402. 'display_binary_as_hex', __('Show binary contents as HEX'),
  1403. ! empty($_SESSION['tmp_user_values']['display_binary_as_hex']), false
  1404. )
  1405. . '</div>';
  1406. // I would have preferred to name this "display_transformation".
  1407. // This is the only way I found to be able to keep this setting sticky
  1408. // per SQL query, and at the same time have a default that displays
  1409. // the transformations.
  1410. $options_html .= '<div class="formelement">'
  1411. . PMA_Util::getCheckbox(
  1412. 'hide_transformation', __('Hide browser transformation'),
  1413. ! empty($_SESSION['tmp_user_values']['hide_transformation']), false
  1414. )
  1415. . '</div>';
  1416. if (! PMA_DRIZZLE) {
  1417. $options_html .= '<div class="formelement">';
  1418. $choices = array(
  1419. 'GEOM' => __('Geometry'),
  1420. 'WKT' => __('Well Known Text'),
  1421. 'WKB' => __('Well Known Binary')
  1422. );
  1423. $options_html .= PMA_Util::getRadioFields(
  1424. 'geometry_display', $choices,
  1425. $_SESSION['tmp_user_values']['geometry_display']
  1426. )
  1427. . '</div>';
  1428. }
  1429. $options_html .= '<div class="clearfloat"></div>'
  1430. . '</fieldset>';
  1431. $options_html .= '<fieldset class="tblFooters">'
  1432. . '<input type="submit" value="' . __('Go') . '" />'
  1433. . '</fieldset>'
  1434. . '</div>'
  1435. . '</form>';
  1436. return $options_html;
  1437. } // end of the '_getOptionsBlock()' function
  1438. /**
  1439. * Get full/partial text button or link
  1440. *
  1441. * @return string html content
  1442. *
  1443. * @access private
  1444. *
  1445. * @see _getTableHeaders()
  1446. */
  1447. private function _getFullOrPartialTextButtonOrLink()
  1448. {
  1449. $url_params_full_text = array(
  1450. 'db' => $this->__get('db'),
  1451. 'table' => $this->__get('table'),
  1452. 'sql_query' => $this->__get('sql_query'),
  1453. 'goto' => $this->__get('goto'),
  1454. 'full_text_button' => 1
  1455. );
  1456. if ($_SESSION['tmp_user_values']['display_text'] == self::DISPLAY_FULL_TEXT) {
  1457. // currently in fulltext mode so show the opposite link
  1458. $tmp_image_file = $this->__get('pma_theme_image') . 's_partialtext.png';
  1459. $tmp_txt = __('Partial texts');
  1460. $url_params_full_text['display_text'] = self::DISPLAY_PARTIAL_TEXT;
  1461. } else {
  1462. $tmp_image_file = $this->__get('pma_theme_image') . 's_fulltext.png';
  1463. $tmp_txt = __('Full texts');
  1464. $url_params_full_text['display_text'] = self::DISPLAY_FULL_TEXT;
  1465. }
  1466. $tmp_image = '<img class="fulltext" src="' . $tmp_image_file . '" alt="'
  1467. . $tmp_txt . '" title="' . $tmp_txt . '" />';
  1468. $tmp_url = 'sql.php' . PMA_generate_common_url($url_params_full_text);
  1469. return PMA_Util::linkOrButton(
  1470. $tmp_url, $tmp_image, array(), false
  1471. );
  1472. } // end of the '_getFullOrPartialTextButtonOrLink()' function
  1473. /**
  1474. * Prepare html form for multi row operations
  1475. *
  1476. * @param string $del_lnk the delete link of current row
  1477. *
  1478. * @return string $form_html html content
  1479. *
  1480. * @access private
  1481. *
  1482. * @see _getTableHeaders()
  1483. */
  1484. private function _getFormForMultiRowOperations($del_lnk)
  1485. {
  1486. $form_html = '';
  1487. if (($del_lnk == self::DELETE_ROW) || ($del_lnk == self::KILL_PROCESS)) {
  1488. $form_html .= '<form method="post" action="tbl_row_action.php" '
  1489. . 'name="resultsForm" id="resultsForm"';
  1490. $form_html .= ' class="ajax" ';
  1491. $form_html .= '>'
  1492. . PMA_generate_common_hidden_inputs(
  1493. $this->__get('db'), $this->__get('table'), 1
  1494. )
  1495. . '<input type="hidden" name="goto" value="sql.php" />';
  1496. }
  1497. $form_html .= '<table id="table_results" class="data';
  1498. $form_html .= ' ajax';
  1499. $form_html .= '">';
  1500. return $form_html;
  1501. } // end of the '_getFormForMultiRowOperations()' function
  1502. /**
  1503. * Get comment for row
  1504. *
  1505. * @param array $comments_map comments array
  1506. * @param array $fields_meta set of field properties
  1507. *
  1508. * @return string $comment html content
  1509. *
  1510. * @access private
  1511. *
  1512. * @see _getTableHeaders()
  1513. */
  1514. private function _getCommentForRow($comments_map, $fields_meta)
  1515. {
  1516. $comments = '';
  1517. if (isset($comments_map)
  1518. && isset($comments_map[$fields_meta->table])
  1519. && isset($comments_map[$fields_meta->table][$fields_meta->name])
  1520. ) {
  1521. $comments = '<span class="tblcomment">'
  1522. . htmlspecialchars(
  1523. $comments_map[$fields_meta->table][$fields_meta->name]
  1524. )
  1525. . '</span>';
  1526. }
  1527. return $comments;
  1528. } // end of the '_getCommentForRow()' function
  1529. /**
  1530. * Prepare parameters and html for sorted table header fields
  1531. *
  1532. * @param array $fields_meta set of field properties
  1533. * @param string $sort_expression sort expression
  1534. * @param string $sort_expression_nodirection sort expression without direction
  1535. * @param integer $column_index the index of the column
  1536. * @param string $unsorted_sql_query the unsorted sql query
  1537. * @param integer $session_max_rows maximum rows resulted by sql
  1538. * @param string $direction the display direction
  1539. * @param string $comments comment for row
  1540. * @param string $sort_direction sort direction
  1541. * @param boolean $directionCondition display direction horizontal
  1542. * or horizontalflipped
  1543. * @param boolean $col_visib column is visible(false)
  1544. * array column isn't visible(string array)
  1545. * @param string $col_visib_j element of $col_visib array
  1546. * @param boolean $condition_field whether the column is a part of
  1547. * the where clause
  1548. *
  1549. * @return array 2 element array - $order_link, $sorted_header_html
  1550. *
  1551. * @access private
  1552. *
  1553. * @see _getTableHeaders()
  1554. */
  1555. private function _getOrderLinkAndSortedHeaderHtml(
  1556. $fields_meta, $sort_expression, $sort_expression_nodirection,
  1557. $column_index, $unsorted_sql_query, $session_max_rows, $direction,
  1558. $comments, $sort_direction, $directionCondition, $col_visib,
  1559. $col_visib_j, $condition_field
  1560. ) {
  1561. $sorted_header_html = '';
  1562. // Checks if the table name is required; it's the case
  1563. // for a query with a "JOIN" statement and if the column
  1564. // isn't aliased, or in queries like
  1565. // SELECT `1`.`master_field` , `2`.`master_field`
  1566. // FROM `PMA_relation` AS `1` , `PMA_relation` AS `2`
  1567. $sort_tbl = (isset($fields_meta->table)
  1568. && strlen($fields_meta->table))
  1569. ? PMA_Util::backquote(
  1570. $fields_meta->table
  1571. ) . '.'
  1572. : '';
  1573. // Checks if the current column is used to sort the
  1574. // results
  1575. // the orgname member does not exist for all MySQL versions
  1576. // but if found, it's the one on which to sort
  1577. $name_to_use_in_sort = $fields_meta->name;
  1578. $is_orgname = false;
  1579. if (isset($fields_meta->orgname)
  1580. && strlen($fields_meta->orgname)
  1581. ) {
  1582. $name_to_use_in_sort = $fields_meta->orgname;
  1583. $is_orgname = true;
  1584. }
  1585. // $name_to_use_in_sort might contain a space due to
  1586. // formatting of function expressions like "COUNT(name )"
  1587. // so we remove the space in this situation
  1588. $name_to_use_in_sort = str_replace(' )', ')', $name_to_use_in_sort);
  1589. $is_in_sort = $this->_isInSorted(
  1590. $sort_expression, $sort_expression_nodirection,
  1591. $sort_tbl, $name_to_use_in_sort
  1592. );
  1593. // Check the field name for a bracket.
  1594. // If it contains one, it's probably a function column
  1595. // like 'COUNT(`field`)'
  1596. // It still might be a column name of a view. See bug #3383711
  1597. // Check is_orgname.
  1598. if ((strpos($name_to_use_in_sort, '(') !== false) && ! $is_orgname) {
  1599. $sort_order = "\n" . 'ORDER BY ' . $name_to_use_in_sort . ' ';
  1600. } else {
  1601. $sort_order = "\n" . 'ORDER BY ' . $sort_tbl
  1602. . PMA_Util::backquote(
  1603. $name_to_use_in_sort
  1604. ) . ' ';
  1605. }
  1606. unset($name_to_use_in_sort);
  1607. unset($is_orgname);
  1608. // Do define the sorting URL
  1609. list($sort_order, $order_img) = $this->_getSortingUrlParams(
  1610. $is_in_sort, $sort_direction, $fields_meta,
  1611. $sort_order, $column_index
  1612. );
  1613. if (preg_match(
  1614. '@(.*)([[:space:]](LIMIT (.*)|PROCEDURE (.*)|FOR UPDATE|'
  1615. . 'LOCK IN SHARE MODE))@is',
  1616. $unsorted_sql_query, $regs3
  1617. )) {
  1618. $sorted_sql_query = $regs3[1] . $sort_order . $regs3[2];
  1619. } else {
  1620. $sorted_sql_query = $unsorted_sql_query . $sort_order;
  1621. }
  1622. $_url_params = array(
  1623. 'db' => $this->__get('db'),
  1624. 'table' => $this->__get('table'),
  1625. 'sql_query' => $sorted_sql_query,
  1626. 'session_max_rows' => $session_max_rows
  1627. );
  1628. $order_url = 'sql.php' . PMA_generate_common_url($_url_params);
  1629. // Displays the sorting URL
  1630. // enable sort order swapping for image
  1631. $order_link = $this->_getSortOrderLink(
  1632. $order_img, $column_index, $direction,
  1633. $fields_meta, $order_url
  1634. );
  1635. if ($directionCondition) {
  1636. $sorted_header_html .= $this->_getDraggableClassForSortableColumns(
  1637. $col_visib, $col_visib_j, $condition_field, $direction,
  1638. $fields_meta, $order_link, $comments
  1639. );
  1640. }
  1641. return array($order_link, $sorted_header_html);
  1642. } // end of the '_getOrderLinkAndSortedHeaderHtml()' function
  1643. /**
  1644. * Check whether the column is sorted
  1645. *
  1646. * @param string $sort_expression sort expression
  1647. * @param string $sort_expression_nodirection sort expression without direction
  1648. * @param string $sort_tbl the table name
  1649. * @param string $name_to_use_in_sort the sorting column name
  1650. *
  1651. * @return boolean $is_in_sort the column sorted or not
  1652. *
  1653. * @access private
  1654. *
  1655. * @see _getTableHeaders()
  1656. */
  1657. private function _isInSorted(
  1658. $sort_expression, $sort_expression_nodirection, $sort_tbl,
  1659. $name_to_use_in_sort
  1660. ) {
  1661. if (empty($sort_expression)) {
  1662. $is_in_sort = false;
  1663. } else {
  1664. // Field name may be preceded by a space, or any number
  1665. // of characters followed by a dot (tablename.fieldname)
  1666. // so do a direct comparison for the sort expression;
  1667. // this avoids problems with queries like
  1668. // "SELECT id, count(id)..." and clicking to sort
  1669. // on id or on count(id).
  1670. // Another query to test this:
  1671. // SELECT p.*, FROM_UNIXTIME(p.temps) FROM mytable AS p
  1672. // (and try clicking on each column's header twice)
  1673. if (! empty($sort_tbl)
  1674. && strpos($sort_expression_nodirection, $sort_tbl) === false
  1675. && strpos($sort_expression_nodirection, '(') === false
  1676. ) {
  1677. $new_sort_expression_nodirection = $sort_tbl
  1678. . $sort_expression_nodirection;
  1679. } else {
  1680. $new_sort_expression_nodirection = $sort_expression_nodirection;
  1681. }
  1682. $is_in_sort = false;
  1683. $sort_name = str_replace('`', '', $sort_tbl) . $name_to_use_in_sort;
  1684. if ($sort_name == str_replace('`', '', $new_sort_expression_nodirection)
  1685. || $sort_name == str_replace('`', '', $sort_expression_nodirection)
  1686. ) {
  1687. $is_in_sort = true;
  1688. }
  1689. }
  1690. return $is_in_sort;
  1691. } // end of the '_isInSorted()' function
  1692. /**
  1693. * Get sort url paramaeters - sort order and order image
  1694. *
  1695. * @param boolean $is_in_sort the column sorted or not
  1696. * @param string $sort_direction the sort direction
  1697. * @param array $fields_meta set of field properties
  1698. * @param string $sort_order the sorting order
  1699. * @param integer $column_index the index of the column
  1700. *
  1701. * @return array 2 element array - $sort_order, $order_img
  1702. *
  1703. * @access private
  1704. *
  1705. * @see _getTableHeaders()
  1706. */
  1707. private function _getSortingUrlParams(
  1708. $is_in_sort, $sort_direction, $fields_meta, $sort_order, $column_index
  1709. ) {
  1710. if (! $is_in_sort) {
  1711. // patch #455484 ("Smart" order)
  1712. $GLOBALS['cfg']['Order'] = strtoupper($GLOBALS['cfg']['Order']);
  1713. if ($GLOBALS['cfg']['Order'] === self::SMART_SORT_ORDER) {
  1714. $sort_order .= (preg_match(
  1715. '@time|date@i',
  1716. $fields_meta->type
  1717. )) ? self::DESCENDING_SORT_DIR : self::ASCENDING_SORT_DIR;
  1718. } else {
  1719. $sort_order .= $GLOBALS['cfg']['Order'];
  1720. }
  1721. $order_img = '';
  1722. } elseif ($sort_direction == self::DESCENDING_SORT_DIR) {
  1723. $sort_order .= ' ASC';
  1724. $order_img = ' ' . PMA_Util::getImage(
  1725. 's_desc.png', __('Descending'),
  1726. array('class' => "soimg$column_index", 'title' => '')
  1727. );
  1728. $order_img .= ' ' . PMA_Util::getImage(
  1729. 's_asc.png', __('Ascending'),
  1730. array('class' => "soimg$column_index hide", 'title' => '')
  1731. );
  1732. } else {
  1733. $sort_order .= ' DESC';
  1734. $order_img = ' ' . PMA_Util::getImage(
  1735. 's_asc.png', __('Ascending'),
  1736. array('class' => "soimg$column_index", 'title' => '')
  1737. );
  1738. $order_img .= ' ' . PMA_Util::getImage(
  1739. 's_desc.png', __('Descending'),
  1740. array('class' => "soimg$column_index hide", 'title' => '')
  1741. );
  1742. }
  1743. return array($sort_order, $order_img);
  1744. } // end of the '_getSortingUrlParams()' function
  1745. /**
  1746. * Get sort order link
  1747. *
  1748. * @param string $order_img the sort order image
  1749. * @param integer $col_index the index of the column
  1750. * @param string $direction the display direction
  1751. * @param array $fields_meta set of field properties
  1752. * @param string $order_url the url for sort
  1753. *
  1754. * @return string the sort order link
  1755. *
  1756. * @access private
  1757. *
  1758. * @see _getTableHeaders()
  1759. */
  1760. private function _getSortOrderLink(
  1761. $order_img, $col_index, $direction, $fields_meta, $order_url
  1762. ) {
  1763. $order_link_params = array();
  1764. if (isset($order_img) && ($order_img != '')) {
  1765. if (strstr($order_img, 'asc')) {
  1766. $order_link_params['onmouseover'] = "$('.soimg$col_index').toggle()";
  1767. $order_link_params['onmouseout'] = "$('.soimg$col_index').toggle()";
  1768. } elseif (strstr($order_img, 'desc')) {
  1769. $order_link_params['onmouseover'] = "$('.soimg$col_index').toggle()";
  1770. $order_link_params['onmouseout'] = "$('.soimg$col_index').toggle()";
  1771. }
  1772. }
  1773. if ($GLOBALS['cfg']['HeaderFlipType'] == self::HEADER_FLIP_TYPE_AUTO) {
  1774. $GLOBALS['cfg']['HeaderFlipType']
  1775. = (PMA_USR_BROWSER_AGENT == 'IE')
  1776. ? self::HEADER_FLIP_TYPE_CSS
  1777. : self::HEADER_FLIP_TYPE_FAKE;
  1778. }
  1779. if ($direction == self::DISP_DIR_HORIZONTAL_FLIPPED
  1780. && $GLOBALS['cfg']['HeaderFlipType'] == self::HEADER_FLIP_TYPE_CSS
  1781. ) {
  1782. $order_link_params['style'] = 'direction: ltr; writing-mode: tb-rl;';
  1783. }
  1784. $order_link_content = (($direction == self::DISP_DIR_HORIZONTAL_FLIPPED)
  1785. && ($GLOBALS['cfg']['HeaderFlipType'] == self::HEADER_FLIP_TYPE_FAKE))
  1786. ? PMA_Util::flipstring(
  1787. htmlspecialchars($fields_meta->name),
  1788. "<br />\n"
  1789. )
  1790. : htmlspecialchars($fields_meta->name);
  1791. return PMA_Util::linkOrButton(
  1792. $order_url, $order_link_content . $order_img,
  1793. $order_link_params, false, true
  1794. );
  1795. } // end of the '_getSortOrderLink()' function
  1796. /**
  1797. * Prepare columns to draggable effect for sortable columns
  1798. *
  1799. * @param boolean $col_visib the column is visible (false)
  1800. * array the column is not visible (string array)
  1801. * @param string $col_visib_j element of $col_visib array
  1802. * @param boolean $condition_field whether to add CSS class condition
  1803. * @param string $direction the display direction
  1804. * @param array $fields_meta set of field properties
  1805. * @param string $order_link the order link
  1806. * @param string $comments the comment for the column
  1807. *
  1808. * @return string $draggable_html html content
  1809. *
  1810. * @access private
  1811. *
  1812. * @see _getTableHeaders()
  1813. */
  1814. private function _getDraggableClassForSortableColumns(
  1815. $col_visib, $col_visib_j, $condition_field, $direction, $fields_meta,
  1816. $order_link, $comments
  1817. ) {
  1818. $draggable_html = '<th';
  1819. $th_class = array();
  1820. $th_class[] = 'draggable';
  1821. if ($col_visib && !$col_visib_j) {
  1822. $th_class[] = 'hide';
  1823. }
  1824. if ($condition_field) {
  1825. $th_class[] = 'condition';
  1826. }
  1827. $th_class[] = 'column_heading';
  1828. if ($GLOBALS['cfg']['BrowsePointerEnable'] == true) {
  1829. $th_class[] = 'pointer';
  1830. }
  1831. if ($GLOBALS['cfg']['BrowseMarkerEnable'] == true) {
  1832. $th_class[] = 'marker';
  1833. }
  1834. $draggable_html .= ' class="' . implode(' ', $th_class);
  1835. if ($direction == self::DISP_DIR_HORIZONTAL_FLIPPED) {
  1836. $draggable_html .= ' vbottom';
  1837. }
  1838. $draggable_html .= '" data-column="' . htmlspecialchars($fields_meta->name)
  1839. . '">' . $order_link . $comments . '</th>';
  1840. return $draggable_html;
  1841. } // end of the '_getDraggableClassForSortableColumns()' function
  1842. /**
  1843. * Prepare columns to draggable effect for non sortable columns
  1844. *
  1845. * @param boolean $col_visib the column is visible (false)
  1846. * array the column is not visible (string array)
  1847. * @param string $col_visib_j element of $col_visib array
  1848. * @param boolean $condition_field whether to add CSS class condition
  1849. * @param string $direction the display direction
  1850. * @param array $fields_meta set of field properties
  1851. * @param string $comments the comment for the column
  1852. *
  1853. * @return string $draggable_html html content
  1854. *
  1855. * @access private
  1856. *
  1857. * @see _getTableHeaders()
  1858. */
  1859. private function _getDraggableClassForNonSortableColumns(
  1860. $col_visib, $col_visib_j, $condition_field,
  1861. $direction, $fields_meta, $comments
  1862. ) {
  1863. $draggable_html = '<th';
  1864. $th_class = array();
  1865. $th_class[] = 'draggable';
  1866. if ($col_visib && !$col_visib_j) {
  1867. $th_class[] = 'hide';
  1868. }
  1869. if ($condition_field) {
  1870. $th_class[] = 'condition';
  1871. }
  1872. $draggable_html .= ' class="' . implode(' ', $th_class);
  1873. if ($direction == self::DISP_DIR_HORIZONTAL_FLIPPED) {
  1874. $draggable_html .= ' vbottom';
  1875. }
  1876. $draggable_html .= '"';
  1877. if (($direction == self::DISP_DIR_HORIZONTAL_FLIPPED)
  1878. && ($GLOBALS['cfg']['HeaderFlipType'] == self::HEADER_FLIP_TYPE_CSS)
  1879. ) {
  1880. $draggable_html .= ' style="direction: ltr; writing-mode: tb-rl;"';
  1881. }
  1882. $draggable_html .= ' data-column="'
  1883. . htmlspecialchars($fields_meta->name) . '">';
  1884. if (($direction == self::DISP_DIR_HORIZONTAL_FLIPPED)
  1885. && ($GLOBALS['cfg']['HeaderFlipType'] == self::HEADER_FLIP_TYPE_FAKE)
  1886. ) {
  1887. $draggable_html .= PMA_Util::flipstring(
  1888. htmlspecialchars($fields_meta->name), '<br />'
  1889. );
  1890. } else {
  1891. $draggable_html .= htmlspecialchars($fields_meta->name);
  1892. }
  1893. $draggable_html .= "\n" . $comments . '</th>';
  1894. return $draggable_html;
  1895. } // end of the '_getDraggableClassForNonSortableColumns()' function
  1896. /**
  1897. * Prepare column to show at right side - check boxes or empty column
  1898. *
  1899. * @param array &$is_display which elements to display
  1900. * @param boolean $directionCondition display direction horizontal
  1901. * or horizontalflipped
  1902. * @param string $full_or_partial_text_link full/partial link or text button
  1903. * @param string $colspan column span of table header
  1904. * @param string $rowspan row span of table header
  1905. *
  1906. * @return string html content
  1907. *
  1908. * @access private
  1909. *
  1910. * @see _getTableHeaders()
  1911. */
  1912. private function _getColumnAtRightSide(
  1913. &$is_display, $directionCondition, $full_or_partial_text_link,
  1914. $colspan, $rowspan
  1915. ) {
  1916. $right_column_html = '';
  1917. $vertical_display = $this->__get('vertical_display');
  1918. // Displays the needed checkboxes at the right
  1919. // column of the result table header if possible and required...
  1920. if ((($GLOBALS['cfg']['RowActionLinks'] == self::POSITION_RIGHT)
  1921. || ($GLOBALS['cfg']['RowActionLinks'] == self::POSITION_BOTH))
  1922. && (($is_display['edit_lnk'] != self::NO_EDIT_OR_DELETE)
  1923. || ($is_display['del_lnk'] != self::NO_EDIT_OR_DELETE))
  1924. && ($is_display['text_btn'] == '1')
  1925. ) {
  1926. $vertical_display['emptyafter']
  1927. = (($is_display['edit_lnk'] != self::NO_EDIT_OR_DELETE)
  1928. && ($is_display['del_lnk'] != self::NO_EDIT_OR_DELETE)) ? 4 : 1;
  1929. if ($directionCondition) {
  1930. $right_column_html .= "\n"
  1931. . '<th ' . $colspan . '>' . $full_or_partial_text_link
  1932. . '</th>';
  1933. // end horizontal/horizontalflipped mode
  1934. } else {
  1935. $vertical_display['textbtn'] = ' <th ' . $rowspan
  1936. . ' class="vmiddle">' . "\n"
  1937. . ' ' . "\n"
  1938. . ' </th>' . "\n";
  1939. } // end vertical mode
  1940. } elseif ((($GLOBALS['cfg']['RowActionLinks'] == self::POSITION_LEFT)
  1941. || ($GLOBALS['cfg']['RowActionLinks'] == self::POSITION_BOTH))
  1942. && (($is_display['edit_lnk'] == self::NO_EDIT_OR_DELETE)
  1943. && ($is_display['del_lnk'] == self::NO_EDIT_OR_DELETE))
  1944. && (! isset($GLOBALS['is_header_sent']) || ! $GLOBALS['is_header_sent'])
  1945. ) {
  1946. // ... elseif no button, displays empty columns if required
  1947. // (unless coming from Browse mode print view)
  1948. $vertical_display['emptyafter']
  1949. = (($is_display['edit_lnk'] != self::NO_EDIT_OR_DELETE)
  1950. && ($is_display['del_lnk'] != self::NO_EDIT_OR_DELETE)) ? 4 : 1;
  1951. if ($directionCondition) {
  1952. $right_column_html .= "\n"
  1953. . '<td ' . $colspan . '></td>';
  1954. // end horizontal/horizontalflipped mode
  1955. } else {
  1956. $vertical_display['textbtn'] = ' <td' . $rowspan
  1957. . '></td>' . "\n";
  1958. } // end vertical mode
  1959. }
  1960. $this->__set('vertical_display', $vertical_display);
  1961. return $right_column_html;
  1962. } // end of the '_getColumnAtRightSide()' function
  1963. /**
  1964. * Prepares the display for a value
  1965. *
  1966. * @param string $class class of table cell
  1967. * @param bool $condition_field whether to add CSS class condition
  1968. * @param string $value value to display
  1969. *
  1970. * @return string the td
  1971. *
  1972. * @access private
  1973. *
  1974. * @see _getDataCellForBlobColumns(), _getDataCellForGeometryColumns(),
  1975. * _getDataCellForNonNumericAndNonBlobColumns()
  1976. */
  1977. private function _buildValueDisplay($class, $condition_field, $value)
  1978. {
  1979. return '<td class="left ' . $class . ($condition_field ? ' condition' : '')
  1980. . '">' . $value . '</td>';
  1981. } // end of the '_buildValueDisplay()' function
  1982. /**
  1983. * Prepares the display for a null value
  1984. *
  1985. * @param string $class class of table cell
  1986. * @param bool $condition_field whether to add CSS class condition
  1987. * @param object $meta the meta-information about this field
  1988. * @param string $align cell allignment
  1989. *
  1990. * @return string the td
  1991. *
  1992. * @access private
  1993. *
  1994. * @see _getDataCellForNumericColumns(), _getDataCellForBlobColumns(),
  1995. * _getDataCellForGeometryColumns(),
  1996. * _getDataCellForNonNumericAndNonBlobColumns()
  1997. */
  1998. private function _buildNullDisplay($class, $condition_field, $meta, $align = '')
  1999. {
  2000. // the null class is needed for grid editing
  2001. return '<td ' . $align . ' class="'
  2002. . $this->_addClass(
  2003. $class, $condition_field, $meta, ''
  2004. )
  2005. . ' null"><i>NULL</i></td>';
  2006. } // end of the '_buildNullDisplay()' function
  2007. /**
  2008. * Prepares the display for an empty value
  2009. *
  2010. * @param string $class class of table cell
  2011. * @param bool $condition_field whether to add CSS class condition
  2012. * @param object $meta the meta-information about this field
  2013. * @param string $align cell allignment
  2014. *
  2015. * @return string the td
  2016. *
  2017. * @access private
  2018. *
  2019. * @see _getDataCellForNumericColumns(), _getDataCellForBlobColumns(),
  2020. * _getDataCellForGeometryColumns(),
  2021. * _getDataCellForNonNumericAndNonBlobColumns()
  2022. */
  2023. private function _buildEmptyDisplay($class, $condition_field, $meta, $align = '')
  2024. {
  2025. return '<td ' . $align . ' class="'
  2026. . $this->_addClass(
  2027. $class, $condition_field, $meta, ' nowrap'
  2028. )
  2029. . '"></td>';
  2030. } // end of the '_buildEmptyDisplay()' function
  2031. /**
  2032. * Adds the relavant classes.
  2033. *
  2034. * @param string $class class of table cell
  2035. * @param bool $condition_field whether to add CSS class condition
  2036. * @param object $meta the meta-information about the field
  2037. * @param string $nowrap avoid wrapping
  2038. * @param bool $is_field_truncated is field truncated (display ...)
  2039. * @param string $transformation_plugin transformation plugin.
  2040. * Can also be the default function:
  2041. * PMA_mimeDefaultFunction
  2042. * @param string $default_function default transformation function
  2043. *
  2044. * @return string the list of classes
  2045. *
  2046. * @access private
  2047. *
  2048. * @see _buildNullDisplay(), _getRowData()
  2049. */
  2050. private function _addClass(
  2051. $class, $condition_field, $meta, $nowrap, $is_field_truncated = false,
  2052. $transformation_plugin = '', $default_function = ''
  2053. ) {
  2054. // Define classes to be added to this data field based on the type of data
  2055. $enum_class = '';
  2056. if (strpos($meta->flags, 'enum') !== false) {
  2057. $enum_class = ' enum';
  2058. }
  2059. $set_class = '';
  2060. if (strpos($meta->flags, 'set') !== false) {
  2061. $set_class = ' set';
  2062. }
  2063. $bit_class = '';
  2064. if (strpos($meta->type, 'bit') !== false) {
  2065. $bit_class = ' bit';
  2066. }
  2067. $mime_type_class = '';
  2068. if (isset($meta->mimetype)) {
  2069. $mime_type_class = ' ' . preg_replace('/\//', '_', $meta->mimetype);
  2070. }
  2071. return $class . ($condition_field ? ' condition' : '') . $nowrap
  2072. . ' ' . ($is_field_truncated ? ' truncated' : '')
  2073. . ($transformation_plugin != $default_function ? ' transformed' : '')
  2074. . $enum_class . $set_class . $bit_class . $mime_type_class;
  2075. } // end of the '_addClass()' function
  2076. /**
  2077. * Prepare the body of the results table
  2078. *
  2079. * @param integer &$dt_result the link id associated to the query
  2080. * which results have to be displayed
  2081. * @param array &$is_display which elements to display
  2082. * @param array $map the list of relations
  2083. * @param array $analyzed_sql the analyzed query
  2084. * @param boolean $is_limited_display with limited operations or not
  2085. *
  2086. * @return string $table_body_html html content
  2087. *
  2088. * @global array $row current row data
  2089. *
  2090. * @access private
  2091. *
  2092. * @see getTable()
  2093. */
  2094. private function _getTableBody(
  2095. &$dt_result, &$is_display, $map, $analyzed_sql, $is_limited_display = false
  2096. ) {
  2097. global $row; // mostly because of browser transformations,
  2098. // to make the row-data accessible in a plugin
  2099. $table_body_html = '';
  2100. // query without conditions to shorten URLs when needed, 200 is just
  2101. // guess, it should depend on remaining URL length
  2102. $url_sql_query = $this->_getUrlSqlQuery($analyzed_sql);
  2103. $vertical_display = $this->__get('vertical_display');
  2104. if (! is_array($map)) {
  2105. $map = array();
  2106. }
  2107. $row_no = 0;
  2108. $vertical_display['edit'] = array();
  2109. $vertical_display['copy'] = array();
  2110. $vertical_display['delete'] = array();
  2111. $vertical_display['data'] = array();
  2112. $vertical_display['row_delete'] = array();
  2113. $this->__set('vertical_display', $vertical_display);
  2114. // name of the class added to all grid editable elements;
  2115. // if we don't have all the columns of a unique key in the result set,
  2116. // do not permit grid editing
  2117. if ($is_limited_display || ! $this->__get('editable')) {
  2118. $grid_edit_class = '';
  2119. } else {
  2120. switch ($GLOBALS['cfg']['GridEditing']) {
  2121. case 'double-click':
  2122. // trying to reduce generated HTML by using shorter
  2123. // classes like click1 and click2
  2124. $grid_edit_class = 'grid_edit click2';
  2125. break;
  2126. case 'click':
  2127. $grid_edit_class = 'grid_edit click1';
  2128. break;
  2129. case 'disabled':
  2130. $grid_edit_class = '';
  2131. break;
  2132. }
  2133. }
  2134. // prepare to get the column order, if available
  2135. list($col_order, $col_visib) = $this->_getColumnParams($analyzed_sql);
  2136. // Correction University of Virginia 19991216 in the while below
  2137. // Previous code assumed that all tables have keys, specifically that
  2138. // the phpMyAdmin GUI should support row delete/edit only for such
  2139. // tables.
  2140. // Although always using keys is arguably the prescribed way of
  2141. // defining a relational table, it is not required. This will in
  2142. // particular be violated by the novice.
  2143. // We want to encourage phpMyAdmin usage by such novices. So the code
  2144. // below has been changed to conditionally work as before when the
  2145. // table being displayed has one or more keys; but to display
  2146. // delete/edit options correctly for tables without keys.
  2147. $odd_row = true;
  2148. $directionCondition
  2149. = ($_SESSION['tmp_user_values']['disp_direction']
  2150. == self::DISP_DIR_HORIZONTAL)
  2151. || ($_SESSION['tmp_user_values']['disp_direction']
  2152. == self::DISP_DIR_HORIZONTAL_FLIPPED);
  2153. while ($row = PMA_DBI_fetch_row($dt_result)) {
  2154. // "vertical display" mode stuff
  2155. $table_body_html .= $this->_getVerticalDisplaySupportSegments(
  2156. $vertical_display, $row_no, $directionCondition
  2157. );
  2158. $alternating_color_class = ($odd_row ? 'odd' : 'even');
  2159. $odd_row = ! $odd_row;
  2160. if ($directionCondition) {
  2161. // pointer code part
  2162. $table_body_html .= '<tr class="' . $alternating_color_class . '">';
  2163. }
  2164. // 1. Prepares the row
  2165. // 1.1 Results from a "SELECT" statement -> builds the
  2166. // WHERE clause to use in links (a unique key if possible)
  2167. /**
  2168. * @todo $where_clause could be empty, for example a table
  2169. * with only one field and it's a BLOB; in this case,
  2170. * avoid to display the delete and edit links
  2171. */
  2172. list($where_clause, $clause_is_unique, $condition_array)
  2173. = PMA_Util::getUniqueCondition(
  2174. $dt_result,
  2175. $this->__get('fields_cnt'),
  2176. $this->__get('fields_meta'),
  2177. $row
  2178. );
  2179. $where_clause_html = urlencode($where_clause);
  2180. // In print view these variable needs toinitialized
  2181. $del_url = $del_query = $del_str = $edit_anchor_class
  2182. = $edit_str = $js_conf = $copy_url = $copy_str = $edit_url = null;
  2183. // 1.2 Defines the URLs for the modify/delete link(s)
  2184. if (($is_display['edit_lnk'] != self::NO_EDIT_OR_DELETE)
  2185. || ($is_display['del_lnk'] != self::NO_EDIT_OR_DELETE)
  2186. ) {
  2187. // We need to copy the value
  2188. // or else the == 'both' check will always return true
  2189. if ($GLOBALS['cfg']['ActionLinksMode'] === self::POSITION_BOTH) {
  2190. $iconic_spacer = '<div class="nowrap">';
  2191. } else {
  2192. $iconic_spacer = '';
  2193. }
  2194. // 1.2.1 Modify link(s) - update row case
  2195. if ($is_display['edit_lnk'] == self::UPDATE_ROW) {
  2196. list($edit_url, $copy_url, $edit_str, $copy_str,
  2197. $edit_anchor_class)
  2198. = $this->_getModifiedLinks(
  2199. $where_clause,
  2200. $clause_is_unique, $url_sql_query
  2201. );
  2202. } // end if (1.2.1)
  2203. // 1.2.2 Delete/Kill link(s)
  2204. if (($is_display['del_lnk'] == self::DELETE_ROW)
  2205. || ($is_display['del_lnk'] == self::KILL_PROCESS)
  2206. ) {
  2207. list($del_query, $del_url, $del_str, $js_conf)
  2208. = $this->_getDeleteAndKillLinks(
  2209. $where_clause, $clause_is_unique,
  2210. $url_sql_query, $is_display['del_lnk'],
  2211. $row
  2212. );
  2213. } // end if (1.2.2)
  2214. // 1.3 Displays the links at left if required
  2215. if ((($GLOBALS['cfg']['RowActionLinks'] == self::POSITION_LEFT)
  2216. || ($GLOBALS['cfg']['RowActionLinks'] == self::POSITION_BOTH))
  2217. && $directionCondition
  2218. ) {
  2219. $table_body_html .= $this->_getPlacedLinks(
  2220. self::POSITION_LEFT, $del_url, $is_display, $row_no,
  2221. $where_clause, $where_clause_html, $condition_array,
  2222. $del_query, 'l', $edit_url, $copy_url, $edit_anchor_class,
  2223. $edit_str, $copy_str, $del_str, $js_conf
  2224. );
  2225. } elseif (($GLOBALS['cfg']['RowActionLinks'] == self::POSITION_NONE)
  2226. && $directionCondition
  2227. ) {
  2228. $table_body_html .= $this->_getPlacedLinks(
  2229. self::POSITION_NONE, $del_url, $is_display, $row_no,
  2230. $where_clause, $where_clause_html, $condition_array,
  2231. $del_query, 'l', $edit_url, $copy_url, $edit_anchor_class,
  2232. $edit_str, $copy_str, $del_str, $js_conf
  2233. );
  2234. } // end if (1.3)
  2235. } // end if (1)
  2236. // 2. Displays the rows' values
  2237. $table_body_html .= $this->_getRowValues(
  2238. $dt_result, $row, $row_no, $col_order, $map,
  2239. $grid_edit_class, $col_visib, $where_clause,
  2240. $url_sql_query, $analyzed_sql, $directionCondition
  2241. );
  2242. // 3. Displays the modify/delete links on the right if required
  2243. if ((($GLOBALS['cfg']['RowActionLinks'] == self::POSITION_RIGHT)
  2244. || ($GLOBALS['cfg']['RowActionLinks'] == self::POSITION_BOTH))
  2245. && $directionCondition
  2246. ) {
  2247. $table_body_html .= $this->_getPlacedLinks(
  2248. self::POSITION_RIGHT, $del_url, $is_display, $row_no,
  2249. $where_clause, $where_clause_html, $condition_array,
  2250. $del_query, 'r', $edit_url, $copy_url, $edit_anchor_class,
  2251. $edit_str, $copy_str, $del_str, $js_conf
  2252. );
  2253. } // end if (3)
  2254. if ($directionCondition) {
  2255. $table_body_html .= '</tr>';
  2256. } // end if
  2257. // 4. Gather links of del_urls and edit_urls in an array for later
  2258. // output
  2259. $this->_gatherLinksForLaterOutputs(
  2260. $row_no, $is_display, $where_clause, $where_clause_html, $js_conf,
  2261. $del_url, $del_query, $del_str, $edit_anchor_class, $edit_url,
  2262. $edit_str, $copy_url, $copy_str, $alternating_color_class,
  2263. $condition_array
  2264. );
  2265. $table_body_html .= $directionCondition ? "\n" : '';
  2266. $row_no++;
  2267. } // end while
  2268. return $table_body_html;
  2269. } // end of the '_getTableBody()' function
  2270. /**
  2271. * Get the values for one data row
  2272. *
  2273. * @param integer &$dt_result the link id associated to the query
  2274. * which results have to be displayed
  2275. * @param array $row current row data
  2276. * @param integer $row_no the index of current row
  2277. * @param array $col_order the column order
  2278. * false when a property not found
  2279. * @param array $map the list of relations
  2280. * @param string $grid_edit_class the class for all editable columns
  2281. * @param boolean $col_visib column is visible(false)
  2282. * array column isn't visible(string array)
  2283. * @param string $where_clause where clause
  2284. * @param string $url_sql_query the analyzed sql query
  2285. * @param array $analyzed_sql the analyzed query
  2286. * @param boolean $directionCondition the directional condition
  2287. *
  2288. * @return string $row_values_html html content
  2289. *
  2290. * @access private
  2291. *
  2292. * @see _getTableBody()
  2293. */
  2294. private function _getRowValues(
  2295. &$dt_result, $row, $row_no, $col_order, $map,
  2296. $grid_edit_class, $col_visib, $where_clause,
  2297. $url_sql_query, $analyzed_sql, $directionCondition
  2298. ) {
  2299. $row_values_html = '';
  2300. // Following variable are needed for use in isset/empty or
  2301. // use with array indexes/safe use in foreach
  2302. $sql_query = $this->__get('sql_query');
  2303. $fields_meta = $this->__get('fields_meta');
  2304. $highlight_columns = $this->__get('highlight_columns');
  2305. $mime_map = $this->__get('mime_map');
  2306. $row_info = $this->_getRowInfoForSpecialLinks($row, $col_order);
  2307. for ($currentColumn = 0;
  2308. $currentColumn < $this->__get('fields_cnt');
  2309. ++$currentColumn) {
  2310. // assign $i with appropriate column order
  2311. $i = $col_order ? $col_order[$currentColumn] : $currentColumn;
  2312. $meta = $fields_meta[$i];
  2313. $not_null_class = $meta->not_null ? 'not_null' : '';
  2314. $relation_class = isset($map[$meta->name]) ? 'relation' : '';
  2315. $hide_class = ($col_visib && ! $col_visib[$currentColumn]
  2316. // hide per <td> only if the display dir is not vertical
  2317. && ($_SESSION['tmp_user_values']['disp_direction']
  2318. != self::DISP_DIR_VERTICAL))
  2319. ? 'hide'
  2320. : '';
  2321. // handle datetime-related class, for grid editing
  2322. $field_type_class
  2323. = $this->_getClassForDateTimeRelatedFields($meta->type);
  2324. $is_field_truncated = false;
  2325. // combine all the classes applicable to this column's value
  2326. $class = $this->_getClassesForColumn(
  2327. $grid_edit_class, $not_null_class, $relation_class,
  2328. $hide_class, $field_type_class, $row_no
  2329. );
  2330. // See if this column should get highlight because it's used in the
  2331. // where-query.
  2332. $condition_field = (isset($highlight_columns)
  2333. && (isset($highlight_columns[$meta->name])
  2334. || isset($highlight_columns[PMA_Util::backquote($meta->name)])))
  2335. ? true
  2336. : false;
  2337. // Wrap MIME-transformations. [MIME]
  2338. $default_function = '_mimeDefaultFunction'; // default_function
  2339. $transformation_plugin = $default_function;
  2340. $transform_options = array();
  2341. if ($GLOBALS['cfgRelation']['mimework']
  2342. && $GLOBALS['cfg']['BrowseMIME']
  2343. ) {
  2344. if (isset($mime_map[$meta->name]['mimetype'])
  2345. && isset($mime_map[$meta->name]['transformation'])
  2346. && !empty($mime_map[$meta->name]['transformation'])
  2347. ) {
  2348. $file = $mime_map[$meta->name]['transformation'];
  2349. $include_file = 'libraries/plugins/transformations/' . $file;
  2350. if (file_exists($include_file)) {
  2351. include_once $include_file;
  2352. $class_name = str_replace('.class.php', '', $file);
  2353. // todo add $plugin_manager
  2354. $plugin_manager = null;
  2355. $transformation_plugin = new $class_name(
  2356. $plugin_manager
  2357. );
  2358. $transform_options = PMA_transformation_getOptions(
  2359. isset($mime_map[$meta->name]
  2360. ['transformation_options']
  2361. )
  2362. ? $mime_map[$meta->name]
  2363. ['transformation_options']
  2364. : ''
  2365. );
  2366. $meta->mimetype = str_replace(
  2367. '_', '/',
  2368. $mime_map[$meta->name]['mimetype']
  2369. );
  2370. } // end if file_exists
  2371. } // end if transformation is set
  2372. } // end if mime/transformation works.
  2373. $_url_params = array(
  2374. 'db' => $this->__get('db'),
  2375. 'table' => $this->__get('table'),
  2376. 'where_clause' => $where_clause,
  2377. 'transform_key' => $meta->name,
  2378. );
  2379. if (! empty($sql_query)) {
  2380. $_url_params['sql_query'] = $url_sql_query;
  2381. }
  2382. $transform_options['wrapper_link']
  2383. = PMA_generate_common_url($_url_params);
  2384. $vertical_display = $this->__get('vertical_display');
  2385. // Check whether the field needs to display with syntax highlighting
  2386. if ($this->_isNeedToSyntaxHighlight($meta->name)
  2387. && (trim($row[$i]) != '')
  2388. ) {
  2389. $parsed_sql = PMA_SQP_parse($row[$i]);
  2390. $row[$i] = PMA_Util::formatSql(
  2391. $parsed_sql, $row[$i]
  2392. );
  2393. include_once $this->transformation_info[strtolower($this->__get('db'))][strtolower($this->__get('table'))][strtolower($meta->name)][0];
  2394. $transformation_plugin = new $this->transformation_info[strtolower($this->__get('db'))][strtolower($this->__get('table'))][strtolower($meta->name)][1](null);
  2395. $transform_options = PMA_transformation_getOptions(
  2396. isset($mime_map[$meta->name]['transformation_options'])
  2397. ? $mime_map[$meta->name]['transformation_options']
  2398. : ''
  2399. );
  2400. $meta->mimetype = str_replace(
  2401. '_', '/',
  2402. $this->transformation_info[strtolower($this->__get('db'))][strtolower($this->__get('table'))][strtolower($meta->name)][2]
  2403. );
  2404. }
  2405. // Check for the predefined fields need to show as link in schemas
  2406. include_once 'libraries/special_schema_links.lib.php';
  2407. if (isset($GLOBALS['special_schema_links'])
  2408. && ($this->_isFieldNeedToLink(strtolower($meta->name)))
  2409. ) {
  2410. $linking_url = $this->_getSpecialLinkUrl(
  2411. $row[$i], $row_info, strtolower($meta->name)
  2412. );
  2413. include_once "libraries/plugins/transformations/Text_Plain_Link.class.php";
  2414. $transformation_plugin = new Text_Plain_Link(null);
  2415. $transform_options = array(
  2416. 0 => $linking_url,
  2417. 2 => true
  2418. );
  2419. $meta->mimetype = str_replace(
  2420. '_', '/',
  2421. 'Text/Plain'
  2422. );
  2423. }
  2424. if ($meta->numeric == 1) {
  2425. // n u m e r i c
  2426. $vertical_display['data'][$row_no][$i]
  2427. = $this->_getDataCellForNumericColumns(
  2428. $row[$i], $class, $condition_field, $meta, $map,
  2429. $is_field_truncated, $analyzed_sql,
  2430. $transformation_plugin, $default_function,
  2431. $transform_options
  2432. );
  2433. } elseif (stristr($meta->type, self::BLOB_FIELD)) {
  2434. // b l o b
  2435. // PMA_mysql_fetch_fields returns BLOB in place of
  2436. // TEXT fields type so we have to ensure it's really a BLOB
  2437. $field_flags = PMA_DBI_field_flags($dt_result, $i);
  2438. $vertical_display['data'][$row_no][$i]
  2439. = $this->_getDataCellForBlobColumns(
  2440. $row[$i], $class, $meta, $_url_params, $field_flags,
  2441. $transformation_plugin, $default_function,
  2442. $transform_options, $condition_field, $is_field_truncated
  2443. );
  2444. } elseif ($meta->type == self::GEOMETRY_FIELD) {
  2445. // g e o m e t r y
  2446. // Remove 'grid_edit' from $class as we do not allow to
  2447. // inline-edit geometry data.
  2448. $class = str_replace('grid_edit', '', $class);
  2449. $vertical_display['data'][$row_no][$i]
  2450. = $this->_getDataCellForGeometryColumns(
  2451. $row[$i], $class, $meta, $map, $_url_params,
  2452. $condition_field, $transformation_plugin,
  2453. $default_function, $transform_options,
  2454. $is_field_truncated, $analyzed_sql
  2455. );
  2456. } else {
  2457. // n o t n u m e r i c a n d n o t B L O B
  2458. $vertical_display['data'][$row_no][$i]
  2459. = $this->_getDataCellForNonNumericAndNonBlobColumns(
  2460. $row[$i], $class, $meta, $map, $_url_params,
  2461. $condition_field, $transformation_plugin,
  2462. $default_function, $transform_options,
  2463. $is_field_truncated, $analyzed_sql, $dt_result, $i
  2464. );
  2465. }
  2466. // output stored cell
  2467. if ($directionCondition) {
  2468. $row_values_html
  2469. .= $vertical_display['data'][$row_no][$i];
  2470. }
  2471. if (isset($vertical_display['rowdata'][$i][$row_no])) {
  2472. $vertical_display['rowdata'][$i][$row_no]
  2473. .= $vertical_display['data'][$row_no][$i];
  2474. } else {
  2475. $vertical_display['rowdata'][$i][$row_no]
  2476. = $vertical_display['data'][$row_no][$i];
  2477. }
  2478. $this->__set('vertical_display', $vertical_display);
  2479. } // end for
  2480. return $row_values_html;
  2481. } // end of the '_getRowValues()' function
  2482. /**
  2483. * Gather delete/edit url links for further outputs
  2484. *
  2485. * @param integer $row_no the index of current row
  2486. * @param array $is_display which elements to display
  2487. * @param string $where_clause where clause
  2488. * @param string $where_clause_html the html encoded where clause
  2489. * @param string $js_conf text for the JS confirmation
  2490. * @param string $del_url the url for delete row
  2491. * @param string $del_query the query for delete row
  2492. * @param string $del_str the label for delete row
  2493. * @param string $edit_anchor_class the class for html element for edit
  2494. * @param string $edit_url the url for edit row
  2495. * @param string $edit_str the label for edit row
  2496. * @param string $copy_url the url for copy row
  2497. * @param string $copy_str the label for copy row
  2498. * @param string $alternating_color_class class for display two colors in rows
  2499. * @param array $condition_array array of keys
  2500. * (primary,unique,condition)
  2501. *
  2502. * @return void
  2503. *
  2504. * @access private
  2505. *
  2506. * @see _getTableBody()
  2507. */
  2508. private function _gatherLinksForLaterOutputs(
  2509. $row_no, $is_display, $where_clause, $where_clause_html, $js_conf,
  2510. $del_url, $del_query, $del_str, $edit_anchor_class, $edit_url, $edit_str,
  2511. $copy_url, $copy_str, $alternating_color_class, $condition_array
  2512. ) {
  2513. $vertical_display = $this->__get('vertical_display');
  2514. if (! isset($vertical_display['edit'][$row_no])) {
  2515. $vertical_display['edit'][$row_no] = '';
  2516. $vertical_display['copy'][$row_no] = '';
  2517. $vertical_display['delete'][$row_no] = '';
  2518. $vertical_display['row_delete'][$row_no] = '';
  2519. }
  2520. $vertical_class = ' row_' . $row_no;
  2521. if ($GLOBALS['cfg']['BrowsePointerEnable'] == true) {
  2522. $vertical_class .= ' vpointer';
  2523. }
  2524. if ($GLOBALS['cfg']['BrowseMarkerEnable'] == true) {
  2525. $vertical_class .= ' vmarker';
  2526. }
  2527. if (!empty($del_url)
  2528. && ($is_display['del_lnk'] != self::KILL_PROCESS)
  2529. ) {
  2530. $vertical_display['row_delete'][$row_no]
  2531. .= $this->_getCheckboxForMultiRowSubmissions(
  2532. $del_url, $is_display, $row_no, $where_clause_html,
  2533. $condition_array, $del_query, '[%_PMA_CHECKBOX_DIR_%]',
  2534. $alternating_color_class . $vertical_class
  2535. );
  2536. } else {
  2537. unset($vertical_display['row_delete'][$row_no]);
  2538. }
  2539. if (isset($edit_url)) {
  2540. $vertical_display['edit'][$row_no] .= $this->_getEditLink(
  2541. $edit_url,
  2542. $alternating_color_class . ' ' . $edit_anchor_class
  2543. . $vertical_class, $edit_str,
  2544. $where_clause,
  2545. $where_clause_html
  2546. );
  2547. } else {
  2548. unset($vertical_display['edit'][$row_no]);
  2549. }
  2550. if (isset($copy_url)) {
  2551. $vertical_display['copy'][$row_no] .= $this->_getCopyLink(
  2552. $copy_url, $copy_str, $where_clause, $where_clause_html,
  2553. $alternating_color_class . $vertical_class
  2554. );
  2555. } else {
  2556. unset($vertical_display['copy'][$row_no]);
  2557. }
  2558. if (isset($del_url)) {
  2559. if (! isset($js_conf)) {
  2560. $js_conf = '';
  2561. }
  2562. $vertical_display['delete'][$row_no]
  2563. .= $this->_getDeleteLink(
  2564. $del_url, $del_str, $js_conf,
  2565. $alternating_color_class . $vertical_class
  2566. );
  2567. } else {
  2568. unset($vertical_display['delete'][$row_no]);
  2569. }
  2570. $this->__set('vertical_display', $vertical_display);
  2571. } // end of the '_gatherLinksForLaterOutputs()' function
  2572. /**
  2573. * Check whether any field is marked as need to syntax highlight
  2574. *
  2575. * @param string $field field to check
  2576. *
  2577. * @return boolean
  2578. */
  2579. private function _isNeedToSyntaxHighlight($field)
  2580. {
  2581. if (! empty($this->transformation_info[strtolower($this->__get('db'))][strtolower($this->__get('table'))][strtolower($field)])) {
  2582. return true;
  2583. }
  2584. return false;
  2585. }
  2586. /**
  2587. * Check whether the field needs to be link
  2588. *
  2589. * @param string $field field to check
  2590. *
  2591. * @return boolean
  2592. */
  2593. private function _isFieldNeedToLink($field)
  2594. {
  2595. if (! empty($GLOBALS['special_schema_links'][strtolower($this->__get('db'))][strtolower($this->__get('table'))][$field])) {
  2596. return true;
  2597. }
  2598. return false;
  2599. }
  2600. /**
  2601. * Get link for display special schema links
  2602. *
  2603. * @param string $column_value column value
  2604. * @param array $row_info information about row
  2605. * @param string $field_name column name
  2606. *
  2607. * @return string generated link
  2608. */
  2609. private function _getSpecialLinkUrl($column_value, $row_info, $field_name)
  2610. {
  2611. $linking_url_params = array();
  2612. $link_relations = $GLOBALS['special_schema_links']
  2613. [strtolower($this->__get('db'))]
  2614. [strtolower($this->__get('table'))]
  2615. [$field_name];
  2616. if (! is_array($link_relations['link_param'])) {
  2617. $linking_url_params[$link_relations['link_param']] = $column_value;
  2618. } else {
  2619. // Consider only the case of creating link for column field
  2620. // sql query need to be pass as url param
  2621. $sql = 'SELECT `'.$column_value.'` FROM `'
  2622. . $row_info[$link_relations['link_param'][1]] .'`.`'
  2623. . $row_info[$link_relations['link_param'][2]] .'`';
  2624. $linking_url_params[$link_relations['link_param'][0]] = $sql;
  2625. }
  2626. if (! empty($link_relations['link_dependancy_params'])) {
  2627. foreach ($link_relations['link_dependancy_params'] as $new_param) {
  2628. // If param_info is an array, set the key and value
  2629. // from that array
  2630. if (is_array($new_param['param_info'])) {
  2631. $linking_url_params[$new_param['param_info'][0]]
  2632. = $new_param['param_info'][1];
  2633. } else {
  2634. $linking_url_params[$new_param['param_info']]
  2635. = $row_info[strtolower($new_param['column_name'])];
  2636. // Special case 1 - when executing routines, according
  2637. // to the type of the routine, url param changes
  2638. if (!empty($row_info['routine_type'])) {
  2639. if (strtolower($row_info['routine_type']) == self::ROUTINE_PROCEDURE
  2640. || strtolower($row_info['routine_type']) == self::ROUTINE_FUNCTION
  2641. ) {
  2642. $linking_url_params['edit_item'] = 1;
  2643. }
  2644. }
  2645. }
  2646. }
  2647. }
  2648. return $link_relations['default_page']
  2649. . PMA_generate_common_url($linking_url_params);
  2650. }
  2651. /**
  2652. * Prepare row information for display special links
  2653. *
  2654. * @param array $row current row data
  2655. * @param array $col_order the column order
  2656. *
  2657. * @return array $row_info associative array with column nama -> value
  2658. */
  2659. private function _getRowInfoForSpecialLinks($row, $col_order)
  2660. {
  2661. $row_info = array();
  2662. $fields_meta = $this->__get('fields_meta');
  2663. for ($n = 0; $n < $this->__get('fields_cnt'); ++$n) {
  2664. $m = $col_order ? $col_order[$n] : $n;
  2665. $row_info[strtolower($fields_meta[$m]->name)] = $row[$m];
  2666. }
  2667. return $row_info;
  2668. }
  2669. /**
  2670. * Get url sql query without conditions to shorten URLs
  2671. *
  2672. * @param array $analyzed_sql analyzed query
  2673. *
  2674. * @return string $url_sql analyzed sql query
  2675. *
  2676. * @access private
  2677. *
  2678. * @see _getTableBody()
  2679. */
  2680. private function _getUrlSqlQuery($analyzed_sql)
  2681. {
  2682. if (isset($analyzed_sql)
  2683. && isset($analyzed_sql[0])
  2684. && isset($analyzed_sql[0]['querytype'])
  2685. && ($analyzed_sql[0]['querytype'] == self::QUERY_TYPE_SELECT)
  2686. && (strlen($this->__get('sql_query')) > 200)
  2687. ) {
  2688. $url_sql_query = 'SELECT ';
  2689. if (isset($analyzed_sql[0]['queryflags']['distinct'])) {
  2690. $url_sql_query .= ' DISTINCT ';
  2691. }
  2692. $url_sql_query .= $analyzed_sql[0]['select_expr_clause'];
  2693. if (!empty($analyzed_sql[0]['from_clause'])) {
  2694. $url_sql_query .= ' FROM ' . $analyzed_sql[0]['from_clause'];
  2695. }
  2696. return $url_sql_query;
  2697. }
  2698. return $this->__get('sql_query');
  2699. } // end of the '_getUrlSqlQuery()' function
  2700. /**
  2701. * Get column order and column visibility
  2702. *
  2703. * @param array $analyzed_sql the analyzed query
  2704. *
  2705. * @return array 2 element array - $col_order, $col_visib
  2706. *
  2707. * @access private
  2708. *
  2709. * @see _getTableBody()
  2710. */
  2711. private function _getColumnParams($analyzed_sql)
  2712. {
  2713. if ($this->_isSelect($analyzed_sql)) {
  2714. $pmatable = new PMA_Table($this->__get('table'), $this->__get('db'));
  2715. $col_order = $pmatable->getUiProp(PMA_Table::PROP_COLUMN_ORDER);
  2716. $col_visib = $pmatable->getUiProp(PMA_Table::PROP_COLUMN_VISIB);
  2717. } else {
  2718. $col_order = false;
  2719. $col_visib = false;
  2720. }
  2721. return array($col_order, $col_visib);
  2722. } // end of the '_getColumnParams()' function
  2723. /**
  2724. * Prepare vertical display mode necessay HTML stuff
  2725. *
  2726. * @param array $vertical_display informations used with vertical
  2727. * display mode
  2728. * @param integer $row_no the index of current row
  2729. * @param boolean $directionCondition the directional condition
  2730. *
  2731. * @return string $vertical_disp_html html content
  2732. *
  2733. * @access private
  2734. *
  2735. * @see _getTableBody()
  2736. */
  2737. private function _getVerticalDisplaySupportSegments(
  2738. $vertical_display, $row_no, $directionCondition
  2739. ) {
  2740. $support_html = '';
  2741. if ((($row_no != 0) && ($_SESSION['tmp_user_values']['repeat_cells'] != 0))
  2742. && !($row_no % $_SESSION['tmp_user_values']['repeat_cells'])
  2743. && $directionCondition
  2744. ) {
  2745. $support_html .= '<tr>' . "\n";
  2746. if ($vertical_display['emptypre'] > 0) {
  2747. $support_html .= ' <th colspan="'
  2748. . $vertical_display['emptypre'] . '">'
  2749. . "\n".' &nbsp;</th>' . "\n";
  2750. } else if ($GLOBALS['cfg']['RowActionLinks'] == self::POSITION_NONE) {
  2751. $support_html .= ' <th></th>' . "\n";
  2752. }
  2753. foreach ($vertical_display['desc'] as $val) {
  2754. $support_html .= $val;
  2755. }
  2756. if ($vertical_display['emptyafter'] > 0) {
  2757. $support_html
  2758. .= ' <th colspan="' . $vertical_display['emptyafter']
  2759. . '">'
  2760. . "\n" . ' &nbsp;</th>' . "\n";
  2761. }
  2762. $support_html .= '</tr>' . "\n";
  2763. } // end if
  2764. return $support_html;
  2765. } // end of the '_getVerticalDisplaySupportSegments()' function
  2766. /**
  2767. * Get modified links
  2768. *
  2769. * @param string $where_clause the where clause of the sql
  2770. * @param boolean $clause_is_unique the unique condition of clause
  2771. * @param string $url_sql_query the analyzed sql query
  2772. *
  2773. * @return array 5 element array - $edit_url, $copy_url,
  2774. * $edit_str, $copy_str, $edit_anchor_class
  2775. *
  2776. * @access private
  2777. *
  2778. * @see _getTableBody()
  2779. */
  2780. private function _getModifiedLinks(
  2781. $where_clause, $clause_is_unique, $url_sql_query
  2782. ) {
  2783. $_url_params = array(
  2784. 'db' => $this->__get('db'),
  2785. 'table' => $this->__get('table'),
  2786. 'where_clause' => $where_clause,
  2787. 'clause_is_unique' => $clause_is_unique,
  2788. 'sql_query' => $url_sql_query,
  2789. 'goto' => 'sql.php',
  2790. );
  2791. $edit_url = 'tbl_change.php'
  2792. . PMA_generate_common_url(
  2793. $_url_params + array('default_action' => 'update')
  2794. );
  2795. $copy_url = 'tbl_change.php'
  2796. . PMA_generate_common_url(
  2797. $_url_params + array('default_action' => 'insert')
  2798. );
  2799. $edit_str = PMA_Util::getIcon(
  2800. 'b_edit.png', __('Edit')
  2801. );
  2802. $copy_str = PMA_Util::getIcon(
  2803. 'b_insrow.png', __('Copy')
  2804. );
  2805. // Class definitions required for grid editing jQuery scripts
  2806. $edit_anchor_class = "edit_row_anchor";
  2807. if ( $clause_is_unique == 0) {
  2808. $edit_anchor_class .= ' nonunique';
  2809. }
  2810. return array($edit_url, $copy_url, $edit_str, $copy_str, $edit_anchor_class);
  2811. } // end of the '_getModifiedLinks()' function
  2812. /**
  2813. * Get delete and kill links
  2814. *
  2815. * @param string $where_clause the where clause of the sql
  2816. * @param boolean $clause_is_unique the unique condition of clause
  2817. * @param string $url_sql_query the analyzed sql query
  2818. * @param string $del_lnk the delete link of current row
  2819. * @param array $row the current row
  2820. *
  2821. * @return array 4 element array - $del_query,
  2822. * $del_url, $del_str, $js_conf
  2823. *
  2824. * @access private
  2825. *
  2826. * @see _getTableBody()
  2827. */
  2828. private function _getDeleteAndKillLinks(
  2829. $where_clause, $clause_is_unique, $url_sql_query, $del_lnk, $row
  2830. ) {
  2831. $goto = $this->__get('goto');
  2832. if ($del_lnk == self::DELETE_ROW) { // delete row case
  2833. $_url_params = array(
  2834. 'db' => $this->__get('db'),
  2835. 'table' => $this->__get('table'),
  2836. 'sql_query' => $url_sql_query,
  2837. 'message_to_show' => __('The row has been deleted'),
  2838. 'goto' => (empty($goto) ? 'tbl_sql.php' : $goto),
  2839. );
  2840. $lnk_goto = 'sql.php' . PMA_generate_common_url($_url_params, 'text');
  2841. $del_query = 'DELETE FROM '
  2842. . PMA_Util::backquote($this->__get('db')) . '.'
  2843. . PMA_Util::backquote($this->__get('table'))
  2844. . ' WHERE ' . $where_clause .
  2845. ($clause_is_unique ? '' : ' LIMIT 1');
  2846. $_url_params = array(
  2847. 'db' => $this->__get('db'),
  2848. 'table' => $this->__get('table'),
  2849. 'sql_query' => $del_query,
  2850. 'message_to_show' => __('The row has been deleted'),
  2851. 'goto' => $lnk_goto,
  2852. );
  2853. $del_url = 'sql.php' . PMA_generate_common_url($_url_params);
  2854. $js_conf = 'DELETE FROM ' . PMA_jsFormat($this->__get('db')) . '.'
  2855. . PMA_jsFormat($this->__get('table'))
  2856. . ' WHERE ' . PMA_jsFormat($where_clause, false)
  2857. . ($clause_is_unique ? '' : ' LIMIT 1');
  2858. $del_str = PMA_Util::getIcon(
  2859. 'b_drop.png', __('Delete')
  2860. );
  2861. } elseif ($del_lnk == self::KILL_PROCESS) { // kill process case
  2862. $_url_params = array(
  2863. 'db' => $this->__get('db'),
  2864. 'table' => $this->__get('table'),
  2865. 'sql_query' => $url_sql_query,
  2866. 'goto' => 'index.php',
  2867. );
  2868. $lnk_goto = 'sql.php'
  2869. . PMA_generate_common_url(
  2870. $_url_params, 'text'
  2871. );
  2872. $_url_params = array(
  2873. 'db' => 'mysql',
  2874. 'sql_query' => 'KILL ' . $row[0],
  2875. 'goto' => $lnk_goto,
  2876. );
  2877. $del_url = 'sql.php' . PMA_generate_common_url($_url_params);
  2878. $del_query = 'KILL ' . $row[0];
  2879. $js_conf = 'KILL ' . $row[0];
  2880. $del_str = PMA_Util::getIcon(
  2881. 'b_drop.png', __('Kill')
  2882. );
  2883. }
  2884. return array($del_query, $del_url, $del_str, $js_conf);
  2885. } // end of the '_getDeleteAndKillLinks()' function
  2886. /**
  2887. * Prepare placed links
  2888. *
  2889. * @param string $dir the direction of links should place
  2890. * @param string $del_url the url for delete row
  2891. * @param array $is_display which elements to display
  2892. * @param integer $row_no the index of current row
  2893. * @param string $where_clause the where clause of the sql
  2894. * @param string $where_clause_html the html encoded where clause
  2895. * @param array $condition_array array of keys (primary, unique, condition)
  2896. * @param string $del_query the query for delete row
  2897. * @param string $dir_letter the letter denoted the direction
  2898. * @param string $edit_url the url for edit row
  2899. * @param string $copy_url the url for copy row
  2900. * @param string $edit_anchor_class the class for html element for edit
  2901. * @param string $edit_str the label for edit row
  2902. * @param string $copy_str the label for copy row
  2903. * @param string $del_str the label for delete row
  2904. * @param string $js_conf text for the JS confirmation
  2905. *
  2906. * @return string html content
  2907. *
  2908. * @access private
  2909. *
  2910. * @see _getTableBody()
  2911. */
  2912. private function _getPlacedLinks(
  2913. $dir, $del_url, $is_display, $row_no, $where_clause, $where_clause_html,
  2914. $condition_array, $del_query, $dir_letter, $edit_url, $copy_url,
  2915. $edit_anchor_class, $edit_str, $copy_str, $del_str, $js_conf
  2916. ) {
  2917. if (! isset($js_conf)) {
  2918. $js_conf = '';
  2919. }
  2920. return $this->_getCheckboxAndLinks(
  2921. $dir, $del_url, $is_display,
  2922. $row_no, $where_clause, $where_clause_html, $condition_array,
  2923. $del_query, 'l', $edit_url, $copy_url, $edit_anchor_class,
  2924. $edit_str, $copy_str, $del_str, $js_conf
  2925. );
  2926. } // end of the '_getPlacedLinks()' function
  2927. /**
  2928. * Get the combined classes for a column
  2929. *
  2930. * @param string $grid_edit_class the class for all editable columns
  2931. * @param string $not_null_class the class for not null columns
  2932. * @param string $relation_class the class for relations in a column
  2933. * @param string $hide_class the class for visibility of a column
  2934. * @param string $field_type_class the class related to type of the field
  2935. * @param integer $row_no the row index
  2936. *
  2937. * @return string $class the combined classes
  2938. *
  2939. * @access private
  2940. *
  2941. * @see _getTableBody()
  2942. */
  2943. private function _getClassesForColumn(
  2944. $grid_edit_class, $not_null_class, $relation_class,
  2945. $hide_class, $field_type_class, $row_no
  2946. ) {
  2947. $printview = $this->__get('printview');
  2948. $class = 'data ' . $grid_edit_class . ' ' . $not_null_class . ' '
  2949. . $relation_class . ' ' . $hide_class . ' ' . $field_type_class;
  2950. if (($_SESSION['tmp_user_values']['disp_direction'] == self::DISP_DIR_VERTICAL)
  2951. && (! isset($printview) || ($printview != '1'))
  2952. ) {
  2953. // the row number corresponds to a data row, not HTML table row
  2954. $class .= ' row_' . $row_no;
  2955. if ($GLOBALS['cfg']['BrowsePointerEnable'] == true) {
  2956. $class .= ' vpointer';
  2957. }
  2958. if ($GLOBALS['cfg']['BrowseMarkerEnable'] == true) {
  2959. $class .= ' vmarker';
  2960. }
  2961. }
  2962. return $class;
  2963. } // end of the '_getClassesForColumn()' function
  2964. /**
  2965. * Get class for datetime related fields
  2966. *
  2967. * @param string $type the type of the column field
  2968. *
  2969. * @return string $field_type_class the class for the column
  2970. *
  2971. * @access private
  2972. *
  2973. * @see _getTableBody()
  2974. */
  2975. private function _getClassForDateTimeRelatedFields($type)
  2976. {
  2977. if ((substr($type, 0, 9) == self::TIMESTAMP_FIELD)
  2978. || ($type == self::DATETIME_FIELD)
  2979. ) {
  2980. $field_type_class = 'datetimefield';
  2981. } else if ($type == self::DATE_FIELD) {
  2982. $field_type_class = 'datefield';
  2983. } else {
  2984. $field_type_class = '';
  2985. }
  2986. return $field_type_class;
  2987. } // end of the '_getClassForDateTimeRelatedFields()' function
  2988. /**
  2989. * Prepare data cell for numeric type fields
  2990. *
  2991. * @param string $column the relavent column in data row
  2992. * @param string $class the html class for column
  2993. * @param boolean $condition_field the column should highlighted
  2994. * or not
  2995. * @param object $meta the meta-information about this
  2996. * field
  2997. * @param array $map the list of relations
  2998. * @param boolean $is_field_truncated the condition for blob data
  2999. * replacements
  3000. * @param array $analyzed_sql the analyzed query
  3001. * @param string $transformation_plugin the name of transformation plugin
  3002. * @param string $default_function the default transformation function
  3003. * @param string $transform_options the transformation parameters
  3004. *
  3005. * @return string $cell the prepared cell, html content
  3006. *
  3007. * @access private
  3008. *
  3009. * @see _getTableBody()
  3010. */
  3011. private function _getDataCellForNumericColumns(
  3012. $column, $class, $condition_field, $meta, $map, $is_field_truncated,
  3013. $analyzed_sql, $transformation_plugin, $default_function,
  3014. $transform_options
  3015. ) {
  3016. if (! isset($column) || is_null($column)) {
  3017. $cell = $this->_buildNullDisplay(
  3018. 'right '.$class, $condition_field, $meta, ''
  3019. );
  3020. } elseif ($column != '') {
  3021. $nowrap = ' nowrap';
  3022. $where_comparison = ' = ' . $column;
  3023. $cell = $this->_getRowData(
  3024. 'right '.$class, $condition_field,
  3025. $analyzed_sql, $meta, $map, $column,
  3026. $transformation_plugin, $default_function, $nowrap,
  3027. $where_comparison, $transform_options,
  3028. $is_field_truncated
  3029. );
  3030. } else {
  3031. $cell = $this->_buildEmptyDisplay(
  3032. 'right '.$class, $condition_field, $meta, ''
  3033. );
  3034. }
  3035. return $cell;
  3036. } // end of the '_getDataCellForNumericColumns()' function
  3037. /**
  3038. * Get data cell for blob type fields
  3039. *
  3040. * @param string $column the relavent column in data row
  3041. * @param string $class the html class for column
  3042. * @param object $meta the meta-information about this
  3043. * field
  3044. * @param array $_url_params the parameters for generate url
  3045. * @param string $field_flags field flags for column(blob,
  3046. * primary etc)
  3047. * @param string $transformation_plugin the name of transformation function
  3048. * @param string $default_function the default transformation function
  3049. * @param string $transform_options the transformation parameters
  3050. * @param boolean $condition_field the column should highlighted
  3051. * or not
  3052. * @param boolean $is_field_truncated the condition for blob data
  3053. * replacements
  3054. *
  3055. * @return string $cell the prepared cell, html content
  3056. *
  3057. * @access private
  3058. *
  3059. * @see _getTableBody()
  3060. */
  3061. private function _getDataCellForBlobColumns(
  3062. $column, $class, $meta, $_url_params, $field_flags, $transformation_plugin,
  3063. $default_function, $transform_options, $condition_field, $is_field_truncated
  3064. ) {
  3065. if (stristr($field_flags, self::BINARY_FIELD)) {
  3066. // remove 'grid_edit' from $class as we can't edit binary data.
  3067. $class = str_replace('grid_edit', '', $class);
  3068. if (! isset($column) || is_null($column)) {
  3069. $cell = $this->_buildNullDisplay($class, $condition_field, $meta);
  3070. } else {
  3071. $blobtext = $this->_handleNonPrintableContents(
  3072. self::BLOB_FIELD, (isset($column) ? $column : ''),
  3073. $transformation_plugin, $transform_options,
  3074. $default_function, $meta, $_url_params
  3075. );
  3076. $cell = $this->_buildValueDisplay(
  3077. $class, $condition_field, $blobtext
  3078. );
  3079. unset($blobtext);
  3080. }
  3081. } else {
  3082. // not binary:
  3083. if (! isset($column) || is_null($column)) {
  3084. $cell = $this->_buildNullDisplay($class, $condition_field, $meta);
  3085. } elseif ($column != '') {
  3086. // if a transform function for blob is set, none of these
  3087. // replacements will be made
  3088. if ((PMA_strlen($column) > $GLOBALS['cfg']['LimitChars'])
  3089. && ($_SESSION['tmp_user_values']['display_text'] == self::DISPLAY_PARTIAL_TEXT)
  3090. && ! $this->_isNeedToSyntaxHighlight(strtolower($meta->name))
  3091. ) {
  3092. $column = PMA_substr($column, 0, $GLOBALS['cfg']['LimitChars'])
  3093. . '...';
  3094. $is_field_truncated = true;
  3095. }
  3096. // displays all space characters, 4 space
  3097. // characters for tabulations and <cr>/<lf>
  3098. $column = ($default_function != $transformation_plugin)
  3099. ? $transformation_plugin->applyTransformation(
  3100. $column,
  3101. $transform_options,
  3102. $meta
  3103. )
  3104. : $this->$default_function($column, array(), $meta);
  3105. if ($is_field_truncated) {
  3106. $class .= ' truncated';
  3107. }
  3108. $cell = $this->_buildValueDisplay($class, $condition_field, $column);
  3109. } else {
  3110. $cell = $this->_buildEmptyDisplay($class, $condition_field, $meta);
  3111. }
  3112. }
  3113. return $cell;
  3114. } // end of the '_getDataCellForBlobColumns()' function
  3115. /**
  3116. * Get data cell for geometry type fields
  3117. *
  3118. * @param string $column the relavent column in data row
  3119. * @param string $class the html class for column
  3120. * @param object $meta the meta-information about this field
  3121. * @param array $map the list of relations
  3122. * @param array $_url_params the parameters for generate url
  3123. * @param boolean $condition_field the column should highlighted or not
  3124. * @param string $transformation_plugin the name of transformation function
  3125. * @param string $default_function the default transformation function
  3126. * @param string $transform_options the transformation parameters
  3127. * @param boolean $is_field_truncated the condition for blob data replacements
  3128. * @param array $analyzed_sql the analyzed query
  3129. *
  3130. * @return string $cell the prepared data cell, html content
  3131. *
  3132. * @access private
  3133. *
  3134. * @see _getTableBody()
  3135. */
  3136. private function _getDataCellForGeometryColumns(
  3137. $column, $class, $meta, $map, $_url_params, $condition_field,
  3138. $transformation_plugin, $default_function, $transform_options,
  3139. $is_field_truncated, $analyzed_sql
  3140. ) {
  3141. if (! isset($column) || is_null($column)) {
  3142. $cell = $this->_buildNullDisplay($class, $condition_field, $meta);
  3143. } elseif ($column != '') {
  3144. // Display as [GEOMETRY - (size)]
  3145. if ($_SESSION['tmp_user_values']['geometry_display'] == self::GEOMETRY_DISP_GEOM) {
  3146. $geometry_text = $this->_handleNonPrintableContents(
  3147. strtoupper(self::GEOMETRY_FIELD),
  3148. (isset($column) ? $column : ''), $transformation_plugin,
  3149. $transform_options, $default_function, $meta
  3150. );
  3151. $cell = $this->_buildValueDisplay(
  3152. $class, $condition_field, $geometry_text
  3153. );
  3154. } elseif ($_SESSION['tmp_user_values']['geometry_display']
  3155. == self::GEOMETRY_DISP_WKT
  3156. ) {
  3157. // Prepare in Well Known Text(WKT) format.
  3158. $where_comparison = ' = ' . $column;
  3159. // Convert to WKT format
  3160. $wktval = PMA_Util::asWKT($column);
  3161. if ((PMA_strlen($wktval) > $GLOBALS['cfg']['LimitChars'])
  3162. && ($_SESSION['tmp_user_values']['display_text'] == self::DISPLAY_PARTIAL_TEXT)
  3163. ) {
  3164. $wktval = PMA_substr($wktval, 0, $GLOBALS['cfg']['LimitChars'])
  3165. . '...';
  3166. $is_field_truncated = true;
  3167. }
  3168. $cell = $this->_getRowData(
  3169. $class, $condition_field, $analyzed_sql, $meta, $map,
  3170. $wktval, $transformation_plugin, $default_function, '',
  3171. $where_comparison, $transform_options,
  3172. $is_field_truncated
  3173. );
  3174. } else {
  3175. // Prepare in Well Known Binary (WKB) format.
  3176. if ($_SESSION['tmp_user_values']['display_binary']) {
  3177. $where_comparison = ' = ' . $column;
  3178. $wkbval = $this->_displayBinaryAsPrintable($column, 'binary', 8);
  3179. if ((PMA_strlen($wkbval) > $GLOBALS['cfg']['LimitChars'])
  3180. && ($_SESSION['tmp_user_values']['display_text'] == self::DISPLAY_PARTIAL_TEXT)
  3181. ) {
  3182. $wkbval
  3183. = PMA_substr($wkbval, 0, $GLOBALS['cfg']['LimitChars'])
  3184. . '...';
  3185. $is_field_truncated = true;
  3186. }
  3187. $cell = $this->_getRowData(
  3188. $class, $condition_field,
  3189. $analyzed_sql, $meta, $map, $wkbval,
  3190. $transformation_plugin, $default_function, '',
  3191. $where_comparison, $transform_options,
  3192. $is_field_truncated
  3193. );
  3194. } else {
  3195. $wkbval = $this->_handleNonPrintableContents(
  3196. self::BINARY_FIELD, $column, $transformation_plugin,
  3197. $transform_options, $default_function, $meta,
  3198. $_url_params
  3199. );
  3200. $cell = $this->_buildValueDisplay(
  3201. $class, $condition_field, $wkbval
  3202. );
  3203. }
  3204. }
  3205. } else {
  3206. $cell = $this->_buildEmptyDisplay($class, $condition_field, $meta);
  3207. }
  3208. return $cell;
  3209. } // end of the '_getDataCellForGeometryColumns()' function
  3210. /**
  3211. * Get data cell for non numeric and non blob type fields
  3212. *
  3213. * @param string $column the relavent column in data row
  3214. * @param string $class the html class for column
  3215. * @param object $meta the meta-information about the field
  3216. * @param array $map the list of relations
  3217. * @param array $_url_params the parameters for generate url
  3218. * @param boolean $condition_field the column should highlighted
  3219. * or not
  3220. * @param string $transformation_plugin the name of transformation function
  3221. * @param string $default_function the default transformation function
  3222. * @param string $transform_options the transformation parameters
  3223. * @param boolean $is_field_truncated the condition for blob data
  3224. * replacements
  3225. * @param array $analyzed_sql the analyzed query
  3226. * @param integer &$dt_result the link id associated to the query
  3227. * which results have to be displayed
  3228. * @param integer $col_index the column index
  3229. *
  3230. * @return string $cell the prepared data cell, html content
  3231. *
  3232. * @access private
  3233. *
  3234. * @see _getTableBody()
  3235. */
  3236. private function _getDataCellForNonNumericAndNonBlobColumns(
  3237. $column, $class, $meta, $map, $_url_params, $condition_field,
  3238. $transformation_plugin, $default_function, $transform_options,
  3239. $is_field_truncated, $analyzed_sql, &$dt_result, $col_index
  3240. ) {
  3241. $is_analyse = $this->__get('is_analyse');
  3242. $field_flags = PMA_DBI_field_flags($dt_result, $col_index);
  3243. if (stristr($field_flags, self::BINARY_FIELD)
  3244. && ($GLOBALS['cfg']['ProtectBinary'] == 'all'
  3245. || $GLOBALS['cfg']['ProtectBinary'] == 'noblob')
  3246. ) {
  3247. $class = str_replace('grid_edit', '', $class);
  3248. }
  3249. if (! isset($column) || is_null($column)) {
  3250. $cell = $this->_buildNullDisplay($class, $condition_field, $meta);
  3251. } elseif ($column != '') {
  3252. // Cut all fields to $GLOBALS['cfg']['LimitChars']
  3253. // (unless it's a link-type transformation)
  3254. if (PMA_strlen($column) > $GLOBALS['cfg']['LimitChars']
  3255. && ($_SESSION['tmp_user_values']['display_text'] == self::DISPLAY_PARTIAL_TEXT)
  3256. && ! (gettype($transformation_plugin) == "object"
  3257. && strpos($transformation_plugin->getName(), 'Link') !== false)
  3258. ) {
  3259. $column = PMA_substr($column, 0, $GLOBALS['cfg']['LimitChars'])
  3260. . '...';
  3261. $is_field_truncated = true;
  3262. }
  3263. $formatted = false;
  3264. if (isset($meta->_type) && $meta->_type === MYSQLI_TYPE_BIT) {
  3265. $column = PMA_Util::printableBitValue(
  3266. $column, $meta->length
  3267. );
  3268. // some results of PROCEDURE ANALYSE() are reported as
  3269. // being BINARY but they are quite readable,
  3270. // so don't treat them as BINARY
  3271. } elseif (stristr($field_flags, self::BINARY_FIELD)
  3272. && ($meta->type == self::STRING_FIELD)
  3273. && !(isset($is_analyse) && $is_analyse)
  3274. ) {
  3275. if ($_SESSION['tmp_user_values']['display_binary']) {
  3276. // user asked to see the real contents of BINARY
  3277. // fields
  3278. $column = $this->_displayBinaryAsPrintable($column, 'binary');
  3279. } else {
  3280. // we show the BINARY message and field's size
  3281. // (or maybe use a transformation)
  3282. $column = $this->_handleNonPrintableContents(
  3283. self::BINARY_FIELD, $column, $transformation_plugin,
  3284. $transform_options, $default_function,
  3285. $meta, $_url_params
  3286. );
  3287. $formatted = true;
  3288. }
  3289. }
  3290. if ($formatted) {
  3291. $cell = $this->_buildValueDisplay(
  3292. $class, $condition_field, $column
  3293. );
  3294. } else {
  3295. // transform functions may enable no-wrapping:
  3296. $function_nowrap = 'applyTransformationNoWrap';
  3297. $bool_nowrap = (($default_function != $transformation_plugin)
  3298. && function_exists($transformation_plugin->$function_nowrap()))
  3299. ? $transformation_plugin->$function_nowrap($transform_options)
  3300. : false;
  3301. // do not wrap if date field type
  3302. $nowrap = (preg_match('@DATE|TIME@i', $meta->type)
  3303. || $bool_nowrap) ? ' nowrap' : '';
  3304. $where_comparison = ' = \''
  3305. . PMA_Util::sqlAddSlashes($column)
  3306. . '\'';
  3307. $cell = $this->_getRowData(
  3308. $class, $condition_field,
  3309. $analyzed_sql, $meta, $map, $column,
  3310. $transformation_plugin, $default_function, $nowrap,
  3311. $where_comparison, $transform_options,
  3312. $is_field_truncated
  3313. );
  3314. }
  3315. } else {
  3316. $cell = $this->_buildEmptyDisplay($class, $condition_field, $meta);
  3317. }
  3318. return $cell;
  3319. } // end of the '_getDataCellForNonNumericAndNonBlobColumns()' function
  3320. /**
  3321. * Get the resulted table with the vertical direction mode.
  3322. *
  3323. * @param array $analyzed_sql the analyzed query
  3324. * @param array $is_display display mode
  3325. *
  3326. * @return string html content
  3327. *
  3328. * @access private
  3329. *
  3330. * @see _getTable()
  3331. */
  3332. private function _getVerticalTable($analyzed_sql, $is_display)
  3333. {
  3334. $vertical_table_html = '';
  3335. $vertical_display = $this->__get('vertical_display');
  3336. // Prepares "multi row delete" link at top if required
  3337. if (($GLOBALS['cfg']['RowActionLinks'] != self::POSITION_RIGHT)
  3338. && is_array($vertical_display['row_delete'])
  3339. && ((count($vertical_display['row_delete']) > 0)
  3340. || !empty($vertical_display['textbtn']))
  3341. ) {
  3342. $vertical_table_html .= '<tr>' . "\n";
  3343. if ($GLOBALS['cfg']['RowActionLinks'] == self::POSITION_NONE) {
  3344. // if we are not showing the RowActionLinks, then we need to show
  3345. // the Multi-Row-Action checkboxes
  3346. $vertical_table_html .= '<th></th>' . "\n";
  3347. }
  3348. $vertical_table_html .= $vertical_display['textbtn']
  3349. . $this->_getCheckBoxesForMultipleRowOperations('_left', $is_display)
  3350. . '</tr>' . "\n";
  3351. } // end if
  3352. // Prepares "edit" link at top if required
  3353. if ((($GLOBALS['cfg']['RowActionLinks'] == self::POSITION_LEFT)
  3354. || ($GLOBALS['cfg']['RowActionLinks'] == self::POSITION_BOTH))
  3355. && is_array($vertical_display['edit'])
  3356. && ((count($vertical_display['edit']) > 0)
  3357. || !empty($vertical_display['textbtn']))
  3358. ) {
  3359. $vertical_table_html .= $this->_getOperationLinksForVerticleTable(
  3360. 'edit'
  3361. );
  3362. } // end if
  3363. // Prepares "copy" link at top if required
  3364. if ((($GLOBALS['cfg']['RowActionLinks'] == self::POSITION_LEFT)
  3365. || ($GLOBALS['cfg']['RowActionLinks'] == self::POSITION_BOTH))
  3366. && is_array($vertical_display['copy'])
  3367. && ((count($vertical_display['copy']) > 0)
  3368. || !empty($vertical_display['textbtn']))
  3369. ) {
  3370. $vertical_table_html .= $this->_getOperationLinksForVerticleTable(
  3371. 'copy'
  3372. );
  3373. } // end if
  3374. // Prepares "delete" link at top if required
  3375. if ((($GLOBALS['cfg']['RowActionLinks'] == self::POSITION_LEFT)
  3376. || ($GLOBALS['cfg']['RowActionLinks'] == self::POSITION_BOTH))
  3377. && is_array($vertical_display['delete'])
  3378. && ((count($vertical_display['delete']) > 0)
  3379. || !empty($vertical_display['textbtn']))
  3380. ) {
  3381. $vertical_table_html .= $this->_getOperationLinksForVerticleTable(
  3382. 'delete'
  3383. );
  3384. } // end if
  3385. list($col_order, $col_visib) = $this->_getColumnParams($analyzed_sql);
  3386. // Prepares data
  3387. foreach ($vertical_display['desc'] AS $j => $val) {
  3388. // assign appropriate key with current column order
  3389. $key = $col_order ? $col_order[$j] : $j;
  3390. $vertical_table_html .= '<tr'
  3391. . (($col_visib && !$col_visib[$j]) ? ' class="hide"' : '')
  3392. . '>' . "\n"
  3393. . $val;
  3394. $cell_displayed = 0;
  3395. foreach ($vertical_display['rowdata'][$key] as $subval) {
  3396. if (($cell_displayed != 0)
  3397. && ($_SESSION['tmp_user_values']['repeat_cells'] != 0)
  3398. && ! ($cell_displayed % $_SESSION['tmp_user_values']['repeat_cells'])
  3399. ) {
  3400. $vertical_table_html .= $val;
  3401. }
  3402. $vertical_table_html .= $subval;
  3403. $cell_displayed++;
  3404. } // end while
  3405. $vertical_table_html .= '</tr>' . "\n";
  3406. } // end while
  3407. // Prepares "multi row delete" link at bottom if required
  3408. if ((($GLOBALS['cfg']['RowActionLinks'] == self::POSITION_RIGHT)
  3409. || ($GLOBALS['cfg']['RowActionLinks'] == self::POSITION_BOTH))
  3410. && is_array($vertical_display['row_delete'])
  3411. && ((count($vertical_display['row_delete']) > 0)
  3412. || !empty($vertical_display['textbtn']))
  3413. ) {
  3414. $vertical_table_html .= '<tr>' . "\n"
  3415. . $vertical_display['textbtn']
  3416. . $this->_getCheckBoxesForMultipleRowOperations('_right', $is_display)
  3417. . '</tr>' . "\n";
  3418. } // end if
  3419. // Prepares "edit" link at bottom if required
  3420. if ((($GLOBALS['cfg']['RowActionLinks'] == self::POSITION_RIGHT)
  3421. || ($GLOBALS['cfg']['RowActionLinks'] == self::POSITION_BOTH))
  3422. && is_array($vertical_display['edit'])
  3423. && ((count($vertical_display['edit']) > 0)
  3424. || !empty($vertical_display['textbtn']))
  3425. ) {
  3426. $vertical_table_html .= $this->_getOperationLinksForVerticleTable(
  3427. 'edit'
  3428. );
  3429. } // end if
  3430. // Prepares "copy" link at bottom if required
  3431. if ((($GLOBALS['cfg']['RowActionLinks'] == self::POSITION_RIGHT)
  3432. || ($GLOBALS['cfg']['RowActionLinks'] == self::POSITION_BOTH))
  3433. && is_array($vertical_display['copy'])
  3434. && ((count($vertical_display['copy']) > 0)
  3435. || !empty($vertical_display['textbtn']))
  3436. ) {
  3437. $vertical_table_html .= $this->_getOperationLinksForVerticleTable(
  3438. 'copy'
  3439. );
  3440. } // end if
  3441. // Prepares "delete" link at bottom if required
  3442. if ((($GLOBALS['cfg']['RowActionLinks'] == self::POSITION_RIGHT)
  3443. || ($GLOBALS['cfg']['RowActionLinks'] == self::POSITION_BOTH))
  3444. && is_array($vertical_display['delete'])
  3445. && ((count($vertical_display['delete']) > 0)
  3446. || !empty($vertical_display['textbtn']))
  3447. ) {
  3448. $vertical_table_html .= $this->_getOperationLinksForVerticleTable(
  3449. 'delete'
  3450. );
  3451. }
  3452. return $vertical_table_html;
  3453. } // end of the '_getVerticalTable' function
  3454. /**
  3455. * Prepare edit, copy and delete links for verticle table
  3456. *
  3457. * @param string $operation edit/copy/delete
  3458. *
  3459. * @return string $links_html html content
  3460. *
  3461. * @access private
  3462. *
  3463. * @see _getVerticalTable()
  3464. */
  3465. private function _getOperationLinksForVerticleTable($operation)
  3466. {
  3467. $link_html = '<tr>' . "\n";
  3468. $vertical_display = $this->__get('vertical_display');
  3469. if (! is_array($vertical_display['row_delete'])) {
  3470. if (($operation == 'edit') || ($operation == 'copy')) {
  3471. $link_html .= $vertical_display['textbtn'];
  3472. } elseif ($operation == 'delete') {
  3473. if (! is_array($vertical_display['edit'])) {
  3474. $link_html .= $vertical_display['textbtn'];
  3475. }
  3476. }
  3477. }
  3478. foreach ($vertical_display[$operation] as $val) {
  3479. $link_html .= $val;
  3480. } // end while
  3481. $link_html .= '</tr>' . "\n";
  3482. return $link_html;
  3483. } // end of the '_getOperationLinksForVerticleTable' function
  3484. /**
  3485. * Get checkboxes for multiple row data operations
  3486. *
  3487. * @param string $dir _left / _right
  3488. * @param array $is_display display mode
  3489. *
  3490. * @return $checkBoxes_html html content
  3491. *
  3492. * @access private
  3493. *
  3494. * @see _getVerticalTable()
  3495. */
  3496. private function _getCheckBoxesForMultipleRowOperations($dir, $is_display)
  3497. {
  3498. $checkBoxes_html = '';
  3499. $cell_displayed = 0;
  3500. $vertical_display = $this->__get('vertical_display');
  3501. foreach ($vertical_display['row_delete'] as $val) {
  3502. if (($cell_displayed != 0)
  3503. && ($_SESSION['tmp_user_values']['repeat_cells'] != 0)
  3504. && !($cell_displayed % $_SESSION['tmp_user_values']['repeat_cells'])
  3505. ) {
  3506. $checkBoxes_html .= '<th'
  3507. . (($is_display['edit_lnk'] != self::NO_EDIT_OR_DELETE)
  3508. && ($is_display['del_lnk'] != self::NO_EDIT_OR_DELETE))
  3509. ? ' rowspan="4"'
  3510. : ''
  3511. . '></th>' . "\n";
  3512. }
  3513. $checkBoxes_html .= str_replace('[%_PMA_CHECKBOX_DIR_%]', $dir, $val);
  3514. $cell_displayed++;
  3515. } // end while
  3516. return $checkBoxes_html;
  3517. } // end of the '_getCheckBoxesForMultipleRowOperations' function
  3518. /**
  3519. * Checks the posted options for viewing query resutls
  3520. * and sets appropriate values in the session.
  3521. *
  3522. * @todo make maximum remembered queries configurable
  3523. * @todo move/split into SQL class!?
  3524. * @todo currently this is called twice unnecessary
  3525. * @todo ignore LIMIT and ORDER in query!?
  3526. *
  3527. * @return void
  3528. *
  3529. * @access public
  3530. *
  3531. * @see sql.php file
  3532. */
  3533. public function setConfigParamsForDisplayTable()
  3534. {
  3535. $sql_md5 = md5($this->__get('sql_query'));
  3536. $_SESSION['tmp_user_values']['query'][$sql_md5]['sql']
  3537. = $this->__get('sql_query');
  3538. $valid_disp_dir = PMA_isValid(
  3539. $_REQUEST['disp_direction'],
  3540. array(self::DISP_DIR_HORIZONTAL, self::DISP_DIR_VERTICAL,
  3541. self::DISP_DIR_HORIZONTAL_FLIPPED
  3542. )
  3543. );
  3544. if ($valid_disp_dir) {
  3545. $_SESSION['tmp_user_values']['query'][$sql_md5]['disp_direction']
  3546. = $_REQUEST['disp_direction'];
  3547. unset($_REQUEST['disp_direction']);
  3548. } elseif (
  3549. empty($_SESSION['tmp_user_values']['query'][$sql_md5]['disp_direction'])
  3550. ) {
  3551. $_SESSION['tmp_user_values']['query'][$sql_md5]['disp_direction']
  3552. = $GLOBALS['cfg']['DefaultDisplay'];
  3553. }
  3554. if (PMA_isValid($_REQUEST['repeat_cells'], 'numeric')) {
  3555. $_SESSION['tmp_user_values']['query'][$sql_md5]['repeat_cells']
  3556. = $_REQUEST['repeat_cells'];
  3557. unset($_REQUEST['repeat_cells']);
  3558. } elseif (
  3559. empty($_SESSION['tmp_user_values']['query'][$sql_md5]['repeat_cells'])
  3560. ) {
  3561. $_SESSION['tmp_user_values']['query'][$sql_md5]['repeat_cells']
  3562. = $GLOBALS['cfg']['RepeatCells'];
  3563. }
  3564. // as this is a form value, the type is always string so we cannot
  3565. // use PMA_isValid($_REQUEST['session_max_rows'], 'integer')
  3566. if ((PMA_isValid($_REQUEST['session_max_rows'], 'numeric')
  3567. && ((int) $_REQUEST['session_max_rows'] == $_REQUEST['session_max_rows']))
  3568. || ($_REQUEST['session_max_rows'] == self::ALL_ROWS)
  3569. ) {
  3570. $_SESSION['tmp_user_values']['query'][$sql_md5]['max_rows']
  3571. = $_REQUEST['session_max_rows'];
  3572. unset($_REQUEST['session_max_rows']);
  3573. } elseif (empty($_SESSION['tmp_user_values']['query'][$sql_md5]['max_rows'])) {
  3574. $_SESSION['tmp_user_values']['query'][$sql_md5]['max_rows']
  3575. = $GLOBALS['cfg']['MaxRows'];
  3576. }
  3577. if (PMA_isValid($_REQUEST['pos'], 'numeric')) {
  3578. $_SESSION['tmp_user_values']['query'][$sql_md5]['pos']
  3579. = $_REQUEST['pos'];
  3580. unset($_REQUEST['pos']);
  3581. } elseif (empty($_SESSION['tmp_user_values']['query'][$sql_md5]['pos'])) {
  3582. $_SESSION['tmp_user_values']['query'][$sql_md5]['pos'] = 0;
  3583. }
  3584. if (PMA_isValid(
  3585. $_REQUEST['display_text'],
  3586. array(
  3587. self::DISPLAY_PARTIAL_TEXT, self::DISPLAY_FULL_TEXT
  3588. )
  3589. )
  3590. ) {
  3591. $_SESSION['tmp_user_values']['query'][$sql_md5]['display_text']
  3592. = $_REQUEST['display_text'];
  3593. unset($_REQUEST['display_text']);
  3594. } elseif (
  3595. empty($_SESSION['tmp_user_values']['query'][$sql_md5]['display_text'])
  3596. ) {
  3597. $_SESSION['tmp_user_values']['query'][$sql_md5]['display_text']
  3598. = self::DISPLAY_PARTIAL_TEXT;
  3599. }
  3600. if (PMA_isValid(
  3601. $_REQUEST['relational_display'],
  3602. array(
  3603. self::RELATIONAL_KEY, self::RELATIONAL_DISPLAY_COLUMN
  3604. )
  3605. )
  3606. ) {
  3607. $_SESSION['tmp_user_values']['query'][$sql_md5]['relational_display']
  3608. = $_REQUEST['relational_display'];
  3609. unset($_REQUEST['relational_display']);
  3610. } elseif (
  3611. empty(
  3612. $_SESSION['tmp_user_values']['query'][$sql_md5]['relational_display']
  3613. )
  3614. ) {
  3615. $_SESSION['tmp_user_values']['query'][$sql_md5]['relational_display']
  3616. = self::RELATIONAL_KEY;
  3617. }
  3618. if (PMA_isValid(
  3619. $_REQUEST['geometry_display'],
  3620. array(
  3621. self::GEOMETRY_DISP_WKT, self::GEOMETRY_DISP_WKB,
  3622. self::GEOMETRY_DISP_GEOM
  3623. )
  3624. )
  3625. ) {
  3626. $_SESSION['tmp_user_values']['query'][$sql_md5]['geometry_display']
  3627. = $_REQUEST['geometry_display'];
  3628. unset($_REQUEST['geometry_display']);
  3629. } elseif (
  3630. empty(
  3631. $_SESSION['tmp_user_values']['query'][$sql_md5]['geometry_display']
  3632. )
  3633. ) {
  3634. $_SESSION['tmp_user_values']['query'][$sql_md5]['geometry_display']
  3635. = self::GEOMETRY_DISP_GEOM;
  3636. }
  3637. if (isset($_REQUEST['display_binary'])) {
  3638. $_SESSION['tmp_user_values']['query'][$sql_md5]['display_binary'] = true;
  3639. unset($_REQUEST['display_binary']);
  3640. } elseif (isset($_REQUEST['display_options_form'])) {
  3641. // we know that the checkbox was unchecked
  3642. unset($_SESSION['tmp_user_values']['query'][$sql_md5]['display_binary']);
  3643. } elseif (isset($_REQUEST['full_text_button'])) {
  3644. // do nothing to keep the value that is there in the session
  3645. } else {
  3646. // selected by default because some operations like OPTIMIZE TABLE
  3647. // and all queries involving functions return "binary" contents,
  3648. // according to low-level field flags
  3649. $_SESSION['tmp_user_values']['query'][$sql_md5]['display_binary'] = true;
  3650. }
  3651. if (isset($_REQUEST['display_binary_as_hex'])) {
  3652. $_SESSION['tmp_user_values']['query'][$sql_md5]['display_binary_as_hex']
  3653. = true;
  3654. unset($_REQUEST['display_binary_as_hex']);
  3655. } elseif (isset($_REQUEST['display_options_form'])) {
  3656. // we know that the checkbox was unchecked
  3657. unset($_SESSION['tmp_user_values']['query'][$sql_md5]
  3658. ['display_binary_as_hex']
  3659. );
  3660. } elseif (isset($_REQUEST['full_text_button'])) {
  3661. // do nothing to keep the value that is there in the session
  3662. } else {
  3663. // display_binary_as_hex config option
  3664. if (isset($GLOBALS['cfg']['DisplayBinaryAsHex'])
  3665. && ($GLOBALS['cfg']['DisplayBinaryAsHex'] === true)
  3666. ) {
  3667. $_SESSION['tmp_user_values']['query'][$sql_md5]
  3668. ['display_binary_as_hex'] = true;
  3669. }
  3670. }
  3671. if (isset($_REQUEST['display_blob'])) {
  3672. $_SESSION['tmp_user_values']['query'][$sql_md5]['display_blob'] = true;
  3673. unset($_REQUEST['display_blob']);
  3674. } elseif (isset($_REQUEST['display_options_form'])) {
  3675. // we know that the checkbox was unchecked
  3676. unset($_SESSION['tmp_user_values']['query'][$sql_md5]['display_blob']);
  3677. }
  3678. if (isset($_REQUEST['hide_transformation'])) {
  3679. $_SESSION['tmp_user_values']['query'][$sql_md5]['hide_transformation']
  3680. = true;
  3681. unset($_REQUEST['hide_transformation']);
  3682. } elseif (isset($_REQUEST['display_options_form'])) {
  3683. // we know that the checkbox was unchecked
  3684. unset($_SESSION['tmp_user_values']['query'][$sql_md5]
  3685. ['hide_transformation']
  3686. );
  3687. }
  3688. // move current query to the last position, to be removed last
  3689. // so only least executed query will be removed if maximum remembered queries
  3690. // limit is reached
  3691. $tmp = $_SESSION['tmp_user_values']['query'][$sql_md5];
  3692. unset($_SESSION['tmp_user_values']['query'][$sql_md5]);
  3693. $_SESSION['tmp_user_values']['query'][$sql_md5] = $tmp;
  3694. // do not exceed a maximum number of queries to remember
  3695. if (count($_SESSION['tmp_user_values']['query']) > 10) {
  3696. array_shift($_SESSION['tmp_user_values']['query']);
  3697. //echo 'deleting one element ...';
  3698. }
  3699. // populate query configuration
  3700. $_SESSION['tmp_user_values']['display_text']
  3701. = $_SESSION['tmp_user_values']['query'][$sql_md5]['display_text'];
  3702. $_SESSION['tmp_user_values']['relational_display']
  3703. = $_SESSION['tmp_user_values']['query'][$sql_md5]['relational_display'];
  3704. $_SESSION['tmp_user_values']['geometry_display']
  3705. = $_SESSION['tmp_user_values']['query'][$sql_md5]['geometry_display'];
  3706. $_SESSION['tmp_user_values']['display_binary']
  3707. = isset($_SESSION['tmp_user_values']['query'][$sql_md5]
  3708. ['display_binary']
  3709. )
  3710. ? true
  3711. : false;
  3712. $_SESSION['tmp_user_values']['display_binary_as_hex']
  3713. = isset($_SESSION['tmp_user_values']['query'][$sql_md5]
  3714. ['display_binary_as_hex']
  3715. )
  3716. ? true
  3717. : false;
  3718. $_SESSION['tmp_user_values']['display_blob']
  3719. = isset($_SESSION['tmp_user_values']['query'][$sql_md5]['display_blob'])
  3720. ? true
  3721. : false;
  3722. $_SESSION['tmp_user_values']['hide_transformation']
  3723. = isset($_SESSION['tmp_user_values']['query'][$sql_md5]
  3724. ['hide_transformation']
  3725. )
  3726. ? true
  3727. : false;
  3728. $_SESSION['tmp_user_values']['pos']
  3729. = $_SESSION['tmp_user_values']['query'][$sql_md5]['pos'];
  3730. $_SESSION['tmp_user_values']['max_rows']
  3731. = $_SESSION['tmp_user_values']['query'][$sql_md5]['max_rows'];
  3732. $_SESSION['tmp_user_values']['repeat_cells']
  3733. = $_SESSION['tmp_user_values']['query'][$sql_md5]['repeat_cells'];
  3734. $_SESSION['tmp_user_values']['disp_direction']
  3735. = $_SESSION['tmp_user_values']['query'][$sql_md5]['disp_direction'];
  3736. }
  3737. /**
  3738. * Prepare a table of results returned by a SQL query.
  3739. * This function is called by the "sql.php" script.
  3740. *
  3741. * @param integer &$dt_result the link id associated to the query
  3742. * which results have to be displayed
  3743. * @param array &$the_disp_mode the display mode
  3744. * @param array $analyzed_sql the analyzed query
  3745. * @param boolean $is_limited_display With limited operations or not
  3746. *
  3747. * @return string $table_html Generated HTML content for resulted table
  3748. *
  3749. * @access public
  3750. *
  3751. * @see sql.php file
  3752. */
  3753. public function getTable(
  3754. &$dt_result, &$the_disp_mode, $analyzed_sql, $is_limited_display = false
  3755. ) {
  3756. $table_html = '';
  3757. // Following variable are needed for use in isset/empty or
  3758. // use with array indexes/safe use in foreach
  3759. $fields_meta = $this->__get('fields_meta');
  3760. $showtable = $this->__get('showtable');
  3761. $printview = $this->__get('printview');
  3762. // why was this called here? (already called from sql.php)
  3763. //$this->setConfigParamsForDisplayTable();
  3764. /**
  3765. * @todo move this to a central place
  3766. * @todo for other future table types
  3767. */
  3768. $is_innodb = (isset($showtable['Type'])
  3769. && $showtable['Type'] == self::TABLE_TYPE_INNO_DB);
  3770. if ($is_innodb
  3771. && ! isset($analyzed_sql[0]['queryflags']['union'])
  3772. && ! isset($analyzed_sql[0]['table_ref'][1]['table_name'])
  3773. && (empty($analyzed_sql[0]['where_clause'])
  3774. || ($analyzed_sql[0]['where_clause'] == '1 '))
  3775. ) {
  3776. // "j u s t b r o w s i n g"
  3777. $pre_count = '~';
  3778. $after_count = PMA_Util::showHint(
  3779. PMA_sanitize(
  3780. __('May be approximate. See [doc@faq3-11]FAQ 3.11[/doc]')
  3781. )
  3782. );
  3783. } else {
  3784. $pre_count = '';
  3785. $after_count = '';
  3786. }
  3787. // 1. ----- Prepares the work -----
  3788. // 1.1 Gets the informations about which functionalities should be
  3789. // displayed
  3790. $total = '';
  3791. $is_display = $this->_setDisplayMode($the_disp_mode, $total);
  3792. // 1.2 Defines offsets for the next and previous pages
  3793. if ($is_display['nav_bar'] == '1') {
  3794. list($pos_next, $pos_prev) = $this->_getOffsets();
  3795. } // end if
  3796. if (!isset($analyzed_sql[0]['order_by_clause'])) {
  3797. $analyzed_sql[0]['order_by_clause'] = "";
  3798. }
  3799. // 1.3 Find the sort expression
  3800. // we need $sort_expression and $sort_expression_nodirection
  3801. // even if there are many table references
  3802. list($sort_expression, $sort_expression_nodirection, $sort_direction)
  3803. = $this->_getSortParams($analyzed_sql[0]['order_by_clause']);
  3804. // 1.4 Prepares display of first and last value of the sorted column
  3805. $sorted_column_message = $this->_getSortedColumnMessage(
  3806. $dt_result, $sort_expression_nodirection
  3807. );
  3808. // 2. ----- Prepare to display the top of the page -----
  3809. // 2.1 Prepares a messages with position informations
  3810. if (($is_display['nav_bar'] == '1') && isset($pos_next)) {
  3811. $message = $this->_setMessageInformation(
  3812. $sorted_column_message, $analyzed_sql[0]['limit_clause'],
  3813. $total, $pos_next, $pre_count, $after_count
  3814. );
  3815. $table_html .= PMA_Util::getMessage(
  3816. $message, $this->__get('sql_query'), 'success'
  3817. );
  3818. } elseif (! isset($printview) || ($printview != '1')) {
  3819. $table_html .= PMA_Util::getMessage(
  3820. __('Your SQL query has been executed successfully'),
  3821. $this->__get('sql_query'), 'success'
  3822. );
  3823. }
  3824. // 2.3 Prepare the navigation bars
  3825. if (! strlen($this->__get('table'))) {
  3826. if (isset($analyzed_sql[0]['query_type'])
  3827. && ($analyzed_sql[0]['query_type'] == self::QUERY_TYPE_SELECT)
  3828. ) {
  3829. // table does not always contain a real table name,
  3830. // for example in MySQL 5.0.x, the query SHOW STATUS
  3831. // returns STATUS as a table name
  3832. $this->__set('table', $fields_meta[0]->table);
  3833. } else {
  3834. $this->__set('table', '');
  3835. }
  3836. }
  3837. if (($is_display['nav_bar'] == '1')
  3838. && empty($analyzed_sql[0]['limit_clause'])
  3839. ) {
  3840. $table_html .= $this->_getPlacedTableNavigatoins(
  3841. $pos_next, $pos_prev, self::PLACE_TOP_DIRECTION_DROPDOWN,
  3842. "\n", $is_innodb
  3843. );
  3844. } elseif (! isset($printview) || ($printview != '1')) {
  3845. $table_html .= "\n" . '<br /><br />' . "\n";
  3846. }
  3847. // 2b ----- Get field references from Database -----
  3848. // (see the 'relation' configuration variable)
  3849. // initialize map
  3850. $map = array();
  3851. // find tables
  3852. $target=array();
  3853. if (isset($analyzed_sql[0]['table_ref'])
  3854. && is_array($analyzed_sql[0]['table_ref'])
  3855. ) {
  3856. foreach ($analyzed_sql[0]['table_ref']
  3857. as $table_ref_position => $table_ref) {
  3858. $target[] = $analyzed_sql[0]['table_ref']
  3859. [$table_ref_position]['table_true_name'];
  3860. }
  3861. }
  3862. $tabs = '(\'' . join('\',\'', $target) . '\')';
  3863. if (! strlen($this->__get('table'))) {
  3864. $exist_rel = false;
  3865. } else {
  3866. // This method set the values for $map array
  3867. $this->_setParamForLinkForeignKeyRelatedTables($map);
  3868. } // end if
  3869. // end 2b
  3870. // 3. ----- Prepare the results table -----
  3871. $table_html .= $this->_getTableHeaders(
  3872. $is_display, $analyzed_sql, $sort_expression,
  3873. $sort_expression_nodirection, $sort_direction, $is_limited_display
  3874. )
  3875. . '<tbody>' . "\n";
  3876. $url_query = '';
  3877. $table_html .= $this->_getTableBody(
  3878. $dt_result, $is_display, $map, $analyzed_sql, $is_limited_display
  3879. );
  3880. // vertical output case
  3881. if ($_SESSION['tmp_user_values']['disp_direction'] == self::DISP_DIR_VERTICAL) {
  3882. $table_html .= $this->_getVerticalTable($analyzed_sql, $is_display);
  3883. } // end if
  3884. $this->__set('vertical_display', null);
  3885. $table_html .= '</tbody>' . "\n"
  3886. . '</table>';
  3887. // 4. ----- Prepares the link for multi-fields edit and delete
  3888. if ($is_display['del_lnk'] == self::DELETE_ROW
  3889. && $is_display['del_lnk'] != self::KILL_PROCESS
  3890. ) {
  3891. $table_html .= $this->_getMultiRowOperationLinks(
  3892. $dt_result, $analyzed_sql, $is_display['del_lnk']
  3893. );
  3894. }
  3895. // 5. ----- Get the navigation bar at the bottom if required -----
  3896. if (($is_display['nav_bar'] == '1')
  3897. && empty($analyzed_sql[0]['limit_clause'])
  3898. ) {
  3899. $table_html .= $this->_getPlacedTableNavigatoins(
  3900. $pos_next, $pos_prev, self::PLACE_BOTTOM_DIRECTION_DROPDOWN,
  3901. '<br />' . "\n", $is_innodb
  3902. );
  3903. } elseif (! isset($printview) || ($printview != '1')) {
  3904. $table_html .= "\n" . '<br /><br />' . "\n";
  3905. }
  3906. // 6. ----- Prepare "Query results operations"
  3907. if ((! isset($printview) || ($printview != '1')) && ! $is_limited_display) {
  3908. $table_html .= $this->_getResultsOperations(
  3909. $the_disp_mode, $analyzed_sql
  3910. );
  3911. }
  3912. return $table_html;
  3913. } // end of the 'getTable()' function
  3914. /**
  3915. * Get offsets for next page and previous page
  3916. *
  3917. * @return array array with two elements - $pos_next, $pos_prev
  3918. *
  3919. * @access private
  3920. *
  3921. * @see getTable()
  3922. */
  3923. private function _getOffsets()
  3924. {
  3925. if ($_SESSION['tmp_user_values']['max_rows'] == self::ALL_ROWS) {
  3926. $pos_next = 0;
  3927. $pos_prev = 0;
  3928. } else {
  3929. $pos_next = $_SESSION['tmp_user_values']['pos']
  3930. + $_SESSION['tmp_user_values']['max_rows'];
  3931. $pos_prev = $_SESSION['tmp_user_values']['pos']
  3932. - $_SESSION['tmp_user_values']['max_rows'];
  3933. if ($pos_prev < 0) {
  3934. $pos_prev = 0;
  3935. }
  3936. }
  3937. return array($pos_next, $pos_prev);
  3938. } // end of the '_getOffsets()' function
  3939. /**
  3940. * Get sort parameters
  3941. *
  3942. * @param string $order_by_clause the order by clause of the sql query
  3943. *
  3944. * @return array 3 element array: $sort_expression,
  3945. * $sort_expression_nodirection, $sort_direction
  3946. *
  3947. * @access private
  3948. *
  3949. * @see getTable()
  3950. */
  3951. private function _getSortParams($order_by_clause)
  3952. {
  3953. if (! empty($order_by_clause)) {
  3954. $sort_expression = trim(
  3955. str_replace(' ', ' ', $order_by_clause)
  3956. );
  3957. /**
  3958. * Get rid of ASC|DESC
  3959. */
  3960. preg_match(
  3961. '@(.*)([[:space:]]*(ASC|DESC))@si', $sort_expression, $matches
  3962. );
  3963. $sort_expression_nodirection = isset($matches[1])
  3964. ? trim($matches[1])
  3965. : $sort_expression;
  3966. $sort_direction = isset($matches[2]) ? trim($matches[2]) : '';
  3967. unset($matches);
  3968. } else {
  3969. $sort_expression = $sort_expression_nodirection = $sort_direction = '';
  3970. }
  3971. return array($sort_expression, $sort_expression_nodirection,
  3972. $sort_direction
  3973. );
  3974. } // end of the '_getSortParams()' function
  3975. /**
  3976. * Prepare sorted column message
  3977. *
  3978. * @param integer &$dt_result the link id associated to the
  3979. * query which results have to
  3980. * be displayed
  3981. * @param string $sort_expression_nodirection sort expression without direction
  3982. *
  3983. * @return string html content
  3984. * null if not found sorted column
  3985. *
  3986. * @access private
  3987. *
  3988. * @see getTable()
  3989. */
  3990. private function _getSortedColumnMessage(
  3991. &$dt_result, $sort_expression_nodirection
  3992. ) {
  3993. $fields_meta = $this->__get('fields_meta'); // To use array indexes
  3994. if (! empty($sort_expression_nodirection)) {
  3995. if (strpos($sort_expression_nodirection, '.') === false) {
  3996. $sort_table = $this->__get('table');
  3997. $sort_column = $sort_expression_nodirection;
  3998. } else {
  3999. list($sort_table, $sort_column)
  4000. = explode('.', $sort_expression_nodirection);
  4001. }
  4002. $sort_table = PMA_Util::unQuote($sort_table);
  4003. $sort_column = PMA_Util::unQuote($sort_column);
  4004. // find the sorted column index in row result
  4005. // (this might be a multi-table query)
  4006. $sorted_column_index = false;
  4007. foreach ($fields_meta as $key => $meta) {
  4008. if (($meta->table == $sort_table) && ($meta->name == $sort_column)) {
  4009. $sorted_column_index = $key;
  4010. break;
  4011. }
  4012. }
  4013. if ($sorted_column_index !== false) {
  4014. // fetch first row of the result set
  4015. $row = PMA_DBI_fetch_row($dt_result);
  4016. // initializing default arguments
  4017. $default_function = '_mimeDefaultFunction';
  4018. $transformation_plugin = $default_function;
  4019. $transform_options = array();
  4020. // check for non printable sorted row data
  4021. $meta = $fields_meta[$sorted_column_index];
  4022. if (stristr($meta->type, self::BLOB_FIELD)
  4023. || ($meta->type == self::GEOMETRY_FIELD)
  4024. ) {
  4025. $column_for_first_row = $this->_handleNonPrintableContents(
  4026. $meta->type, $row[$sorted_column_index],
  4027. $transformation_plugin, $transform_options,
  4028. $default_function, $meta, null
  4029. );
  4030. } else {
  4031. $column_for_first_row = $row[$sorted_column_index];
  4032. }
  4033. $column_for_first_row = strtoupper(
  4034. substr($column_for_first_row, 0, $GLOBALS['cfg']['LimitChars'])
  4035. );
  4036. // fetch last row of the result set
  4037. PMA_DBI_data_seek($dt_result, $this->__get('num_rows') - 1);
  4038. $row = PMA_DBI_fetch_row($dt_result);
  4039. // check for non printable sorted row data
  4040. $meta = $fields_meta[$sorted_column_index];
  4041. if (stristr($meta->type, self::BLOB_FIELD)
  4042. || ($meta->type == self::GEOMETRY_FIELD)
  4043. ) {
  4044. $column_for_last_row = $this->_handleNonPrintableContents(
  4045. $meta->type, $row[$sorted_column_index],
  4046. $transformation_plugin, $transform_options,
  4047. $default_function, $meta, null
  4048. );
  4049. } else {
  4050. $column_for_last_row = $row[$sorted_column_index];
  4051. }
  4052. $column_for_last_row = strtoupper(
  4053. substr($column_for_last_row, 0, $GLOBALS['cfg']['LimitChars'])
  4054. );
  4055. // reset to first row for the loop in _getTableBody()
  4056. PMA_DBI_data_seek($dt_result, 0);
  4057. // we could also use here $sort_expression_nodirection
  4058. return ' [' . htmlspecialchars($sort_column)
  4059. . ': <strong>' . htmlspecialchars($column_for_first_row) . ' - '
  4060. . htmlspecialchars($column_for_last_row) . '</strong>]';
  4061. }
  4062. }
  4063. return null;
  4064. } // end of the '_getSortedColumnMessage()' function
  4065. /**
  4066. * Set the content need to be show in message
  4067. *
  4068. * @param string $sorted_column_message the message for sorted column
  4069. * @param string $limit_clause the limit clause of analyzed query
  4070. * @param integer $total the total number of rows returned by
  4071. * the SQL query without any
  4072. * programmatically appended LIMIT clause
  4073. * @param integer $pos_next the offset for next page
  4074. * @param string $pre_count the string renders before row count
  4075. * @param string $after_count the string renders after row count
  4076. *
  4077. * @return PMA_Message $message an object of PMA_Message
  4078. *
  4079. * @access private
  4080. *
  4081. * @see getTable()
  4082. */
  4083. private function _setMessageInformation(
  4084. $sorted_column_message, $limit_clause, $total,
  4085. $pos_next, $pre_count, $after_count
  4086. ) {
  4087. $unlim_num_rows = $this->__get('unlim_num_rows'); // To use in isset()
  4088. if (isset($unlim_num_rows) && ($unlim_num_rows != $total)) {
  4089. $selectstring = ', ' . $unlim_num_rows . ' ' . __('in query');
  4090. } else {
  4091. $selectstring = '';
  4092. }
  4093. if (! empty($limit_clause)) {
  4094. $limit_data
  4095. = PMA_Util::analyzeLimitClause($limit_clause);
  4096. $first_shown_rec = $limit_data['start'];
  4097. if ($limit_data['length'] < $total) {
  4098. $last_shown_rec = $limit_data['start'] + $limit_data['length'] - 1;
  4099. } else {
  4100. $last_shown_rec = $limit_data['start'] + $total - 1;
  4101. }
  4102. } elseif (($_SESSION['tmp_user_values']['max_rows'] == self::ALL_ROWS)
  4103. || ($pos_next > $total)
  4104. ) {
  4105. $first_shown_rec = $_SESSION['tmp_user_values']['pos'];
  4106. $last_shown_rec = $total - 1;
  4107. } else {
  4108. $first_shown_rec = $_SESSION['tmp_user_values']['pos'];
  4109. $last_shown_rec = $pos_next - 1;
  4110. }
  4111. if (PMA_Table::isView($this->__get('db'), $this->__get('table'))
  4112. && ($total == $GLOBALS['cfg']['MaxExactCountViews'])
  4113. ) {
  4114. $message = PMA_Message::notice(
  4115. __(
  4116. 'This view has at least this number of rows. '
  4117. . 'Please refer to %sdocumentation%s.'
  4118. )
  4119. );
  4120. $message->addParam('[doc@cfg_MaxExactCount]');
  4121. $message->addParam('[/doc]');
  4122. $message_view_warning = PMA_Util::showHint($message);
  4123. } else {
  4124. $message_view_warning = false;
  4125. }
  4126. $message = PMA_Message::success(__('Showing rows %1s - %2s'));
  4127. $message->addParam($first_shown_rec);
  4128. if ($message_view_warning) {
  4129. $message->addParam('... ' . $message_view_warning, false);
  4130. } else {
  4131. $message->addParam($last_shown_rec);
  4132. }
  4133. $message->addMessage('(');
  4134. if (!$message_view_warning) {
  4135. $message_total = PMA_Message::notice($pre_count . __('%d total'));
  4136. $message_total->addParam($total);
  4137. if (!empty($after_count)) {
  4138. $message_total->addMessage($after_count);
  4139. }
  4140. $message->addMessage($message_total, '');
  4141. $message->addMessage($selectstring, '');
  4142. $message->addMessage(', ', '');
  4143. }
  4144. $messagge_qt = PMA_Message::notice(__('Query took %01.4f sec') . ')');
  4145. $messagge_qt->addParam($this->__get('querytime'));
  4146. $message->addMessage($messagge_qt, '');
  4147. if (! is_null($sorted_column_message)) {
  4148. $message->addMessage($sorted_column_message, '');
  4149. }
  4150. return $message;
  4151. } // end of the '_setMessageInformation()' function
  4152. /**
  4153. * Set the value of $map array for linking foreign key related tables
  4154. *
  4155. * @param array &$map the list of relations
  4156. *
  4157. * @return void
  4158. *
  4159. * @access private
  4160. *
  4161. * @see getTable()
  4162. */
  4163. private function _setParamForLinkForeignKeyRelatedTables(&$map)
  4164. {
  4165. // To be able to later display a link to the related table,
  4166. // we verify both types of relations: either those that are
  4167. // native foreign keys or those defined in the phpMyAdmin
  4168. // configuration storage. If no PMA storage, we won't be able
  4169. // to use the "column to display" notion (for example show
  4170. // the name related to a numeric id).
  4171. $exist_rel = PMA_getForeigners(
  4172. $this->__get('db'), $this->__get('table'), '', self::POSITION_BOTH
  4173. );
  4174. if ($exist_rel) {
  4175. foreach ($exist_rel as $master_field => $rel) {
  4176. $display_field = PMA_getDisplayField(
  4177. $rel['foreign_db'], $rel['foreign_table']
  4178. );
  4179. $map[$master_field] = array(
  4180. $rel['foreign_table'],
  4181. $rel['foreign_field'],
  4182. $display_field,
  4183. $rel['foreign_db']
  4184. );
  4185. } // end while
  4186. } // end if
  4187. } // end of the '_setParamForLinkForeignKeyRelatedTables()' function
  4188. /**
  4189. * Prepare multi field edit/delete links
  4190. *
  4191. * @param integer &$dt_result the link id associated to the query
  4192. * which results have to be displayed
  4193. * @param array $analyzed_sql the analyzed query
  4194. * @param string $del_link the display element - 'del_link'
  4195. *
  4196. * @return string $links_html html content
  4197. *
  4198. * @access private
  4199. *
  4200. * @see getTable()
  4201. */
  4202. private function _getMultiRowOperationLinks(
  4203. &$dt_result, $analyzed_sql, $del_link
  4204. ) {
  4205. $links_html = '';
  4206. $url_query = $this->__get('url_query');
  4207. $delete_text = ($del_link == self::DELETE_ROW) ? __('Delete') : __('Kill');
  4208. $_url_params = array(
  4209. 'db' => $this->__get('db'),
  4210. 'table' => $this->__get('table'),
  4211. 'sql_query' => $this->__get('sql_query'),
  4212. 'goto' => $this->__get('goto'),
  4213. );
  4214. if ($_SESSION['tmp_user_values']['disp_direction'] != self::DISP_DIR_VERTICAL) {
  4215. $links_html .= '<img class="selectallarrow" width="38" height="22"'
  4216. . ' src="' . $this->__get('pma_theme_image') . 'arrow_'
  4217. . $this->__get('text_dir') . '.png' . '"'
  4218. . ' alt="' . __('With selected:') . '" />';
  4219. }
  4220. $links_html .= '<input type="checkbox" id="checkall" title="'
  4221. . __('Check All') . '" /> '
  4222. . '<label for="checkall">' . __('Check All') . '</label> '
  4223. . '<i style="margin-left: 2em">' . __('With selected:') . '</i>' . "\n";
  4224. $links_html .= PMA_Util::getButtonOrImage(
  4225. 'submit_mult', 'mult_submit', 'submit_mult_change',
  4226. __('Change'), 'b_edit.png', 'edit'
  4227. );
  4228. $links_html .= PMA_Util::getButtonOrImage(
  4229. 'submit_mult', 'mult_submit', 'submit_mult_delete',
  4230. $delete_text, 'b_drop.png', 'delete'
  4231. );
  4232. if (isset($analyzed_sql[0])
  4233. && $analyzed_sql[0]['querytype'] == self::QUERY_TYPE_SELECT
  4234. ) {
  4235. $links_html .= PMA_Util::getButtonOrImage(
  4236. 'submit_mult', 'mult_submit', 'submit_mult_export',
  4237. __('Export'), 'b_tblexport.png', 'export'
  4238. );
  4239. }
  4240. $links_html .= "\n";
  4241. $links_html .= '<input type="hidden" name="sql_query"'
  4242. .' value="' . htmlspecialchars($this->__get('sql_query')) . '" />'
  4243. . "\n";
  4244. if (! empty($url_query)) {
  4245. $links_html .= '<input type="hidden" name="url_query"'
  4246. .' value="' . $url_query . '" />' . "\n";
  4247. }
  4248. // fetch last row of the result set
  4249. PMA_DBI_data_seek($dt_result, $this->__get('num_rows') - 1);
  4250. $row = PMA_DBI_fetch_row($dt_result);
  4251. // $clause_is_unique is needed by getTable() to generate the proper param
  4252. // in the multi-edit and multi-delete form
  4253. list($where_clause, $clause_is_unique, $condition_array)
  4254. = PMA_Util::getUniqueCondition(
  4255. $dt_result,
  4256. $this->__get('fields_cnt'),
  4257. $this->__get('fields_meta'),
  4258. $row
  4259. );
  4260. // reset to first row for the loop in _getTableBody()
  4261. PMA_DBI_data_seek($dt_result, 0);
  4262. $links_html .= '<input type="hidden" name="clause_is_unique"'
  4263. .' value="' . $clause_is_unique . '" />' . "\n";
  4264. $links_html .= '</form>' . "\n";
  4265. return $links_html;
  4266. } // end of the '_getMultiRowOperationLinks()' function
  4267. /**
  4268. * Prepare table navigation bar at the top or bottom
  4269. *
  4270. * @param integer $pos_next the offset for the "next" page
  4271. * @param integer $pos_prev the offset for the "previous" page
  4272. * @param string $place the place to show navigation
  4273. * @param string $empty_line empty line depend on the $place
  4274. * @param boolean $is_innodb whether its InnoDB or not
  4275. *
  4276. * @return string html content of navigation bar
  4277. *
  4278. * @access private
  4279. *
  4280. * @see _getTable()
  4281. */
  4282. private function _getPlacedTableNavigatoins(
  4283. $pos_next, $pos_prev, $place, $empty_line, $is_innodb
  4284. ) {
  4285. $navigation_html = '';
  4286. if ($place == self::PLACE_BOTTOM_DIRECTION_DROPDOWN) {
  4287. $navigation_html .= '<br />' . "\n";
  4288. }
  4289. $navigation_html .= $this->_getTableNavigation(
  4290. $pos_next, $pos_prev, 'top_direction_dropdown', $is_innodb
  4291. );
  4292. if ($place == self::PLACE_TOP_DIRECTION_DROPDOWN) {
  4293. $navigation_html .= "\n";
  4294. }
  4295. return $navigation_html;
  4296. } // end of the '_getPlacedTableNavigatoins()' function
  4297. /**
  4298. * Get operations that are available on results.
  4299. *
  4300. * @param array $the_disp_mode the display mode
  4301. * @param array $analyzed_sql the analyzed query
  4302. *
  4303. * @return string $results_operations_html html content
  4304. *
  4305. * @access private
  4306. *
  4307. * @see getTable()
  4308. */
  4309. private function _getResultsOperations($the_disp_mode, $analyzed_sql)
  4310. {
  4311. global $printview;
  4312. $results_operations_html = '';
  4313. $fields_meta = $this->__get('fields_meta'); // To safe use in foreach
  4314. $header_shown = false;
  4315. $header = '<fieldset><legend>' . __('Query results operations')
  4316. . '</legend>';
  4317. if (($the_disp_mode[6] == '1') || ($the_disp_mode[9] == '1')) {
  4318. // Displays "printable view" link if required
  4319. if ($the_disp_mode[9] == '1') {
  4320. if (!$header_shown) {
  4321. $results_operations_html .= $header;
  4322. $header_shown = true;
  4323. }
  4324. $_url_params = array(
  4325. 'db' => $this->__get('db'),
  4326. 'table' => $this->__get('table'),
  4327. 'printview' => '1',
  4328. 'sql_query' => $this->__get('sql_query'),
  4329. );
  4330. $url_query = PMA_generate_common_url($_url_params);
  4331. $results_operations_html
  4332. .= PMA_Util::linkOrButton(
  4333. 'sql.php' . $url_query,
  4334. PMA_Util::getIcon(
  4335. 'b_print.png', __('Print view'), true
  4336. ),
  4337. array('target' => 'print_view'),
  4338. true,
  4339. true,
  4340. 'print_view'
  4341. )
  4342. . "\n";
  4343. if ($_SESSION['tmp_user_values']['display_text']) {
  4344. $_url_params['display_text'] = self::DISPLAY_FULL_TEXT;
  4345. $results_operations_html
  4346. .= PMA_Util::linkOrButton(
  4347. 'sql.php' . PMA_generate_common_url($_url_params),
  4348. PMA_Util::getIcon(
  4349. 'b_print.png',
  4350. __('Print view (with full texts)'), true
  4351. ),
  4352. array('target' => 'print_view'),
  4353. true,
  4354. true,
  4355. 'print_view'
  4356. )
  4357. . "\n";
  4358. unset($_url_params['display_text']);
  4359. }
  4360. } // end displays "printable view"
  4361. }
  4362. // Export link
  4363. // (the url_query has extra parameters that won't be used to export)
  4364. // (the single_table parameter is used in display_export.lib.php
  4365. // to hide the SQL and the structure export dialogs)
  4366. // If the parser found a PROCEDURE clause
  4367. // (most probably PROCEDURE ANALYSE()) it makes no sense to
  4368. // display the Export link).
  4369. if (isset($analyzed_sql[0])
  4370. && ($analyzed_sql[0]['querytype'] == self::QUERY_TYPE_SELECT)
  4371. && ! isset($printview)
  4372. && ! isset($analyzed_sql[0]['queryflags']['procedure'])
  4373. ) {
  4374. if (isset($analyzed_sql[0]['table_ref'][0]['table_true_name'])
  4375. && ! isset($analyzed_sql[0]['table_ref'][1]['table_true_name'])
  4376. ) {
  4377. $_url_params['single_table'] = 'true';
  4378. }
  4379. if (! $header_shown) {
  4380. $results_operations_html .= $header;
  4381. $header_shown = true;
  4382. }
  4383. $_url_params['unlim_num_rows'] = $this->__get('unlim_num_rows');
  4384. /**
  4385. * At this point we don't know the table name; this can happen
  4386. * for example with a query like
  4387. * SELECT bike_code FROM (SELECT bike_code FROM bikes) tmp
  4388. * As a workaround we set in the table parameter the name of the
  4389. * first table of this database, so that tbl_export.php and
  4390. * the script it calls do not fail
  4391. */
  4392. if (empty($_url_params['table']) && ! empty($_url_params['db'])) {
  4393. $_url_params['table'] = PMA_DBI_fetch_value("SHOW TABLES");
  4394. /* No result (probably no database selected) */
  4395. if ($_url_params['table'] === false) {
  4396. unset($_url_params['table']);
  4397. }
  4398. }
  4399. $results_operations_html .= PMA_Util::linkOrButton(
  4400. 'tbl_export.php' . PMA_generate_common_url($_url_params),
  4401. PMA_Util::getIcon(
  4402. 'b_tblexport.png', __('Export'), true
  4403. ),
  4404. '',
  4405. true,
  4406. true,
  4407. ''
  4408. )
  4409. . "\n";
  4410. // prepare chart
  4411. $results_operations_html .= PMA_Util::linkOrButton(
  4412. 'tbl_chart.php' . PMA_generate_common_url($_url_params),
  4413. PMA_Util::getIcon(
  4414. 'b_chart.png', __('Display chart'), true
  4415. ),
  4416. '',
  4417. true,
  4418. true,
  4419. ''
  4420. )
  4421. . "\n";
  4422. // prepare GIS chart
  4423. $geometry_found = false;
  4424. // If atleast one geometry field is found
  4425. foreach ($fields_meta as $meta) {
  4426. if ($meta->type == self::GEOMETRY_FIELD) {
  4427. $geometry_found = true;
  4428. break;
  4429. }
  4430. }
  4431. if ($geometry_found) {
  4432. $results_operations_html
  4433. .= PMA_Util::linkOrButton(
  4434. 'tbl_gis_visualization.php'
  4435. . PMA_generate_common_url($_url_params),
  4436. PMA_Util::getIcon(
  4437. 'b_globe.gif', __('Visualize GIS data'), true
  4438. ),
  4439. '',
  4440. true,
  4441. true,
  4442. ''
  4443. )
  4444. . "\n";
  4445. }
  4446. }
  4447. // CREATE VIEW
  4448. /**
  4449. *
  4450. * @todo detect privileges to create a view
  4451. * (but see 2006-01-19 note in display_create_table.lib.php,
  4452. * I think we cannot detect db-specific privileges reliably)
  4453. * Note: we don't display a Create view link if we found a PROCEDURE clause
  4454. */
  4455. if (!$header_shown) {
  4456. $results_operations_html .= $header;
  4457. $header_shown = true;
  4458. }
  4459. if (!PMA_DRIZZLE && !isset($analyzed_sql[0]['queryflags']['procedure'])) {
  4460. $ajax_class = ' ajax';
  4461. $results_operations_html .= '<span>'
  4462. . PMA_Util::linkOrButton(
  4463. 'view_create.php' . $url_query,
  4464. PMA_Util::getIcon(
  4465. 'b_views.png', __('Create view'), true
  4466. ),
  4467. array('class' => 'create_view' . $ajax_class), true, true, ''
  4468. )
  4469. . '</span>' . "\n";
  4470. }
  4471. if ($header_shown) {
  4472. $results_operations_html .= '</fieldset><br />';
  4473. }
  4474. return $results_operations_html;
  4475. } // end of the '_getResultsOperations()' function
  4476. /**
  4477. * Verifies what to do with non-printable contents (binary or BLOB)
  4478. * in Browse mode.
  4479. *
  4480. * @param string $category BLOB|BINARY|GEOMETRY
  4481. * @param string $content the binary content
  4482. * @param string $transformation_plugin transformation plugin.
  4483. * Can also be the default function:
  4484. * PMA_mimeDefaultFunction
  4485. * @param string $transform_options transformation parameters
  4486. * @param string $default_function default transformation function
  4487. * @param object $meta the meta-information about the field
  4488. * @param array $url_params parameters that should go to the
  4489. * download link
  4490. *
  4491. * @return mixed string or float
  4492. *
  4493. * @access private
  4494. *
  4495. * @see _getDataCellForBlobColumns(),
  4496. * _getDataCellForGeometryColumns(),
  4497. * _getDataCellForNonNumericAndNonBlobColumns(),
  4498. * _getSortedColumnMessage()
  4499. */
  4500. private function _handleNonPrintableContents(
  4501. $category, $content, $transformation_plugin, $transform_options,
  4502. $default_function, $meta, $url_params = array()
  4503. ) {
  4504. $result = '[' . $category;
  4505. if (is_null($content)) {
  4506. $result .= ' - NULL';
  4507. $size = 0;
  4508. } elseif (isset($content)) {
  4509. $size = strlen($content);
  4510. $display_size
  4511. = PMA_Util::formatByteDown($size, 3, 1);
  4512. $result .= ' - '. $display_size[0] . ' ' . $display_size[1];
  4513. }
  4514. $result .= ']';
  4515. if (gettype($transformation_plugin) == "object"
  4516. && (strpos($transformation_plugin->getMIMESubtype(), 'Octetstream')
  4517. // if we want to use a text transformation on a BLOB column
  4518. || strpos($transformation_plugin->getMIMEtype(), 'Text') !== false)
  4519. ) {
  4520. $result = $content;
  4521. }
  4522. if ($size > 0) {
  4523. if ($default_function != $transformation_plugin) {
  4524. $result = $transformation_plugin->applyTransformation(
  4525. $result,
  4526. $transform_options,
  4527. $meta
  4528. );
  4529. } else {
  4530. $result = $this->$default_function($result, array(), $meta);
  4531. if (stristr($meta->type, self::BLOB_FIELD)
  4532. && $_SESSION['tmp_user_values']['display_blob']
  4533. ) {
  4534. // in this case, restart from the original $content
  4535. $result = $this->_displayBinaryAsPrintable($content, 'blob');
  4536. }
  4537. /* Create link to download */
  4538. if (count($url_params) > 0) {
  4539. $result = '<a href="tbl_get_field.php'
  4540. . PMA_generate_common_url($url_params) . '" class="disableAjax">'
  4541. . $result . '</a>';
  4542. }
  4543. }
  4544. }
  4545. return($result);
  4546. } // end of the '_handleNonPrintableContents()' function
  4547. /**
  4548. * Prepares the displayable content of a data cell in Browse mode,
  4549. * taking into account foreign key description field and transformations
  4550. *
  4551. * @param string $class css classes for the td element
  4552. * @param bool $condition_field whether the column is a part of the
  4553. * where clause
  4554. * @param string $analyzed_sql the analyzed query
  4555. * @param object $meta the meta-information about the field
  4556. * @param array $map the list of relations
  4557. * @param string $data data
  4558. * @param string $transformation_plugin transformation plugin.
  4559. * Can also be the default function:
  4560. * PMA_mimeDefaultFunction
  4561. * @param string $default_function default function
  4562. * @param string $nowrap 'nowrap' if the content should not
  4563. * be wrapped
  4564. * @param string $where_comparison data for the where clause
  4565. * @param array $transform_options array of options for transformation
  4566. * @param bool $is_field_truncated whether the field is truncated
  4567. *
  4568. * @return string formatted data
  4569. *
  4570. * @access private
  4571. *
  4572. * @see _getDataCellForNumericColumns(), _getDataCellForGeometryColumns(),
  4573. * _getDataCellForNonNumericAndNonBlobColumns(),
  4574. *
  4575. */
  4576. private function _getRowData(
  4577. $class, $condition_field, $analyzed_sql, $meta, $map, $data,
  4578. $transformation_plugin, $default_function, $nowrap, $where_comparison,
  4579. $transform_options, $is_field_truncated
  4580. ) {
  4581. $printview = $this->__get('printview');
  4582. $result = '<td class="'
  4583. . $this->_addClass(
  4584. $class, $condition_field, $meta, $nowrap,
  4585. $is_field_truncated, $transformation_plugin, $default_function
  4586. )
  4587. . '">';
  4588. if (isset($analyzed_sql[0]['select_expr'])
  4589. && is_array($analyzed_sql[0]['select_expr'])
  4590. ) {
  4591. foreach ($analyzed_sql[0]['select_expr']
  4592. as $select_expr_position => $select_expr
  4593. ) {
  4594. $alias = $analyzed_sql[0]['select_expr']
  4595. [$select_expr_position]['alias'];
  4596. if (isset($alias) && strlen($alias)) {
  4597. $true_column = $analyzed_sql[0]['select_expr']
  4598. [$select_expr_position]['column'];
  4599. if ($alias == $meta->name) {
  4600. // this change in the parameter does not matter
  4601. // outside of the function
  4602. $meta->name = $true_column;
  4603. } // end if
  4604. } // end if
  4605. } // end foreach
  4606. } // end if
  4607. if (isset($map[$meta->name])) {
  4608. // Field to display from the foreign table?
  4609. if (isset($map[$meta->name][2]) && strlen($map[$meta->name][2])) {
  4610. $dispsql = 'SELECT '
  4611. . PMA_Util::backquote($map[$meta->name][2])
  4612. . ' FROM '
  4613. . PMA_Util::backquote($map[$meta->name][3])
  4614. . '.'
  4615. . PMA_Util::backquote($map[$meta->name][0])
  4616. . ' WHERE '
  4617. . PMA_Util::backquote($map[$meta->name][1])
  4618. . $where_comparison;
  4619. $dispresult = PMA_DBI_try_query($dispsql, null, PMA_DBI_QUERY_STORE);
  4620. if ($dispresult && PMA_DBI_num_rows($dispresult) > 0) {
  4621. list($dispval) = PMA_DBI_fetch_row($dispresult, 0);
  4622. } else {
  4623. $dispval = __('Link not found');
  4624. }
  4625. @PMA_DBI_free_result($dispresult);
  4626. } else {
  4627. $dispval = '';
  4628. } // end if... else...
  4629. if (isset($printview) && ($printview == '1')) {
  4630. $result .= ($transformation_plugin != $default_function
  4631. ? $transformation_plugin->applyTransformation(
  4632. $data,
  4633. $transform_options,
  4634. $meta
  4635. )
  4636. : $this->$default_function($data)
  4637. )
  4638. . ' <code>[-&gt;' . $dispval . ']</code>';
  4639. } else {
  4640. if ($_SESSION['tmp_user_values']['relational_display'] == self::RELATIONAL_KEY) {
  4641. // user chose "relational key" in the display options, so
  4642. // the title contains the display field
  4643. $title = (! empty($dispval))
  4644. ? ' title="' . htmlspecialchars($dispval) . '"'
  4645. : '';
  4646. } else {
  4647. $title = ' title="' . htmlspecialchars($data) . '"';
  4648. }
  4649. $_url_params = array(
  4650. 'db' => $map[$meta->name][3],
  4651. 'table' => $map[$meta->name][0],
  4652. 'pos' => '0',
  4653. 'sql_query' => 'SELECT * FROM '
  4654. . PMA_Util::backquote(
  4655. $map[$meta->name][3]
  4656. ) . '.'
  4657. . PMA_Util::backquote(
  4658. $map[$meta->name][0]
  4659. )
  4660. . ' WHERE '
  4661. . PMA_Util::backquote(
  4662. $map[$meta->name][1]
  4663. )
  4664. . $where_comparison,
  4665. );
  4666. $result .= '<a class="ajax" href="sql.php' . PMA_generate_common_url($_url_params)
  4667. . '"' . $title . '>';
  4668. if ($transformation_plugin != $default_function) {
  4669. // always apply a transformation on the real data,
  4670. // not on the display field
  4671. $result .= $transformation_plugin->applyTransformation(
  4672. $data,
  4673. $transform_options,
  4674. $meta
  4675. );
  4676. } else {
  4677. if ($_SESSION['tmp_user_values']['relational_display'] == self::RELATIONAL_DISPLAY_COLUMN) {
  4678. // user chose "relational display field" in the
  4679. // display options, so show display field in the cell
  4680. $result .= $this->$default_function($dispval);
  4681. } else {
  4682. // otherwise display data in the cell
  4683. $result .= $this->$default_function($data);
  4684. }
  4685. }
  4686. $result .= '</a>';
  4687. }
  4688. } else {
  4689. $result .= ($transformation_plugin != $default_function
  4690. ? $transformation_plugin->applyTransformation(
  4691. $data,
  4692. $transform_options,
  4693. $meta
  4694. )
  4695. : $this->$default_function($data)
  4696. );
  4697. }
  4698. // create hidden field if results from structure table
  4699. if (isset($_GET['browse_distinct']) && ($_GET['browse_distinct'] == 1)) {
  4700. $where_comparison = " = '" . $data . "'";
  4701. $_url_params_for_show_data_row = array(
  4702. 'db' => $this->__get('db'),
  4703. 'table' => $meta->orgtable,
  4704. 'pos' => '0',
  4705. 'sql_query' => 'SELECT * FROM '
  4706. . PMA_Util::backquote($this->__get('db'))
  4707. . '.' . PMA_Util::backquote($meta->orgtable)
  4708. . ' WHERE '
  4709. . PMA_Util::backquote($meta->orgname)
  4710. . $where_comparison,
  4711. );
  4712. $result .= '<input type="hidden" class="data_browse_link" value="'
  4713. . PMA_generate_common_url($_url_params_for_show_data_row). '" />';
  4714. }
  4715. $result .= '</td>' . "\n";
  4716. return $result;
  4717. } // end of the '_getRowData()' function
  4718. /**
  4719. * Prepares a checkbox for multi-row submits
  4720. *
  4721. * @param string $del_url delete url
  4722. * @param array $is_display array with explicit indexes for all
  4723. * the display elements
  4724. * @param string $row_no the row number
  4725. * @param string $where_clause_html url encoded where clause
  4726. * @param array $condition_array array of conditions in the where clause
  4727. * @param string $del_query delete query
  4728. * @param string $id_suffix suffix for the id
  4729. * @param string $class css classes for the td element
  4730. *
  4731. * @return string the generated HTML
  4732. *
  4733. * @access private
  4734. *
  4735. * @see _getTableBody(), _getCheckboxAndLinks()
  4736. */
  4737. private function _getCheckboxForMultiRowSubmissions(
  4738. $del_url, $is_display, $row_no, $where_clause_html, $condition_array,
  4739. $del_query, $id_suffix, $class
  4740. ) {
  4741. $ret = '';
  4742. if (! empty($del_url) && $is_display['del_lnk'] != self::KILL_PROCESS) {
  4743. $ret .= '<td ';
  4744. if (! empty($class)) {
  4745. $ret .= 'class="' . $class . '"';
  4746. }
  4747. $ret .= ' class="center">'
  4748. . '<input type="checkbox" id="id_rows_to_delete'
  4749. . $row_no . $id_suffix
  4750. . '" name="rows_to_delete[' . $row_no . ']"'
  4751. . ' class="multi_checkbox checkall"'
  4752. . ' value="' . $where_clause_html . '" '
  4753. . ' />'
  4754. . '<input type="hidden" class="condition_array" value="'
  4755. . htmlspecialchars(json_encode($condition_array)) . '" />'
  4756. . ' </td>';
  4757. }
  4758. return $ret;
  4759. } // end of the '_getCheckboxForMultiRowSubmissions()' function
  4760. /**
  4761. * Prepares an Edit link
  4762. *
  4763. * @param string $edit_url edit url
  4764. * @param string $class css classes for td element
  4765. * @param string $edit_str text for the edit link
  4766. * @param string $where_clause where clause
  4767. * @param string $where_clause_html url encoded where clause
  4768. *
  4769. * @return string the generated HTML
  4770. *
  4771. * @access private
  4772. *
  4773. * @see _getTableBody(), _getCheckboxAndLinks()
  4774. */
  4775. private function _getEditLink(
  4776. $edit_url, $class, $edit_str, $where_clause, $where_clause_html
  4777. ) {
  4778. $ret = '';
  4779. if (! empty($edit_url)) {
  4780. $ret .= '<td class="' . $class . ' center" ' . ' ><span class="nowrap">'
  4781. . PMA_Util::linkOrButton(
  4782. $edit_url, $edit_str, array(), false
  4783. );
  4784. /*
  4785. * Where clause for selecting this row uniquely is provided as
  4786. * a hidden input. Used by jQuery scripts for handling grid editing
  4787. */
  4788. if (! empty($where_clause)) {
  4789. $ret .= '<input type="hidden" class="where_clause" value ="'
  4790. . $where_clause_html . '" />';
  4791. }
  4792. $ret .= '</span></td>';
  4793. }
  4794. return $ret;
  4795. } // end of the '_getEditLink()' function
  4796. /**
  4797. * Prepares an Copy link
  4798. *
  4799. * @param string $copy_url copy url
  4800. * @param string $copy_str text for the copy link
  4801. * @param string $where_clause where clause
  4802. * @param string $where_clause_html url encoded where clause
  4803. * @param string $class css classes for the td element
  4804. *
  4805. * @return string the generated HTML
  4806. *
  4807. * @access private
  4808. *
  4809. * @see _getTableBody(), _getCheckboxAndLinks()
  4810. */
  4811. private function _getCopyLink(
  4812. $copy_url, $copy_str, $where_clause, $where_clause_html, $class
  4813. ) {
  4814. $ret = '';
  4815. if (! empty($copy_url)) {
  4816. $ret .= '<td class="';
  4817. if (! empty($class)) {
  4818. $ret .= $class . ' ';
  4819. }
  4820. $ret .= 'center" ' . ' ><span class="nowrap">'
  4821. . PMA_Util::linkOrButton(
  4822. $copy_url, $copy_str, array(), false
  4823. );
  4824. /*
  4825. * Where clause for selecting this row uniquely is provided as
  4826. * a hidden input. Used by jQuery scripts for handling grid editing
  4827. */
  4828. if (! empty($where_clause)) {
  4829. $ret .= '<input type="hidden" class="where_clause" value="'
  4830. . $where_clause_html . '" />';
  4831. }
  4832. $ret .= '</span></td>';
  4833. }
  4834. return $ret;
  4835. } // end of the '_getCopyLink()' function
  4836. /**
  4837. * Prepares a Delete link
  4838. *
  4839. * @param string $del_url delete url
  4840. * @param string $del_str text for the delete link
  4841. * @param string $js_conf text for the JS confirmation
  4842. * @param string $class css classes for the td element
  4843. *
  4844. * @return string the generated HTML
  4845. *
  4846. * @access private
  4847. *
  4848. * @see _getTableBody(), _getCheckboxAndLinks()
  4849. */
  4850. private function _getDeleteLink($del_url, $del_str, $js_conf, $class)
  4851. {
  4852. $ret = '';
  4853. if (! empty($del_url)) {
  4854. $ret .= '<td class="';
  4855. if (! empty($class)) {
  4856. $ret .= $class . ' ';
  4857. }
  4858. $ajax = PMA_Response::getInstance()->isAjax() ? ' ajax' : '';
  4859. $ret .= 'center" ' . ' >'
  4860. . PMA_Util::linkOrButton(
  4861. $del_url, $del_str, array('class' => 'delete_row' . $ajax), false
  4862. )
  4863. . '<div class="hide">' . $js_conf . '</div>'
  4864. . '</td>';
  4865. }
  4866. return $ret;
  4867. } // end of the '_getDeleteLink()' function
  4868. /**
  4869. * Prepare checkbox and links at some position (left or right)
  4870. * (only called for horizontal mode)
  4871. *
  4872. * @param string $position the position of the checkbox and links
  4873. * @param string $del_url delete url
  4874. * @param array $is_display array with explicit indexes for all the
  4875. * display elements
  4876. * @param string $row_no row number
  4877. * @param string $where_clause where clause
  4878. * @param string $where_clause_html url encoded where clause
  4879. * @param array $condition_array array of conditions in the where clause
  4880. * @param string $del_query delete query
  4881. * @param string $id_suffix suffix for the id
  4882. * @param string $edit_url edit url
  4883. * @param string $copy_url copy url
  4884. * @param string $class css classes for the td elements
  4885. * @param string $edit_str text for the edit link
  4886. * @param string $copy_str text for the copy link
  4887. * @param string $del_str text for the delete link
  4888. * @param string $js_conf text for the JS confirmation
  4889. *
  4890. * @return string the generated HTML
  4891. *
  4892. * @access private
  4893. *
  4894. * @see _getPlacedLinks()
  4895. */
  4896. private function _getCheckboxAndLinks(
  4897. $position, $del_url, $is_display, $row_no, $where_clause,
  4898. $where_clause_html, $condition_array, $del_query, $id_suffix,
  4899. $edit_url, $copy_url, $class, $edit_str, $copy_str, $del_str, $js_conf
  4900. ) {
  4901. $ret = '';
  4902. if ($position == self::POSITION_LEFT) {
  4903. $ret .= $this->_getCheckboxForMultiRowSubmissions(
  4904. $del_url, $is_display, $row_no, $where_clause_html, $condition_array,
  4905. $del_query, $id_suffix = '_left', ''
  4906. );
  4907. $ret .= $this->_getEditLink(
  4908. $edit_url, $class, $edit_str, $where_clause, $where_clause_html
  4909. );
  4910. $ret .= $this->_getCopyLink(
  4911. $copy_url, $copy_str, $where_clause, $where_clause_html, ''
  4912. );
  4913. $ret .= $this->_getDeleteLink($del_url, $del_str, $js_conf, '');
  4914. } elseif ($position == self::POSITION_RIGHT) {
  4915. $ret .= $this->_getDeleteLink($del_url, $del_str, $js_conf, '');
  4916. $ret .= $this->_getCopyLink(
  4917. $copy_url, $copy_str, $where_clause, $where_clause_html, ''
  4918. );
  4919. $ret .= $this->_getEditLink(
  4920. $edit_url, $class, $edit_str, $where_clause, $where_clause_html
  4921. );
  4922. $ret .= $this->_getCheckboxForMultiRowSubmissions(
  4923. $del_url, $is_display, $row_no, $where_clause_html, $condition_array,
  4924. $del_query, $id_suffix = '_right', ''
  4925. );
  4926. } else { // $position == self::POSITION_NONE
  4927. $ret .= $this->_getCheckboxForMultiRowSubmissions(
  4928. $del_url, $is_display, $row_no, $where_clause_html, $condition_array,
  4929. $del_query, $id_suffix = '_left', ''
  4930. );
  4931. }
  4932. return $ret;
  4933. } // end of the '_getCheckboxAndLinks()' function
  4934. /**
  4935. * Replace some html-unfriendly stuff
  4936. *
  4937. * @param string $buffer String to process
  4938. *
  4939. * @return Escaped and cleaned up text suitable for html.
  4940. *
  4941. * @access private
  4942. *
  4943. * @see _getDataCellForBlobField(), _getRowData(),
  4944. * _handleNonPrintableContents()
  4945. */
  4946. private function _mimeDefaultFunction($buffer)
  4947. {
  4948. $buffer = htmlspecialchars($buffer);
  4949. $buffer = str_replace(
  4950. "\011",
  4951. ' &nbsp;&nbsp;&nbsp;',
  4952. str_replace(' ', ' &nbsp;', $buffer)
  4953. );
  4954. $buffer = preg_replace("@((\015\012)|(\015)|(\012))@", '<br />', $buffer);
  4955. return $buffer;
  4956. }
  4957. /**
  4958. * Display binary fields as hex string for PHP <5.4,
  4959. * otherwise escape the contents if it may be displayed as hex
  4960. *
  4961. * @param string $content String to parse
  4962. * @param string $binary_or_blob 'binary' or 'blob'
  4963. * @param int $hexlength optional, get substring
  4964. *
  4965. * @return Displayable version of the binary string
  4966. *
  4967. * @access private
  4968. *
  4969. * @see _getDataCellForGeometryColumns
  4970. * _getDataCellForNonNumericAndNonBlobColumns
  4971. * _handleNonPrintableContents
  4972. */
  4973. private function _displayBinaryAsPrintable(
  4974. $content, $binary_or_blob, $hexlength = null
  4975. ) {
  4976. if (PMA_PHP_INT_VERSION < 50400
  4977. || ($binary_or_blob === 'binary'
  4978. && $_SESSION['tmp_user_values']['display_binary_as_hex']
  4979. && PMA_Util::containsNonPrintableAscii($content)
  4980. )
  4981. ) {
  4982. $content = bin2hex($content);
  4983. if ($hexlength !== null) {
  4984. $content = PMA_substr($content, $hexlength);
  4985. }
  4986. } else {
  4987. $content = htmlspecialchars(
  4988. PMA_Util::replaceBinaryContents(
  4989. $content
  4990. ),
  4991. ENT_SUBSTITUTE
  4992. );
  4993. }
  4994. return $content;
  4995. }
  4996. }
  4997. ?>